Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Wed, Feb 5, 9:22 PM

in-portal

Index: branches/5.2.x/core/kernel/utility/debugger.php
===================================================================
--- branches/5.2.x/core/kernel/utility/debugger.php (revision 14706)
+++ branches/5.2.x/core/kernel/utility/debugger.php (revision 14707)
@@ -1,1662 +1,1656 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
if( !class_exists('Debugger') ) {
class DebuggerUtil {
/**
* Checks if constant is defined and has positive value
*
* @param string $const_name
* @return bool
*/
public static function constOn($const_name)
{
return defined($const_name) && constant($const_name);
}
/**
* Define constant if it was not already defined before
*
* @param string $const_name
* @param string $const_value
* @access public
*/
public static function safeDefine($const_name, $const_value)
{
if ( !defined($const_name) ) {
define($const_name, $const_value);
}
}
/**
* Formats file/memory size in nice way
*
* @param int $bytes
* @return string
* @access public
*/
public static function formatSize($bytes)
{
if ($bytes >= 1099511627776) {
$return = round($bytes / 1024 / 1024 / 1024 / 1024, 2);
$suffix = "TB";
} elseif ($bytes >= 1073741824) {
$return = round($bytes / 1024 / 1024 / 1024, 2);
$suffix = "GB";
} elseif ($bytes >= 1048576) {
$return = round($bytes / 1024 / 1024, 2);
$suffix = "MB";
} elseif ($bytes >= 1024) {
$return = round($bytes / 1024, 2);
$suffix = "KB";
} else {
$return = $bytes;
$suffix = "Byte";
}
$return .= ' '.$suffix;
return $return;
}
/**
* Checks, that user IP address is within allowed range
*
* @param string $ip_list semi-column (by default) separated ip address list
* @param string $separator ip address separator (default ";")
*
* @return bool
*/
public static function ipMatch($ip_list, $separator = ';')
{
if ( !isset($_SERVER['REMOTE_ADDR']) ) {
// PHP CLI used -> never match
return false;
}
$ip_match = false;
$ip_addresses = $ip_list ? explode($separator, $ip_list) : Array ();
foreach ($ip_addresses as $ip_address) {
if (self::netMatch($ip_address, $_SERVER['REMOTE_ADDR'])) {
$ip_match = true;
break;
}
}
return $ip_match;
}
public static function netMatch($network, $ip) {
$network = trim($network);
$ip = trim($ip);
if ( preg_replace('/[\d\.\/-]/', '', $network) != '' ) {
$network = gethostbyname($network);
}
if ($network == $ip) {
// comparing two ip addresses directly
return true;
}
$d = strpos($network, '-');
if ($d !== false) {
// ip address range specified
$from = ip2long(trim(substr($network, 0, $d)));
$to = ip2long(trim(substr($network, $d + 1)));
$ip = ip2long($ip);
return ($ip >= $from && $ip <= $to);
}
elseif (strpos($network, '/') !== false) {
// sigle subnet specified
$ip_arr = explode('/', $network);
if (!preg_match("@\d*\.\d*\.\d*\.\d*@", $ip_arr[0], $matches)) {
$ip_arr[0] .= '.0'; // Alternate form 194.1.4/24
}
$network_long = ip2long($ip_arr[0]);
$x = ip2long($ip_arr[1]);
$mask = long2ip($x) == $ip_arr[1] ? $x : (0xffffffff << (32 - $ip_arr[1]));
$ip_long = ip2long($ip);
return ($ip_long & $mask) == ($network_long & $mask);
}
return false;
}
}
class Debugger {
/**
* Holds reference to global KernelApplication instance
*
* @access public
* @var kApplication
*/
var $Application = null;
/**
* Set to true if fatal error occurred
*
* @var bool
*/
var $IsFatalError = false;
/**
* Counts warnings on the page
*
* @var int
*/
var $WarningCount = 0;
/**
* Allows to track compile errors, like "stack-overflow"
*
* @var bool
*/
var $_compileError = false;
/**
* Debugger data for building report
*
* @var Array
*/
var $Data = Array();
var $ProfilerData = Array();
var $ProfilerTotals = Array();
var $ProfilerTotalCount = Array();
var $ProfilePoints = Array();
/**
* Prevent recursion when processing debug_backtrace() function results
*
* @var Array
*/
var $RecursionStack = Array();
var $scrollbarWidth = 0;
/**
* Long errors are saved here, because trigger_error doesn't support error messages over 1KB in size
*
* @var Array
*/
var $longErrors = Array();
var $IncludesData = Array();
var $IncludeLevel = 0;
var $reportDone = false;
/**
* Transparent spacer image used in case of none spacer image defined via SPACER_URL contant.
* Used while drawing progress bars (memory usage, time usage, etc.)
*
* @var string
*/
var $dummyImage = '';
/**
* Temporary files created by debugger will be stored here
*
* @var string
*/
var $tempFolder = '';
/**
* Debug rows will be separated using this string before writing to debug file
*
* @var string
*/
var $rowSeparator = '@@';
/**
* Base URL for debugger includes
*
* @var string
*/
var $baseURL = '';
/**
* Holds last recorded timestamp (for appendTimestamp)
*
* @var int
*/
var $LastMoment;
/**
* Determines, that current request is AJAX request
*
* @var bool
*/
var $_isAjax = false;
public function __construct()
{
global $start, $dbg_options;
// check if user haven't defined DEBUG_MODE contant directly
if (defined('DEBUG_MODE') && DEBUG_MODE) {
die('error: contant DEBUG_MODE defined directly, please use <strong>$dbg_options</strong> array instead');
}
// check IP before enabling debug mode
$ip_match = DebuggerUtil::ipMatch(isset($dbg_options['DBG_IP']) ? $dbg_options['DBG_IP'] : '');
if (!$ip_match) {
define('DEBUG_MODE', 0);
return ;
}
// debug is allowed for user, continue initialization
$this->InitDebugger();
$this->profileStart('kernel4_startup', 'Startup and Initialization of kernel4', $start);
$this->profileStart('script_runtime', 'Script runtime', $start);
$this->LastMoment = $start;
error_reporting(E_ALL);
ini_set('display_errors', DebuggerUtil::constOn('DBG_ZEND_PRESENT') ? 0 : 1); // show errors on screen in case if not in Zend Studio debugging
$this->scrollbarWidth = $this->isGecko() ? 22 : 25; // vertical scrollbar width differs in Firefox and other browsers
$this->appendRequest();
}
/**
* Set's default values to constants debugger uses
*
*/
function InitDebugger()
{
global $dbg_options;
unset($dbg_options['DBG_IP']);
// Detect fact, that this session beeing debugged by Zend Studio
foreach ($_COOKIE as $cookie_name => $cookie_value) {
if (substr($cookie_name, 0, 6) == 'debug_') {
DebuggerUtil::safeDefine('DBG_ZEND_PRESENT', 1);
break;
}
}
DebuggerUtil::safeDefine('DBG_ZEND_PRESENT', 0); // set this constant value to 0 (zero) to debug debugger using Zend Studio
// set default values for debugger constants
$dbg_constMap = Array (
'DBG_USE_HIGHLIGHT' => 1, // highlight output same as php code using "highlight_string" function
'DBG_WINDOW_WIDTH' => 700, // set width of debugger window (in pixels) for better viewing large amount of debug data
'DBG_USE_SHUTDOWN_FUNC' => DBG_ZEND_PRESENT ? 0 : 1, // use shutdown function to include debugger code into output
'DBG_HANDLE_ERRORS' => DBG_ZEND_PRESENT ? 0 : 1, // handle all allowed by php (see php manual) errors instead of default handler
'DBG_IGNORE_STRICT_ERRORS' => 0, // ignore PHP5 errors about private/public view modified missing in class declarations
'DBG_DOMVIEWER' => '/temp/domviewer.html', // path to DOMViewer on website
'DOC_ROOT' => str_replace('\\', '/', realpath($_SERVER['DOCUMENT_ROOT']) ), // windows hack
'DBG_LOCAL_BASE_PATH' => 'w:', // replace DOC_ROOT in filenames (in errors) using this path
);
// only for IE, in case if no windows php script editor defined
if (!defined('DBG_EDITOR')) {
// $dbg_constMap['DBG_EDITOR'] = 'c:\Program Files\UltraEdit\uedit32.exe %F/%L';
$dbg_constMap['DBG_EDITOR'] = 'c:\Program Files\Zend\ZendStudio-5.2.0\bin\ZDE.exe %F';
}
// debugger is initialized before kHTTPQuery, so do jQuery headers check here too
if (array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
$this->_isAjax = true;
}
elseif (array_key_exists('ajax', $_GET) && $_GET['ajax'] == 'yes') {
$this->_isAjax = true;
}
// user defined options override debugger defaults
$dbg_constMap = array_merge($dbg_constMap, $dbg_options);
if ($this->_isAjax && array_key_exists('DBG_SKIP_AJAX', $dbg_constMap) && $dbg_constMap['DBG_SKIP_AJAX']) {
$dbg_constMap['DBG_SKIP_REPORTING'] = 1;
}
// allows to validate unit configs via request variable
if ( !array_key_exists('DBG_VALIDATE_CONFIGS', $dbg_constMap) ) {
$dbg_constMap['DBG_VALIDATE_CONFIGS'] = array_key_exists('validate_configs', $_GET) ? (int)$_GET['validate_configs'] : 0;
}
// when validation configs, don't show sqls for better validation error displaying
if ($dbg_constMap['DBG_VALIDATE_CONFIGS']) {
$dbg_constMap['DBG_SQL_PROFILE'] = 0;
}
// when showing explain make shure, that debugger window is large enough
if (array_key_exists('DBG_SQL_EXPLAIN', $dbg_constMap) && $dbg_constMap['DBG_SQL_EXPLAIN']) {
$dbg_constMap['DBG_WINDOW_WIDTH'] = 1000;
}
foreach ($dbg_constMap as $dbg_constName => $dbg_constValue) {
DebuggerUtil::safeDefine($dbg_constName, $dbg_constValue);
}
}
function InitReport()
{
if ( !class_exists('kApplication') ) {
return ;
}
$application =& kApplication::Instance();
// string used to separate debugger records while in file (used in debugger dump filename too)
$this->rowSeparator = '@' . (is_object($application->Factory) && $application->InitDone ? $application->GetSID() : 0) . '@';
// $this->rowSeparator = '@'.rand(0,100000).'@';
// include debugger files from this url
$reg_exp = '/^' . preg_quote(FULL_PATH, '/') . '/';
$kernel_path = preg_replace($reg_exp, '', KERNEL_PATH, 1);
$this->baseURL = PROTOCOL . SERVER_NAME . (defined('PORT') ? ':' . PORT : '') . rtrim(BASE_PATH, '/') . $kernel_path . '/utility/debugger';
// save debug output in this folder
$this->tempFolder = defined('RESTRICTED') ? RESTRICTED : WRITEABLE . '/cache';
}
function mapLongError($msg)
{
$key = $this->generateID();
$this->longErrors[$key] = $msg;
return $key;
}
/**
* Appends all passed variable values (wihout variable names) to debug output
*
*/
function dumpVars()
{
$dump_mode = 'var_dump';
$dumpVars = func_get_args();
if ($dumpVars[count($dumpVars) - 1] === 'STRICT') {
$dump_mode = 'strict_var_dump';
array_pop($dumpVars);
}
foreach ($dumpVars as $varValue) {
$this->Data[] = Array('value' => $varValue, 'debug_type' => $dump_mode);
}
}
function prepareHTML($dataIndex)
{
static $errors_displayed = 0;
$Data =& $this->Data[$dataIndex];
if ($Data['debug_type'] == 'html') {
return $Data['html'];
}
switch ($Data['debug_type']) {
case 'error':
$errors_displayed++;
$fileLink = $this->getFileLink($Data['file'], $Data['line']);
$ret = '<b class="debug_error">' . $this->getErrorNameByCode($Data['no']) . ' (#' . $errors_displayed . ')</b>: ' . $Data['str'];
$ret .= ' in <b>'.$fileLink.'</b> on line <b>'.$Data['line'].'</b>';
return $ret;
break;
case 'exception':
$fileLink = $this->getFileLink($Data['file'], $Data['line']);
$ret = '<b class="debug_error">'.$Data['exception_class'].'</b>: '.$Data['str'];
$ret .= ' in <b>'.$fileLink.'</b> on line <b>'.$Data['line'].'</b>';
return $ret;
break;
case 'var_dump':
return $this->highlightString( $this->print_r($Data['value'], true) );
break;
case 'strict_var_dump':
return $this->highlightString( var_export($Data['value'], true) );
break;
case 'trace':
ini_set('memory_limit', '500M');
$trace =& $Data['trace'];
$i = 0; $traceCount = count($trace);
$ret = '';
while ($i < $traceCount) {
$traceRec =& $trace[$i];
$argsID = 'trace_args_'.$dataIndex.'_'.$i;
$has_args = isset($traceRec['args']);
if (isset($traceRec['file'])) {
$func_name = isset($traceRec['class']) ? $traceRec['class'].$traceRec['type'].$traceRec['function'] : $traceRec['function'];
$args_link = $has_args ? '<a href="javascript:$Debugger.ToggleTraceArgs(\''.$argsID.'\');" title="Show/Hide Function Arguments"><b>Function</b></a>' : '<b>Function</b>';
$ret .= $args_link.': '.$this->getFileLink($traceRec['file'], $traceRec['line'], $func_name);
$ret .= ' in <b>'.basename($traceRec['file']).'</b> on line <b>'.$traceRec['line'].'</b><br>';
}
else {
$ret .= 'no file information available';
}
if ($has_args) {
// if parameter value is longer then 200 symbols, then leave only first 50
$args = $this->highlightString($this->print_r($traceRec['args'], true));
$ret .= '<div id="'.$argsID.'" style="display: none;">'.$args.'</div>';
}
$i++;
}
return $ret;
break;
case 'profiler':
$profileKey = $Data['profile_key'];
$Data =& $this->ProfilerData[$profileKey];
$runtime = ($Data['ends'] - $Data['begins']); // in seconds
$totals_key = getArrayValue($Data, 'totalsKey');
if ($totals_key) {
$total_before = $Data['totalsBefore'];
$total = $this->ProfilerTotals[$totals_key];
$div_width = Array();
$total_width = ($this->getWindowWidth() - 10);
$div_width['before'] = round(($total_before / $total) * $total_width);
$div_width['current'] = round(($runtime / $total) * $total_width);
$div_width['left'] = round((($total - $total_before - $runtime) / $total) * $total_width);
$subtitle = array_key_exists('subtitle', $Data) ? ' (' . $Data['subtitle'] . ')' : '';
$ret = '<b>Name' . $subtitle . '</b>: '.$Data['description'].'<br />';
$additional = isset($Data['additional']) ? $Data['additional'] : Array ();
if (isset($Data['file'])) {
array_unshift($additional, Array('name' => 'File', 'value' => $this->getFileLink($Data['file'], $Data['line'], basename($Data['file']).':'.$Data['line'])));
}
array_unshift($additional, Array('name' => 'Runtime', 'value' => $runtime.'s'));
$ret .= '<div>'; //FF 3.5 needs this!
foreach ($additional as $mixed_param) {
$ret .= '[<strong>'.$mixed_param['name'].'</strong>: '.$mixed_param['value'].'] ';
}
/*if (isset($Data['file'])) {
$ret .= '[<b>Runtime</b>: '.$runtime.'s] [<b>File</b>: '.$this->getFileLink($Data['file'], $Data['line'], basename($Data['file']).':'.$Data['line']).']<br />';
}
else {
$ret .= '<b>Runtime</b>: '.$runtime.'s<br />';
}*/
$ret .= '</div>';
$ret .= '<div class="dbg_profiler" style="width: '.$div_width['before'].'px; border-right: 0px; background-color: #298DDF;"><img src="'.$this->dummyImage.'" width="1" height="1"/></div>';
$ret .= '<div class="dbg_profiler" style="width: '.$div_width['current'].'px; border-left: 0px; border-right: 0px; background-color: #EF4A4A;"><img src="'.$this->dummyImage.'" width="1" height="1"/></div>';
$ret .= '<div class="dbg_profiler" style="width: '.$div_width['left'].'px; border-left: 0px; background-color: #DFDFDF;"><img src="'.$this->dummyImage.'" width="1" height="1"/></div>';
return $ret;
}
else {
return '<b>Name</b>: '.$Data['description'].'<br><b>Runtime</b>: '.$runtime.'s';
}
break;
default:
return 'incorrect debug data';
break;
}
}
function getWindowWidth()
{
return DBG_WINDOW_WIDTH - $this->scrollbarWidth - 8;
}
/**
* Tells debugger to skip objects that are heavy in plan of memory usage while printing debug_backtrace results
*
* @param Object $object
* @return bool
*/
function IsBigObject(&$object)
{
$skip_classes = Array(
defined('APPLICATION_CLASS') ? APPLICATION_CLASS : 'kApplication',
'kFactory',
'kUnitConfigReader',
'NParser',
);
foreach ($skip_classes as $class_name) {
if (strtolower(get_class($object)) == strtolower($class_name)) {
return true;
}
}
return false;
}
/**
* Advanced version of print_r (for debugger only). Don't print objects recursively
*
* @param Array $array
* @param bool $return_output return output or print it out
* @param int $tab_count offset in tabs
* @return string
*/
function print_r(&$array, $return_output = false, $tab_count = -1)
{
static $first_line = true;
// not an array at all
if (!is_array($array)) {
switch (gettype($array)) {
case 'NULL':
return 'NULL'."\n";
break;
case 'object':
return $this->processObject($array, $tab_count);
break;
default:
// number or string
if (strlen($array) > 200) {
$array = substr($array, 0, 50).' ...';
}
return $array."\n";
break;
}
}
$output = '';
$tab_count++;
$output .= "Array\n".str_repeat(' ', $tab_count)."(\n";
$tab_count++;
$tabsign = $tab_count ? str_repeat(' ', $tab_count) : '';
$array_keys = array_keys($array);
foreach ($array_keys as $key) {
switch (gettype($array[$key])) {
case 'array':
$output .= $tabsign.'['.$key.'] = '.$this->print_r($array[$key], true, $tab_count);
break;
case 'boolean':
$output .= $tabsign.'['.$key.'] = '.($array[$key] ? 'true' : 'false')."\n";
break;
case 'integer':
case 'double':
case 'string':
if (strlen($array[$key]) > 200) {
$array[$key] = substr($array[$key], 0, 50).' ...';
}
$output .= $tabsign.'['.$key.'] = '.$array[$key]."\n";
break;
case 'NULL':
$output .= $tabsign.'['.$key."] = NULL\n";
break;
case 'object':
$output .= $tabsign.'['.$key."] = ";
$output .= "Object (".get_class($array[$key]).") = \n".str_repeat(' ', $tab_count + 1)."(\n";
$output .= $this->processObject($array[$key], $tab_count + 2);
$output .= str_repeat(' ', $tab_count + 1).")\n";
break;
default:
$output .= $tabsign.'['.$key.'] unknown = '.gettype($array[$key])."\n";
break;
}
}
$tab_count--;
$output .= str_repeat(' ', $tab_count).")\n";
if ($first_line) {
$first_line = false;
$output .= "\n";
}
$tab_count--;
if ($return_output) {
return $output;
}
else {
echo $output;
}
return true;
}
function processObject(&$object, $tab_count)
{
$object_class = get_class($object);
if (!in_array($object_class, $this->RecursionStack)) {
if ($this->IsBigObject($object)) {
return 'SKIPPED (class: '.$object_class.")\n";
}
$attribute_names = get_class_vars($object_class);
if (!$attribute_names) {
return "NO_ATTRIBUTES\n";
}
else {
$output = '';
array_push($this->RecursionStack, $object_class);
$tabsign = $tab_count ? str_repeat(' ', $tab_count) : '';
foreach ($attribute_names as $attribute_name => $attribute_value) {
if (is_object($object->$attribute_name)) {
// it is object
$output .= $tabsign.'['.$attribute_name.'] = '.$this->processObject($object->$attribute_name, $tab_count + 1);
}
else {
$output .= $tabsign.'['.$attribute_name.'] = '.$this->print_r($object->$attribute_name, true, $tab_count);
}
}
array_pop($this->RecursionStack);
return $output;
}
}
else {
// object [in recursion stack]
return '*** RECURSION *** (class: '.$object_class.")\n";
}
}
/**
* Format SQL Query using predefined formatting
* and highlighting techniques
*
* @param string $sql
* @return string
*/
function formatSQL($sql)
{
$sql = trim( preg_replace('/(\n|\t| )+/is', ' ', $sql) );
// whitespace in the beginning of the regex is to avoid splitting inside words, for exmaple "FROM int_ConfigurationValues" into "FROM intConfiguration\n\tValues"
$formatted_sql = preg_replace('/\s(CREATE TABLE|DROP TABLE|SELECT|UPDATE|SET|REPLACE|INSERT|DELETE|VALUES|FROM|LEFT JOIN|INNER JOIN|LIMIT|WHERE|HAVING|GROUP BY|ORDER BY)\s/is', "\n\t$1 ", ' ' . $sql);
$formatted_sql = $this->highlightString($formatted_sql);
if (defined('DBG_SQL_EXPLAIN') && DBG_SQL_EXPLAIN) {
if (substr($sql, 0, 6) == 'SELECT') {
$formatted_sql .= '<br/>' . '<strong>Explain</strong>:<br /><br />';
$explain_result = $this->Application->Conn->Query('EXPLAIN ' . $sql, null, true);
$explain_table = '';
foreach ($explain_result as $explain_row) {
if (!$explain_table) {
// first row -> draw header
$explain_table .= '<tr class="explain_header"><td>' . implode('</td><td>', array_keys($explain_row)) . '</td></tr>';
}
$explain_table .= '<tr><td>' . implode('</td><td>', $explain_row) . '</td></tr>';
}
$formatted_sql .= '<table class="dbg_explain_table">' . $explain_table . '</table>';
}
}
return $formatted_sql;
}
function highlightString($string)
{
if (!(defined('DBG_USE_HIGHLIGHT') && DBG_USE_HIGHLIGHT) || $this->_compileError) {
return nl2br($string);
}
$string = str_replace( Array('\\', '/') , Array('_no_match_string_', '_n_m_s_'), $string);
$this->_compileError = true; // next line is possible cause of compile error
$string = highlight_string('<?php '.$string.' ?>', true);
$this->_compileError = false;
$string = str_replace( Array('_no_match_string_', '_n_m_s_'), Array('\\', '/'), $string);
if (strlen($string) >= 65536) {
// preg_replace will fail, when string is longer, then 65KB
return str_replace(Array ('&lt;?php&nbsp;', '?&gt;'), '', $string);
}
return preg_replace('/&lt;\?(.*)php&nbsp;(.*)\?&gt;/Us', '\\2', $string);
}
/**
* Determine by php type of browser used to show debugger
*
* @return bool
*/
function isGecko()
{
// we need isset because we may run scripts from shell with no user_agent at all
return isset($_SERVER['HTTP_USER_AGENT']) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'firefox') !== false;
}
/**
* Returns link for editing php file (from error) in external editor
*
* @param string $file filename with path from root folder
* @param int $lineno line number in file where error is found
* @param string $title text to show on file edit link
* @return string
*/
function getFileLink($file, $lineno = 1, $title = '')
{
if (!$title) {
$title = str_replace('/', '\\', $this->getLocalFile($file));
}
if ($this->isGecko()) {
return '<a href="file://'.$this->getLocalFile($file).'">'.$title.'</a>';
}
else {
return '<a href="javascript:$Debugger.editFile(\''.$this->getLocalFile($file).'\', '.$lineno.');" title="'.$file.'">'.$title.'</a>';
}
}
/**
* Converts filepath on server to filepath in mapped DocumentRoot on developer pc
*
* @param string $remoteFile
* @return string
*/
function getLocalFile($remoteFile)
{
return preg_replace('/^'.preg_quote(DOC_ROOT, '/').'/', DBG_LOCAL_BASE_PATH, $remoteFile, 1);
}
/**
* Appends call trace till this method call
*
* @param int $levels_to_shift
*/
function appendTrace($levels_to_shift = 1)
{
$levels_shifted = 0;
$trace = debug_backtrace();
while ($levels_shifted < $levels_to_shift) {
array_shift($trace);
$levels_shifted++;
}
$this->Data[] = Array('trace' => $trace, 'debug_type' => 'trace');
}
/**
* Appends call trace till this method call
*
* @param Exception $exception
*/
private function appendExceptionTrace(&$exception)
{
$trace = $exception->getTrace();
$this->Data[] = Array('trace' => $trace, 'debug_type' => 'trace');
}
function appendMemoryUsage($msg, $used = null)
{
if (!isset($used)) {
$used = round(memory_get_usage() / 1024);
}
$this->appendHTML('<b>Memory usage</b> '.$msg.' '.$used.'Kb');
}
/**
* Appends HTML code whithout transformations
*
* @param string $html
*/
function appendHTML($html)
{
$this->Data[] = Array('html' => $html, 'debug_type' => 'html');
}
/**
* Change debugger info that was already generated before.
* Returns true if html was set.
*
* @param int $index
* @param string $html
* @param string $type = {'append','prepend','replace'}
* @return bool
*/
function setHTMLByIndex($index, $html, $type = 'append')
{
if (!isset($this->Data[$index]) || $this->Data[$index]['debug_type'] != 'html') {
return false;
}
switch ($type) {
case 'append':
$this->Data[$index]['html'] .= '<br>'.$html;
break;
case 'prepend':
$this->Data[$index]['html'] = $this->Data[$index]['html'].'<br>'.$html;
break;
case 'replace':
$this->Data[$index]['html'] = $html;
break;
}
return true;
}
/**
* Move $debugLineCount lines of input from debug output
* end to beginning.
*
* @param int $debugLineCount
*/
function moveToBegin($debugLineCount)
{
$lines = array_splice($this->Data,count($this->Data)-$debugLineCount,$debugLineCount);
$this->Data = array_merge($lines,$this->Data);
}
function moveAfterRow($new_row, $debugLineCount)
{
$lines = array_splice($this->Data,count($this->Data)-$debugLineCount,$debugLineCount);
$rows_before = array_splice($this->Data,0,$new_row,$lines);
$this->Data = array_merge($rows_before,$this->Data);
}
function appendRequest()
{
if (isset($_SERVER['SCRIPT_FILENAME'])) {
$script = $_SERVER['SCRIPT_FILENAME'];
}
else {
$script = $_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF'];
}
$this->appendHTML('ScriptName: <b>'.$this->getFileLink($script, 1, basename($script)).'</b> (<b>'.dirname($script).'</b>)');
if ($this->_isAjax) {
$this->appendHTML('RequestURI: '.$_SERVER['REQUEST_URI'].' (QS Length:'.strlen($_SERVER['QUERY_STRING']).')');
}
$tools_html = ' <table style="width: ' . $this->getWindowWidth() . 'px;">
<tr>
<td>' . $this->_getDomViewerHTML() . '</td>
<td>' . $this->_getToolsHTML() . '</td>
</tr>
</table>';
$this->appendHTML($tools_html);
ob_start();
?>
<table border="0" cellspacing="0" cellpadding="0" class="dbg_flat_table" style="width: <?php echo $this->getWindowWidth(); ?>px;">
<thead style="font-weight: bold;">
<td width="20">Src</td><td>Name</td><td>Value</td>
</thead>
<?php
foreach ($_REQUEST as $key => $value) {
if(!is_array($value) && trim($value) == '') {
$value = '<b class="debug_error">no value</b>';
}
else {
$value = htmlspecialchars($this->print_r($value, true));
}
$in_cookie = isset($_COOKIE[$key]);
$src = isset($_GET[$key]) && !$in_cookie ? 'GE' : (isset($_POST[$key]) && !$in_cookie ? 'PO' : ($in_cookie ? 'CO' : '?') );
echo '<tr><td>'.$src.'</td><td>'.$key.'</td><td>'.$value.'</td></tr>';
}
?>
</table>
<?php
$this->appendHTML(ob_get_contents());
ob_end_clean();
}
/**
* Appends php session content to debugger output
*
*/
function appendSession()
{
if (isset($_SESSION) && $_SESSION) {
$this->appendHTML('PHP Session: [<b>'.ini_get('session.name').'</b>]');
$this->dumpVars($_SESSION);
$this->moveToBegin(2);
}
}
function profileStart($key, $description = null, $timeStamp = null)
{
if (!isset($timeStamp)) {
- $timeStamp = $this->getMoment();
+ $timeStamp = microtime(true);
}
$this->ProfilerData[$key] = Array('begins' => $timeStamp, 'ends' => 5000, 'debuggerRowID' => count($this->Data));
if (isset($description)) {
$this->ProfilerData[$key]['description'] = $description;
}
if (substr($key, 0, 4) == 'sql_') {
// append place from what was called
$trace_results = debug_backtrace();
$trace_count = count($trace_results);
$i = 0;
while ($i < $trace_count) {
if ( !isset($trace_results[$i]['file']) ) {
$i++;
continue;
}
$trace_file = basename($trace_results[$i]['file']);
if ($trace_file != 'db_connection.php' && $trace_file != 'db_load_balancer.php' && $trace_file != 'adodb.inc.php') {
break;
}
$i++;
}
$this->ProfilerData[$key]['file'] = $trace_results[$i]['file'];
$this->ProfilerData[$key]['line'] = $trace_results[$i]['line'];
if (array_key_exists('object', $trace_results[$i + 1]) && isset($trace_results[$i + 1]['object']->Prefix)) {
$object =& $trace_results[$i + 1]['object'];
/* @var $object kBase */
$prefix_special = rtrim($object->Prefix . '.' . $object->Special, '.');
$this->ProfilerData[$key]['prefix_special'] = $prefix_special;
}
unset($trace_results);
}
$this->Data[] = Array('profile_key' => $key, 'debug_type' => 'profiler');
}
function profileFinish($key, $description = null, $timeStamp = null)
{
if (!isset($timeStamp)) {
- $timeStamp = $this->getMoment();
+ $timeStamp = microtime(true);
}
$this->ProfilerData[$key]['ends'] = $timeStamp;
if (isset($description)) {
$this->ProfilerData[$key]['description'] = $description;
}
if (substr($key, 0, 4) == 'sql_') {
$func_arguments = func_get_args();
$rows_affected = $func_arguments[3];
$additional = Array ();
if ($rows_affected > 0) {
$additional[] = Array ('name' => 'Affected Rows', 'value' => $rows_affected);
if (isset($func_arguments[4])) {
if (strlen($func_arguments[4]) > 200) {
$func_arguments[4] = substr($func_arguments[4], 0, 50) . ' ...';
}
$additional[] = Array ('name' => 'Result', 'value' => $func_arguments[4]);
}
}
$additional[] = Array ('name' => 'Query Number', 'value' => $func_arguments[5]);
if ($func_arguments[6]) {
$this->profilerAddTotal('cachable_queries', $key);
$this->ProfilerData[$key]['subtitle'] = 'cachable';
}
if ($func_arguments[7]) {
$additional[] = Array ('name' => 'Server #', 'value' => $func_arguments[7]);
}
if (array_key_exists('prefix_special', $this->ProfilerData[$key])) {
$additional[] = Array ('name' => 'PrefixSpecial', 'value' => $this->ProfilerData[$key]['prefix_special']);
}
$this->ProfilerData[$key]['additional'] =& $additional;
}
}
function profilerAddTotal($total_key, $key = null, $value = null)
{
if (!isset($this->ProfilerTotals[$total_key])) {
$this->ProfilerTotals[$total_key] = 0;
$this->ProfilerTotalCount[$total_key] = 0;
}
if (!isset($value)) {
$value = $this->ProfilerData[$key]['ends'] - $this->ProfilerData[$key]['begins'];
}
if (isset($key)) {
$this->ProfilerData[$key]['totalsKey'] = $total_key;
$this->ProfilerData[$key]['totalsBefore'] = $this->ProfilerTotals[$total_key];
}
$this->ProfilerTotals[$total_key] += $value;
$this->ProfilerTotalCount[$total_key]++;
}
- function getMoment()
- {
- list($usec, $sec) = explode(' ', microtime());
- return ((float)$usec + (float)$sec);
- }
-
function appendTimestamp($message)
{
global $start;
- $time = $this->getMoment();
+ $time = microtime(true);
$from_last = $time - $this->LastMoment;
$from_start = $time - $start;
$this->appendHTML(sprintf("<b>%s</b> %.5f from last %.5f from start", $message, $from_last, $from_start));
$this->LastMoment = $time;
}
function generateID()
{
list($usec, $sec) = explode(' ', microtime());
$id_part_1 = substr($usec, 4, 4);
$id_part_2 = mt_rand(1,9);
$id_part_3 = substr($sec, 6, 4);
$digit_one = substr($id_part_1, 0, 1);
if ($digit_one == 0) {
$digit_one = mt_rand(1,9);
$id_part_1 = preg_replace('/^0/', '', $id_part_1);
$id_part_1=$digit_one.$id_part_1;
}
return $id_part_1.$id_part_2.$id_part_3;
}
function getErrorNameByCode($error_code)
{
$error_map = Array(
'Fatal Error' => Array(E_USER_ERROR),
'Warning' => Array(E_WARNING, E_USER_WARNING),
'Notice' => Array(E_NOTICE, E_USER_NOTICE),
);
if (defined('E_STRICT')) {
// since PHP 5
$error_map['PHP5 Strict'] = Array(E_STRICT);
}
if (defined('E_RECOVERABLE_ERROR')) {
// since PHP 5.2
$error_map['Fatal Error (recoverable)'] = Array(E_RECOVERABLE_ERROR);
}
if (defined('E_DEPRECATED')) {
// since PHP 5.3
$error_map['PHP5 Depricated'] = Array(E_DEPRECATED, E_USER_DEPRECATED);
}
foreach ($error_map as $error_name => $error_codes) {
if (in_array($error_code, $error_codes)) {
return $error_name;
}
}
return '';
}
/**
* Returns profile total key (check against unexisting key too)
*
* @param string $key
* @return int
*/
function getProfilerTotal($key)
{
if (isset($this->ProfilerTotalCount[$key])) {
return (int)$this->ProfilerTotalCount[$key];
}
return 0;
}
function ProfilePoint($title, $level=1)
{
$trace_results = debug_backtrace();
$level = min($level,count($trace_results)-1);
do {
$point = $trace_results[$level];
$location = $point['file'].':'.$point['line'];
$level++;
$has_more = isset($trace_results[$level]);
} while ($has_more && $point['function'] == $trace_results[$level]['function'] );
if (!isset($this->ProfilePoints[$title])) {
$this->ProfilePoints[$title] = array();
}
if (!isset($this->ProfilePoints[$title][$location])) {
$this->ProfilePoints[$title][$location] = 0;
}
$this->ProfilePoints[$title][$location]++;
}
/**
* Generates report
*
* @param bool $returnResult
* @param bool $clean_output_buffer
*
* @return string
* @access public
*/
public function printReport($returnResult = false, $clean_output_buffer = true)
{
if ($this->reportDone) {
// don't print same report twice (in case if shutdown function used + compression + fatal error)
return '';
}
$this->profileFinish('script_runtime');
$this->breakOutofBuffering(!$returnResult);
$debugger_start = memory_get_usage();
if (defined('SPACER_URL')) {
$this->dummyImage = SPACER_URL;
}
$this->InitReport(); // set parameters required by AJAX
// defined here, because user can define this contant while script is running, not event before debugger is started
DebuggerUtil::safeDefine('DBG_RAISE_ON_WARNINGS', 0);
DebuggerUtil::safeDefine('DBG_TOOLBAR_BUTTONS', 1);
$this->appendSession(); // show php session if any
// ensure, that 1st line of debug output always is this one:
$top_line = '<table cellspacing="0" cellpadding="0" style="width: '.$this->getWindowWidth().'px; margin: 0px;"><tr><td align="left" width="50%">[<a href="javascript:window.location.reload();">Reload Frame</a>] [<a href="javascript:$Debugger.Toggle(27);">Hide Debugger</a>] [<a href="javascript:$Debugger.Clear();">Clear Debugger</a>]</td><td align="right" width="50%">[Current Time: <b>'.date('H:i:s').'</b>] [File Size: <b>#DBG_FILESIZE#</b>]</td></tr></table>';
$this->appendHTML($top_line);
$this->moveToBegin(1);
if (count($this->ProfilePoints)>0) {
foreach($this->ProfilePoints as $point => $locations) {
arsort($this->ProfilePoints[$point]);
}
$this->appendHTML($this->highlightString($this->print_r($this->ProfilePoints, true)));
/*foreach ($this->ProfilePoints as $point => $locations) {
foreach ($locations as $location => $occurrences) {
}
}*/
}
if (DebuggerUtil::constOn('DBG_SQL_PROFILE') && isset($this->ProfilerTotals['sql'])) {
// sql query profiling was enabled -> show totals
if (array_key_exists('cachable_queries', $this->ProfilerTotalCount)) {
$append = ' <strong>Cachable queries</strong>: ' . $this->ProfilerTotalCount['cachable_queries'];
}
else {
$append = '';
}
$this->appendHTML('<b>SQL Total time:</b> '.$this->ProfilerTotals['sql'].' <b>Number of queries</b>: '.$this->ProfilerTotalCount['sql'] . $append);
}
if (DebuggerUtil::constOn('DBG_PROFILE_INCLUDES') && isset($this->ProfilerTotals['includes'])) {
// included file profiling was enabled -> show totals
$this->appendHTML('<b>Included Files Total time:</b> '.$this->ProfilerTotals['includes'].' Number of includes: '.$this->ProfilerTotalCount['includes']);
}
if (DebuggerUtil::constOn('DBG_PROFILE_MEMORY')) {
// detailed memory usage reporting by objects was enabled -> show totals
$this->appendHTML('<b>Memory used by Objects:</b> '.round($this->ProfilerTotals['objects'] / 1024, 2).'Kb');
}
if (DebuggerUtil::constOn('DBG_INCLUDED_FILES')) {
$files = get_included_files();
$this->appendHTML('<b>Included files:</b>');
foreach ($files as $file) {
$this->appendHTML($this->getFileLink($this->getLocalFile($file)).' ('.round(filesize($file) / 1024, 2).'Kb)');
}
}
if (DebuggerUtil::constOn('DBG_PROFILE_INCLUDES')) {
$this->appendHTML('<b>Included files statistics:</b>'.( DebuggerUtil::constOn('DBG_SORT_INCLUDES_MEM') ? ' (sorted by memory usage)':''));
$totals = Array( 'mem' => 0, 'time' => 0);
$totals_configs = Array( 'mem' => 0, 'time' => 0);
if (is_array($this->IncludesData['mem'])) {
if ( DebuggerUtil::constOn('DBG_SORT_INCLUDES_MEM') ) {
array_multisort($this->IncludesData['mem'], SORT_DESC, $this->IncludesData['file'], $this->IncludesData['time'], $this->IncludesData['level']);
}
foreach ($this->IncludesData['file'] as $key => $file_name) {
$this->appendHTML( str_repeat('&nbsp;->&nbsp;', ($this->IncludesData['level'][$key] >= 0 ? $this->IncludesData['level'][$key] : 0)).$file_name.' Mem: '.sprintf("%.4f Kb", $this->IncludesData['mem'][$key]/1024).' Time: '.sprintf("%.4f", $this->IncludesData['time'][$key]));
if ($this->IncludesData['level'][$key] == 0) {
$totals['mem'] += $this->IncludesData['mem'][$key];
$totals['time'] += $this->IncludesData['time'][$key];
}
else if ($this->IncludesData['level'][$key] == -1) {
$totals_configs['mem'] += $this->IncludesData['mem'][$key];
$totals_configs['time'] += $this->IncludesData['time'][$key];
}
}
$this->appendHTML('<b>Sub-Total classes:</b> '.' Mem: '.sprintf("%.4f Kb", $totals['mem']/1024).' Time: '.sprintf("%.4f", $totals['time']));
$this->appendHTML('<b>Sub-Total configs:</b> '.' Mem: '.sprintf("%.4f Kb", $totals_configs['mem']/1024).' Time: '.sprintf("%.4f", $totals_configs['time']));
$this->appendHTML('<span class="error"><b>Grand Total:</b></span> '.' Mem: '.sprintf("%.4f Kb", ($totals['mem']+$totals_configs['mem'])/1024).' Time: '.sprintf("%.4f", $totals['time']+$totals_configs['time']));
}
}
$skip_reporting = DebuggerUtil::constOn('DBG_SKIP_REPORTING') || DebuggerUtil::constOn('DBG_ZEND_PRESENT');
if (($this->_isAjax && !DebuggerUtil::constOn('DBG_SKIP_AJAX')) || !$skip_reporting) {
$debug_file = $this->tempFolder.'/debug_'.$this->rowSeparator.'.txt';
if (file_exists($debug_file)) unlink($debug_file);
$i = 0;
$fp = fopen($debug_file, 'a');
$lineCount = count($this->Data);
while ($i < $lineCount) {
fwrite($fp, $this->prepareHTML($i).$this->rowSeparator);
$i++;
}
fclose($fp);
}
if ($skip_reporting) {
// let debugger write report and then don't output anything
$this->reportDone = true;
return '';
}
$application =& kApplication::Instance();
$dbg_path = str_replace(FULL_PATH, '', $this->tempFolder);
ob_start();
// the <script .. /script> and hidden div helps browser to break out of script tag or attribute esacped
// with " or ' in case fatal error (or user-error) occurs inside it in compiled template,
// otherwise it has no effect
?>
<div style="display: none" x='nothing'><script></script></div><html><body></body></html>
<script type="text/javascript" src="<?php echo $this->baseURL; ?>/debugger.js?v2"></script>
<link rel="stylesheet" rev="stylesheet" href="<?php echo $this->baseURL; ?>/debugger.css" type="text/css" media="screen" />
<script type="text/javascript">
var $Debugger = new Debugger(<?php echo "'".$this->rowSeparator."', ".$this->getProfilerTotal('error_handling').', '.($this->IsFatalError ? 'true' : 'false').', '.$this->getProfilerTotal('sql'); ?>);
$Debugger.createEnvironment(<?php echo DBG_WINDOW_WIDTH; ?>, <?php echo $this->getWindowWidth(); ?>);
$Debugger.DOMViewerURL = '<?php echo constant('DBG_DOMVIEWER'); ?>';
$Debugger.EditorPath = '<?php echo defined('DBG_EDITOR') ? addslashes(DBG_EDITOR) : '' ?>';
$Debugger.DebugURL = '<?php echo $this->baseURL.'/debugger_responce.php?sid='.$this->rowSeparator.'&path='.urlencode($dbg_path); ?>';
$Debugger.EventURL = '<?php echo is_object($application->Factory) && $application->InitDone ? $application->HREF('dummy', '', Array ('pass' => 'm', '__NO_REWRITE__' => 1)) : ''; ?>';
<?php
$is_install = defined('IS_INSTALL') && IS_INSTALL;
if ($this->IsFatalError || (!$is_install && DBG_RAISE_ON_WARNINGS && $this->WarningCount)) {
echo '$Debugger.Toggle();';
}
if (DBG_TOOLBAR_BUTTONS) {
echo '$Debugger.AddToolbar("$Debugger");';
}
?>
window.focus();
</script>
<?php
if (!isset($this->ProfilerTotals['error_handling'])) {
$memory_used = $debugger_start;
$this->ProfilerTotalCount['error_handling'] = 0;
}
else {
$memory_used = $debugger_start - $this->ProfilerTotals['error_handling'];
}
if ($returnResult) {
$ret = ob_get_contents();
if ($clean_output_buffer) {
ob_end_clean();
}
$ret .= $this->getShortReport($memory_used);
$this->reportDone = true;
return $ret;
}
else {
if (!DebuggerUtil::constOn('DBG_HIDE_FULL_REPORT')) {
$this->breakOutofBuffering();
}
elseif ($clean_output_buffer) {
ob_clean();
}
echo $this->getShortReport($memory_used);
$this->reportDone = true;
}
return '';
}
/**
* Format's memory usage report by debugger
*
* @param int $memory_used
* @return string
* @access private
*/
function getShortReport($memory_used)
{
if (DebuggerUtil::constOn('DBG_TOOLBAR_BUTTONS')) {
// we have sql & error count in toolbar, don't duplicate here
$info = Array(
'Script Runtime' => 'PROFILE:script_runtime',
'SQL\'s Runtime' => 'PROFILE_T:sql',
);
}
else {
// toolbar not visible, then show sql & error count too
$info = Array (
'Script Runtime' => 'PROFILE:script_runtime',
'SQL\'s Runtime' => 'PROFILE_T:sql',
'-' => 'SEP:-',
'Notice / Warning' => 'PROFILE_TC:error_handling',
'SQLs Count' => 'PROFILE_TC:sql',
);
}
$ret = '<tr><td>Application:</td><td><b>'.DebuggerUtil::formatSize($memory_used).'</b> ('.$memory_used.')</td></tr>';
foreach ($info as $title => $value_key) {
list ($record_type, $record_data) = explode(':', $value_key, 2);
switch ($record_type) {
case 'PROFILE': // profiler totals value
$Data =& $this->ProfilerData[$record_data];
$profile_time = ($Data['ends'] - $Data['begins']); // in seconds
$ret .= '<tr><td>'.$title.':</td><td><b>'.sprintf('%.5f', $profile_time).' s</b></td></tr>';
break;
case 'PROFILE_TC': // profile totals record count
$record_cell = '<td>';
if ($record_data == 'error_handling' && $this->ProfilerTotalCount[$record_data] > 0) {
$record_cell = '<td class="debug_error">';
}
$ret .= '<tr>'.$record_cell.$title.':</td>'.$record_cell.'<b>'.$this->ProfilerTotalCount[$record_data].'</b></td></tr>';
break;
case 'PROFILE_T': // profile total
$record_cell = '<td>';
$total = array_key_exists($record_data, $this->ProfilerTotals) ? $this->ProfilerTotals[$record_data] : 0;
$ret .= '<tr>'.$record_cell.$title.':</td>'.$record_cell.'<b>'.sprintf('%.5f', $total).' s</b></td></tr>';
break;
case 'SEP':
$ret .= '<tr><td colspan="2" style="height: 1px; background-color: #000000; padding: 0px;"><img src="'.$this->dummyImage.'" height="1" alt=""/></td></tr>';
break;
}
}
return '<br /><table class="dbg_stats_table"><tr><td style="border-color: #FFFFFF;"><table class="dbg_stats_table" align="left">'.$ret.'</table></td></tr></table>';
}
/**
* User-defined error handler
*
* @throws Exception
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param array $errcontext
* @return bool
* @access public
*/
public function saveError($errno, $errstr, $errfile = null, $errline = null, $errcontext = Array ())
{
$this->ProfilerData['error_handling']['begins'] = memory_get_usage();
$errorType = $this->getErrorNameByCode($errno);
if (!$errorType) {
throw new Exception('Unknown error type [' . $errno . ']');
return false;
}
elseif ( substr($errorType, 0, 5) == 'Fatal' ) {
$this->IsFatalError = true;
$this->appendTrace(4);
}
if ( DebuggerUtil::constOn('DBG_IGNORE_STRICT_ERRORS') && defined('E_STRICT') && ($errno == E_STRICT) ) {
return false;
}
$this->expandError($errstr, $errfile, $errline);
$this->Data[] = Array (
'no' => $errno, 'str' => $errstr, 'file' => $errfile, 'line' => $errline,
'context' => $errcontext, 'debug_type' => 'error'
);
$this->ProfilerData['error_handling']['ends'] = memory_get_usage();
$this->profilerAddTotal('error_handling', 'error_handling');
if ($errorType == 'Warning') {
$this->WarningCount++;
}
if ( $this->IsFatalError ) {
// append debugger report to data in buffer & clean buffer afterwards
die( $this->breakOutofBuffering(false) . $this->printReport(true) );
}
return true;
}
/**
* User-defined exception handler
*
* @param Exception $exception
* @return void
* @access public
*/
public function saveException($exception)
{
$this->ProfilerData['error_handling']['begins'] = memory_get_usage();
$this->appendExceptionTrace($exception);
$errno = $exception->getCode();
$errstr = $exception->getMessage();
$errfile = $exception->getFile();
$errline = $exception->getLine();
$this->expandError($errstr, $errfile, $errline);
$this->Data[] = Array (
'no' => $errno, 'str' => $errstr, 'file' => $errfile, 'line' => $errline,
'exception_class' => get_class($exception), 'debug_type' => 'exception'
);
$this->ProfilerData['error_handling']['ends'] = memory_get_usage();
$this->profilerAddTotal('error_handling', 'error_handling');
$this->IsFatalError = true;
// append debugger report to data in buffer & clean buffer afterwards
die( $this->breakOutofBuffering(false) . $this->printReport(true) );
}
function expandError(&$errstr, &$errfile, &$errline)
{
if ( preg_match('/(.*)#([\d]+)$/', $errstr, $rets) ) {
// replace short message with long one (due triger_error limitations on message size)
$long_id = $rets[2];
$errstr = $this->longErrors[$long_id];
unset($this->longErrors[$long_id]);
}
if ( strpos($errfile, 'eval()\'d code') !== false ) {
$errstr = '[<b>EVAL</b>, line <b>' . $errline . '</b>]: ' . $errstr;
$tmpStr = $errfile;
$pos = strpos($tmpStr, '(');
$errfile = substr($tmpStr, 0, $pos);
$pos++;
$errline = substr($tmpStr, $pos, strpos($tmpStr, ')', $pos) - $pos);
}
}
function breakOutofBuffering($flush = true)
{
$buffer_content = Array();
while (ob_get_level()) {
$buffer_content[] = ob_get_clean();
}
$ret = implode('', array_reverse($buffer_content));
if ($flush) {
echo $ret;
flush();
}
return $ret;
}
function saveToFile($msg)
{
$fp = fopen($_SERVER['DOCUMENT_ROOT'].'/vb_debug.txt', 'a');
fwrite($fp, $msg."\n");
fclose($fp);
}
function printConstants($constants)
{
if (!is_array($constants)) {
$constants = explode(',', $constants);
}
$contant_tpl = '<tr><td>%s</td><td><b>%s</b></td></tr>';
$ret = '<table class="dbg_flat_table" style="width: '.$this->getWindowWidth().'px;">';
foreach ($constants as $constant_name) {
$ret .= sprintf($contant_tpl, $constant_name, constant($constant_name));
}
$ret .= '</table>';
$this->appendHTML($ret);
}
/**
* Attaches debugger to Application
*
* @return void
* @access public
*/
public function AttachToApplication()
{
if ( !DebuggerUtil::constOn('DBG_HANDLE_ERRORS') ) {
return;
}
if ( class_exists('kApplication') ) {
// replace application error/exception handler with own
restore_error_handler();
restore_exception_handler();
$this->Application =& kApplication::Instance();
$this->Application->Debugger =& $this;
$this->Application->errorHandlers[] = Array (&$this, 'saveError');
$this->Application->exceptionHandlers[] = Array (&$this, 'saveException');
}
else {
set_error_handler( Array (&$this, 'saveError') );
set_exception_handler( Array (&$this, 'saveException') );
}
}
/**
* Returns HTML for tools section
*
* @return string
*/
function _getToolsHTML()
{
$html = '<table>
<tr>
<td>System Tools:</td>
<td>
<select id="reset_cache" style="border: 1px solid #000000;">
<option value=""></option>
<option value="events[adm][OnResetModRwCache]">Reset mod_rewrite Cache</option>
<option value="events[adm][OnResetCMSMenuCache]">Reset SMS Menu Cache</option>
<option value="events[adm][OnResetSections]">Reset Sections Cache</option>
<option value="events[adm][OnResetConfigsCache]">Reset Configs Cache</option>
<option value="events[adm][OnRebuildThemes]">Re-build Themes Files</option>
<option value="events[lang][OnReflectMultiLingualFields]">Re-build Multilanguage Fields</option>
<option value="events[adm][OnDeleteCompiledTemplates]">Delete Compiled Templates</option>
</select>
</td>
<td>
<input type="button" class="button" onclick="$Debugger.resetCache(\'reset_cache\');" value="Go"/>
</td>
</tr>
</table>';
return $html;
}
/**
* Returns HTML for dom viewer section
*
* @return string
*/
function _getDomViewerHTML()
{
$html = '<table>
<tr>
<td>
<a href="http://www.brainjar.com/dhtml/domviewer/" target="_blank">DomViewer</a>:
</td>
<td>
<input id="dbg_domviewer" type="text" value="window" style="border: 1px solid #000000;"/>
</td>
<td>
<button class="button" onclick="return $Debugger.OpenDOMViewer();">Show</button>
</td>
</tr>
</table>';
return $html;
}
}
if (!function_exists('memory_get_usage')) {
// PHP 4.x and compiled without --enable-memory-limit option
function memory_get_usage(){ return -1; }
}
if (!DebuggerUtil::constOn('DBG_ZEND_PRESENT')) {
$debugger = new Debugger();
}
if (DebuggerUtil::constOn('DBG_USE_SHUTDOWN_FUNC')) {
register_shutdown_function( Array(&$debugger, 'printReport') );
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/helpers/backup_helper.php
===================================================================
--- branches/5.2.x/core/units/helpers/backup_helper.php (nonexistent)
+++ branches/5.2.x/core/units/helpers/backup_helper.php (revision 14707)
@@ -0,0 +1,525 @@
+<?php
+/**
+* @version $Id$
+* @package In-Portal
+* @copyright Copyright (C) 1997 - 2011 Intechnic. All rights reserved.
+* @license GNU/GPL
+* In-Portal is Open Source software.
+* This means that this software may have been modified pursuant
+* the GNU General Public License, and as distributed it includes
+* or is derivative of works licensed under the GNU General Public License
+* or other free or open source software licenses.
+* See http://www.in-portal.org/license for copyright notices and details.
+*/
+
+defined('FULL_PATH') or die('restricted access!');
+
+class BackupHelper extends kBase {
+
+ const SQL_ERROR_DURING_RESTORE = -3;
+
+ const FAILED_READING_BACKUP_FILE = -1;
+
+ /**
+ * Backup 50 records per step
+ */
+ const BACKUP_PER_STEP = 50;
+
+ /**
+ * Restore 200 lines per step
+ */
+ const RESTORE_PER_STEP = 200;
+
+ /**
+ * Path, where backups are stored
+ *
+ * @var string
+ */
+ protected $path = '';
+
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->path = $this->Application->ConfigValue('Backup_Path');
+ }
+
+ /**
+ * Backup all data
+ *
+ * @return bool
+ */
+ function initBackup()
+ {
+ $file_helper =& $this->Application->recallObject('FileHelper');
+ /* @var $file_helper FileHelper */
+
+ if (!$file_helper->CheckFolder($this->path) || !is_writable($this->path)) {
+ $this->Application->SetVar('error_msg', $this->Application->Phrase('la_Text_backup_access'));
+
+ return false;
+ }
+
+ $tables = $this->_getBackupTables();
+
+ $backup_progress = Array (
+ 'table_num' => 0,
+ 'table_names' => $tables,
+ 'table_count' => count($tables),
+ 'record_count' => 0,
+ 'file_name' => $this->getBackupFile( adodb_mktime() ),
+ );
+
+ $this->Application->RemoveVar('adm.backupcomplete_filename');
+ $this->Application->RemoveVar('adm.backupcomplete_filesize');
+
+ $fp = fopen($backup_progress['file_name'], 'a');
+
+ // write down module versions, used during backup
+ foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
+ fwrite($fp, '# ' . $module_name . ' Version: ' . $module_info['Version'] . ";\n");
+ }
+
+ fwrite($fp, "#------------------------------------------\n\n");
+
+ // write down table structure
+ $out = Array ();
+
+ foreach ($tables as $table) {
+ $out[] = $this->_getCreateTableSql($table);
+ }
+
+ fwrite($fp, implode("\n", $out) . "\n");
+ fclose($fp);
+
+ $this->Application->StoreVar('adm.backup_status', serialize($backup_progress));
+
+ return true;
+ }
+
+ /**
+ * Returns tables, that can be backed up
+ *
+ * @return Array
+ * @access protected
+ */
+ protected function _getBackupTables()
+ {
+ $ret = Array ();
+ $tables = $this->Conn->GetCol('SHOW TABLES LIKE "' . TABLE_PREFIX . '%"');
+
+ foreach ($tables as $table) {
+ if ( strpos($table, 'ses_') === false ) {
+ $ret[] = $table;
+ }
+ }
+
+ return $ret;
+ }
+
+ public function performBackup()
+ {
+ $backup_progress = unserialize($this->Application->RecallVar('adm.backup_status'));
+ $current_table = $backup_progress['table_names'][ $backup_progress['table_num'] ];
+
+ // get records
+ $a_records = $this->_getInsertIntoSql($current_table, $backup_progress['record_count'], self::BACKUP_PER_STEP);
+
+ if ( $a_records['num'] < self::BACKUP_PER_STEP ) {
+ $backup_progress['table_num']++;
+ $backup_progress['record_count'] = 0;
+ }
+ else {
+ $backup_progress['record_count'] += self::BACKUP_PER_STEP;
+ }
+
+ if ( $a_records['sql'] ) {
+ $fp = fopen($backup_progress['file_name'], 'a');
+ fwrite($fp, $a_records['sql']);
+ fclose($fp);
+ }
+
+ $percent = ($backup_progress['table_num'] / $backup_progress['table_count']) * 100;
+
+ if ( $percent >= 100 ) {
+ $percent = 100;
+ $this->Application->StoreVar('adm.backupcomplete_filename', $backup_progress['file_name']);
+ $this->Application->StoreVar('adm.backupcomplete_filesize', round(filesize($backup_progress['file_name']) / 1024 / 1024, 2)); // Mbytes
+ }
+ else {
+ $this->Application->StoreVar('adm.backup_status', serialize($backup_progress));
+ }
+
+ return round($percent);
+
+ }
+
+ /**
+ * Returns sql, that will insert given amount of data into given table
+ *
+ * @param string $table
+ * @param int $start
+ * @param int $limit
+ * @return Array
+ * @access protected
+ */
+ protected function _getInsertIntoSql($table, $start, $limit)
+ {
+ $sql = 'SELECT *
+ FROM ' . $table . '
+ ' . $this->Conn->getLimitClause($start, $limit);
+ $a_data = $this->Conn->Query($sql);
+
+ if ( !$a_data ) {
+ return Array ('num' => 0, 'sql' => '',);
+ }
+
+ $ret = '';
+ $fields_sql = $this->_getFieldsSql( $a_data[0] );
+
+ foreach ($a_data AS $a_row) {
+ $values_sql = '';
+
+ foreach ($a_row as $field_value) {
+ $values_sql .= $this->Conn->qstr($field_value) . ',';
+ }
+
+ $values_sql = substr($values_sql, 0, -1);
+
+ $sql = 'INSERT INTO ' . $table . ' (' . $fields_sql . ') VALUES (' . $values_sql . ');';
+ $sql = str_replace("\n", "\\n", $sql);
+ $sql = str_replace("\r", "\\r", $sql);
+ $ret .= $sql . "\n";
+ }
+
+ if ( strlen(TABLE_PREFIX) ) {
+ $ret = str_replace('INSERT INTO ' . TABLE_PREFIX, 'INSERT INTO ', $ret);
+ }
+
+ return Array ('num' => count($a_data), 'sql' => $ret);
+ }
+
+ /**
+ * Builds field list part of INSERT INTO statement based on given fields
+ *
+ * @param Array $row
+ * @return string
+ */
+ protected function _getFieldsSql($row)
+ {
+ $ret = '';
+ $a_fields = array_keys($row);
+
+ foreach ($a_fields AS $field_name) {
+ $ret .= '`' . $field_name . '`,';
+ }
+
+ return substr($ret, 0, -1);
+ }
+
+ /**
+ * Returns sql, that will create given table
+ *
+ * @param string $table
+ * @param string $crlf
+ * @return string
+ */
+ protected function _getCreateTableSql($table, $crlf = "\n")
+ {
+ $this->Conn->Query('SET SQL_QUOTE_SHOW_CREATE = 0');
+ $tmp_res = $this->Conn->Query('SHOW CREATE TABLE ' . $table);
+
+ if ( !is_array($tmp_res) || !isset($tmp_res[0]) ) {
+ return '';
+ }
+
+ // add drop table & create table
+ $schema_create = 'DROP TABLE IF EXISTS ' . $table . ';' . $crlf;
+ $schema_create .= '# --------------------------------------------------------' . $crlf;
+ $schema_create .= str_replace("\n", $crlf, $tmp_res[0]['Create Table']);
+
+ // remove table prefix from dump
+ if ( strlen(TABLE_PREFIX) ) {
+ $schema_create = str_replace('DROP TABLE IF EXISTS ' . TABLE_PREFIX, 'DROP TABLE ', $schema_create);
+ $schema_create = str_replace('CREATE TABLE ' . TABLE_PREFIX, 'CREATE TABLE ', $schema_create);
+ }
+
+ // remove any table properties (e.g. auto-increment, collation, etc)
+ $last_brace_pos = strrpos($schema_create, ')');
+
+ if ( $last_brace_pos !== false ) {
+ $schema_create = substr($schema_create, 0, $last_brace_pos + 1);
+ }
+
+ $schema_create .= "\n# --------------------------------------------------------\n";
+
+ return $schema_create;
+ }
+
+ public function initRestore()
+ {
+ $file = $this->getBackupFile();
+
+ $restoreProgress = Array (
+ 'file_pos' => 0,
+ 'file_name' => $file,
+ 'file_size' => filesize($file),
+ );
+
+ $this->Application->RemoveVar('adm.restore_success');
+ $this->Application->StoreVar('adm.restore_status', serialize($restoreProgress));
+ }
+
+ /**
+ * Restores part of backup file
+ *
+ * @return int
+ * @access public
+ */
+ public function performRestore()
+ {
+ $restore_progress = unserialize($this->Application->RecallVar('adm.restore_status'));
+ $filename = $restore_progress['file_name'];
+ $file_offset = $restore_progress['file_pos'];
+ $size = filesize($filename);
+
+ if ( $file_offset > $size ) {
+ return self::FAILED_READING_BACKUP_FILE;
+ }
+
+ $fp = fopen($filename, "r");
+ if ( !$fp ) {
+ return self::FAILED_READING_BACKUP_FILE;
+ }
+
+ if ( $file_offset > 0 ) {
+ fseek($fp, $file_offset);
+ }
+ else {
+ $end_of_sql = FALSE;
+ $sql = "";
+
+ while ( !feof($fp) && !$end_of_sql ) {
+ $line = fgets($fp);
+
+ if ( substr($line, 0, 11) == "INSERT INTO" ) {
+ $end_of_sql = TRUE;
+ }
+ else {
+ $sql .= $line;
+ $file_offset = ftell($fp) - strlen($line);
+ }
+ }
+
+ if ( strlen($sql) ) {
+ $error = $this->runSchemaText($sql);
+
+ if ( $error != '' ) {
+ $this->Application->StoreVar('adm.restore_error', $error);
+
+ return self::SQL_ERROR_DURING_RESTORE;
+ }
+ }
+
+ fseek($fp, $file_offset);
+ }
+
+ $lines_read = 0;
+ $all_sqls = Array ();
+
+ while ( $lines_read < self::RESTORE_PER_STEP && !feof($fp) ) {
+ $sql = fgets($fp);
+
+ if ( strlen($sql) ) {
+ $all_sqls[] = $sql;
+ $lines_read++;
+ }
+ }
+
+ $file_offset = !feof($fp) ? ftell($fp) : $size;
+
+ fclose($fp);
+
+ if ( count($all_sqls) > 0 ) {
+ $error = $this->runSQLText($all_sqls);
+
+ if ( $error != '' ) {
+ $this->Application->StoreVar('adm.restore_error', $error);
+
+ return self::SQL_ERROR_DURING_RESTORE;
+ }
+ }
+
+ $restore_progress['file_pos'] = $file_offset;
+ $this->Application->StoreVar('adm.restore_status', serialize($restore_progress));
+
+ return round($file_offset / $size * 100);
+ }
+
+ /**
+ * Run given schema sqls and return error, if any
+ *
+ * @param $sql
+ * @return string
+ * @access protected
+ */
+ protected function runSchemaText($sql)
+ {
+ $table_prefix = 'restore' . TABLE_PREFIX;
+
+ if ( strlen($table_prefix) > 0 ) {
+ $replacements = Array ('INSERT INTO ', 'UPDATE ', 'ALTER TABLE ', 'DELETE FROM ', 'REPLACE INTO ');
+
+ foreach ($replacements as $replacement) {
+ $sql = str_replace($replacement, $replacement . $table_prefix, $sql);
+ }
+ }
+
+ $sql = str_replace('CREATE TABLE ', 'CREATE TABLE IF NOT EXISTS ' . $table_prefix, $sql);
+ $sql = str_replace('DROP TABLE ', 'DROP TABLE IF EXISTS ' . $table_prefix, $sql);
+
+ $commands = explode("# --------------------------------------------------------", $sql);
+
+ if ( count($commands) > 0 ) {
+ $commands = array_map('trim', $commands);
+
+ foreach ($commands as $cmd) {
+ if ( strlen($cmd) > 0 ) {
+ $this->Conn->Query($cmd);
+
+ if ( $this->Conn->hasError() ) {
+ return $this->Conn->getErrorMsg() . " COMMAND:<PRE>$cmd</PRE>";
+ }
+ }
+ }
+ }
+
+ return '';
+ }
+
+ /**
+ * Runs given sqls and return error message, if any
+ *
+ * @param $all_sqls
+ * @return string
+ * @access protected
+ */
+ protected function runSQLText($all_sqls)
+ {
+ $line = 0;
+
+ while ( $line < count($all_sqls) ) {
+ $sql = $all_sqls[$line];
+
+ if ( strlen(trim($sql)) > 0 && substr($sql, 0, 1) != "#" ) {
+ $table_prefix = 'restore' . TABLE_PREFIX;
+
+ if ( strlen($table_prefix) > 0 ) {
+ $replacements = Array ('INSERT INTO ', 'UPDATE ', 'ALTER TABLE ', 'DELETE FROM ', 'REPLACE INTO ');
+
+ foreach ($replacements as $replacement) {
+ $sql = str_replace($replacement, $replacement . $table_prefix, $sql);
+ }
+ }
+
+ $sql = str_replace('CREATE TABLE ', 'CREATE TABLE IF NOT EXISTS ' . $table_prefix, $sql);
+ $sql = str_replace('DROP TABLE ', 'DROP TABLE IF EXISTS ' . $table_prefix, $sql);
+ $sql = trim($sql);
+
+ if ( strlen($sql) > 0 ) {
+ $this->Conn->Query($sql);
+
+ if ( $this->Conn->hasError() ) {
+ return $this->Conn->getErrorMsg() . " COMMAND:<PRE>$sql</PRE>";
+ }
+ }
+ }
+
+ $line++;
+ }
+
+ return '';
+ }
+
+ /**
+ * Replaces current tables with restored tables
+ *
+ * @return void
+ * @access public
+ */
+ public function replaceRestoredFiles()
+ {
+ // gather restored table names
+ $tables = $this->Conn->GetCol('SHOW TABLES');
+ $mask_restore_table = '/^restore' . TABLE_PREFIX . '(.*)$/';
+
+ foreach ($tables as $table) {
+ if ( preg_match($mask_restore_table, $table) ) {
+ $old_table = substr($table, 7);
+
+ $this->Conn->Query('DROP TABLE IF EXISTS ' . $old_table);
+ $this->Conn->Query('CREATE TABLE ' . $old_table . ' LIKE ' . $table);
+ $this->Conn->Query('INSERT INTO ' . $old_table . ' SELECT * FROM ' . $table);
+ $this->Conn->Query('DROP TABLE ' . $table);
+ }
+ }
+ }
+
+ /**
+ * Deletes current backup file
+ *
+ * @return void
+ * @access public
+ */
+ public function delete()
+ {
+ @unlink($this->getBackupFile());
+ }
+
+ /**
+ * Returns path to current backup file
+ *
+ * @param int|null $backup_date
+ * @return string
+ * @access protected
+ */
+ protected function getBackupFile($backup_date = null)
+ {
+ if ( !isset($backup_date) ) {
+ $backup_date = $this->Application->GetVar('backupdate');
+ }
+
+ return $this->path . '/dump' . $backup_date . '.txt';
+ }
+
+ /**
+ * Returns list of backup files, available for restore
+ *
+ * @return Array
+ * @access public
+ */
+ public function getBackupFiles()
+ {
+ $file_helper =& $this->Application->recallObject('FileHelper');
+ /* @var $file_helper FileHelper */
+
+ $ret = Array ();
+ $backup_path = $this->Application->ConfigValue('Backup_Path');
+ $file_helper->CheckFolder($backup_path);
+ $backup_files = glob($backup_path . DIRECTORY_SEPARATOR . 'dump*.txt');
+
+ if ( !$backup_files ) {
+ return Array ();
+ }
+
+ foreach ($backup_files as $backup_file) {
+ $ret[] = Array (
+ 'filedate' => preg_replace('/^dump([\d]+)\.txt$/', '\\1', basename($backup_file)),
+ 'filesize' => filesize($backup_file));
+ }
+
+ rsort($ret);
+
+ return $ret;
+ }
+}
\ No newline at end of file
Index: branches/5.2.x/core/units/helpers/helpers_config.php
===================================================================
--- branches/5.2.x/core/units/helpers/helpers_config.php (revision 14706)
+++ branches/5.2.x/core/units/helpers/helpers_config.php (revision 14707)
@@ -1,72 +1,73 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
$config = Array (
'Prefix' => 'helpers',
'EventHandlerClass' => Array ('class' => 'kEventHandler', 'file' => '', 'build_event' => 'OnBuild'),
'RegisterClasses' => Array (
Array ('pseudo' => 'kMultiLanguageHelper', 'class' => 'kMultiLanguageHelper', 'file' => 'multilanguage_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SearchHelper', 'class' => 'kSearchHelper', 'file' => 'search_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SectionsHelper', 'class' => 'kSectionsHelper', 'file' => 'sections_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'PermissionsHelper', 'class' => 'kPermissionsHelper', 'file' => 'permissions_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ModulesHelper', 'class' => 'kModulesHelper', 'file' => 'modules_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ModRewriteHelper', 'class' => 'kModRewriteHelper', 'file' => 'mod_rewrite_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'RecursiveHelper', 'class' => 'kRecursiveHelper', 'file' => 'recursive_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FilenamesHelper', 'class' => 'kFilenamesHelper', 'file' => 'filenames_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ClipboardHelper', 'class' => 'kClipboardHelper', 'file' => 'clipboard_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ColumnPickerHelper', 'class' => 'kColumnPickerHelper', 'file' => 'col_picker_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ThemesHelper', 'class' => 'kThemesHelper', 'file' => 'themes_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CaptchaHelper', 'class' => 'kCaptchaHelper', 'file' => 'captcha_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'PriorityHelper', 'class' => 'kPriorityHelper', 'file' => 'priority_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CurlHelper', 'class' => 'kCurlHelper', 'file' => 'curl_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CountHelper', 'class' => 'kCountHelper', 'file' => 'count_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ImageHelper', 'class' => 'ImageHelper', 'file' => 'image_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FileHelper', 'class' => 'FileHelper', 'file' => 'file_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CategoryHelper', 'class' => 'CategoryHelper', 'file' => 'category_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CSVHelper', 'class' => 'kCSVHelper', 'file' => 'csv_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ChartHelper', 'class' => 'kChartHelper', 'file' => 'chart_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'RatingHelper', 'class' => 'RatingHelper', 'file' => 'rating_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FCKHelper', 'class' => 'fckFCKHelper', 'file' => 'fck_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SpamHelper', 'class' => 'SpamHelper', 'file' => 'spam_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'TemplateHelper', 'class' => 'TemplateHelper', 'file' => 'template_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'MailingListHelper', 'class' => 'MailingListHelper', 'file' => 'mailing_list_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'JSONHelper', 'class' => 'JSONHelper', 'file' => 'json_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'LanguageImportHelper', 'class' => 'LanguageImportHelper', 'file' => 'language_import_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SkinHelper', 'class' => 'SkinHelper', 'file' => 'skin_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SiteConfigHelper', 'class' => 'SiteConfigHelper', 'file' => 'site_config_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'MenuHelper', 'class' => 'MenuHelper', 'file' => 'menu_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'InpCustomFieldsHelper', 'class' => 'InpCustomFieldsHelper', 'file' => 'custom_fields_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CountryStatesHelper', 'class' => 'kCountryStatesHelper', 'file' => 'country_states_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'BracketsHelper', 'class' => 'kBracketsHelper', 'file' => 'brackets_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'kXMLHelper', 'class' => 'kXMLHelper', 'file' => 'xml_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CatItemExportHelper', 'class' => 'kCatDBItemExportHelper', 'file' => 'cat_dbitem_export_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'EmailMessageHelper', 'class' => 'EmailMessageHelper', 'file' => 'email_message_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ListHelper', 'class' => 'ListHelper', 'file' => 'list_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FormSubmissionHelper', 'class' => 'FormSubmissionHelper', 'file' => 'form_submission_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'MailboxHelper', 'class' => 'MailboxHelper', 'file' => 'mailbox_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'POP3Helper', 'class' => 'POP3Helper', 'file' => 'pop3_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'MimeDecodeHelper', 'class' => 'MimeDecodeHelper', 'file' => 'mime_decode_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'UserHelper', 'class' => 'UserHelper', 'file' => 'user_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SiteHelper', 'class' => 'SiteHelper', 'file' => 'site_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'DeploymentHelper', 'class' => 'DeploymentHelper', 'file' => 'deployment_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'BackupHelper', 'class' => 'BackupHelper', 'file' => 'backup_helper.php', 'build_event' => ''),
),
);
\ No newline at end of file
Index: branches/5.2.x/core/units/admin/admin_events_handler.php
===================================================================
--- branches/5.2.x/core/units/admin/admin_events_handler.php (revision 14706)
+++ branches/5.2.x/core/units/admin/admin_events_handler.php (revision 14707)
@@ -1,1510 +1,1099 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class AdminEventsHandler extends kDBEventHandler {
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array(
'OnSaveColumns' => array('self' => true),
'OnClosePopup' => array('self' => true),
'OnSaveSetting' => array('self' => true),
// export/import permissions is checked within events
'OnExportCSV' => Array('self' => true),
'OnGetCSV' => Array('self' => true),
'OnCSVImportBegin' => Array('self' => true),
'OnCSVImportStep' => Array('self' => true),
'OnDropTempTablesByWID' => Array('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(&$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;
}
if (isset($perm_value)) {
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
return $perm_helper->finalizePermissionCheck($event, $perm_value);
}
return parent::CheckPermission($event);
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnResetModRwCache(&$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(&$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);
}
function OnResetConfigsCache(&$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
*/
function OnResetParsedData(&$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);
}
function OnCompileTemplates(&$event)
{
$compiler =& $this->Application->recallObject('NParserCompiler');
/* @var $compiler NParserCompiler */
$compiler->CompileTemplatesStep();
$event->status = kEvent::erSTOP;
}
/**
* Deletes all compiled templates
*
* @param kEvent $event
*/
function OnDeleteCompiledTemplates(&$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);
}
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 sturcture for specified table
*
* @param kEvent $event
* @author Alex
*/
function OnGenerateTableStructure(&$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 (),
)
);
$grid_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 ();
$grid_col_options = Array(
'title' => 'la_col_' . $field_info['Field'],
'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_rage_filter';
}
}
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;"'));
?>
<script type="text/javascript">
set_window_title('Table "<?php echo $table_name; ?>" Structure');
</script>
<a href="javascript:window_close();">Close Window</a><br /><br />
<?php echo $GLOBALS['debugger']->highlightString($ret); ?>
<br /><br /><a href="javascript:window_close();">Close Window</a><br />
<?php
echo $this->Application->ParseBlock(Array('name' => 'incs/footer'));
echo ob_get_clean();
$event->status = kEvent::erSTOP;
}
/**
* Refreshes ThemeFiles & Theme tables by actual content on HDD
*
* @param kEvent $event
*/
function OnRebuildThemes(&$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);
}
function OnSaveColumns(&$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
*/
function OnSaveSetting(&$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
*/
function OnClosePopup(&$event)
{
$event->SetRedirectParam('opener', 'u');
}
/**
* Occurs right after initialization of the kernel, used mainly as hook-to event
*
* @param kEvent $event
*/
function OnStartup(&$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
*/
function OnBeforeShutdown(&$event)
{
}
/**
* Is called after tree was build (when not from cache)
*
* @param kEvent $event
*/
function OnAfterBuildTree(&$event)
{
}
/**
* Called by AJAX to perform CSV export
*
* @param kEvent $event
*/
function OnExportCSV(&$event)
{
$export_helper =& $this->Application->recallObject('CSVHelper');
/* @var $export_helper kCSVHelper */
$prefix_special = $this->Application->GetVar('PrefixSpecial');
if(!$prefix_special) {
$prefix_special = $export_helper->ExportData('prefix');
}
$prefix_elems = preg_split('/\.|_/', $prefix_special, 2);
$perm_sections = $this->Application->getUnitOption($prefix_elems[0], 'PermSection');
if(!$this->Application->CheckPermission($perm_sections['main'].'.view')) {
$event->status = kEvent::erPERM_FAIL;
return ;
}
$export_helper->PrefixSpecial = $prefix_special;
$export_helper->grid = $this->Application->GetVar('grid');
$export_helper->ExportStep();
$event->status = kEvent::erSTOP;
}
/**
* Returning created by AJAX CSV file
*
* @param kEvent $event
*/
function OnGetCSV(&$event)
{
$export_helper =& $this->Application->recallObject('CSVHelper');
/* @var $export_helper kCSVHelper */
$prefix_special = $export_helper->ExportData('prefix');
$prefix_elems = preg_split('/\.|_/', $prefix_special, 2);
$perm_sections = $this->Application->getUnitOption($prefix_elems[0], 'PermSection');
if(!$this->Application->CheckPermission($perm_sections['main'].'.view')) {
$event->status = kEvent::erPERM_FAIL;
return ;
}
$export_helper->GetCSV();
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnCSVImportBegin(&$event)
{
$prefix_special = $this->Application->GetVar('PrefixSpecial');
$prefix_elems = preg_split('/\.|_/', $prefix_special, 2);
$perm_sections = $this->Application->getUnitOption($prefix_elems[0], 'PermSection');
if(!$this->Application->CheckPermission($perm_sections['main'].'.add') && !$this->Application->CheckPermission($perm_sections['main'].'.edit')) {
$event->status = kEvent::erPERM_FAIL;
return ;
}
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
$field_values = array_shift($items_info);
$object->SetFieldsFromHash($field_values);
$event->redirect = false;
$result = 'required';
if($object->GetDBField('ImportFile')) {
$import_helper =& $this->Application->recallObject('CSVHelper');
/* @var $import_helper kCSVHelper */
$import_helper->PrefixSpecial = $this->Application->GetVar('PrefixSpecial');
$import_helper->grid = $this->Application->GetVar('grid');
$result = $import_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;
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnCSVImportStep(&$event)
{
$import_helper =& $this->Application->recallObject('CSVHelper');
/* @var $import_helper kCSVHelper */
$prefix_special = $import_helper->ImportData('prefix');
$prefix_elems = preg_split('/\.|_/', $prefix_special, 2);
$perm_sections = $this->Application->getUnitOption($prefix_elems[0], 'PermSection');
if ( !$this->Application->CheckPermission($perm_sections['main'] . '.add') && !$this->Application->CheckPermission($perm_sections['main'] . '.edit') ) {
$event->status = kEvent::erPERM_FAIL;
return;
}
$import_helper->ImportStep();
$event->status = kEvent::erSTOP;
}
/**
* Shows unit config filename, where requested prefix is defined
*
* @param kEvent $event
*/
function OnCheckPrefixConfig(&$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;"'));
?>
<script type="text/javascript">
set_window_title('Unit Config of "<?php echo $prefix; ?>" prefix');
</script>
<a href="javascript:window_close();">Close Window</a><br /><br />
<strong>Prefix:</strong> <?php echo $prefix; ?><br />
<strong>Unit Config:</strong> <?php echo $GLOBALS['debugger']->highlightString($config_file); ?><br />
<br /><a href="javascript:window_close();">Close Window</a><br />
<?php
echo $this->Application->ParseBlock(Array('name' => 'incs/footer'));
echo ob_get_clean();
$event->status = kEvent::erSTOP;
}
function OnDropTempTablesByWID(&$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;
return ;
}
/**
* Backup all data
*
* @param kEvent $event
*/
function OnBackup(&$event)
{
- $backup_path = $this->Application->ConfigValue('Backup_Path');
+ $backup_helper =& $this->Application->recallObject('BackupHelper');
+ /* @var $backup_helper BackupHelper */
- $file_helper =& $this->Application->recallObject('FileHelper');
- /* @var $file_helper FileHelper */
-
- if (!$file_helper->CheckFolder($backup_path) || !is_writable($backup_path)) {
+ if ( !$backup_helper->initBackup() ) {
$event->status = kEvent::erFAIL;
-
- $this->Application->SetVar('error_msg', $this->Application->Phrase('la_Text_backup_access'));
- return ;
- }
-
- $a_tables = $this->Conn->GetCol('SHOW TABLES'); // array_keys($tables);
- $TableNames = Array();
- for($x=0;$x<count($a_tables);$x++)
- {
- if(substr($a_tables[$x],0,strlen(TABLE_PREFIX))==TABLE_PREFIX)
- {
- if (!strstr($a_tables[$x], 'ses_')) {
- $TableNames[] = $a_tables[$x];
- }
- }
- }
-
- $backupProgress = Array (
- 'table_num' => 0,
- 'table_names' => $TableNames,
- 'table_count' => count($TableNames),
- 'record_count' => 0,
- 'file_name' => $backup_path."/dump".adodb_mktime().".txt",
- );
- $this->Application->RemoveVar('adm.backupcomplete_filename');
- $this->Application->RemoveVar('adm.backupcomplete_filesize');
-
- $out = array();
-
- for($x=0;$x<count($TableNames);$x++) {
- if (!strstr($TableNames[$x], 'ses_')) {
- $out[] = $this->GetTableCreate($TableNames[$x]);
- }
- }
-
- $fp = fopen($backupProgress['file_name'], 'a');
-
- $sql = "SELECT Name, Version FROM ".TABLE_PREFIX."Modules";
- $r = $this->Conn->Query($sql);
- foreach ($r AS $a_module) {
- $version = $a_module['Version'];
- fwrite($fp, "# ".$a_module['Name']." Version: $version;\n");
}
- fwrite($fp, "#------------------------------------------\n\n");
- fwrite($fp,implode("\n",$out));
- fwrite($fp,"\n");
-
- fclose($fp);
-
- $this->Application->StoreVar('adm.backup_status', serialize($backupProgress));
$event->redirect = 'tools/backup2';
}
/**
* Perform next backup step
*
* @param kEvent $event
*/
function OnBackupProgress(&$event)
{
- $done_percent = $this->performBackup();
+ $backup_helper =& $this->Application->recallObject('BackupHelper');
+ /* @var $backup_helper BackupHelper */
+
+ $done_percent = $backup_helper->performBackup();
- if ($done_percent == 100) {
+ if ( $done_percent == 100 ) {
$event->redirect = 'tools/backup3';
- return ;
+ return;
}
- echo $done_percent;
$event->status = kEvent::erSTOP;
+ echo $done_percent;
}
/**
* Stops Backup & redirect to Backup template
*
* @param kEvent $event
*/
function OnBackupCancel(&$event)
{
$event->redirect = 'tools/backup1';
}
/**
- * Stops Restore & redirect to Restore template
- *
- * @param kEvent $event
- */
- function OnRestoreCancel(&$event)
- {
- $event->redirect = 'tools/restore1';
- }
-
- function performBackup()
- {
- $backupProgress = unserialize($this->Application->RecallVar('adm.backup_status'));
-// echo "<pre>"; print_r($backupProgress); echo "</pre>";
-// exit;
- $CurrentTable = $backupProgress['table_names'][$backupProgress['table_num']];
-
- // get records
- $a_records = $this->insert_data($CurrentTable,$backupProgress['record_count'],50,"");
-// echo "<pre>"; print_r($a_records); echo "</pre>";
-// exit;
-
- if ($a_records['num'] < 50) {
- $backupProgress['table_num']++;
-// if ($backupProgress['table_names'][$backupProgress['table_num']] == TABLE_PREFIX.'Cache') {
-// $backupProgress['table_num']++;
-// }
- $backupProgress['record_count'] = 0;
- } else {
- $backupProgress['record_count']+=50;
- }
-
- if ($a_records['sql']) {
- $fp = fopen($backupProgress['file_name'], 'a');
- fwrite($fp, $a_records['sql']);
- fclose($fp);
- }
- $percent = ($backupProgress['table_num'] / $backupProgress['table_count']) * 100;
- if ($percent >= 100) {
- $percent = 100;
- $this->Application->StoreVar('adm.backupcomplete_filename', $backupProgress['file_name']);
- $this->Application->StoreVar('adm.backupcomplete_filesize', round(filesize($backupProgress['file_name'])/1024/1024, 2)); // Mbytes
- } else {
- $this->Application->StoreVar('adm.backup_status', serialize($backupProgress));
- }
-
- return round($percent);
-
- }
-
- //extracts the rows of data from tables using limits
- function insert_data($table, $start, $limit, $mywhere)
- {
-// global $out;
-
- if ($mywhere !="")
- {
- $whereclause= " WHERE ".$mywhere." ";
- }
- else
- {
- $whereclause = "";
- }
-
- $a_data = $this->Conn->Query("SELECT * from $table $whereclause LIMIT $start, $limit");
-// echo "SELECT * from $table $whereclause LIMIT $start, $limit";
-// echo "<pre>"; print_r($a_records); echo "</pre>";
-// exit;
- if (!$a_data) {
- return Array(
- 'num' => 0,
- 'sql' => '',
- );
- }
-// $prefix = GetTablePrefix();
- $rowcount = 0;
- $a_fields = array_keys($a_data[0]);
- $fields_sql = '';
- foreach ($a_fields AS $field_name) {
- $fields_sql .= '`'.$field_name.'`,';
- }
- $fields_sql = substr($fields_sql, 0, -1);
- $temp = '';
- foreach ($a_data AS $a_row)
- {
- $values_sql = '';
- foreach ($a_row as $field_name => $field_value) {
- $values_sql .= $this->Conn->qstr($field_value).',';
- }
- $values_sql = substr($values_sql, 0, -1);
- $sql = 'INSERT INTO '.$table.' ('.$fields_sql.') VALUES ('.$values_sql.');';
- $sql = str_replace("\n", "\\n", $sql);
- $sql = str_replace("\r", "\\r", $sql);
- $temp .= $sql."\n";
- }
-
- if(strlen(TABLE_PREFIX))
- {
- $temp = str_replace("INSERT INTO ".TABLE_PREFIX, "INSERT INTO ", $temp);
- }
-
- return Array(
- 'num' => count($a_data),
- 'sql' => $temp,
- );
- }
-
-
-
- function GetTableCreate($table, $crlf="\n")
- {
- $schema_create = 'DROP TABLE IF EXISTS ' . $table . ';' . $crlf;
- $schema_create .="# --------------------------------------------------------".$crlf;
- $this->Conn->Query("SET SQL_QUOTE_SHOW_CREATE = 0");
- $tmpres = $this->Conn->Query("SHOW CREATE TABLE $table");
-// echo "<pre>"; print_r($tmpres); echo "</pre>";
-// exit;
- if(is_array($tmpres) && isset($tmpres[0]))
- {
- $tmpres = $tmpres[0];
- $pos = strpos($tmpres["Create Table"], ' (');
- $pos2 = strpos($tmpres["Create Table"], '(');
- if ($pos2 != $pos + 1)
- {
- $pos = $pos2;
- $tmpres["Create Table"] = str_replace(",", ",\n ", $tmpres["Create Table"]);
- }
-
- $tmpres["Create Table"] = substr($tmpres["Create Table"], 0, 13)
- . (($use_backquotes) ? $tmpres["Table"] : $tmpres["Table"])
- . substr($tmpres["Create Table"], $pos);
- $tmpres["Create Table"] = str_replace("\n", $crlf, $tmpres["Create Table"]);
- if (preg_match_all('((,\r?\n[\s]*(CONSTRAINT|FOREIGN[\s]*KEY)[^\r\n,]+)+)', $tmpres["Create Table"], $regs)) {
- if (!isset($sql_constraints)) {
- if (isset($GLOBALS['no_constraints_comments'])) {
- $sql_constraints = '';
- } else {
- $sql_constraints = $crlf . '#' . $crlf
- . '# ' . $GLOBALS['strConstraintsForDumped'] . $crlf
- . '#' . $crlf;
- }
- }
- if (!isset($GLOBALS['no_constraints_comments'])) {
- $sql_constraints .= $crlf .'#' . $crlf .'# ' . $GLOBALS['strConstraintsForTable'] . ' ' . $table . $crlf . '#' . $crlf;
- }
- $sql_constraints .= 'ALTER TABLE $table $crlf '
- . preg_replace('/(,\r?\n|^)([\s]*)(CONSTRAINT|FOREIGN[\s]*KEY)/', '\1\2ADD \3', substr($regs[0][0], 2))
- . ";\n";
- $tmpres["Create Table"] = preg_replace('((,\r?\n[\s]*(CONSTRAINT|FOREIGN[\s]*KEY)[^\r\n,]+)+)', '', $tmpres["Create Table"]);
- }
- $schema_create .= $tmpres["Create Table"];
- }
- if(strlen($schema_create))
- {
- $schema_create = str_replace("DROP TABLE IF EXISTS ".TABLE_PREFIX,"DROP TABLE ",$schema_create);
- $schema_create = str_replace("CREATE TABLE ".TABLE_PREFIX,"CREATE TABLE ",$schema_create);
- while(strlen($schema_create && substr($schema_create,-1)!=")"))
- {
- $schema_create = substr($schema_create,0,-1);
- }
- }
- $schema_create .= "\n# --------------------------------------------------------\n";
- return $schema_create;
- }
-
- /**
- * Deletes one backup file
- *
- * @param kEvent $event
- */
- function OnDeleteBackup(&$event)
- {
- @unlink($this->get_backup_file());
- }
-
- function get_backup_file()
- {
- return $this->Application->ConfigValue('Backup_Path').'/dump'.$this->Application->GetVar('backupdate').'.txt';
- }
-
- /**
* Starts restore process
*
* @param kEvent $event
*/
function OnRestore(&$event)
{
- $file = $this->get_backup_file();
+ $backup_helper =& $this->Application->recallObject('BackupHelper');
+ /* @var $backup_helper BackupHelper */
- $restoreProgress = Array (
- 'file_pos' => 0,
- 'file_name' => $file,
- 'file_size' => filesize($file),
- );
- $this->Application->RemoveVar('adm.restore_success');
- $this->Application->StoreVar('adm.restore_status', serialize($restoreProgress));
+ $backup_helper->initRestore();
$event->redirect = 'tools/restore3';
}
function OnRestoreProgress(&$event)
{
- $done_percent = $this->performRestore();
+ $backup_helper =& $this->Application->recallObject('BackupHelper');
+ /* @var $backup_helper BackupHelper */
- if ($done_percent == -3) {
+ $done_percent = $backup_helper->performRestore();
+
+ if ( $done_percent == BackupHelper::SQL_ERROR_DURING_RESTORE ) {
$event->redirect = 'tools/restore4';
- return ;
}
-
- if ($done_percent < 0) {
- $this->Application->StoreVar('adm.restore_error', 'File read error'); $event->redirect = 'tools/restore4';
- return ;
+ elseif ( $done_percent == BackupHelper::FAILED_READING_BACKUP_FILE ) {
+ $this->Application->StoreVar('adm.restore_error', 'File read error');
+ $event->redirect = 'tools/restore4';
}
-
- if ($done_percent == 100) {
- $this->replaceRestoredFiles();
+ elseif ( $done_percent == 100 ) {
+ $backup_helper->replaceRestoredFiles();
$this->Application->StoreVar('adm.restore_success', 1);
$event->redirect = 'tools/restore4';
- return ;
- }
-
- echo $done_percent;
- $event->status = kEvent::erSTOP;
-
- }
-
- function replaceRestoredFiles()
- {
- // gather restored table names
- $tables = $this->Conn->GetCol('SHOW TABLES');
- $mask_restore_table = '/^restore'.TABLE_PREFIX.'(.*)$/';
- foreach($tables as $table)
- {
- if( preg_match($mask_restore_table,$table,$rets) )
- {
- $old_table = substr($table, 7);
- $this->Conn->Query('DROP TABLE IF EXISTS '.$old_table);
- $this->Conn->Query('CREATE TABLE '.$old_table.' LIKE '.$table);
- $this->Conn->Query('INSERT INTO '.$old_table.' SELECT * FROM '.$table);
- $this->Conn->Query('DROP TABLE '.$table);
- }
}
-
- }
-
- function performRestore()
- {
- $restoreProgress = unserialize($this->Application->RecallVar('adm.restore_status'));
- $filename = $restoreProgress['file_name'];
- $FileOffset = $restoreProgress['file_pos'];
- $MaxLines = 200;
- $size = filesize($filename);
-
- if($FileOffset > $size) {
- return -2;
- }
-
- $fp = fopen($filename,"r");
- if(!$fp) {
- return -1;
- }
-
-
- if($FileOffset>0)
- {
- fseek($fp,$FileOffset);
- }
- else
- {
- $EndOfSQL = FALSE;
- $sql = "";
- while(!feof($fp) && !$EndOfSQL)
- {
- $l = fgets($fp);
- if(substr($l,0,11)=="INSERT INTO")
- {
- $EndOfSQL = TRUE;
- }
- else
- {
- $sql .= $l;
- $FileOffset = ftell($fp) - strlen($l);
- }
- }
- if(strlen($sql))
- {
- $error = $this->runSchemaText($sql);
- if ($error != '') {
-
- $this->Application->StoreVar('adm.restore_error', $error);
- return -3;
- }
- }
- fseek($fp,$FileOffset);
- }
-
- $LinesRead = 0;
- $sql = "";
- $AllSql = array();
- while($LinesRead < $MaxLines && !feof($fp))
- {
- $sql = fgets($fp);
- if(strlen($sql))
- {
- $AllSql[] = $sql;
- $LinesRead++;
- }
- }
- if(!feof($fp))
- {
- $FileOffset = ftell($fp);
- }
- else
- {
- $FileOffset = $size;
- }
- fclose($fp);
-
- if(count($AllSql)>0) {
- $error = $this->runSQLText($AllSql);
- if ($error != '') {
-
- $this->Application->StoreVar('adm.restore_error', $error);
- return -3;
- }
-
+ else {
+ $event->status = kEvent::erSTOP;
+ echo $done_percent;
}
- $restoreProgress['file_pos'] = $FileOffset;
- $this->Application->StoreVar('adm.restore_status', serialize($restoreProgress));
-
- return round($FileOffset/$size * 100);
-// $this->Application->StoreVar('adm.restore_error', 'lalalal');
-// $event->redirect = 'tools/restore4';
}
-
/**
- * Run given schema sqls and return error, if any
+ * Stops Restore & redirect to Restore template
*
- * @param $sql
- * @return string
- * @access protected
+ * @param kEvent $event
*/
- protected function runSchemaText($sql)
+ function OnRestoreCancel(&$event)
{
- $table_prefix = 'restore' . TABLE_PREFIX;
-
- if ( strlen($table_prefix) > 0 ) {
- $replacements = Array ('INSERT INTO ', 'UPDATE ', 'ALTER TABLE ', 'DELETE FROM ', 'REPLACE INTO ');
-
- foreach ($replacements as $replacement) {
- $sql = str_replace($replacement, $replacement . $table_prefix, $sql);
- }
- }
-
- $sql = str_replace('CREATE TABLE ', 'CREATE TABLE IF NOT EXISTS ' . $table_prefix, $sql);
- $sql = str_replace('DROP TABLE ', 'DROP TABLE IF EXISTS ' . $table_prefix, $sql);
-
- $commands = explode("# --------------------------------------------------------", $sql);
-
- if ( count($commands) > 0 ) {
- for ($i = 0; $i < count($commands); $i++) {
- $cmd = trim( $commands[$i] );
-
- if ( strlen($cmd) > 0 ) {
- $this->Conn->Query($cmd);
-
- if ( $this->Conn->hasError() ) {
- return $this->Conn->getErrorMsg() . " COMMAND:<PRE>$cmd</PRE>";
- }
- }
- }
- }
-
- return '';
+ $event->redirect = 'tools/restore1';
}
/**
- * Runs given sqls and return error message, if any
+ * Deletes one backup file
*
- * @param $all_sqls
- * @return string
- * @access protected
+ * @param kEvent $event
*/
- protected function runSQLText($all_sqls)
+ function OnDeleteBackup(&$event)
{
- $line = 0;
-
- while ( $line < count($all_sqls) ) {
- $sql = $all_sqls[$line];
- if ( strlen(trim($sql)) > 0 && substr($sql, 0, 1) != "#" ) {
- $table_prefix = 'restore' . TABLE_PREFIX;
-
- if ( strlen($table_prefix) > 0 ) {
- $replacements = Array ('INSERT INTO ', 'UPDATE ', 'ALTER TABLE ', 'DELETE FROM ', 'REPLACE INTO ');
-
- foreach ($replacements as $replacement) {
- $sql = str_replace($replacement, $replacement . $table_prefix, $sql);
- }
- }
-
- $sql = str_replace('CREATE TABLE ', 'CREATE TABLE IF NOT EXISTS ' . $table_prefix, $sql);
- $sql = str_replace('DROP TABLE ', 'DROP TABLE IF EXISTS ' . $table_prefix, $sql);
- $sql = trim($sql);
+ $backup_helper =& $this->Application->recallObject('BackupHelper');
+ /* @var $backup_helper BackupHelper */
- if ( strlen($sql) > 0 ) {
- $this->Conn->Query($sql);
-
- if ( $this->Conn->hasError() ) {
- return $this->Conn->getErrorMsg() . " COMMAND:<PRE>$sql</PRE>";
- }
- }
- }
-
- $line++;
- }
-
- return '';
+ $backup_helper->delete();
}
/**
* Starts restore process
*
* @param kEvent $event
*/
function OnSqlQuery(&$event)
{
$sql = $this->Application->GetVar('sql');
if ($sql) {
- $start = $this->getMoment();
+ $start = microtime(true);
$result = $this->Conn->Query($sql);
- $this->Application->SetVar('sql_time', round($this->getMoment() - $start, 7));
+ $this->Application->SetVar('sql_time', round(microtime(true) - $start, 7));
if ($result)
{
if (is_array($result))
{
$this->Application->SetVar('sql_has_rows', 1);
$this->Application->SetVar('sql_rows', serialize($result));
}
}
$check_sql = trim(strtolower($sql));
if (
(substr($check_sql, 0, 6) == 'insert')
|| (substr($check_sql, 0, 6) == 'update')
|| (substr($check_sql, 0, 7) == 'replace')
|| (substr($check_sql, 0, 6) == 'delete')
) {
$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;
}
- function getMoment()
- {
- list($usec, $sec) = explode(' ', microtime());
- return ((float)$usec + (float)$sec);
- }
-
/**
* Occurs after unit config cache was successfully rebuilt
*
* @param kEvent $event
*/
function OnAfterCacheRebuild(&$event)
{
}
/**
* Removes "Community -> Groups" section when it is not allowed
*
* @param kEvent $event
*/
function OnAfterConfigRead(&$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
*/
function OnSaveMenuFrameWidth(&$event)
{
$event->status = kEvent::erSTOP;
if (!$this->Application->ConfigValue('ResizableFrames')) {
return ;
}
$sql = 'UPDATE ' . $this->Application->getUnitOption('conf', 'TableName') . '
SET VariableValue = ' . (int)$this->Application->GetVar('width') . '
WHERE VariableName = "MenuFrameWidth"';
$this->Conn->Query($sql);
if ($this->Conn->getAffectedRows()) {
$this->Application->DeleteUnitCache(false);
}
}
/**
* Retrieves data from memory cache
*
* @param kEvent $event
*/
function OnMemoryCacheGet(&$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
*/
function OnMemoryCacheSet(&$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
*/
function OnDeploy(&$event)
{
if ( isset($GLOBALS['argv']) ) {
// command line invocation -> don't perform redirect
$event->status = kEvent::erSTOP;
}
$deployment_helper =& $this->Application->recallObject('DeploymentHelper');
/* @var $deployment_helper DeploymentHelper */
$deployment_helper->deployAll();
$event->SetRedirectParam('action_completed', 1);
}
/**
* Synchronizes database revisions from "project_upgrades.sql" file
*
* @param kEvent $event
*/
function OnSynchronizeDBRevisions(&$event)
{
$deployment_helper =& $this->Application->recallObject('DeploymentHelper');
/* @var $deployment_helper DeploymentHelper */
if ( !$deployment_helper->deployAll(true) ) {
$event->status = kEvent::erFAIL;
}
else {
$event->SetRedirectParam('action_completed', 1);
}
}
/**
* [AGENT]
* 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(&$event)
{
$start_time = adodb_mktime();
$sql = 'SELECT SessionKey
FROM ' . TABLE_PREFIX . 'UserSession
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);
}
}
}
class UnitConfigDecorator {
var $parentPath = Array ();
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) . ', ';
array_pop($this->parentPath);
}
$prepend = $expand ? "\n" . str_repeat("\t", $level) : '';
$ret = rtrim($ret, ', ') . $prepend . ')';
}
else {
if (is_null($var)) {
$ret = 'NULL';
}
elseif (is_string($var)) {
$ret = "'" . $var . "'";
}
else {
$ret = $var;
}
}
return $ret;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/admin/admin_tag_processor.php
===================================================================
--- branches/5.2.x/core/units/admin/admin_tag_processor.php (revision 14706)
+++ branches/5.2.x/core/units/admin/admin_tag_processor.php (revision 14707)
@@ -1,1145 +1,1122 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class AdminTagProcessor extends kDBTagProcessor {
/**
* Allows to execute js script after the page is fully loaded
*
* @param Array $params
* @return string
*/
function AfterScript($params)
{
$after_script = $this->Application->GetVar('after_script');
if ($after_script) {
return '<script type="text/javascript">'.$after_script.'</script>';
}
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 "<strong>' . $section . '</strong>" in "<strong>' . __METHOD__ . '</strong>"');
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':
if ($section && ($section != 'in-portal:root')) {
// don't translate label for top section, because it's already translated
$no_editing = array_key_exists('no_editing', $params) ? $params['no_editing'] : false;
$res = $this->Application->Phrase($section_data['label'], !$no_editing);
}
else {
$res = '';
}
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;
$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) );
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']);
}
function TreeEditWarrning($params)
{
$ret = $this->Application->Phrase($params['label']);
$ret = str_replace(Array('&lt;', '&gt;', 'br/', 'br /', "\n", "\r"), Array('<', '>', 'br', 'br', '', ''), $ret);
if (getArrayValue($params, 'escape')) {
$ret = addslashes($ret);
}
$ret = str_replace('<br>', '\n', $ret);
return $ret;
}
/**
* 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['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('no_amp' => 1, '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, <comma separated prefix list>}
$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');
if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild')) {
$updater =& $this->Application->makeClass('kPermCacheUpdater');
/* @var $updater kPermCacheUpdater */
$updater->OneStepRun();
$this->Application->HandleEvent($event, 'c:OnResetCMSMenuCache');
}
else {
// 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 .= "<option value='$col'>".$title;
}
}
else {
foreach ($cols['order'] as $col) {
if (in_array($col, $cols['hidden_fields'])) continue;
$title = $this->Application->Phrase($cols['titles'][$col]);
$o .= "<option value='$col'>".$title;
}
}
return $o;
}
/**
* Allows to set popup size (key - current template name)
*
* @param Array $params
*/
function SetPopupSize($params)
{
$width = $params['width'];
$height = $params['height'];
if ($this->Application->GetVar('ajax') == 'yes') {
// during AJAX request just output size
die($width.'x'.$height);
}
if (!$this->UsePopups($params)) {
return ;
}
$t = $this->Application->GetVar('t');
$sql = 'SELECT *
FROM '.TABLE_PREFIX.'PopupSizes
WHERE TemplateName = '.$this->Conn->qstr($t);
$popup_info = $this->Conn->GetRow($sql);
if (!$popup_info) {
// create new popup size record
$fields_hash = Array (
'TemplateName' => $t,
'PopupWidth' => $width,
'PopupHeight' => $height,
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'PopupSizes');
}
elseif ($popup_info['PopupWidth'] != $width || $popup_info['PopupHeight'] != $height) {
// popup found and size in tag differs from one in db -> update in db
$fields_hash = Array (
'PopupWidth' => $width,
'PopupHeight' => $height,
);
$this->Conn->doUpdate($fields_hash, TABLE_PREFIX.'PopupSizes', 'PopupId = '.$popup_info['PopupId']);
}
}
/**
* Returns popup size (by template), if not cached, then parse template to get value
*
* @param Array $params
* @return string
*/
function GetPopupSize($params)
{
$t = $this->Application->GetVar('template_name');
$sql = 'SELECT *
FROM '.TABLE_PREFIX.'PopupSizes
WHERE TemplateName = '.$this->Conn->qstr($t);
$popup_info = $this->Conn->GetRow($sql);
if (!$popup_info) {
$this->Application->InitParser();
$this->Application->ParseBlock(array('name' => $t)); // dies when SetPopupSize tag found & in ajax requrest
return '750x400'; // tag SetPopupSize not found in template -> use default size
}
return $popup_info['PopupWidth'].'x'.$popup_info['PopupHeight'];
}
/**
* Allows to check if popups are generally enabled OR to check for "popup" or "modal" mode is enabled
*
* @param Array $params
* @return bool
*/
function UsePopups($params)
{
if ($this->Application->GetVar('_force_popup')) {
return true;
}
$use_popups = (int)$this->Application->ConfigValue('UsePopups');
if (array_key_exists('mode', $params)) {
$mode_mapping = Array ('popup' => 1, 'modal' => 2);
return $use_popups == $mode_mapping[ $params['mode'] ];
}
return $use_popups;
}
function UseToolbarLabels($params)
{
return (int)$this->Application->ConfigValue('UseToolbarLabels');
}
/**
* Checks if debug mode enabled (optionally) and specified constant is on
*
* @param Array $params
* @return bool
* @todo Could be a duplicate of kMainTagProcessor::ConstOn
*/
function ConstOn($params)
{
$constant_name = $this->SelectParam($params, 'name,const');
$debug_mode = isset($params['debug_mode']) && $params['debug_mode'] ? $this->Application->isDebugMode() : true;
return $debug_mode && kUtil::constOn($constant_name);
}
/**
* Builds link to last template in main frame of admin
*
* @param Array $params
* @return string
*/
function MainFrameLink($params)
{
$persistent = isset($params['persistent']) && $params['persistent'];
if ($persistent && $this->Application->ConfigValue('RememberLastAdminTemplate')) {
// check last_template in persistent session
$last_template = $this->Application->RecallPersistentVar('last_template_popup');
}
else {
// check last_template in session
$last_template = $this->Application->RecallVar('last_template_popup'); // because of m_opener=s there
}
if (!$last_template) {
$params['persistent'] = 1;
return $persistent ? false : $this->MainFrameLink($params);
}
list($index_file, $env) = explode('|', $last_template);
$vars = $this->Application->HttpQuery->processQueryString($env, 'pass');
$recursion_templates = Array ('login', 'index', 'no_permission');
if (isset($vars['admin']) && $vars['admin'] == 1) {
// index template doesn't begin recursion on front-end (in admin frame)
$vars['m_theme'] = '';
if (isset($params['m_opener']) && $params['m_opener'] == 'r') {
// front-end link for highlighting purposes
$vars['t'] = 'index';
$vars['m_cat_id'] = $this->Application->getBaseCategory();
}
unset($recursion_templates[ array_search('index', $recursion_templates)]);
}
if (in_array($vars['t'], $recursion_templates)) {
// prevents redirect recursion OR old in-portal pages
$params['persistent'] = 1;
return $persistent ? false : $this->MainFrameLink($params);
}
$vars = array_merge($vars, $params);
$t = $vars['t'];
unset($vars['t'], $vars['persistent']);
// substitute language in link to current (link will work, even when language will be changed)
$vars['m_lang'] = $this->Application->GetVar('m_lang');
return $this->Application->HREF($t, '', $vars, $index_file);
}
/**
* Returns menu frame width or 200 in case, when invalid width specified in config
*
* @param Array $params
* @return string
*/
function MenuFrameWidth($params)
{
$width = (int)$this->Application->ConfigValue('MenuFrameWidth');
return $width > 0 ? $width : 200;
}
function AdminSkin($params)
{
$skin_helper =& $this->Application->recallObject('SkinHelper');
/* @var $skin_helper SkinHelper */
return $skin_helper->AdminSkinTag($params);
}
/**
* Prints errors, discovered during mass template compilation
*
* @param $params
* @return string
* @access protected
*/
protected function PrintCompileErrors($params)
{
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
$errors = $this->Application->RecallVar('compile_errors');
if ( !$errors ) {
return '';
}
$ret = '';
$errors = unserialize($errors);
foreach ($errors as $an_error) {
$block_params['file'] = str_replace(FULL_PATH, '', $an_error['file']);
$block_params['line'] = $an_error['line'];
$block_params['message'] = $an_error['msg'];
$ret .= $this->Application->ParseBlock($block_params);
}
$this->Application->RemoveVar('compile_errors');
return $ret;
}
function CompileErrorCount($params)
{
$errors = $this->Application->RecallVar('compile_errors');
if (!$errors) {
return 0;
}
return count( unserialize($errors) );
}
function ExportData($params)
{
$export_helper =& $this->Application->recallObject('CSVHelper');
/* @var $export_helper kCSVHelper */
$result = $export_helper->ExportData( $this->SelectParam($params, 'var,name,field') );
return ($result === false) ? '' : $result;
}
function ImportData($params)
{
$import_helper =& $this->Application->recallObject('CSVHelper');
/* @var $import_helper kCSVHelper */
$result = $import_helper->ImportData( $this->SelectParam($params, 'var,name,field') );
return ($result === false) ? '' : $result;
}
function PrintCSVNotImportedLines($params)
{
$import_helper =& $this->Application->recallObject('CSVHelper');
/* @var $import_helper kCSVHelper */
return $import_helper->GetNotImportedLines();
}
/**
* Returns input field name to
* be placed on form (for correct
* event processing)
*
* @param Array $params
* @return string
* @access public
*/
function InputName($params)
{
list($id, $field) = $this->prepareInputName($params);
$ret = $this->getPrefixSpecial().'[0]['.$field.']'; // 0 always, as has no idfield
if( getArrayValue($params, 'as_preg') ) $ret = preg_quote($ret, '/');
return $ret;
}
/**
* Returns list of all backup file dates formatted
* in passed block
*
* @param Array $params
* @return string
* @access public
*/
function PrintBackupDates($params)
{
- $ret = '';
- $datearray = $this->getBackupFiles();
+ $backup_helper =& $this->Application->recallObject('BackupHelper');
+ /* @var $backup_helper BackupHelper */
- foreach ($datearray as $value) {
- $params['backuptimestamp'] = $value['filedate'];
- $params['backuptime'] = date('F j, Y, g:i a', $value['filedate']);
- $params['backupsize'] = round($value['filesize'] / 1024 / 1024, 2); // MBytes
- $ret .= $this->Application->ParseBlock($params);
- }
-
- return $ret;
- }
-
- function getBackupFiles()
- {
- $file_helper =& $this->Application->recallObject('FileHelper');
- /* @var $file_helper FileHelper */
-
- $ret = Array ();
- $backup_path = $this->Application->ConfigValue('Backup_Path');
- $file_helper->CheckFolder($backup_path);
- $backup_files = glob($backup_path . DIRECTORY_SEPARATOR . 'dump*.txt');
+ $ret = '';
+ $dates = $backup_helper->getBackupFiles();
- if ( !$backup_files ) {
- return Array ();
- }
+ foreach ($dates as $date) {
+ $params['backuptimestamp'] = $date['filedate'];
+ $params['backuptime'] = date('F j, Y, g:i a', $date['filedate']);
+ $params['backupsize'] = round($date['filesize'] / 1024 / 1024, 2); // MBytes
- foreach ($backup_files as $backup_file) {
- $ret[] = Array (
- 'filedate' => preg_replace('/^dump([\d]+)\.txt$/', '\\1', basename($backup_file)),
- 'filesize' => filesize($backup_file)
- );
+ $ret .= $this->Application->ParseBlock($params);
}
- rsort($ret);
-
- return $ret;
-
+ return $ret;
}
/**
* Returns phpinfo() output
*
* @param Array $params
* @return string
*/
function PrintPHPinfo($params)
{
ob_start();
phpinfo();
return ob_get_clean();
}
function PrintSqlCols($params)
{
$a_data = unserialize($this->Application->GetVar('sql_rows'));
$ret = '';
$block = $params['render_as'];
foreach ($a_data AS $a_row)
{
foreach ($a_row AS $col => $value)
{
$ret .= $this->Application->ParseBlock(Array('name'=>$block, 'value'=>$col));
}
break;
}
return $ret;
}
function PrintSqlRows($params)
{
$a_data = unserialize($this->Application->GetVar('sql_rows'));
$ret = '';
$block = $params['render_as'];
foreach ($a_data AS $a_row)
{
$cells = '';
foreach ($a_row AS $col => $value)
{
$cells .= '<td>'.$value.'</td>';
}
$ret .= $this->Application->ParseBlock(Array('name'=>$block, 'cells'=>$cells));
}
return $ret;
}
/**
* Prints available and enabled import sources using given block
*
* @param Array $params
* @return string
*/
function PrintImportSources($params)
{
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'ImportScripts
WHERE (Status = ' . STATUS_ACTIVE . ') AND (Type = "CSV")';
$import_sources = $this->Conn->Query($sql);
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
$ret = '';
foreach ($import_sources as $import_source) {
$block_params['script_id'] = $import_source['ImportId'];
$block_params['script_module'] = mb_strtolower($import_source['Module']);
$block_params['script_name'] = $import_source['Name'];
$block_params['script_prefix'] = $import_source['Prefix'];
$block_params['module_path'] = $this->Application->findModule('Name', $import_source['Module'], 'Path');
$ret .= $this->Application->ParseBlock($block_params);
}
return $ret;
}
/**
* Checks, that new window should be opened in "incs/close_popup" template instead of refreshing parent window
*
* @param Array $params
* @return bool
*/
function OpenNewWindow($params)
{
if (!$this->UsePopups($params)) {
return false;
}
$diff = array_key_exists('diff', $params) ? $params['diff'] : 0;
$wid = $this->Application->GetVar('m_wid');
$stack_name = rtrim('opener_stack_' . $wid, '_');
$opener_stack = $this->Application->RecallVar($stack_name);
$opener_stack = $opener_stack ? unserialize($opener_stack) : Array ();
return count($opener_stack) >= 2 - $diff;
}
/**
* Allows to dynamically change current language in template
*
* @param Array $params
*/
function SetLanguage($params)
{
$this->Application->SetVar('m_lang', $params['language_id']);
$this->Application->Phrases->Init('phrases', '', $params['language_id']);
}
/**
* Performs HTTP Authentification for administrative console
*
* @param Array $params
*/
function HTTPAuth($params)
{
if (!$this->Application->ConfigValue('UseHTTPAuth')) {
// http authentification not required
return true;
}
$super_admin_ips = defined('SA_IP') ? SA_IP : false;
$auth_bypass_ips = $this->Application->ConfigValue('HTTPAuthBypassIPs');
if (($auth_bypass_ips && kUtil::ipMatch($auth_bypass_ips)) || ($super_admin_ips && kUtil::ipMatch($super_admin_ips))) {
// user ip is in ip bypass list
return true;
}
if (!array_key_exists('PHP_AUTH_USER', $_SERVER)) {
// ask user to authentificate, when not authentificated before
return $this->_httpAuthentificate();
}
else {
// validate user credentials (browsers remembers user/password
// and sends them each time page is visited, so no need to save
// authentification result in session)
if ($this->Application->ConfigValue('HTTPAuthUsername') != $_SERVER['PHP_AUTH_USER']) {
// incorrect username
return $this->_httpAuthentificate();
}
$password_formatter =& $this->Application->recallObject('kPasswordFormatter');
/* @var $password_formatter kPasswordFormatter */
$password = $password_formatter->EncryptPassword($_SERVER['PHP_AUTH_PW'], 'b38');
if ($this->Application->ConfigValue('HTTPAuthPassword') != $password) {
// incorrect password
return $this->_httpAuthentificate();
}
}
return true;
}
/**
* Ask user to authentificate
*
* @return false
*/
function _httpAuthentificate()
{
$realm = strip_tags( $this->Application->ConfigValue('Site_Name') );
header('WWW-Authenticate: Basic realm="' . $realm . '"');
header('HTTP/1.0 401 Unauthorized');
return false;
}
/**
* Checks, that we are using memory cache
*
* @param Array $params
* @return bool
*/
function MemoryCacheEnabled($params)
{
return $this->Application->isCachingType(CACHING_TYPE_MEMORY);
}
}
\ No newline at end of file

Event Timeline