Index: branches/5.2.x/core/units/admin/admin_events_handler.php =================================================================== --- branches/5.2.x/core/units/admin/admin_events_handler.php (revision 16372) +++ branches/5.2.x/core/units/admin/admin_events_handler.php (revision 16373) @@ -1,1251 +1,1251 @@ Array ('self' => true), 'OnGetPopupSize' => Array ('self' => true), 'OnClosePopup' => Array ('self' => true), 'OnSaveSetting' => Array ('self' => true), 'OnDropTempTablesByWID' => 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', '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' ) { $perm_value = $this->Application->isAdminUser; } $perm_helper = $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ $csv_events = Array ('OnCSVImportBegin', 'OnCSVImportStep', 'OnExportCSV', 'OnGetCSV'); if ( in_array($event->Name, $csv_events) ) { $csv_helper = $this->Application->recallObject('CSVHelper'); /* @var $csv_helper kCSVHelper */ $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); $skin_helper = $this->Application->recallObject('SkinHelper'); /* @var $skin_helper 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) { $compiler = $this->Application->recallObject('NParserCompiler'); /* @var $compiler 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; } $themes_helper = $this->Application->recallObject('ThemesHelper'); /* @var $themes_helper kThemesHelper */ $themes_helper->refreshThemes(); $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 = $this->Application->recallObject('ColumnPickerHelper'); /* @var $picker_helper kColumnPickerHelper */ $picker_helper->SetGridName($this->Application->GetLinkedVar('grid_name')); $picked = trim($this->Application->GetVar('picked_str'), '|'); $hidden = trim($this->Application->GetVar('hidden_str'), '|'); $main_prefix = $this->Application->GetVar('main_prefix'); $picker_helper->SaveColumns($main_prefix, $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) { $csv_helper = $this->Application->recallObject('CSVHelper'); /* @var $csv_helper kCSVHelper */ $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) { $csv_helper = $this->Application->recallObject('CSVHelper'); /* @var $csv_helper kCSVHelper */ $csv_helper->GetCSV(); } /** * Start CSV import * * @param kEvent $event * @return void * @access protected */ protected function OnCSVImportBegin(kEvent $event) { $object = $event->getObject(Array ('skip_autoload' => true)); /* @var $object kDBItem */ $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') ) { $csv_helper = $this->Application->recallObject('CSVHelper'); /* @var $csv_helper kCSVHelper */ $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) { $import_helper = $this->Application->recallObject('CSVHelper'); /* @var $import_helper kCSVHelper */ $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(); $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) { $backup_helper = $this->Application->recallObject('BackupHelper'); /* @var $backup_helper 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) { $backup_helper = $this->Application->recallObject('BackupHelper'); /* @var $backup_helper 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) { $backup_helper = $this->Application->recallObject('BackupHelper'); /* @var $backup_helper BackupHelper */ $backup_helper->initRestore(); $event->redirect = 'tools/restore3'; } /** * Performs next restore step * * @param kEvent $event * @return void * @access protected */ protected function OnRestoreProgress(kEvent $event) { $backup_helper = $this->Application->recallObject('BackupHelper'); /* @var $backup_helper 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) { $backup_helper = $this->Application->recallObject('BackupHelper'); /* @var $backup_helper 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->SetConfigValue('MenuFrameWidth', (int)$this->Application->GetVar('width')); + $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'; } } $json_helper = $this->Application->recallObject('JSONHelper'); /* @var $json_helper 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'; } $json_helper = $this->Application->recallObject('JSONHelper'); /* @var $json_helper 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) { $deployment_helper = $this->Application->recallObject('DeploymentHelper'); /* @var $deployment_helper 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_@977827436@.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_@([0-9]{9})@.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']; } } } 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; } } Index: branches/5.2.x/core/units/admin/admin_tag_processor.php =================================================================== --- branches/5.2.x/core/units/admin/admin_tag_processor.php (revision 16372) +++ branches/5.2.x/core/units/admin/admin_tag_processor.php (revision 16373) @@ -1,1115 +1,1119 @@ Application->GetVar('after_script'); if ($after_script) { return ''; } return ''; } /** * Returns section title with #section# keyword replaced with current section * * @param Array $params * @return string */ function GetSectionTitle($params) { if (array_key_exists('default', $params)) { return $params['default']; } return $this->Application->Phrase( kUtil::replaceModuleSection($params['phrase']) ); } /** * Returns section icon with #section# keyword replaced with current section * * @param Array $params * @return string */ function GetSectionIcon($params) { return kUtil::replaceModuleSection($params['icon']); } /** * Returns version of module by name * * @param Array $params * @return string */ function ModuleVersion($params) { return $this->Application->findModule('Name', $params['module'], 'Version'); } /** * Used in table form section drawing * * @param Array $params * @return string */ function DrawTree($params) { static $deep_level = 0; // when processings, then sort children by priority (key of children array) $ret = ''; $section_name = $params['section_name']; $params['name'] = $this->SelectParam($params, 'name,render_as,block'); $sections_helper = $this->Application->recallObject('SectionsHelper'); /* @var $sections_helper kSectionsHelper */ $section_data =& $sections_helper->getSectionData($section_name); $params['children_count'] = isset($section_data['children']) ? count($section_data['children']) : 0; $params['deep_level'] = $deep_level++; $template = $section_data['url']['t']; unset($section_data['url']['t']); $section_data['section_url'] = $this->Application->HREF($template, '', $section_data['url']); $ret .= $this->Application->ParseBlock( array_merge($params, $section_data) ); if (!isset($section_data['children'])) { return $ret; } ksort($section_data['children'], SORT_NUMERIC); foreach ($section_data['children'] as $section_name) { if (!$sections_helper->sectionVisible($section_name)) { continue; } $params['section_name'] = $section_name; $ret .= $this->DrawTree($params); $deep_level--; } return $ret; } function SectionInfo($params) { $section = $params['section']; if ($section == '#session#') { $section = $this->Application->RecallVar('section'); } $sections_helper = $this->Application->recallObject('SectionsHelper'); /* @var $sections_helper kSectionsHelper */ $section_data =& $sections_helper->getSectionData($section); if (!$section_data) { throw new Exception('Use of undefined section "' . $section . '" in "' . __METHOD__ . '"'); return ''; } if (array_key_exists('parent', $params) && $params['parent']) { do { $section = $section_data['parent']; $section_data =& $sections_helper->getSectionData($section); } while (array_key_exists('use_parent_header', $section_data) && $section_data['use_parent_header']); } $info = $params['info']; switch ($info) { case 'module_path': if (isset($params['module']) && $params['module']) { $module = $params['module']; } elseif (isset($section_data['icon_module'])) { $module = $section_data['icon_module']; } else { $module = '#session#'; } $res = $this->ModulePath(array('module' => $module)); break; case 'perm_section': $res = $sections_helper->getPermSection($section); break; case 'label': $res = ''; if ( $section ) { if ( $section == 'in-portal:root' ) { // don't translate label for top section, because it's already translated $res = $section_data['label']; } else { $no_editing = array_key_exists('no_editing', $params) ? $params['no_editing'] : false; $res = $this->Application->Phrase($section_data['label'], !$no_editing); } } break; default: $res = $section_data[$info]; break; } if (array_key_exists('as_label', $params) && $params['as_label']) { $res = $this->Application->Phrase($res); } return $res; } function PrintSection($params) { $section_name = $params['section_name']; if ($section_name == '#session#') { $section_name = $this->Application->RecallVar('section'); } $sections_helper = $this->Application->recallObject('SectionsHelper'); /* @var $sections_helper kSectionsHelper */ if (isset($params['use_first_child']) && $params['use_first_child']) { $section_name = $sections_helper->getFirstChild($section_name, true); } $section_data =& $sections_helper->getSectionData($section_name); $params['name'] = $this->SelectParam($params, 'name,render_as,block'); $params['section_name'] = $section_name; $url_params = $section_data['url']; unset($url_params['t']); $section_data['section_url'] = $this->Application->HREF($section_data['url']['t'], '', $url_params); $ret = $this->Application->ParseBlock( array_merge($params, $section_data) ); return $ret; } /** * Used in XML drawing for tree * * @param Array $params * @return string */ function PrintSections($params) { // when processings, then sort children by priority (key of children array) $ret = ''; $section_name = $params['section_name']; if ($section_name == '#session#') { $section_name = $this->Application->RecallVar('section'); } $sections_helper = $this->Application->recallObject('SectionsHelper'); /* @var $sections_helper kSectionsHelper */ $section_data =& $sections_helper->getSectionData($section_name); $params['name'] = $this->SelectParam($params, 'name,render_as,block'); if (!isset($section_data['children'])) { return ''; } ksort($section_data['children'], SORT_NUMERIC); foreach ($section_data['children'] as $section_name) { $params['section_name'] = $section_name; $section_data =& $sections_helper->getSectionData($section_name); if (!$sections_helper->sectionVisible($section_name)) { continue; } else { $show_mode = isset($section_data['show_mode']) ? $section_data['show_mode'] : smNORMAL; $section_data['debug_only'] = ($show_mode == smDEBUG) || ($show_mode == smSUPER_ADMIN) ? 1 : 0; } if (isset($section_data['tabs_only']) && $section_data['tabs_only']) { $perm_status = false; $folder_label = $section_data['label']; ksort($section_data['children'], SORT_NUMERIC); foreach ($section_data['children'] as $priority => $section_name) { // if only tabs in this section & none of them have permission, then skip section too $section_name = $sections_helper->getPermSection($section_name); $perm_status = $this->Application->CheckPermission($section_name.'.view', 1); if ($perm_status) { break; } } if (!$perm_status) { // no permission for all tabs -> don't display tree node either continue; } $params['section_name'] = $section_name; $section_data =& $sections_helper->getSectionData($section_name); $section_data['label'] = $folder_label; // use folder label in tree $section_data['is_tab'] = 1; } else { $section_name = $sections_helper->getPermSection($section_name); if (!$this->Application->CheckPermission($section_name.'.view', 1)) continue; } $params['children_count'] = isset($section_data['children']) ? count($section_data['children']) : 0; // remove template, so it doesn't appear as additional parameter in url $template = $section_data['url']['t']; unset($section_data['url']['t']); $section_data['section_url'] = $this->Application->HREF($template, '', $section_data['url']); $late_load = getArrayValue($section_data, 'late_load'); if ($late_load) { $t = $late_load['t']; unset($late_load['t']); $section_data['late_load'] = $this->Application->HREF($t, '', $late_load); $params['children_count'] = 99; } else { $section_data['late_load'] = ''; } // restore template $section_data['url']['t'] = $template; $ret .= $this->Application->ParseBlock( array_merge($params, $section_data) ); $params['section_name'] = $section_name; } return preg_replace("/\r\n|\n/", '', $ret); } function ListSectionPermissions($params) { $section_name = isset($params['section_name']) ? $params['section_name'] : $this->Application->GetVar('section_name'); $sections_helper = $this->Application->recallObject('SectionsHelper'); /* @var $sections_helper kSectionsHelper */ $section_data =& $sections_helper->getSectionData($section_name); $block_params = array_merge($section_data, Array('name' => $params['render_as'], 'section_name' => $section_name)); $ret = ''; foreach ($section_data['permissions'] as $perm_name) { if (preg_match('/^advanced:(.*)/', $perm_name) != $params['type']) continue; $block_params['perm_name'] = $perm_name; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } function ModuleInclude($params) { foreach ($params as $param_name => $param_value) { $params[$param_name] = kUtil::replaceModuleSection($param_value); } return $this->Application->ProcessParsedTag('m', 'ModuleInclude', $params); } function TodayDate($params) { return date($params['format']); } /** * Draws section tabs using block name passed * * @param Array $params */ function ListTabs($params) { $sections_helper = $this->Application->recallObject('SectionsHelper'); /* @var $sections_helper kSectionsHelper */ $section_data =& $sections_helper->getSectionData($params['section_name']); $ret = ''; $block_params = Array('name' => $params['render_as']); ksort($section_data['children'], SORT_NUMERIC); foreach ($section_data['children'] as $priority => $section_name) { $perm_section = $sections_helper->getPermSection($section_name); if ( !$this->Application->CheckPermission($perm_section.'.view') ) { continue; } $tab_data =& $sections_helper->getSectionData($section_name); $block_params['t'] = $tab_data['url']['t']; $block_params['pass'] = $tab_data['url']['pass']; $block_params['title'] = $tab_data['label']; $block_params['main_prefix'] = $section_data['SectionPrefix']; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } /** * Returns list of module item tabs that have view permission in current category * * @param Array $params */ function ListCatalogTabs($params) { $ret = ''; $special = isset($params['special']) ? $params['special'] : ''; $replace_main = isset($params['replace_m']) && $params['replace_m']; $skip_prefixes = isset($params['skip_prefixes']) ? explode(',', $params['skip_prefixes']) : Array(); $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; foreach ($this->Application->ModuleInfo as $module_name => $module_info) { $prefix = $module_info['Var']; if ($prefix == 'm' && $replace_main) { $prefix = 'c'; } if (in_array($prefix, $skip_prefixes) || !$this->Application->prefixRegistred($prefix) || !$this->Application->getUnitOption($prefix, 'CatalogItem')) { continue; } $icon = $this->Application->getUnitOption($prefix, 'CatalogTabIcon'); if (strpos($icon, ':') !== false) { list ($icon_module, $icon) = explode(':', $icon, 2); } else { $icon_module = 'core'; } $label = $this->Application->getUnitOption($prefix, $params['title_property']); $block_params['title'] = $label; $block_params['prefix'] = $prefix; $block_params['icon_module'] = $icon_module; $block_params['icon'] = $icon; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } /** * Renders inividual catalog tab based on prefix and title_property given * * @param Array $params * @return string */ function CatalogTab($params) { $icon = $this->Application->getUnitOption($params['prefix'], 'CatalogTabIcon'); if (strpos($icon, ':') !== false) { list ($icon_module, $icon) = explode(':', $icon, 2); } else { $icon_module = 'core'; } $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; $block_params['icon_module'] = $icon_module; $block_params['icon'] = $icon; $block_params['title'] = $this->Application->getUnitOption($params['prefix'], $params['title_property']); return $this->Application->ParseBlock($block_params); } /** * Allows to construct link for opening any type of catalog item selector * * @param Array $params * @return string */ function SelectorLink($params) { $mode = 'catalog'; if (isset($params['mode'])) { // {catalog, advanced_view} $mode = $params['mode']; unset($params['mode']); } $params['t'] = 'catalog/item_selector/item_selector_'.$mode; $params['m_cat_id'] = $this->Application->getBaseCategory(); $default_params = Array('pass' => 'all,'.$params['prefix']); unset($params['prefix']); $pass_through = Array(); if (isset($params['tabs_dependant'])) { // {yes, no} $pass_through['td'] = $params['tabs_dependant']; unset($params['tabs_dependant']); } if (isset($params['selection_mode'])) { // {single, multi} $pass_through['tm'] = $params['selection_mode']; unset($params['selection_mode']); } if (isset($params['tab_prefixes'])) { // {all, none, } $pass_through['tp'] = $params['tab_prefixes']; unset($params['tab_prefixes']); } if ($pass_through) { // add pass_through to selector url if any $params['pass_through'] = implode(',', array_keys($pass_through)); $params = array_merge($params, $pass_through); } // user can override default parameters (except pass_through of course) $params = array_merge($default_params, $params); return $this->Application->ProcessParsedTag('m', 'T', $params); } function TimeFrame($params) { $w = adodb_date('w'); $m = adodb_date('m'); $y = adodb_date('Y'); //FirstDayOfWeek is 0 for Sunday and 1 for Monday $fdow = $this->Application->ConfigValue('FirstDayOfWeek'); if ( $fdow && $w == 0 ) { $w = 7; } $today_start = adodb_mktime(0, 0, 0, adodb_date('m'), adodb_date('d'), $y); $first_day_of_this_week = $today_start - ($w - $fdow) * 86400; $first_day_of_this_month = adodb_mktime(0, 0, 0, $m, 1, $y); $this_quater = ceil($m / 3); $this_quater_start = adodb_mktime(0, 0, 0, $this_quater * 3 - 2, 1, $y); switch ( $params['type'] ) { case 'last_week_start': $timestamp = $first_day_of_this_week - 86400 * 7; break; case 'last_week_end': $timestamp = $first_day_of_this_week - 1; break; case 'last_month_start': $timestamp = $m == 1 ? adodb_mktime(0, 0, 0, 12, 1, $y - 1) : adodb_mktime(0, 0, 0, $m - 1, 1, $y); break; case 'last_month_end': $timestamp = $first_day_of_this_month = adodb_mktime(0, 0, 0, $m, 1, $y) - 1; break; case 'last_quater_start': $timestamp = $this_quater == 1 ? adodb_mktime(0, 0, 0, 10, 1, $y - 1) : adodb_mktime(0, 0, 0, ($this_quater - 1) * 3 - 2, 1, $y); break; case 'last_quater_end': $timestamp = $this_quater_start - 1; break; case 'last_6_months_start': $timestamp = $m <= 6 ? adodb_mktime(0, 0, 0, $m + 6, 1, $y - 1) : adodb_mktime(0, 0, 0, $m - 6, 1, $y); break; case 'last_year_start': $timestamp = adodb_mktime(0, 0, 0, 1, 1, $y - 1); break; case 'last_year_end': $timestamp = adodb_mktime(23, 59, 59, 12, 31, $y - 1); break; default: $timestamp = 0; break; } if ( isset($params['format']) ) { $format = $params['format']; if ( preg_match("/_regional_(.*)/", $format, $regs) ) { $lang = $this->Application->recallObject('lang.current'); /* @var $lang LanguagesItem */ $format = $lang->GetDBField($regs[1]); } return adodb_date($format, $timestamp); } return $timestamp; } /** * Redirect to cache rebuild template, when required by installator * * @param Array $params */ function CheckPermCache($params) { // we have separate session between install wizard and admin console, so store in cache $global_mark = $this->Application->getDBCache('ForcePermCacheUpdate'); $local_mark = $this->Application->RecallVar('PermCache_UpdateRequired'); if ( $global_mark || $local_mark ) { $this->Application->RemoveVar('PermCache_UpdateRequired'); $rebuild_mode = $this->Application->ConfigValue('CategoryPermissionRebuildMode'); if ( $rebuild_mode == CategoryPermissionRebuild::SILENT ) { $updater = $this->Application->makeClass('kPermCacheUpdater'); /* @var $updater kPermCacheUpdater */ $updater->OneStepRun(); $this->Application->HandleEvent(new kEvent('c:OnResetCMSMenuCache')); } elseif ( $rebuild_mode == CategoryPermissionRebuild::AUTOMATIC ) { // update with progress bar return true; } } return false; } /** * Checks if current protocol is SSL * * @param Array $params * @return int */ function IsSSL($params) { return (PROTOCOL == 'https://')? 1 : 0; } function PrintColumns($params) { $picker_helper = $this->Application->recallObject('ColumnPickerHelper'); $picker_helper->SetGridName($this->Application->GetLinkedVar('grid_name')); /* @var $picker_helper kColumnPickerHelper */ $main_prefix = $this->Application->RecallVar('main_prefix'); $cols = $picker_helper->LoadColumns($main_prefix); $this->Application->Phrases->AddCachedPhrase('__FREEZER__', '-------------'); $o = ''; if (isset($params['hidden']) && $params['hidden']) { foreach ($cols['hidden_fields'] as $col) { $title = $this->Application->Phrase($cols['titles'][$col]); $o .= "