* @copyright 2007-2014 PrestaShop SA * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ function developpementErrorHandler($errno, $errstr, $errfile, $errline) { if (!(error_reporting() & $errno)) return; switch($errno) { case E_ERROR: echo '[PHP Error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_WARNING: echo '[PHP Warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_PARSE: echo '[PHP Parse #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_NOTICE: echo '[PHP Notice #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_CORE_ERROR: echo '[PHP Core #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_CORE_WARNING: echo '[PHP Core warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_COMPILE_ERROR: echo '[PHP Compile #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_COMPILE_WARNING: echo '[PHP Compile warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_USER_ERROR: echo '[PHP Error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_USER_WARNING: echo '[PHP User warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_USER_NOTICE: echo '[PHP User notice #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_STRICT: echo '[PHP Strict #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; case E_RECOVERABLE_ERROR: echo '[PHP Recoverable error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; break; default: echo '[PHP Unknown error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'; } die; return true; } abstract class Controller extends ControllerCore { public $_memory = array(); public $_time = array(); private static $_footer = true; public static function disableParentCalls() { self::$_footer = false; } private function displayMemoryColor($n) { $n /= 1048576; if ($n > 3) return ''.sprintf('%0.2f', $n).''; if ($n > 1) return ''.sprintf('%0.2f', $n).''; return ''.sprintf('%0.2f', $n).''; } private function displayPeakMemoryColor($n) { $n /= 1048576; if ($n > 16) return ''.sprintf('%0.1f', $n).''; if ($n > 12) return ''.sprintf('%0.1f', $n).''; return ''.sprintf('%0.1f', $n).''; } private function displaySQLQueries($n) { if ($n > 150) return ''.$n.' queries'; if ($n > 100) return ''.$n.' queries'; return ''.$n.' quer'.($n == 1 ? 'y' : 'ies').''; } private function displayRowsBrowsed($n) { if ($n > 400) return ''.$n.' rows browsed'; if ($n > 100) return ''.$n.' rows browsed'; return ''.$n.' row'.($n == 1 ? '' : 's').' browsed'; } private function displayLoadTimeColor($n, $kikoo = false) { if ($n > 1) return ''.round($n * 1000).''.($kikoo ? ' ms
You\'d better run your shop on a toaster' : ''); if ($n > 0.5) return ''.round($n * 1000).''.($kikoo ? ' ms
I hope it is a shared hosting' : ''); return ''.round($n * 1000).''.($kikoo ? ' ms
Good boy! That\'s what I call a webserver!' : ''); } private function getTimeColor($n) { if ($n > 4) return 'style="color:red"'; if ($n > 2) return 'style="color:orange"'; return 'style="color:green"'; } private function getQueryColor($n) { if ($n > 5) return 'style="color:red"'; if ($n > 2) return 'style="color:orange"'; return 'style="color:green"'; } private function getTableColor($n) { if ($n > 30) return 'style="color:red"'; if ($n > 20) return 'style="color:orange"'; return 'style="color:green"'; } private function getObjectModelColor($n) { if ($n > 50) return 'style="color:red"'; if ($n > 10) return 'style="color:orange"'; return 'style="color:green"'; } public function __construct() { //set_error_handler('developpementErrorHandler'); ini_set('html_errors', 'on'); ini_set('display_errors', 'on'); error_reporting(E_ALL | E_STRICT); if (!self::$_footer) return; $this->_memory['config'] = memory_get_usage(); $this->_mempeak['config'] = memory_get_peak_usage(); $this->_time['config'] = microtime(true); parent::__construct(); $this->_memory['constructor'] = memory_get_usage(); $this->_mempeak['constructor'] = memory_get_peak_usage(); $this->_time['constructor'] = microtime(true); } public function run() { $this->init(); $this->_memory['init'] = memory_get_usage(); $this->_mempeak['init'] = memory_get_peak_usage(); $this->_time['init'] = microtime(true); if ($this->checkAccess()) { $this->_memory['checkAccess'] = memory_get_usage(); $this->_mempeak['checkAccess'] = memory_get_peak_usage(); $this->_time['checkAccess'] = microtime(true); if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className))) $this->setMedia(); $this->_memory['setMedia'] = memory_get_usage(); $this->_mempeak['setMedia'] = memory_get_peak_usage(); $this->_time['setMedia'] = microtime(true); // postProcess handles ajaxProcess $this->postProcess(); $this->_memory['postProcess'] = memory_get_usage(); $this->_mempeak['postProcess'] = memory_get_peak_usage(); $this->_time['postProcess'] = microtime(true); if (!empty($this->redirect_after)) $this->redirect(); if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className))) $this->initHeader(); $this->_memory['initHeader'] = memory_get_usage(); $this->_mempeak['initHeader'] = memory_get_peak_usage(); $this->_time['initHeader'] = microtime(true); $this->initContent(); $this->_memory['initContent'] = memory_get_usage(); $this->_mempeak['initContent'] = memory_get_peak_usage(); $this->_time['initContent'] = microtime(true); if (!$this->content_only && ($this->display_footer || (isset($this->className) && $this->className))) $this->initFooter(); $this->_memory['initFooter'] = memory_get_usage(); $this->_mempeak['initFooter'] = memory_get_peak_usage(); $this->_time['initFooter'] = microtime(true); // default behavior for ajax process is to use $_POST[action] or $_GET[action] // then using displayAjax[action] if ($this->ajax) { $action = Tools::getValue('action'); if (!empty($action) && method_exists($this, 'displayAjax'.Tools::toCamelCase($action))) $this->{'displayAjax'.$action}(); elseif (method_exists($this, 'displayAjax')) $this->displayAjax(); } else $this->displayDebug(); } else { $this->initCursedPage(); $this->displayDebug(); } } function ini_get_display_errors() { $a = 'display_errors'; $b = ini_get($a); switch (strtolower($b)) { case 'on': case 'yes': case 'true': return 'assert.active' !== $a; case 'stdout': case 'stderr': return 'display_errors' === $a; default: return (bool)(int)$b; } } private function sizeofvar($var) { $start_memory = memory_get_usage(); try { $tmp = Tools::unSerialize(serialize($var)); } catch (Exception $e) { $tmp = $this->getVarData($var); } $size = memory_get_usage() - $start_memory; return $size; } private function getVarData($var) { if (is_object($var)) return $var; return (string)$var; } public function displayDebug() { global $start_time; $this->display(); $this->_memory['display'] = memory_get_usage(); $this->_mempeak['display'] = memory_get_peak_usage(); $this->_time['display'] = microtime(true); if (!$this->ini_get_display_errors()) return; $memory_peak_usage = memory_get_peak_usage(); $hr = '
'; $totalSize = 0; foreach (get_included_files() as $file) $totalSize += filesize($file); $totalQueryTime = 0; foreach (Db::getInstance()->queries as $data) $totalQueryTime += $data['time']; $executedModules = Hook::getExecutedModules(); $hooktime = Hook::getHookTime(); arsort($hooktime); $totalHookTime = 0; foreach ($hooktime as $time) $totalHookTime += $time; $hookMemoryUsage = Hook::getHookMemoryUsage(); arsort($hookMemoryUsage); $totalHookMemoryUsage = 0; foreach ($hookMemoryUsage as $usage) $totalHookMemoryUsage += $usage; $globalSize = array(); $totalGlobalSize = 0; foreach ($GLOBALS as $key => $value) if ($key != 'GLOBALS') { $totalGlobalSize += ($size = $this->sizeofvar($value)); if ($size > 1024) $globalSize[$key] = round($size / 1024, 1); } arsort($globalSize); $cache = Cache::retrieveAll(); $totalCacheSize = $this->sizeofvar($cache); echo ' '; echo '
Load time: '.$this->displayLoadTimeColor($this->_time['display'] - $start_time, true).'
'; if (self::$_footer){ echo ''; echo ''; $last_time = $start_time; foreach ($this->_time as $k => $time) { echo ''; $last_time = $time; } echo '
ExecutionLoad time (ms)
'.$k.''.$this->displayLoadTimeColor($time - $last_time).'
'; } echo '
Hook processing: '.$this->displayLoadTimeColor($totalHookTime).' ms / '.$this->displayMemoryColor($totalHookMemoryUsage).' Mb
'.(int)count($executedModules).' methods called in '.(int)count(array_unique($executedModules)).' modules
'; echo ''; echo ''; foreach ($hooktime as $hook => $time) echo ''; echo '
HookProcessing
'.$hook.''.$this->displayMemoryColor($hookMemoryUsage[$hook]).' Mb in '.$this->displayLoadTimeColor($time).' ms
Memory peak usage: '.$this->displayPeakMemoryColor($memory_peak_usage).' Mb
'; if (self::$_footer) { echo ''; echo ''; $last_memory = 0; foreach ($this->_memory as $k => $memory) { echo ''; $last_memory = $memory; } echo '
ExecutionMemory (Mb)Total (Mb)
'.$k.''.$this->displayMemoryColor($memory - $last_memory).''.$this->displayPeakMemoryColor($this->_mempeak[$k]).'
'; } echo '
'; echo '
Total cache size (in Cache class): '.$this->displayMemoryColor($totalCacheSize).' Mb
DB type: '.get_class(Db::getInstance()).'
SQL Queries: '.$this->displaySQLQueries(count(Db::getInstance()->queries)).'
Time spent querying: '.$this->displayLoadTimeColor($totalQueryTime).' ms
Included files: '.sizeof(get_included_files()).'
Size of included files: '.$this->displayMemoryColor($totalSize).' Mb
Globals (> 1 Ko only): '.round($totalGlobalSize / 1024).' Ko
    '; foreach ($globalSize as $global => $size) echo '
  • '.$global.' ≈ '.$size.' Ko
  • '; echo '
'; $array_queries = array(); $queries = Db::getInstance()->queries; uasort($queries, 'prestashop_querytime_sort'); foreach ($queries as $data) { $query_row = array( 'time' => $data['time'], 'query' => $data['query'], 'location' => $data['stack'][0]['file'].':'.$data['stack'][0]['line'], 'filesort' => false, 'rows' => 1, 'group_by' => false, 'stack' => $data['stack'] ); if (preg_match('/^\s*select\s+/i', $data['query'])) { $explain = Db::getInstance()->executeS('explain '.$data['query']); if (stristr($explain[0]['Extra'], 'filesort')) $query_row['filesort'] = true; foreach ($explain as $row) $query_row['rows'] *= $row['rows']; if (stristr($data['query'], 'group by') && !preg_match('/(avg|count|min|max|group_concat|sum)\s*\(/i', $data['query'])) $query_row['group_by'] = true; } $array_queries[] = $query_row; } echo '
'; echo '
Stopwatch (with SQL_NO_CACHE) (total = '.count(Db::getInstance()->queries).')'; $i = 1; echo ''; foreach ($array_queries as $data) { $echo_stack = ''; array_shift($data['stack']); foreach ($data['stack'] as $call) $echo_stack .= 'from '.str_replace('\\', '/', substr($call['file'], strlen(_PS_ROOT_DIR_))).':'.$call['line'].'
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; } echo '
Query Time (ms) Rows Filesort Group By Location
'.preg_replace("/(^[\s]*)/m", "", htmlspecialchars($data['query'], ENT_NOQUOTES, 'utf-8', false)).'
getTimeColor($data['time'] * 1000).'>'.round($data['time'] * 1000, 3).''.$data['rows'].''.($data['filesort'] ? 'Yes' : '').''.($data['group_by'] ? 'Yes' : '').'in '.$data['location'].'

'.$echo_stack.'
'; $queries = Db::getInstance()->uniqQueries; arsort($queries); $count = count(Db::getInstance()->uniqQueries); foreach ($queries as $q => &$nb) if ($nb == 1) $count--; if ($count) echo '
Doubles (IDs replaced by "XX") (total = '.$count.') '; foreach ($queries as $q => $nb) if ($nb > 1) echo ''; echo '
getQueryColor($nb).'>'.$nb.' '.$q.'
Tables stress '; $tables = Db::getInstance()->tables; arsort($tables); foreach ($tables as $table => $nb) echo ''; echo '
getTableColor($nb).'>'.$nb.' '.$table.'
'; if (isset(ObjectModel::$debug_list)) { echo '
ObjectModel instances'; $list = ObjectModel::$debug_list; uasort($list, create_function('$a,$b', 'return (count($a) < count($b)) ? 1 : -1;')); $i = 0; echo ''; foreach ($list as $class => $info) { echo ''; echo ''; echo ''; $i++; } echo '
NameInstanceSource
'.$class.'getObjectModelColor(count($info)).'>'.count($info).'
'; foreach ($info as $trace) echo ltrim(str_replace(array(_PS_ROOT_DIR_, '\\'), array('', '/'), $trace['file']), '/').' ['.$trace['line'].']
'; echo '
'; } // List of included files echo '
Included files '; $i = 1; echo ''; foreach (get_included_files() as $file) { $file = ltrim(str_replace('\\', '/', str_replace(_PS_ROOT_DIR_, '', $file)), '/'); $file = ''.dirname($file).'/'.basename($file).''; echo ''; $i++; } echo '
#Filename
'.$i.''.$file.'
'; } } function prestashop_querytime_sort($a, $b) { if ($a['time'] == $b['time']) return 0; return ($a['time'] > $b['time']) ? -1 : 1; }