PageRenderTime 77ms CodeModel.GetById 20ms RepoModel.GetById 10ms app.codeStats 0ms

/admin/include/extensions/yiidebugtb/XWebDebugRouter.php

http://chenjin.googlecode.com/
PHP | 499 lines | 354 code | 57 blank | 88 comment | 44 complexity | 89f613979fad8b4f53142cbf321f8869 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /*
  3. * Yii Debug Toolbar
  4. *
  5. * Using:
  6. * 1. First Step.
  7. * Extract yiidebugtb folder to [webroot]/protected/extensions/yiidebugtb
  8. * --Test:
  9. * -- You must have an "[webroot]/protected/extensions/yiidebugtb/XWebDebugRouter.php" file
  10. * -- if you all right way.
  11. *
  12. * 2. Second Step.
  13. * Open [webroot]/protected/config/main.php, find section 'import' and add following lines which belongs to yiidebugtb:
  14. *
  15. * [...]
  16. * // autoloading model and component classes
  17. * 'import'=>array(
  18. * 'application.models.*',
  19. * 'application.extensions.yiidebugtb.*'
  20. * [...]
  21. * ),
  22. * [...]
  23. *
  24. * 3. And Last Step.
  25. * In [webroot]/protected/config/main.php find section 'routes' and add following lines for XWebDebugRouter:
  26. *
  27. * [...]
  28. * 'routes'=>array(
  29. * array(
  30. * 'class'=>'XWebDebugRouter',
  31. * 'config'=>'alignLeft, opaque, runInDebug, fixedPos, collapsed',
  32. * 'levels'=>'error, warning, trace, profile, info',
  33. * 'allowedIPs'=>array('127.0.0.1','192.168.1.54'),
  34. * ),
  35. * ),
  36. * [...]
  37. *
  38. * Config options are mean:
  39. * 'alignLeft' => Debug toolbar will be aligned to the top left corner of browser window
  40. * 'opaque' => Makes debug toolbar almost invisible when it's minimized
  41. * 'runInDebug' => Show debug toolbar only if Yii application running in DEBUG MODE (see index.php for details)
  42. * 'fixedPos' => Makes debug toolbar sticky with browser window, not document!
  43. * 'collapsed' => Show debug toolbar minimized by default.
  44. *
  45. * Also there is an additional security feature you may need - 'allowedIPs' option. This option
  46. * holds the array of IP addresses of all machines you need to use in development cycle. So if you
  47. * forget to remove YII_DEBUG from bootstrap file for the production stage, your client don't see
  48. * the toolbar anyway.
  49. */
  50. //TODO: Need more comments (rus: ????? ?????? ???????????? ? ????)
  51. /**
  52. * Helper class for array dumping.
  53. */
  54. class arrayDumper
  55. {
  56. private static $_objects;
  57. private static $_output;
  58. private static $_depth;
  59. /**
  60. * Displays a variable.
  61. * This method achieves the similar functionality as var_dump and print_r
  62. * but is more robust when handling complex objects such as Yii controllers.
  63. * @param mixed variable to be dumped
  64. * @param integer maximum depth that the dumper should go into the variable. Defaults to 10.
  65. * @param boolean whether the result should be syntax-highlighted
  66. */
  67. public static function dump($var,$depth=10,$highlight=false, $yamlStyle = false)
  68. {
  69. return $yamlStyle == false ? CVarDumper::dumpAsString($var, $depth, $highlight) : self::dumpAsString($var,$depth,$highlight);
  70. }
  71. /**
  72. * Dumps a variable in terms of a string.
  73. * This method achieves the similar functionality as var_dump and print_r
  74. * but is more robust when handling complex objects such as Yii controllers.
  75. * @param mixed variable to be dumped
  76. * @param integer maximum depth that the dumper should go into the variable. Defaults to 10.
  77. * @param boolean whether the result should be syntax-highlighted
  78. * @return string the string representation of the variable
  79. */
  80. public static function dumpAsString($var,$depth=10,$highlight=false)
  81. {
  82. self::$_output='';
  83. self::$_objects=array();
  84. self::$_depth=$depth;
  85. self::dumpInternal($var,0);
  86. if($highlight)
  87. {
  88. $result=highlight_string("<?php\n".self::$_output,true);
  89. self::$_output=preg_replace('/&lt;\\?php<br \\/>/','',$result,1);
  90. }
  91. return self::$_output;
  92. }
  93. private static function dumpInternal($var,$level)
  94. {
  95. switch(gettype($var))
  96. {
  97. case 'boolean':
  98. self::$_output.=$var?'true':'false';
  99. break;
  100. case 'integer':
  101. self::$_output.="$var";
  102. break;
  103. case 'double':
  104. self::$_output.="$var";
  105. break;
  106. case 'string':
  107. self::$_output.="'$var'";
  108. break;
  109. case 'resource':
  110. self::$_output.='{resource}';
  111. break;
  112. case 'NULL':
  113. self::$_output.="null";
  114. break;
  115. case 'unknown type':
  116. self::$_output.='{unknown}';
  117. break;
  118. case 'array':
  119. if(self::$_depth<=$level)
  120. self::$_output.='array(...)';
  121. else if(empty($var))
  122. self::$_output.='{ }';
  123. else
  124. {
  125. $keys=array_keys($var);
  126. $spaces=str_repeat(' ',$level*2);
  127. self::$_output.=$spaces.'';
  128. foreach($keys as $key)
  129. {
  130. self::$_output.=($level == 0 ? '' : "\n").$spaces." $key: ";
  131. self::$_output.=self::dumpInternal($var[$key],$level+1);
  132. self::$_output.=($level == 0 ? "\n" : '');
  133. }
  134. self::$_output.="";
  135. }
  136. break;
  137. case 'object':
  138. if(($id=array_search($var,self::$_objects,true))!==false)
  139. self::$_output.=get_class($var).'#'.($id+1).'(...)';
  140. else if(self::$_depth<=$level)
  141. self::$_output.=get_class($var).'(...)';
  142. else
  143. {
  144. $id=array_push(self::$_objects,$var);
  145. $className=get_class($var);
  146. $members=(array)$var;
  147. $keys=array_keys($members);
  148. $spaces=str_repeat(' ',$level*2);
  149. self::$_output.="$className ID:#$id";//\n".$spaces.'(';
  150. foreach($keys as $key)
  151. {
  152. $keyDisplay=strtr(trim($key),array("\0"=>'->'));
  153. self::$_output.="\n".$spaces." $keyDisplay: ";
  154. self::$_output.=self::dumpInternal($members[$key],$level+1);
  155. }
  156. self::$_output.="\n".$spaces.')';
  157. }
  158. break;
  159. default:
  160. self::$_output.="\n".$spaces.'~'.$var;
  161. }
  162. }
  163. }
  164. /**
  165. * Render debug panel to document using view and configuration parameters
  166. */
  167. class yiiDebugPanel
  168. {
  169. public function render($items = array(), $config = array())
  170. {
  171. $msg = "Run rendering...\n";
  172. $alignLeft = isset($config['alignLeft']) ? true : false;
  173. $opaque = isset($config['opaque']) ? true : false;;
  174. $fixedPos = isset($config['fixedPos']) ? true : false;
  175. $collapsed = isset($config['collapsed']) ? true : false;;
  176. $viewFile=dirname(__FILE__).DIRECTORY_SEPARATOR.'views'.DIRECTORY_SEPARATOR.'debugPanel.php';
  177. include(Yii::app()->findLocalizedFile($viewFile,'en'));
  178. }
  179. }
  180. /**
  181. * Parent class for the classes may be used on DebugPanel.
  182. * It have basic grid render and configuration functionality .
  183. */
  184. class yiiDebugClass
  185. {
  186. protected static $_config = array();
  187. public static function timestampToTime($timestamp)
  188. {
  189. return date('H:i:s.',$timestamp).(int)(($timestamp-(int)$timestamp)*1000000);
  190. }
  191. public static function render($items)
  192. {
  193. $result = '';
  194. $odd = true;
  195. foreach ($items as $item)
  196. {
  197. list($message, $level, $category, $timestamp) = $item;
  198. $message = CHtml::encode($message);
  199. // put each source file on its own line
  200. $message = implode("<br/>", explode("\n", $message));
  201. $time=yiiDebugTrace::timestampToTime($timestamp);
  202. $odd = !$odd;
  203. $result .= '<tr'.($odd ? ' class="odd"' : '').'><td>'.$time.'</td><td>'.$level.'</td><td>'.$category.'</td><td>'.$message.'</td></tr>';
  204. }
  205. if ($result !== '') $result = '<tbody>'.$result.'</tbody>';
  206. $result = '<table><thead><tr><th>Time</th><th>Level</th><th>Category</th><th width="100%">Message</th></tr></thead>'.$result.'</table>';
  207. return $result;
  208. }
  209. public static function getInfo($data, $config = null)
  210. {
  211. if (!is_null($config))
  212. {
  213. self::$_config = $config;
  214. }
  215. }
  216. }
  217. class yiiDebugDB extends yiiDebugClass
  218. {
  219. public static function getInfo($data, $config = null)
  220. {
  221. parent::getInfo($data);
  222. $result = array();
  223. $result['panelTitle'] = 'Database Queries';
  224. $count = 0;
  225. $items = array();
  226. foreach ($data as $row)
  227. {
  228. if (substr($row[2],0,9) == 'system.db')
  229. {
  230. $exclude1 = 'Querying SQL: SHOW CREATE TABLE';
  231. $exclude2 = 'Querying SQL: SHOW COLUMNS FROM';
  232. $len1 = strlen($exclude1);
  233. $len2 = strlen($exclude2);
  234. if ($row[2] == 'system.db.CDbCommand'
  235. && strncmp($row[0], $exclude1, $len1) && strncmp($row[0], $exclude2, $len2))
  236. {
  237. $items[] = $row;
  238. $count++;
  239. } elseif ($row[2] != 'system.db.CDbCommand') {
  240. $items[] = $row;
  241. }
  242. }
  243. }
  244. if (count($items) > 0) $result['content'] = yiiDebugTrace::render($items);
  245. $result['title'] = 'DB Query: '.$count;
  246. return $result;
  247. }
  248. }
  249. class yiiDebugTrace extends yiiDebugClass
  250. {
  251. public static function getInfo($data, $config = null)
  252. {
  253. parent::getInfo($data);
  254. $result = array();
  255. $result['title'] = 'App Log';
  256. $result['panelTitle'] = 'Application Log';
  257. $items = array();
  258. foreach ($data as $row)
  259. {
  260. if (substr($row[2],0,9) != 'system.db')
  261. $items[] = $row;
  262. }
  263. if (count($items) > 0) $result['content'] = yiiDebugTrace::render($items);
  264. return $result;
  265. }
  266. }
  267. class yiiDebugTime extends yiiDebugClass
  268. {
  269. public static function getInfo($data, $config = null)
  270. {
  271. parent::getInfo($data);
  272. $result = array();
  273. $result['title'] = 'Time: '.(round(Yii::getLogger()->getExecutionTime(),3));
  274. return $result;
  275. }
  276. }
  277. class yiiDebugMem extends yiiDebugClass
  278. {
  279. public static function getInfo($data, $config = null)
  280. {
  281. parent::getInfo($data);
  282. $result = array();
  283. //round it for two digits after point
  284. $result['title'] = 'Memory: '.(round(Yii::getLogger()->getMemoryUsage() / 1024, 2)).'Kb';
  285. return $result;
  286. }
  287. }
  288. class yiiDebugConfig extends yiiDebugClass
  289. {
  290. public static $yamlStyle = false;
  291. public static function getHeadInfo()
  292. {
  293. $result = '';
  294. $config = array(
  295. 'debug' => (DEFINED('YII_DEBUG') && YII_DEBUG != false) ? 'on' : 'off',
  296. 'xdebug' => extension_loaded('xdebug') ? 'on' : 'off',
  297. 'tokenizer' => function_exists('token_get_all') ? 'on' : 'off',
  298. 'eaccelerator' => extension_loaded('eaccelerator') && ini_get('eaccelerator.enable') ? 'on' : 'off',
  299. 'apc' => extension_loaded('apc') && ini_get('apc.enabled') ? 'on' : 'off',
  300. 'xcache' => extension_loaded('xcache') && ini_get('xcache.cacher') ? 'on' : 'off',
  301. );
  302. $result = '<ul class="yiiDebugInfoInline">';
  303. foreach ($config as $key => $value)
  304. {
  305. $result .= '<li class="is'.$value.'">'.$key.'</li>';
  306. }
  307. $result .= '</ul>';
  308. return $result;
  309. }
  310. public static function sessionAsArray()
  311. {
  312. if (isset($_SESSION))
  313. {
  314. $phpSession = array();
  315. $sessKeyLen = null;
  316. foreach ($_SESSION as $key=>$value)
  317. {
  318. if (is_null($sessKeyLen))
  319. {
  320. $values['PHP']['Key'] = substr($key, 1, strpos($key, '_')-1);
  321. $sessKeyLen = strlen($values['PHP']['Key'])+2;
  322. }
  323. $phpSession[substr($key, $sessKeyLen)] = $value;
  324. }
  325. $values['PHP']['Data'] = $phpSession;
  326. }
  327. if (isset($_COOKIE)) $values['Cookie'] = $_COOKIE;
  328. $values['Yii'] = Yii::app()->session;
  329. return $values;
  330. }
  331. public static function globalsAsArray()
  332. {
  333. $values = array();
  334. foreach (array('server', 'files', 'env') as $name)
  335. {
  336. if (!isset($GLOBALS['_'.strtoupper($name)])) continue;
  337. $values[$name] = array();
  338. foreach ($GLOBALS['_'.strtoupper($name)] as $key => $value)
  339. {
  340. $values[$name][$key] = $value;
  341. }
  342. ksort($values[$name]);
  343. }
  344. ksort($values);
  345. return $values;
  346. }
  347. public static function phpInfoAsArray()
  348. {
  349. $values = array(
  350. 'php' => phpversion(),
  351. 'os' => php_uname(),
  352. 'extensions' => get_loaded_extensions(),
  353. );
  354. // assign extension version
  355. if ($values['extensions'])
  356. {
  357. foreach($values['extensions'] as $key => $extension)
  358. {
  359. $values['extensions'][$key] = phpversion($extension) ? sprintf('%s (%s)', $extension, phpversion($extension)) : $extension;
  360. }
  361. }
  362. return $values;
  363. }
  364. public static function requestAsArray()
  365. {
  366. $values = array();
  367. if (isset($_GET)) $values['Get'] = $_GET;
  368. if (isset($_POST)) $values['Post'] = $_POST;
  369. $values['Yii'] = Yii::app()->request;
  370. return $values;
  371. }
  372. public static function yiiAppAsArray()
  373. {
  374. $result = Yii::app();
  375. return Yii::app();
  376. }
  377. protected static function formatArrayAsHtml($id, $values, $highlight = false)
  378. {
  379. $id = ucfirst(strtolower($id));
  380. return '
  381. <div style="text-align: left" class="yiiDebugInfoList">
  382. <h2> <a href="#" onclick="yiiWebDebugToggleVisible(\'yiiWDCFG'.$id.'\'); return false;">+</a>'.$id.'</h2>'.
  383. //'<div id="yiiWDCFG'.$id.'" style="display: none;"><pre>' .($formatted ? $values : arrayDumper::dump(arrayDumper::removeObjects($values),$highlight)) . '</pre></div></div>';
  384. '<div id="yiiWDCFG'.$id.'" style="display: none;"><pre>' .arrayDumper::dump($values, 10, $highlight, isset(self::$_config['yamlStyle'])) . '</pre></div></div>';
  385. }
  386. public static function getInfo($data, $config = null)
  387. {
  388. parent::getInfo($data, $config);
  389. $result = array();
  390. $result['title'] = 'Yii ver: '.(Yii::getVersion());
  391. $result['headinfo'] = self::getHeadInfo();
  392. $result['panelTitle'] = 'Configuration';
  393. $result['content'] = self::formatArrayAsHtml('globals', self::globalsAsArray(),true);
  394. $result['content'] .= self::formatArrayAsHtml('session', self::sessionAsArray(), true);
  395. $result['content'] .= self::formatArrayAsHtml('php', self::phpInfoAsArray(), true);
  396. $result['content'] .= self::formatArrayAsHtml('request', self::requestAsArray(), true);
  397. $result['content'] .= self::formatArrayAsHtml('Yii::app()', self::YiiAppAsArray() , true);
  398. $result['content'] .= self::formatArrayAsHtml('WebdebugToolbar', self::$_config, true);
  399. return $result;
  400. }
  401. }
  402. /**
  403. * Main class for using inside an Yii application
  404. *
  405. * It processes the logs of running instance of application
  406. * and renders self output to the end of server output (after </html> tag of document).
  407. */
  408. class XWebDebugRouter extends CLogRoute
  409. {
  410. public $config = '';
  411. public $allowedIPs = array('127.0.0.1');
  412. public function collectLogs($logger, $processLogs = false)
  413. {
  414. $logs=$logger->getLogs($this->levels,$this->categories);
  415. if(empty($logs)) $logs = array();
  416. $this->processLogs($logs);
  417. }
  418. public function processLogs($logs)
  419. {
  420. $app=Yii::app();
  421. $config = array();
  422. if (!defined('YII_DEBUG_TB')) return;
  423. if( !in_array($app->request->getUserHostAddress(), $this->allowedIPs) ) return;
  424. foreach (explode(',', $this->config) as $value)
  425. {
  426. $value = trim($value);
  427. $config[$value] = true;
  428. }
  429. //Checking for an AJAX Requests
  430. if(!($app instanceof CWebApplication) || $app->getRequest()->getIsAjaxRequest()) return;
  431. //Checking for an DEBUG mode of running app
  432. if (isset($config['runInDebug']) && (!DEFINED('YII_DEBUG') || YII_DEBUG == false)) return;
  433. $items = array();
  434. $items[] = yiiDebugConfig::getInfo($logs, $config);
  435. $items[] = yiiDebugMem::getInfo($logs);
  436. $items[] = yiiDebugTime::getInfo($logs);
  437. $items[] = yiiDebugDB::getInfo($logs);
  438. $items[] = yiiDebugTrace::getInfo($logs);
  439. $panel = new yiiDebugPanel();
  440. $panel->render($items, $config);
  441. }
  442. }