Debugger.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. <?php
  2. /**
  3. * @package Grav.Common
  4. *
  5. * @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Common;
  9. use DebugBar\DataCollector\ConfigCollector;
  10. use DebugBar\JavascriptRenderer;
  11. use DebugBar\StandardDebugBar;
  12. use Grav\Common\Config\Config;
  13. class Debugger
  14. {
  15. /** @var Grav $grav */
  16. protected $grav;
  17. /** @var Config $config */
  18. protected $config;
  19. /** @var JavascriptRenderer $renderer */
  20. protected $renderer;
  21. /** @var StandardDebugBar $debugbar */
  22. protected $debugbar;
  23. protected $enabled;
  24. protected $timers = [];
  25. /**
  26. * Debugger constructor.
  27. */
  28. public function __construct()
  29. {
  30. // Enable debugger until $this->init() gets called.
  31. $this->enabled = true;
  32. $this->debugbar = new StandardDebugBar();
  33. $this->debugbar['time']->addMeasure('Loading', $this->debugbar['time']->getRequestStartTime(), microtime(true));
  34. }
  35. /**
  36. * Initialize the debugger
  37. *
  38. * @return $this
  39. * @throws \DebugBar\DebugBarException
  40. */
  41. public function init()
  42. {
  43. $this->grav = Grav::instance();
  44. $this->config = $this->grav['config'];
  45. // Enable/disable debugger based on configuration.
  46. $this->enabled = $this->config->get('system.debugger.enabled');
  47. if ($this->enabled()) {
  48. $plugins_config = (array)$this->config->get('plugins');
  49. ksort($plugins_config);
  50. $this->debugbar->addCollector(new ConfigCollector((array)$this->config->get('system'), 'Config'));
  51. $this->debugbar->addCollector(new ConfigCollector($plugins_config, 'Plugins'));
  52. $this->addMessage('Grav v' . GRAV_VERSION);
  53. }
  54. return $this;
  55. }
  56. /**
  57. * Set/get the enabled state of the debugger
  58. *
  59. * @param bool $state If null, the method returns the enabled value. If set, the method sets the enabled state
  60. *
  61. * @return null
  62. */
  63. public function enabled($state = null)
  64. {
  65. if ($state !== null) {
  66. $this->enabled = $state;
  67. }
  68. return $this->enabled;
  69. }
  70. /**
  71. * Add the debugger assets to the Grav Assets
  72. *
  73. * @return $this
  74. */
  75. public function addAssets()
  76. {
  77. if ($this->enabled()) {
  78. // Only add assets if Page is HTML
  79. $page = $this->grav['page'];
  80. if ($page->templateFormat() !== 'html') {
  81. return $this;
  82. }
  83. /** @var Assets $assets */
  84. $assets = $this->grav['assets'];
  85. // Add jquery library
  86. $assets->add('jquery', 101);
  87. $this->renderer = $this->debugbar->getJavascriptRenderer();
  88. $this->renderer->setIncludeVendors(false);
  89. // Get the required CSS files
  90. list($css_files, $js_files) = $this->renderer->getAssets(null, JavascriptRenderer::RELATIVE_URL);
  91. foreach ((array)$css_files as $css) {
  92. $assets->addCss($css);
  93. }
  94. $assets->addCss('/system/assets/debugger.css');
  95. foreach ((array)$js_files as $js) {
  96. $assets->addJs($js);
  97. }
  98. }
  99. return $this;
  100. }
  101. public function getCaller($ignore = 2)
  102. {
  103. $trace = debug_backtrace(false, $ignore);
  104. return array_pop($trace);
  105. }
  106. /**
  107. * Adds a data collector
  108. *
  109. * @param $collector
  110. *
  111. * @return $this
  112. * @throws \DebugBar\DebugBarException
  113. */
  114. public function addCollector($collector)
  115. {
  116. $this->debugbar->addCollector($collector);
  117. return $this;
  118. }
  119. /**
  120. * Returns a data collector
  121. *
  122. * @param $collector
  123. *
  124. * @return \DebugBar\DataCollector\DataCollectorInterface
  125. * @throws \DebugBar\DebugBarException
  126. */
  127. public function getCollector($collector)
  128. {
  129. return $this->debugbar->getCollector($collector);
  130. }
  131. /**
  132. * Displays the debug bar
  133. *
  134. * @return $this
  135. */
  136. public function render()
  137. {
  138. if ($this->enabled()) {
  139. // Only add assets if Page is HTML
  140. $page = $this->grav['page'];
  141. if (!$this->renderer || $page->templateFormat() !== 'html') {
  142. return $this;
  143. }
  144. echo $this->renderer->render();
  145. }
  146. return $this;
  147. }
  148. /**
  149. * Sends the data through the HTTP headers
  150. *
  151. * @return $this
  152. */
  153. public function sendDataInHeaders()
  154. {
  155. if ($this->enabled()) {
  156. $this->debugbar->sendDataInHeaders();
  157. }
  158. return $this;
  159. }
  160. /**
  161. * Returns collected debugger data.
  162. *
  163. * @return array
  164. */
  165. public function getData()
  166. {
  167. if (!$this->enabled()) {
  168. return null;
  169. }
  170. $this->timers = [];
  171. return $this->debugbar->getData();
  172. }
  173. /**
  174. * Start a timer with an associated name and description
  175. *
  176. * @param $name
  177. * @param string|null $description
  178. *
  179. * @return $this
  180. */
  181. public function startTimer($name, $description = null)
  182. {
  183. if ($name[0] === '_' || $this->enabled()) {
  184. $this->debugbar['time']->startMeasure($name, $description);
  185. $this->timers[] = $name;
  186. }
  187. return $this;
  188. }
  189. /**
  190. * Stop the named timer
  191. *
  192. * @param string $name
  193. *
  194. * @return $this
  195. */
  196. public function stopTimer($name)
  197. {
  198. if (in_array($name, $this->timers, true) && ($name[0] === '_' || $this->enabled())) {
  199. $this->debugbar['time']->stopMeasure($name);
  200. }
  201. return $this;
  202. }
  203. /**
  204. * Dump variables into the Messages tab of the Debug Bar
  205. *
  206. * @param $message
  207. * @param string $label
  208. * @param bool $isString
  209. *
  210. * @return $this
  211. */
  212. public function addMessage($message, $label = 'info', $isString = true)
  213. {
  214. if ($this->enabled()) {
  215. $this->debugbar['messages']->addMessage($message, $label, $isString);
  216. }
  217. return $this;
  218. }
  219. /**
  220. * Dump exception into the Messages tab of the Debug Bar
  221. *
  222. * @param \Exception $e
  223. * @return Debugger
  224. */
  225. public function addException(\Exception $e)
  226. {
  227. if ($this->enabled()) {
  228. $this->debugbar['exceptions']->addException($e);
  229. }
  230. return $this;
  231. }
  232. }