Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

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