PageRenderTime 63ms CodeModel.GetById 35ms RepoModel.GetById 1ms app.codeStats 0ms

/classes/Kohana/Debugtoolbar.php

https://github.com/smgladkovskiy/debug-toolbar
PHP | 483 lines | 295 code | 70 blank | 118 comment | 26 complexity | db6554bc7cf1b4fd49904ca011dcdc11 MD5 | raw file
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * Kohana v3 Debug Toolbar
  4. *
  5. * @package Debug Toolbar
  6. * @author Aaron Forsander <http://grimhappy.com/>
  7. * @author Ivan Brotkin (BIakaVeron) <BIakaVeron@gmail.com>
  8. * @author Sergei Gladkovskiy <smgladkovskiy@gmail.com>
  9. */
  10. abstract class Kohana_Debugtoolbar {
  11. /**
  12. * Queries container
  13. *
  14. * @var bool|array
  15. */
  16. protected static $_queries = FALSE;
  17. /**
  18. * Benchmarks container
  19. *
  20. * @var bool|array
  21. */
  22. protected static $_benchmarks = FALSE;
  23. /**
  24. * Custom tabs container
  25. *
  26. * @var array
  27. */
  28. protected static $_custom_tabs = array();
  29. /**
  30. * Can we render toolbar?
  31. *
  32. * @var bool
  33. */
  34. protected static $_enabled = TRUE;
  35. /**
  36. * Benchmark name
  37. *
  38. * @var string
  39. */
  40. public static $benchmark_name = 'debug_toolbar';
  41. /**
  42. * Renders the Debug Toolbar
  43. *
  44. * @static
  45. * @return bool|string
  46. */
  47. public static function render()
  48. {
  49. if ( ! self::is_enabled())
  50. {
  51. return FALSE;
  52. }
  53. $token = Profiler::start('custom', self::$benchmark_name);
  54. $template = new View('toolbar');
  55. $config = Kohana::$config->load('debug_toolbar');
  56. // Database panel
  57. if ($config->panels['database'] === TRUE)
  58. {
  59. $queries = self::get_queries();
  60. $template
  61. ->set('queries', $queries['data'])
  62. ->set('query_count', $queries['count'])
  63. ->set('total_time', $queries['time'])
  64. ->set('total_memory', $queries['memory']);
  65. }
  66. // Files panel
  67. if ($config->panels['files'] === TRUE)
  68. {
  69. $template->set('files', self::get_files());
  70. }
  71. // Modules panel
  72. if ($config->panels['modules'] === TRUE)
  73. {
  74. $template->set('modules', self::get_modules());
  75. }
  76. // Routes panel
  77. if ($config->panels['routes'] === TRUE)
  78. {
  79. $template->set('routes', self::get_routes());
  80. }
  81. // Custom data
  82. if ($config->panels['customs'] === TRUE)
  83. {
  84. $template->set('customs', self::get_customs());
  85. }
  86. // FirePHP
  87. if ($config->firephp_enabled === TRUE)
  88. {
  89. self::firephp();
  90. }
  91. // Set alignment for toolbar
  92. switch ($config->align)
  93. {
  94. case 'right':
  95. case 'center':
  96. case 'left':
  97. $template->set('align', $config->align);
  98. break;
  99. default:
  100. $template->set('align', 'left');
  101. }
  102. // Javascript for toolbar
  103. $template->set('scripts', file_get_contents(Kohana::find_file('views', 'toolbar', 'js')));
  104. // CSS for toolbar
  105. $styles = file_get_contents(Kohana::find_file('views', 'toolbar', 'css'));
  106. Profiler::stop($token);
  107. // Benchmarks panel
  108. if ($config->panels['benchmarks'] === TRUE)
  109. {
  110. $template->set('benchmarks', self::get_benchmarks());
  111. }
  112. $template->set('styles', $styles);
  113. echo $template->render();
  114. }
  115. /**
  116. * Adds custom data to render in a separate tab
  117. *
  118. * @param string $tab_name
  119. * @param mixed $data
  120. *
  121. * @return void
  122. */
  123. public static function add_custom($tab_name, $data)
  124. {
  125. self::$_custom_tabs[$tab_name] = $data;
  126. }
  127. /**
  128. * Get user vars
  129. *
  130. * @return array
  131. */
  132. public static function get_customs()
  133. {
  134. $result = array();
  135. foreach (self::$_custom_tabs as $tab => $data)
  136. {
  137. if (is_array($data) OR is_object($data) OR is_bool($data))
  138. {
  139. $data = Debug::dump($data);
  140. }
  141. $result[$tab] = $data;
  142. }
  143. return $result;
  144. }
  145. /**
  146. * Retrieves query benchmarks from Database
  147. *
  148. * @return array
  149. */
  150. public static function get_queries()
  151. {
  152. if (self::$_queries !== FALSE)
  153. {
  154. return self::$_queries;
  155. }
  156. $result = array();
  157. $count = $time = $memory = 0;
  158. $groups = Profiler::groups();
  159. foreach (Database::$instances as $name => $db)
  160. {
  161. $group_name = 'database ('.strtolower($name).')';
  162. $group = arr::get($groups, $group_name, FALSE);
  163. if ($group)
  164. {
  165. $sub_time = $sub_memory = $sub_count = 0;
  166. foreach ($group as $query => $tokens)
  167. {
  168. $sub_count += count($tokens);
  169. foreach ($tokens as $token)
  170. {
  171. $total = Profiler::total($token);
  172. $sub_time += $total[0];
  173. $sub_memory += $total[1];
  174. $result[$name][] = array(
  175. 'name' => $query,
  176. 'time' => $total[0],
  177. 'memory' => $total[1]
  178. );
  179. }
  180. }
  181. $count += $sub_count;
  182. $time += $sub_time;
  183. $memory += $sub_memory;
  184. $result[$name]['total'] = array($sub_count, $sub_time, $sub_memory);
  185. }
  186. }
  187. self::$_queries = array(
  188. 'count' => $count,
  189. 'time' => $time,
  190. 'memory' => $memory,
  191. 'data' => $result
  192. );
  193. return self::$_queries;
  194. }
  195. /**
  196. * Creates a formatted array of all Benchmarks
  197. *
  198. * @return array formatted benchmarks
  199. */
  200. public static function get_benchmarks()
  201. {
  202. if (Kohana::$profiling == FALSE)
  203. {
  204. return array();
  205. }
  206. if (self::$_benchmarks !== FALSE)
  207. {
  208. return self::$_benchmarks;
  209. }
  210. $groups = Profiler::groups();
  211. $result = array();
  212. foreach (array_keys($groups) as $group)
  213. {
  214. if (strpos($group, 'database (') === FALSE)
  215. {
  216. foreach ($groups[$group] as $name => $marks)
  217. {
  218. $stats = Profiler::stats($marks);
  219. $result[$group][] = array
  220. (
  221. 'name' => $name,
  222. 'count' => count($marks),
  223. 'total_time' => $stats['total']['time'],
  224. 'avg_time' => $stats['average']['time'],
  225. 'total_memory' => $stats['total']['memory'],
  226. 'avg_memory' => $stats['average']['memory'],
  227. );
  228. }
  229. }
  230. }
  231. // add total stats
  232. $total = Profiler::application();
  233. $result['application'] = array
  234. (
  235. 'count' => 1,
  236. 'total_time' => $total['current']['time'],
  237. 'avg_time' => $total['average']['time'],
  238. 'total_memory' => $total['current']['memory'],
  239. 'avg_memory' => $total['average']['memory'],
  240. );
  241. self::$_benchmarks = $result;
  242. return $result;
  243. }
  244. /**
  245. * Get list of included files
  246. *
  247. * @return array file currently included by php
  248. */
  249. public static function get_files()
  250. {
  251. $files = (array)get_included_files();
  252. sort($files);
  253. return $files;
  254. }
  255. /**
  256. * Get module list
  257. *
  258. * @return array module_name => module_path
  259. */
  260. public static function get_modules()
  261. {
  262. return Kohana::modules();
  263. }
  264. /**
  265. * Returns all application routes
  266. *
  267. * @return array
  268. */
  269. public static function get_routes()
  270. {
  271. return Route::all();
  272. }
  273. /**
  274. * Add toolbar data to FirePHP console
  275. *
  276. */
  277. private static function firephp()
  278. {
  279. $firephp = FirePHP::getInstance(TRUE);
  280. $firephp->fb('KOHANA DEBUG TOOLBAR:');
  281. // Globals
  282. $globals = array(
  283. 'Post' => empty($_POST) ? array() : $_POST,
  284. 'Get' => empty($_GET) ? array() : $_GET,
  285. 'Cookie' => empty($_COOKIE) ? array() : $_COOKIE,
  286. 'Session' => empty($_SESSION) ? array() : $_SESSION
  287. );
  288. foreach ($globals as $name => $global)
  289. {
  290. $table = array();
  291. $table[] = array($name, 'Value');
  292. foreach ((array)$global as $key => $value)
  293. {
  294. if (is_object($value))
  295. {
  296. $value = get_class($value).' [object]';
  297. }
  298. $table[] = array($key, $value);
  299. }
  300. $message = "$name: ".count($global).' variables';
  301. $firephp->fb(array($message, $table), FirePHP::TABLE);
  302. }
  303. // Database
  304. $query_stats = self::get_queries();
  305. $table = array();
  306. $table[] = array(
  307. 'DB profile',
  308. 'SQL Statement',
  309. 'Time',
  310. 'Memory'
  311. );
  312. foreach ((array)$query_stats['data'] as $db => $queries)
  313. {
  314. unset($queries['total']);
  315. foreach ($queries as $query)
  316. {
  317. $table[] = array(
  318. $db,
  319. str_replace("\n", ' ', $query['name']),
  320. number_format($query['time'] * 1000, 3),
  321. number_format($query['memory'] / 1024, 3),
  322. );
  323. }
  324. }
  325. $message = 'Queries: '.$query_stats['count'].' SQL queries took '.
  326. number_format($query_stats['time'], 3).' seconds and '.$query_stats['memory'].' b';
  327. $firephp->fb(array($message, $table), FirePHP::TABLE);
  328. // Benchmarks
  329. $groups = self::get_benchmarks();
  330. // application benchmarks
  331. $total = array_pop($groups);
  332. $table = array();
  333. $table[] = array(
  334. 'Group',
  335. 'Benchmark',
  336. 'Count',
  337. 'Time',
  338. 'Memory'
  339. );
  340. foreach ((array)$groups as $group => $benchmarks)
  341. {
  342. foreach ((array)$benchmarks as $name => $benchmark)
  343. {
  344. $table[] = array(
  345. ucfirst($group),
  346. ucwords($benchmark['name']),
  347. number_format($benchmark['total_time'], 3).' s',
  348. Text::bytes($benchmark['total_memory']),
  349. );
  350. }
  351. }
  352. $message = 'Application tooks '.number_format($total['total_time'], 3).' seconds and '.text::bytes($total['total_memory']).' memory';
  353. $firephp->fb(array($message, $table), FirePHP::TABLE);
  354. }
  355. /**
  356. * Disable toolbar
  357. * @static
  358. */
  359. public static function disable()
  360. {
  361. self::$_enabled = FALSE;
  362. }
  363. /**
  364. * Enable toolbar
  365. * @static
  366. */
  367. public static function enable()
  368. {
  369. self::$_enabled = TRUE;
  370. }
  371. /**
  372. * Determines if all the conditions are correct to display the toolbar
  373. * (pretty kludgy, I know)
  374. *
  375. * @static
  376. * @return bool
  377. */
  378. public static function is_enabled()
  379. {
  380. // disabled with Debugtoolbar::disable() call
  381. if (self::$_enabled === FALSE) {
  382. return FALSE;
  383. }
  384. $config = Kohana::$config->load('debug_toolbar');
  385. // Auto render if secret key isset
  386. if ($config->secret_key !== FALSE AND isset($_GET[$config->secret_key]))
  387. {
  388. return TRUE;
  389. }
  390. // Don't auto render when in PRODUCTION (this can obviously be
  391. // overridden by the above secret key)
  392. if (Kohana::$environment == Kohana::PRODUCTION)
  393. {
  394. return FALSE;
  395. }
  396. // Don't auto render toolbar for ajax requests
  397. if (Request::initial() === NULL OR Request::initial()->is_ajax())
  398. {
  399. return FALSE;
  400. }
  401. // Don't auto render toolbar for cli requests
  402. if (PHP_SAPI == 'cli')
  403. {
  404. return FALSE;
  405. }
  406. // Don't auto render toolbar if $_GET['debug'] = 'false'
  407. if (isset($_GET['debug']) AND strtolower($_GET['debug']) == 'false')
  408. {
  409. return FALSE;
  410. }
  411. return TRUE;
  412. }
  413. }