PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/app/Plugin/DebugKit/View/Helper/ToolbarHelper.php

https://bitbucket.org/gwhitcher/cakephp-custom-skeleton
PHP | 227 lines | 120 code | 18 blank | 89 comment | 24 complexity | 8646f8fdd6fb651cfeefd89d3f2a4fcb MD5 | raw file
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  10. * @link http://cakephp.org CakePHP(tm) Project
  11. * @package DebugKit.View.Helper
  12. * @since DebugKit 0.1
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. App::uses('DebugKitDebugger', 'DebugKit.Lib');
  16. App::uses('AppHelper', 'View/Helper');
  17. App::uses('ConnectionManager', 'Model');
  18. /**
  19. * Provides Base methods for content specific debug toolbar helpers.
  20. * Acts as a facade for other toolbars helpers as well.
  21. *
  22. * @package DebugKit.View.Helper
  23. * @since DebugKit 0.1
  24. */
  25. class ToolbarHelper extends AppHelper {
  26. /**
  27. * settings property to be overloaded. Subclasses should specify a format
  28. *
  29. * @var array
  30. */
  31. public $settings = array();
  32. /**
  33. * flag for whether or not cache is enabled.
  34. *
  35. * @var boolean
  36. */
  37. protected $_cacheEnabled = false;
  38. /**
  39. * Construct the helper and make the backend helper.
  40. *
  41. * @param $View
  42. * @param array|string $options
  43. * @return \ToolbarHelper
  44. */
  45. public function __construct($View, $options = array()) {
  46. $this->_myName = strtolower(get_class($this));
  47. $this->settings = array_merge($this->settings, $options);
  48. if ($this->_myName !== 'toolbarhelper') {
  49. parent::__construct($View, $options);
  50. return;
  51. }
  52. if (!isset($options['output'])) {
  53. $options['output'] = 'DebugKit.HtmlToolbar';
  54. }
  55. $className = $options['output'];
  56. if (strpos($options['output'], '.') !== false) {
  57. list($plugin, $className) = explode('.', $options['output']);
  58. }
  59. $this->_backEndClassName = $className;
  60. $this->helpers[$options['output']] = $options;
  61. if (isset($options['cacheKey']) && isset($options['cacheConfig'])) {
  62. $this->_cacheKey = $options['cacheKey'];
  63. $this->_cacheConfig = $options['cacheConfig'];
  64. $this->_cacheEnabled = true;
  65. }
  66. parent::__construct($View, $options);
  67. }
  68. /**
  69. * afterLayout callback
  70. *
  71. * @param string $layoutFile
  72. * @return void
  73. */
  74. public function afterLayout($layoutFile) {
  75. if (!$this->request->is('requested')) {
  76. $this->send();
  77. }
  78. }
  79. /**
  80. * Get the name of the backend Helper
  81. * used to conditionally trigger toolbar output
  82. *
  83. * @return string
  84. */
  85. public function getName() {
  86. return $this->_backEndClassName;
  87. }
  88. /**
  89. * call__
  90. *
  91. * Allows method calls on backend helper
  92. *
  93. * @param string $method
  94. * @param mixed $params
  95. * @return mixed|void
  96. */
  97. public function __call($method, $params) {
  98. if (method_exists($this->{$this->_backEndClassName}, $method)) {
  99. return $this->{$this->_backEndClassName}->dispatchMethod($method, $params);
  100. }
  101. }
  102. /**
  103. * Allows for writing to panel cache from view.
  104. * Some panels generate all variables in the view by
  105. * necessity ie. Timer. Using this method, will allow you to replace in full
  106. * the content for a panel.
  107. *
  108. * @param string $name Name of the panel you are replacing.
  109. * @param string $content Content to write to the panel.
  110. * @return boolean Success of write.
  111. */
  112. public function writeCache($name, $content) {
  113. if (!$this->_cacheEnabled) {
  114. return false;
  115. }
  116. $existing = (array)Cache::read($this->_cacheKey, $this->_cacheConfig);
  117. $existing[0][$name]['content'] = $content;
  118. return Cache::write($this->_cacheKey, $existing, $this->_cacheConfig);
  119. }
  120. /**
  121. * Read the toolbar
  122. *
  123. * @param string $name Name of the panel you want cached data for
  124. * @param int $index
  125. * @return mixed Boolean false on failure, array of data otherwise.
  126. */
  127. public function readCache($name, $index = 0) {
  128. if (!$this->_cacheEnabled) {
  129. return false;
  130. }
  131. $existing = (array)Cache::read($this->_cacheKey, $this->_cacheConfig);
  132. if (!isset($existing[$index][$name]['content'])) {
  133. return false;
  134. }
  135. return $existing[$index][$name]['content'];
  136. }
  137. /**
  138. * Gets the query logs for the given connection names.
  139. *
  140. * ### Options
  141. *
  142. * - explain - Whether explain links should be generated for this connection.
  143. * - cache - Whether the toolbar_state Cache should be updated.
  144. * - threshold - The threshold at which a visual 'maybe slow' flag should be added.
  145. * results with rows/ms lower than $threshold will be marked.
  146. *
  147. * @param string $connection Connection name to get logs for.
  148. * @param array $options Options for the query log retrieval.
  149. * @return array Array of data to be converted into a table.
  150. */
  151. public function getQueryLogs($connection, $options = array()) {
  152. $options += array('explain' => false, 'cache' => true, 'threshold' => 20);
  153. $db = ConnectionManager::getDataSource($connection);
  154. if (!method_exists($db, 'getLog')) {
  155. return array();
  156. }
  157. $log = $db->getLog();
  158. $out = array(
  159. 'queries' => array(),
  160. 'count' => $log['count'],
  161. 'time' => $log['time']
  162. );
  163. foreach ($log['log'] as $i => $query) {
  164. $isSlow = (
  165. $query['took'] > 0 &&
  166. $query['numRows'] / $query['took'] != 1 &&
  167. $query['numRows'] / $query['took'] <= $options['threshold']
  168. );
  169. $query['actions'] = '';
  170. $isHtml = ($this->getName() == 'HtmlToolbar');
  171. if ($isSlow && $isHtml) {
  172. $query['actions'] = sprintf(
  173. '<span class="slow-query">%s</span>',
  174. __d('debug_kit', 'maybe slow')
  175. );
  176. } elseif ($isSlow) {
  177. $query['actions'] = '*';
  178. }
  179. if ($options['explain'] && $isHtml) {
  180. $query['actions'] .= $this->explainLink($query['query'], $connection);
  181. }
  182. if ($isHtml) {
  183. $query['query'] = h($query['query']);
  184. if (!empty($query['params']) && is_array($query['params'])) {
  185. $bindParam = $bindType = null;
  186. if (preg_match('/.+ :.+/', $query['query'])) {
  187. $bindType = true;
  188. }
  189. foreach ($query['params'] as $bindKey => $bindVal) {
  190. if ($bindType === true) {
  191. $bindParam .= h($bindKey) ." => " . h($bindVal) . ", ";
  192. } else {
  193. $bindParam .= h($bindVal) . ", ";
  194. }
  195. }
  196. $query['query'] .= " [ " . rtrim($bindParam, ', ') . " ]";
  197. }
  198. }
  199. unset($query['params']);
  200. $out['queries'][] = $query;
  201. }
  202. if ($options['cache']) {
  203. $existing = $this->readCache('sql_log');
  204. $existing[$connection] = $out;
  205. $this->writeCache('sql_log', $existing);
  206. }
  207. return $out;
  208. }
  209. }