Array ('self' => true), 'OnGetPopupSize' => Array ('self' => true), 'OnClosePopup' => Array ('self' => true), 'OnSaveSetting' => Array ('self' => true), 'OnProcessSelected' => Array ('self' => true), // allow CSV import file upload ); $this->permMapping = array_merge($this->permMapping, $permissions); } /** * Checks user permission to execute given $event * * @param kEvent $event * @return bool * @access public */ public function CheckPermission(kEvent $event) { $perm_value = null; $system_events = array( 'OnResetModRwCache', 'OnResetSections', 'OnResetConfigsCache', 'OnResetParsedData', 'OnResetMemcache', 'OnDeleteCompiledTemplates', 'OnCompileTemplates', 'OnGenerateTableStructure', 'OnSynchronizeDBRevisions', 'OnDeploy', 'OnRebuildThemes', 'OnDumpAssets', 'OnCheckPrefixConfig', 'OnMemoryCacheGet', 'OnMemoryCacheSet', ); if ( in_array($event->Name, $system_events) ) { // events from "Tools -> System Tools" section are controlled via that section "edit" permission $perm_value = /*$this->Application->isDebugMode() ||*/ $this->Application->CheckPermission($event->getSection() . '.edit'); } $tools_events = Array ( 'OnBackup' => 'in-portal:backup.view', 'OnBackupProgress' => 'in-portal:backup.view', 'OnDeleteBackup' => 'in-portal:backup.view', 'OnBackupCancel' => 'in-portal:backup.view', 'OnRestore' => 'in-portal:restore.view', 'OnRestoreProgress' => 'in-portal:restore.view', 'OnRestoreCancel' => 'in-portal:backup.view', 'OnSqlQuery' => 'in-portal:sql_query.view', ); if ( array_key_exists($event->Name, $tools_events) ) { $perm_value = $this->Application->CheckPermission($tools_events[$event->Name]); } if ( $event->Name == 'OnSaveMenuFrameWidth' || $event->Name == 'OnDropTempTablesByWID' ) { $perm_value = $this->Application->isAdminUser; } /** @var kPermissionsHelper $perm_helper */ $perm_helper = $this->Application->recallObject('PermissionsHelper'); $csv_events = Array ('OnCSVImportBegin', 'OnCSVImportStep', 'OnExportCSV', 'OnGetCSV'); if ( in_array($event->Name, $csv_events) ) { /** @var kCSVHelper $csv_helper */ $csv_helper = $this->Application->recallObject('CSVHelper'); $prefix = $csv_helper->getPrefix(stripos($event->Name, 'import') !== false); $perm_mapping = Array ( 'OnCSVImportBegin' => 'OnProcessSelected', 'OnCSVImportStep' => 'OnProcessSelected', 'OnExportCSV' => 'OnLoad', 'OnGetCSV' => 'OnLoad', ); $tmp_event = new kEvent($prefix . ':' . $perm_mapping[$event->Name] ); $perm_value = $perm_helper->CheckEventPermission($tmp_event, $this->permMapping); } if ( isset($perm_value) ) { return $perm_helper->finalizePermissionCheck($event, $perm_value); } return parent::CheckPermission($event); } /** * Reset mod-rewrite url cache * * @param kEvent $event * @return void * @access protected */ protected function OnResetModRwCache(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } $this->Conn->Query('DELETE FROM ' . TABLE_PREFIX . 'CachedUrls'); $event->SetRedirectParam('action_completed', 1); } /** * Resets tree section cache and refreshes admin section tree * * @param kEvent $event * @return void * @access protected */ protected function OnResetSections(kEvent $event) { if ($this->Application->GetVar('ajax') == 'yes') { $event->status = kEvent::erSTOP; } if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { $this->Application->rebuildCache('master:sections_parsed', kCache::REBUILD_LATER, CacheSettings::$sectionsParsedRebuildTime); } else { $this->Application->rebuildDBCache('sections_parsed', kCache::REBUILD_LATER, CacheSettings::$sectionsParsedRebuildTime); } $event->SetRedirectParam('refresh_tree', 1); $event->SetRedirectParam('action_completed', 1); } /** * Resets unit config cache * * @param kEvent $event * @return void * @access protected */ protected function OnResetConfigsCache(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) { $this->Application->rebuildCache('master:config_files', kCache::REBUILD_LATER, CacheSettings::$unitCacheRebuildTime); } else { $this->Application->rebuildDBCache('config_files', kCache::REBUILD_LATER, CacheSettings::$unitCacheRebuildTime); } $this->OnResetParsedData($event); /** @var SkinHelper $skin_helper */ $skin_helper = $this->Application->recallObject('SkinHelper'); $skin_helper->deleteCompiled(); } /** * Resets parsed data from unit configs * * @param kEvent $event * @return void * @access protected */ protected function OnResetParsedData(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } $this->Application->DeleteUnitCache(); if ( $this->Application->GetVar('validate_configs') ) { $event->SetRedirectParam('validate_configs', 1); } $event->SetRedirectParam('action_completed', 1); } /** * Resets memory cache * * @param kEvent $event * @return void * @access protected */ protected function OnResetMemcache(kEvent $event) { if ($this->Application->GetVar('ajax') == 'yes') { $event->status = kEvent::erSTOP; } $this->Application->resetCache(); $event->SetRedirectParam('action_completed', 1); } /** * Compiles all templates (with a progress bar) * * @param kEvent $event * @return void * @access protected */ protected function OnCompileTemplates(kEvent $event) { /** @var NParserCompiler $compiler */ $compiler = $this->Application->recallObject('NParserCompiler'); $compiler->CompileTemplatesStep(); $event->status = kEvent::erSTOP; } /** * Deletes all compiled templates * * @param kEvent $event * @return void * @access protected */ protected function OnDeleteCompiledTemplates(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } $base_path = WRITEABLE . DIRECTORY_SEPARATOR . 'cache'; // delete debugger reports $debugger_reports = glob(RESTRICTED . '/debug_@*@.txt'); if ( $debugger_reports ) { foreach ($debugger_reports as $debugger_report) { unlink($debugger_report); } } $this->_deleteCompiledTemplates($base_path); $event->SetRedirectParam('action_completed', 1); } /** * Deletes compiled templates in a given folder * * @param string $folder * @param bool $unlink_folder * @return void * @access protected */ protected function _deleteCompiledTemplates($folder, $unlink_folder = false) { $sub_folders = glob($folder . '/*', GLOB_ONLYDIR); if ( is_array($sub_folders) ) { foreach ($sub_folders as $sub_folder) { $this->_deleteCompiledTemplates($sub_folder, true); } } $files = glob($folder . '/*.php'); if ( is_array($files) ) { foreach ($files as $file) { unlink($file); } } if ( $unlink_folder ) { rmdir($folder); } } /** * Generates structure for specified table * * @param kEvent $event * @return void * @access protected */ protected function OnGenerateTableStructure(kEvent $event) { $types_hash = Array ( 'string' => 'varchar|text|mediumtext|longtext|date|datetime|time|timestamp|char|year|enum|set', 'int' => 'smallint|mediumint|int|bigint|tinyint', 'float' => 'float|double|decimal', ); $table_name = $this->Application->GetVar('table_name'); if ( !$table_name ) { echo 'error: no table name specified'; return; } if ( TABLE_PREFIX && !preg_match('/^' . preg_quote(TABLE_PREFIX, '/') . '(.*)/', $table_name) && (strtolower($table_name) != $table_name) ) { // table name without prefix, then add it (don't affect K3 tables named in lowercase) $table_name = TABLE_PREFIX . $table_name; } if ( !$this->Conn->TableFound($table_name) ) { // table with prefix doesn't exist, assume that just config prefix passed -> resolve table name from it $prefix = preg_replace('/^' . preg_quote(TABLE_PREFIX, '/') . '/', '', $table_name); if ( $this->Application->prefixRegistred($prefix) ) { // when prefix is found -> use it's table (don't affect K3 tables named in lowecase) $table_name = $this->Application->getUnitOption($prefix, 'TableName'); } } $table_info = $this->Conn->Query('DESCRIBE '.$table_name); // 1. prepare config keys $grids = Array ( 'Default' => Array ( 'Icons' => Array ('default' => 'icon16_item.png'), 'Fields' => Array (), ) ); $grids_fields = Array(); $id_field = ''; $fields = Array (); $float_types = Array ('float', 'double', 'numeric'); foreach ($table_info as $field_info) { if ( preg_match('/l[\d]+_.*/', $field_info['Field']) ) { // don't put multilingual fields in config continue; } $field_options = Array (); if ( $field_info['Key'] == 'PRI' ) { if ( $field_info['Field'] == 'Id' ) { $grid_col_options = Array ('filter_block' => 'grid_range_filter', 'width' => 80); } else { $grid_col_options = Array ('title' => 'column:la_fld_Id', 'filter_block' => 'grid_range_filter', 'width' => 80); } } else { $grid_col_options = Array ('filter_block' => 'grid_like_filter'); } // 1. get php field type by mysql field type foreach ($types_hash as $php_type => $db_types) { if ( preg_match('/' . $db_types . '/', $field_info['Type']) ) { $field_options['type'] = $php_type; break; } } // 2. get field default value $default_value = $field_info['Default']; $not_null = $field_info['Null'] != 'YES'; if ( is_numeric($default_value) ) { $default_value = preg_match('/[\.,]/', $default_value) ? (float)$default_value : (int)$default_value; } if ( is_null($default_value) && $not_null ) { $default_value = $field_options['type'] == 'string' ? '' : 0; } if ( in_array($php_type, $float_types) ) { // this is float number if ( preg_match('/' . $db_types . '\([\d]+,([\d]+)\)/i', $field_info['Type'], $regs) ) { // size is described in structure -> add formatter $field_options['formatter'] = 'kFormatter'; $field_options['format'] = '%01.' . $regs[1] . 'f'; if ( $not_null ) { // null fields, will most likely have NULL as default value $default_value = 0; } } elseif ( $not_null ) { // no size information, just convert to float // null fields, will most likely have NULL as default value $default_value = (float)$default_value; } } if ( preg_match('/varchar\(([\d]+)\)/i', $field_info['Type'], $regs) ) { $field_options['max_len'] = (int)$regs[1]; } if ( preg_match('/tinyint\([\d]+\)/i', $field_info['Type']) ) { $field_options['formatter'] = 'kOptionsFormatter'; $field_options['options'] = Array (1 => 'la_Yes', 0 => 'la_No'); $field_options['use_phrases'] = 1; $grid_col_options['filter_block'] = 'grid_options_filter'; } if ( $not_null ) { $field_options['not_null'] = 1; } if ( $field_info['Key'] == 'PRI' ) { $default_value = 0; $id_field = $field_info['Field']; } if ( $php_type == 'int' && !$not_null ) { // numeric null field if ( preg_match('/(On|Date)$/', $field_info['Field']) || $field_info['Field'] == 'Modified' ) { $field_options['formatter'] = 'kDateFormatter'; $grid_col_options['filter_block'] = 'grid_date_range_filter'; $grid_col_options['width'] = 120; } else { $grid_col_options['filter_block'] = 'grid_range_filter'; $grid_col_options['width'] = 80; } } if ( $php_type == 'int' && ($not_null || is_numeric($default_value)) ) { // is integer field AND not null $field_options['default'] = (int)$default_value; } else { $field_options['default'] = $default_value; } $fields[$field_info['Field']] = $field_options; $grids_fields[$field_info['Field']] = $grid_col_options; } $grids['Default']['Fields'] = $grids_fields; $ret = Array ( 'IDField' => $id_field, 'Fields' => $fields, 'Grids' => $grids, ); $decorator = new UnitConfigDecorator(); $ret = $decorator->decorate($ret); $this->Application->InitParser(); ob_start(); echo $this->Application->ParseBlock(Array('name' => 'incs/header', 'body_properties' => 'style="background-color: #E7E7E7; margin: 8px;"')); ?> Close Window

highlightString($ret); ?>

Close Window
Application->ParseBlock(Array('name' => 'incs/footer')); echo ob_get_clean(); $event->status = kEvent::erSTOP; } /** * Refreshes ThemeFiles & Themes tables by actual content on HDD * * @param kEvent $event * @return void * @access protected */ protected function OnRebuildThemes(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } /** @var kThemesHelper $themes_helper */ $themes_helper = $this->Application->recallObject('ThemesHelper'); $themes_helper->refreshThemes(); $event->SetRedirectParam('action_completed', 1); } /** * Dumps assets * * @param kEvent $event Event. * * @return void */ protected function OnDumpAssets(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } /** @var MinifyHelper $minify_helper */ $minify_helper = $this->Application->recallObject('MinifyHelper'); $minify_helper->delete(); $minify_helper->dump(); $event->SetRedirectParam('action_completed', 1); } /** * Saves grid column widths after their resize by user * * @param kEvent $event * @return void * @access protected */ protected function OnSaveColumns(kEvent $event) { $picker_helper = new kColumnPickerHelper( $this->Application->GetVar('main_prefix'), $this->Application->GetLinkedVar('grid_name') ); $picked = trim($this->Application->GetVar('picked_str'), '|'); $hidden = trim($this->Application->GetVar('hidden_str'), '|'); $picker_helper->saveColumns($picked, $hidden); $this->finalizePopup($event); } /** * Saves various admin settings via ajax * * @param kEvent $event * @return void * @access protected */ protected function OnSaveSetting(kEvent $event) { if ( $this->Application->GetVar('ajax') != 'yes' ) { return; } $var_name = $this->Application->GetVar('var_name'); $var_value = $this->Application->GetVar('var_value'); $this->Application->StorePersistentVar($var_name, $var_value); $event->status = kEvent::erSTOP; } /** * Just closes popup & deletes last_template & opener_stack if popup, that is closing * * @param kEvent $event * @return void * @access protected */ protected function OnClosePopup(kEvent $event) { $event->SetRedirectParam('opener', 'u'); } /** * Occurs right after initialization of the kernel, used mainly as hook-to event * * @param kEvent $event * @return void * @access protected */ protected function OnStartup(kEvent $event) { if ( $this->Application->isAdmin ) { return; } $base_url = preg_quote($this->Application->BaseURL(), '/'); $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; if ( $referrer && !preg_match('/^' . $base_url . '/', $referrer) ) { $this->Application->Session->SetCookie('original_referrer', $referrer); $this->Application->SetVar('original_referrer', $referrer); } } /** * Occurs right before echoing the output, in Done method of application, used mainly as hook-to event * * @param kEvent $event * @return void * @access protected */ protected function OnBeforeShutdown(kEvent $event) { } /** * Is called after tree was build (when not from cache) * * @param kEvent $event * @return void * @access protected */ protected function OnAfterBuildTree(kEvent $event) { } /** * Called by AJAX to perform CSV export * * @param kEvent $event * @return void * @access protected */ protected function OnExportCSV(kEvent $event) { /** @var kCSVHelper $csv_helper */ $csv_helper = $this->Application->recallObject('CSVHelper'); $csv_helper->PrefixSpecial = $csv_helper->getPrefix(false); $csv_helper->grid = $this->Application->GetVar('grid'); $csv_helper->ExportStep(); $event->status = kEvent::erSTOP; } /** * Returning created by AJAX CSV file * * @param kEvent $event * @return void * @access protected */ protected function OnGetCSV(kEvent $event) { /** @var kCSVHelper $csv_helper */ $csv_helper = $this->Application->recallObject('CSVHelper'); $csv_helper->GetCSV(); } /** * Start CSV import * * @param kEvent $event * @return void * @access protected */ protected function OnCSVImportBegin(kEvent $event) { /** @var kDBItem $object */ $object = $event->getObject(Array ('skip_autoload' => true)); $object->setID(0); $field_values = $this->getSubmittedFields($event); $object->SetFieldsFromHash($field_values); $event->setEventParam('form_data', $field_values); $event->redirect = false; $result = 'required'; if ( $object->GetDBField('ImportFile') ) { /** @var kCSVHelper $csv_helper */ $csv_helper = $this->Application->recallObject('CSVHelper'); $csv_helper->PrefixSpecial = $csv_helper->getPrefix(true); $csv_helper->grid = $this->Application->GetVar('grid'); $result = $csv_helper->ImportStart($object->GetField('ImportFile', 'file_paths')); if ( $result === true ) { $event->redirect = $this->Application->GetVar('next_template'); $event->SetRedirectParam('PrefixSpecial', $this->Application->GetVar('PrefixSpecial')); $event->SetRedirectParam('grid', $this->Application->GetVar('grid')); } } if ( $event->redirect === false ) { $object->SetError('ImportFile', $result); $event->status = kEvent::erFAIL; } } /** * Performs one CSV import step * * @param kEvent $event * @return void * @access protected */ protected function OnCSVImportStep(kEvent $event) { /** @var kCSVHelper $import_helper */ $import_helper = $this->Application->recallObject('CSVHelper'); $import_helper->ImportStep(); $event->status = kEvent::erSTOP; } /** * Shows unit config filename, where requested prefix is defined * * @param kEvent $event * @return void * @access protected */ protected function OnCheckPrefixConfig(kEvent $event) { $prefix = $this->Application->GetVar('config_prefix'); $config_file = $this->Application->UnitConfigReader->prefixFiles[$prefix]; $this->Application->InitParser(); ob_start(); echo $this->Application->ParseBlock(Array('name' => 'incs/header', 'body_properties' => 'style="background-color: #E7E7E7; margin: 8px;"')); ?> Close Window

Prefix:
Unit Config: highlightString($config_file); ?>

Close Window
Application->ParseBlock(Array ('name' => 'incs/footer')); echo ob_get_clean(); $event->status = kEvent::erSTOP; } /** * Deletes temp tables, when user closes window using "x" button in top right corner * * @param kEvent $event * @return void * @access protected */ protected function OnDropTempTablesByWID(kEvent $event) { $sid = $this->Application->GetSID(Session::PURPOSE_REFERENCE); $wid = $this->Application->GetVar('m_wid'); $tables = $this->Conn->GetCol('SHOW TABLES'); $mask_edit_table = '/' . TABLE_PREFIX . 'ses_' . $sid . '_' . $wid . '_edit_(.*)$/'; foreach ($tables as $table) { if ( preg_match($mask_edit_table, $table, $rets) ) { $this->Conn->Query('DROP TABLE IF EXISTS ' . $table); } } echo 'OK'; $event->status = kEvent::erSTOP; } /** * Backup all data * * @param kEvent $event * @return void * @access protected */ protected function OnBackup(kEvent $event) { /** @var BackupHelper $backup_helper */ $backup_helper = $this->Application->recallObject('BackupHelper'); if ( !$backup_helper->initBackup() ) { $event->status = kEvent::erFAIL; } $event->redirect = 'tools/backup2'; } /** * Perform next backup step * * @param kEvent $event * @return void * @access protected */ protected function OnBackupProgress(kEvent $event) { /** @var BackupHelper $backup_helper */ $backup_helper = $this->Application->recallObject('BackupHelper'); $done_percent = $backup_helper->performBackup(); if ( $done_percent == 100 ) { $event->redirect = 'tools/backup3'; return; } $event->status = kEvent::erSTOP; echo $done_percent; } /** * Stops Backup & redirect to Backup template * * @param kEvent $event * @return void * @access protected */ protected function OnBackupCancel(kEvent $event) { $event->redirect = 'tools/backup1'; } /** * Starts restore process * * @param kEvent $event * @return void * @access protected */ protected function OnRestore(kEvent $event) { /** @var BackupHelper $backup_helper */ $backup_helper = $this->Application->recallObject('BackupHelper'); $backup_helper->initRestore(); $event->redirect = 'tools/restore3'; } /** * Performs next restore step * * @param kEvent $event * @return void * @access protected */ protected function OnRestoreProgress(kEvent $event) { /** @var BackupHelper $backup_helper */ $backup_helper = $this->Application->recallObject('BackupHelper'); $done_percent = $backup_helper->performRestore(); if ( $done_percent == BackupHelper::SQL_ERROR_DURING_RESTORE ) { $event->redirect = 'tools/restore4'; } elseif ( $done_percent == BackupHelper::FAILED_READING_BACKUP_FILE ) { $this->Application->StoreVar('adm.restore_error', 'File read error'); $event->redirect = 'tools/restore4'; } elseif ( $done_percent == 100 ) { $backup_helper->replaceRestoredFiles(); $this->Application->StoreVar('adm.restore_success', 1); $event->redirect = 'tools/restore4'; } else { $event->status = kEvent::erSTOP; echo $done_percent; } } /** * Stops Restore & redirect to Restore template * * @param kEvent $event * @return void * @access protected */ protected function OnRestoreCancel(kEvent $event) { $event->redirect = 'tools/restore1'; } /** * Deletes one backup file * * @param kEvent $event * @return void * @access protected */ protected function OnDeleteBackup(kEvent $event) { /** @var BackupHelper $backup_helper */ $backup_helper = $this->Application->recallObject('BackupHelper'); $backup_helper->delete(); } /** * Starts restore process * * @param kEvent $event * @return void * @access protected */ protected function OnSqlQuery(kEvent $event) { $sql = $this->Application->GetVar('sql'); if ( $sql ) { $start = microtime(true); $result = $this->Conn->Query($sql); $this->Application->SetVar('sql_time', round(microtime(true) - $start, 7)); if ( $result && is_array($result) ) { $this->Application->SetVar('sql_has_rows', 1); $this->Application->SetVar('sql_rows', serialize($result)); } $check_sql = trim(strtolower($sql)); if ( preg_match('/^(insert|update|replace|delete)/', $check_sql) ) { $this->Application->SetVar('sql_has_affected', 1); $this->Application->SetVar('sql_affected', $this->Conn->getAffectedRows()); } } $this->Application->SetVar('query_status', 1); $event->status = kEvent::erFAIL; } /** * Occurs after unit config cache was successfully rebuilt * * @param kEvent $event * @return void * @access protected */ protected function OnAfterCacheRebuild(kEvent $event) { } /** * Removes "Community -> Groups" section when it is not allowed * * @param kEvent $event * @return void * @access protected */ protected function OnAfterConfigRead(kEvent $event) { parent::OnAfterConfigRead($event); $section_adjustments = $this->Application->getUnitOption($event->Prefix, 'SectionAdjustments', Array()); if ( !$this->Application->ConfigValue('AdvancedUserManagement') ) { $section_adjustments['in-portal:user_groups'] = 'remove'; } $section_adjustments['in-portal:root'] = Array ( 'label' => $this->Application->ConfigValue('Site_Name') ); $this->Application->setUnitOption($event->Prefix, 'SectionAdjustments', $section_adjustments); } /** * Saves menu (tree) frame width * * @param kEvent $event * @return void * @access protected */ protected function OnSaveMenuFrameWidth(kEvent $event) { $event->status = kEvent::erSTOP; if ( !$this->Application->ConfigValue('ResizableFrames') ) { return; } $this->Application->StorePersistentVar('MenuFrameWidth', (int)$this->Application->GetVar('width')); } /** * Retrieves data from memory cache * * @param kEvent $event * @return void * @access protected */ protected function OnMemoryCacheGet(kEvent $event) { $event->status = kEvent::erSTOP; $ret = Array ('message' => '', 'code' => 0); // 0 - ok, > 0 - error $key = $this->Application->GetVar('key'); if ( !$key ) { $ret['code'] = 1; $ret['message'] = 'Key name missing'; } else { $value = $this->Application->getCache($key); $ret['value'] =& $value; $ret['size'] = is_string($value) ? kUtil::formatSize(strlen($value)) : '?'; $ret['type'] = gettype($value); if ( kUtil::IsSerialized($value) ) { $value = unserialize($value); } if ( is_array($value) ) { $ret['value'] = print_r($value, true); } if ( $ret['value'] === false ) { $ret['code'] = 2; $ret['message'] = 'Key "' . $key . '" doesn\'t exist'; } } /** @var JSONHelper $json_helper */ $json_helper = $this->Application->recallObject('JSONHelper'); echo $json_helper->encode($ret); } /** * Retrieves data from memory cache * * @param kEvent $event * @return void * @access protected */ protected function OnMemoryCacheSet(kEvent $event) { $event->status = kEvent::erSTOP; $ret = Array ('message' => '', 'code' => 0); // 0 - ok, > 0 - error $key = $this->Application->GetVar('key'); if ( !$key ) { $ret['code'] = 1; $ret['message'] = 'Key name missing'; } else { $value = $this->Application->GetVar('value'); $res = $this->Application->setCache($key, $value); $ret['result'] = $res ? 'OK' : 'FAILED'; } /** @var JSONHelper $json_helper */ $json_helper = $this->Application->recallObject('JSONHelper'); echo $json_helper->encode($ret); } /** * Deploy changes * * Usage: "php tools/run_event.php adm:OnDeploy b674006f3edb1d9cd4d838c150b0567d" * * @param kEvent $event * @return void * @access protected */ protected function OnDeploy(kEvent $event) { $this->_deploymentAction($event); } /** * Synchronizes database revisions from "project_upgrades.sql" file * * @param kEvent $event * @return void * @access protected */ protected function OnSynchronizeDBRevisions(kEvent $event) { $this->_deploymentAction($event, true); } /** * Common code to invoke deployment helper * * @param kEvent $event * @param bool $dry_run * @return void * @access protected */ protected function _deploymentAction(kEvent $event, $dry_run = false) { /** @var DeploymentHelper $deployment_helper */ $deployment_helper = $this->Application->recallObject('DeploymentHelper'); $deployment_helper->setEvent($event); if ( $deployment_helper->deployAll($dry_run) ) { $event->SetRedirectParam('action_completed', 1); if ( !$deployment_helper->isCommandLine ) { // browser invocation -> don't perform redirect $event->redirect = false; // no redirect, but deployment succeeded - set redirect params directly foreach ($event->getRedirectParams() as $param_name => $param_value) { $this->Application->SetVar($param_name, $param_value); } } } else { $event->status = kEvent::erFAIL; } } /** * [SCHEDULED TASK] * 1. Delete all Debug files from system/.restricted folder (format debug_@f353wfsds43g5...@.txt) * 2. Run MySQL OPTIMIZE SQL one by one on all In-Portal tables (found by prefix). * * @param kEvent $event * @return void * @access protected */ protected function OnOptimizePerformance(kEvent $event) { $start_time = adodb_mktime(); $sql = 'SELECT SessionKey FROM ' . TABLE_PREFIX . 'UserSessions WHERE LastAccessed > ' . $start_time; $active_sessions = array_flip($this->Conn->GetCol($sql)); $files = scandir(RESTRICTED); $file_path = RESTRICTED . '/'; foreach ( $files as $file_name ) { if ( !preg_match('#^debug_@([^@]+)@.txt$#', $file_name, $matches) ) { // Not debug file. continue; } $sid = $matches[1]; if ( isset($active_sessions[$sid]) || (filemtime($file_path . $file_name) > $start_time) ) { // debug file belongs to an active session // debug file is recently created (after sessions snapshot) continue; } unlink($file_path . $file_name); } $system_tables = $this->Conn->GetCol('SHOW TABLES LIKE "' . TABLE_PREFIX . '%"'); foreach ($system_tables AS $table_name) { $this->Conn->Query('OPTIMIZE TABLE ' . $table_name); } } /** * Returns popup size (by template), if not cached, then parse template to get value * * @param kEvent $event * @return void * @access protected */ protected function OnGetPopupSize(kEvent $event) { $event->status = kEvent::erSTOP; if ( $this->Application->GetVar('ajax') != 'yes' ) { return; } $t = $this->Application->GetVar('template_name'); $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'PopupSizes WHERE TemplateName = ' . $this->Conn->qstr($t); $popup_info = $this->Conn->GetRow($sql); $this->Application->setContentType('text/plain'); if ( !$popup_info ) { // dies when SetPopupSize tag found & in ajax request $this->Application->InitParser(); $this->Application->ParseBlock(Array ('name' => $t)); // tag SetPopupSize not found in template -> use default size echo '750x400'; } else { echo $popup_info['PopupWidth'] . 'x' . $popup_info['PopupHeight']; } } /** * Writes HTTP request to System Log * * @param kEvent $event * @return void * @access public */ public function OnLogHttpRequest(kEvent $event) { if ( defined('DBG_REQUEST_LOG') && DBG_REQUEST_LOG && $this->Application->LoggedIn() ) { $log = $this->Application->log('HTTP_REQUEST')->addRequestData(); if ( !$log->write() ) { trigger_error('Unable to log Http Request due disabled "System Log"', E_USER_WARNING); } } } /** * Purges expired database cache entries. * * @param kEvent $event Event. * * @return void */ protected function OnPurgeExpiredDatabaseCacheScheduledTask(kEvent $event) { $sql = 'DELETE FROM ' . TABLE_PREFIX . 'SystemCache WHERE LifeTime > 0 AND Cached + LifeTime < ' . time(); $this->Conn->Query($sql); } /** * Populates URL unit cache * * @param kEvent $event Event. * * @return void */ protected function OnPopulateUrlUnitCacheScheduledTask(kEvent $event) { $sql = 'SELECT DISTINCT Prefixes FROM ' . TABLE_PREFIX . 'CachedUrls'; $urls = $this->Conn->GetColIterator($sql); $prefixes = array(); foreach ( $urls as $url_prefixes ) { $url_prefixes = explode('|', trim($url_prefixes, '|')); foreach ( $url_prefixes as $url_prefix ) { $url_prefix = explode(':', $url_prefix); $prefixes[$url_prefix[0]] = 1; } } if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) { $this->Application->setCache('cached_urls_unit_prefixes', array_keys($prefixes), 3600); } else { $this->Application->setDBCache('cached_urls_unit_prefixes', serialize(array_keys($prefixes)), 3600); } } /** * Deletes stuck semaphore records. * * @param kEvent $event Event. * * @return void */ protected function OnDeleteStuckSemaphoresScheduledTask(kEvent $event) { $semaphore_lifetime = $this->Application->ConfigValue('SemaphoreLifetimeInSeconds'); $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'Semaphores WHERE Timestamp < ' . strtotime('-' . $semaphore_lifetime . ' seconds'); $stuck_semaphores = $this->Conn->Query($sql, 'SemaphoreId'); if ( !$stuck_semaphores ) { return; } /** @var LanguagesItem $language */ $language = $this->Application->recallObject('lang.current', null, array('skip_autoload' => true)); $date_format = $language->GetDBField('DateFormat') . ' ' . $language->GetDBField('TimeFormat'); foreach ( $stuck_semaphores as $semaphore_id => $semaphore_data ) { $log = $this->Application->log('Stuck semaphore detected (unit: ' . $semaphore_data['MainPrefix'] . ')'); $log->setLogLevel(kLogger::LL_ERROR); $log->addTrace(unserialize($semaphore_data['Backtrace'])); $log->setUserData(implode(PHP_EOL, array( 'Main Prefix: ' . $semaphore_data['MainPrefix'], 'Main IDs: ' . $semaphore_data['MainIDs'], 'Created On: ' . date($date_format, $semaphore_data['Timestamp']), 'Deleted On: ' . date($date_format), ))); $log->setLogField('LogHostname', $semaphore_data['Hostname']); $log->setLogField('LogRequestSource', 1); // Web. $log->setLogField('LogInterface', kLogger::LI_ADMIN); $log->setLogField('LogRequestURI', $semaphore_data['RequestURI']); $log->setLogField('LogUserId', $semaphore_data['UserId']); $log->setLogField('IpAddress', $semaphore_data['IpAddress']); $log->setLogField('LogSessionKey', $semaphore_data['SessionKey']); $log->write(); $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Semaphores WHERE SemaphoreId = ' . $semaphore_id; $this->Conn->Query($sql); } } } class UnitConfigDecorator { var $parentPath = Array (); /** * Decorates given array * * @param Array $var * @param int $level * @return string */ public function decorate($var, $level = 0) { $ret = ''; $deep_level = count($this->parentPath); if ( $deep_level && ($this->parentPath[0] == 'Fields') ) { $expand = $level < 2; } elseif ( $deep_level && ($this->parentPath[0] == 'Grids') ) { if ( $deep_level == 3 && $this->parentPath[2] == 'Icons' ) { $expand = false; } else { $expand = $level < 4; } } else { $expand = $level == 0; } if ( is_array($var) ) { $ret .= 'array('; $prepend = $expand ? "\n" . str_repeat("\t", $level + 1) : ''; foreach ($var as $key => $value) { array_push($this->parentPath, $key); $ret .= $prepend . (is_string($key) ? "'" . $key . "'" : $key) . ' => ' . $this->decorate($value, $level + 1); $ret .= ',' . ($expand ? '' : ' '); array_pop($this->parentPath); } $prepend = $expand ? "\n" . str_repeat("\t", $level) : ''; if ( !$expand ) { $ret = rtrim($ret, ', '); } $ret .= $prepend . ')'; } else { if ( is_null($var) ) { $ret = 'null'; } elseif ( is_string($var) ) { $ret = "'" . $var . "'"; } else { $ret = $var; } } return $ret; } }