initial commit
This commit is contained in:
16
exp/Plugin/DebugKit/.gitignore
vendored
Normal file
16
exp/Plugin/DebugKit/.gitignore
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
*.diff
|
||||
*.err
|
||||
*.orig
|
||||
*.rej
|
||||
*.swo
|
||||
*.swp
|
||||
*.vi
|
||||
*~
|
||||
.DS_Store
|
||||
.cache
|
||||
.project
|
||||
.settings
|
||||
.svn
|
||||
errors.err
|
||||
tags
|
||||
/nbproject/
|
||||
84
exp/Plugin/DebugKit/.jshintrc
Normal file
84
exp/Plugin/DebugKit/.jshintrc
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
// JSHint Default Configuration File (as on JSHint website)
|
||||
// See http://jshint.com/docs/ for more details
|
||||
|
||||
"maxerr" : 500, // {int} Maximum error before stopping
|
||||
|
||||
// Enforcing
|
||||
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
|
||||
"camelcase" : true, // true: Identifiers must be in camelCase
|
||||
"curly" : true, // true: Require {} for every new block or scope
|
||||
"eqeqeq" : true, // true: Require triple equals (===) for comparison
|
||||
"forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
|
||||
"immed" : true, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
|
||||
"indent" : 2, // {int} Number of spaces to use for indentation
|
||||
"latedef" : false, // true: Require variables/functions to be defined before being used
|
||||
"newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()`
|
||||
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
|
||||
"noempty" : true, // true: Prohibit use of empty blocks
|
||||
"nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment)
|
||||
"plusplus" : false, // true: Prohibit use of `++` & `--`
|
||||
"quotmark" : "single", // Quotation mark consistency:
|
||||
// false : do nothing (default)
|
||||
// true : ensure whatever is used is consistent
|
||||
// "single" : require single quotes
|
||||
// "double" : require double quotes
|
||||
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
|
||||
"unused" : true, // true: Require all defined variables be used
|
||||
"strict" : true, // true: Requires all functions run in ES5 Strict Mode
|
||||
"trailing" : true, // true: Prohibit trailing whitespaces
|
||||
"maxparams" : false, // {int} Max number of formal params allowed per function
|
||||
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
|
||||
"maxstatements" : false, // {int} Max number statements per function
|
||||
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
|
||||
"maxlen" : 120, // {int} Max number of characters per line
|
||||
|
||||
// Relaxing
|
||||
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
|
||||
"boss" : false, // true: Tolerate assignments where comparisons would be expected
|
||||
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
|
||||
"eqnull" : false, // true: Tolerate use of `== null`
|
||||
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
|
||||
"esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
|
||||
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
|
||||
"expr" : false, // true: Tolerate `ExpressionStatement` as Programs
|
||||
"funcscope" : false, // true: Tolerate defining variables inside control statements"
|
||||
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
|
||||
"iterator" : false, // true: Tolerate using the `__iterator__` property
|
||||
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
|
||||
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
|
||||
"laxcomma" : false, // true: Tolerate comma-first style coding
|
||||
"loopfunc" : false, // true: Tolerate functions being defined in loops
|
||||
"multistr" : false, // true: Tolerate multi-line strings
|
||||
"proto" : false, // true: Tolerate using the `__proto__` property
|
||||
"scripturl" : false, // true: Tolerate script-targeted URLs
|
||||
"smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
|
||||
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
|
||||
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
|
||||
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
|
||||
"validthis" : false, // true: Tolerate using this in a non-constructor function
|
||||
|
||||
// Environments
|
||||
"browser" : true, // Web Browser (window, document, etc)
|
||||
"couch" : false, // CouchDB
|
||||
"devel" : true, // Development/debugging (alert, confirm, etc)
|
||||
"dojo" : false, // Dojo Toolkit
|
||||
"jquery" : false, // jQuery
|
||||
"mootools" : false, // MooTools
|
||||
"node" : false, // Node.js
|
||||
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
|
||||
"prototypejs" : false, // Prototype and Scriptaculous
|
||||
"rhino" : false, // Rhino
|
||||
"worker" : false, // Web Workers
|
||||
"wsh" : false, // Windows Scripting Host
|
||||
"yui" : false, // Yahoo User Interface
|
||||
|
||||
// Legacy
|
||||
"nomen" : false, // true: Prohibit dangling `_` in variables
|
||||
"onevar" : false, // true: Allow only one `var` statement per function
|
||||
"passfail" : false, // true: Stop on first error
|
||||
"white" : true, // true: Check against strict whitespace and indentation rules
|
||||
|
||||
// Custom Globals
|
||||
"predef" : [ ] // additional predefined global variables
|
||||
}
|
||||
84
exp/Plugin/DebugKit/.travis.yml
Normal file
84
exp/Plugin/DebugKit/.travis.yml
Normal file
@@ -0,0 +1,84 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
|
||||
env:
|
||||
- CAKE_VERSION=2.3.10 DB=mysql
|
||||
- CAKE_VERSION=2.3.10 DB=pgsql
|
||||
- CAKE_VERSION=2.4.10 DB=mysql
|
||||
- CAKE_VERSION=2.4.10 DB=pgsql
|
||||
- CAKE_VERSION=2.6 DB=mysql
|
||||
- CAKE_VERSION=2.6 DB=pgsql
|
||||
|
||||
install:
|
||||
- git clone git://github.com/cakephp/cakephp ../cakephp && cd ../cakephp && git checkout $CAKE_VERSION
|
||||
- cp -R ../debug_kit plugins/DebugKit
|
||||
- chmod -R 777 ../cakephp/app/tmp
|
||||
- sh -c "composer global require 'phpunit/phpunit=3.7.33'"
|
||||
- sh -c "ln -s ~/.composer/vendor/phpunit/phpunit/PHPUnit ../cakephp/vendors/PHPUnit"
|
||||
|
||||
before_script:
|
||||
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'CREATE DATABASE cakephp_test;'; fi"
|
||||
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi"
|
||||
- set +H
|
||||
- echo "<?php
|
||||
class DATABASE_CONFIG {
|
||||
private \$identities = array(
|
||||
'mysql' => array(
|
||||
'datasource' => 'Database/Mysql',
|
||||
'host' => '0.0.0.0',
|
||||
'login' => 'travis'
|
||||
),
|
||||
'pgsql' => array(
|
||||
'datasource' => 'Database/Postgres',
|
||||
'host' => '127.0.0.1',
|
||||
'login' => 'postgres',
|
||||
'database' => 'cakephp_test',
|
||||
'schema' => array(
|
||||
'default' => 'public',
|
||||
'test' => 'public'
|
||||
)
|
||||
)
|
||||
);
|
||||
public \$default = array(
|
||||
'persistent' => false,
|
||||
'host' => '',
|
||||
'login' => '',
|
||||
'password' => '',
|
||||
'database' => 'cakephp_test',
|
||||
'prefix' => ''
|
||||
);
|
||||
public \$test = array(
|
||||
'persistent' => false,
|
||||
'host' => '',
|
||||
'login' => '',
|
||||
'password' => '',
|
||||
'database' => 'cakephp_test',
|
||||
'prefix' => ''
|
||||
);
|
||||
public function __construct() {
|
||||
\$db = 'mysql';
|
||||
if (!empty(\$_SERVER['DB'])) {
|
||||
\$db = \$_SERVER['DB'];
|
||||
}
|
||||
foreach (array('default', 'test') as \$source) {
|
||||
\$config = array_merge(\$this->{\$source}, \$this->identities[\$db]);
|
||||
if (is_array(\$config['database'])) {
|
||||
\$config['database'] = \$config['database'][\$source];
|
||||
}
|
||||
if (!empty(\$config['schema']) && is_array(\$config['schema'])) {
|
||||
\$config['schema'] = \$config['schema'][\$source];
|
||||
}
|
||||
\$this->{\$source} = \$config;
|
||||
}
|
||||
}
|
||||
}" > ../cakephp/app/Config/database.php
|
||||
|
||||
script:
|
||||
- ./lib/Cake/Console/cake test DebugKit AllDebugKit --stderr
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
159
exp/Plugin/DebugKit/Console/Command/BenchmarkShell.php
Normal file
159
exp/Plugin/DebugKit/Console/Command/BenchmarkShell.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('String', 'Utility');
|
||||
|
||||
/**
|
||||
* Benchmark Shell Class
|
||||
*
|
||||
* Provides basic benchmarking of application requests
|
||||
* functionally similar to Apache AB
|
||||
*
|
||||
* @since DebugKit 1.0
|
||||
* @todo Print/export time detail information
|
||||
* @todo Export/graphing of data to .dot format for graphviz visualization
|
||||
* @todo Make calculated results round to leading significant digit position of std dev.
|
||||
*/
|
||||
class BenchmarkShell extends Shell {
|
||||
|
||||
/**
|
||||
* Main execution of shell
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function main() {
|
||||
$url = $this->args[0];
|
||||
$defaults = array('t' => 100, 'n' => 10);
|
||||
$options = array_merge($defaults, $this->params);
|
||||
$times = array();
|
||||
|
||||
$this->out(String::insert(__d('debug_kit', '-> Testing :url'), compact('url')));
|
||||
$this->out("");
|
||||
for ($i = 0; $i < $options['n']; $i++) {
|
||||
if (floor($options['t'] - array_sum($times)) <= 0 || $options['n'] <= 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
$start = microtime(true);
|
||||
file_get_contents($url);
|
||||
$stop = microtime(true);
|
||||
|
||||
$times[] = $stop - $start;
|
||||
}
|
||||
$this->_results($times);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints calculated results
|
||||
*
|
||||
* @param array $times Array of time values
|
||||
* @return void
|
||||
*/
|
||||
protected function _results($times) {
|
||||
$duration = array_sum($times);
|
||||
$requests = count($times);
|
||||
|
||||
$this->out(String::insert(__d('debug_kit', 'Total Requests made: :requests'), compact('requests')));
|
||||
$this->out(String::insert(__d('debug_kit', 'Total Time elapsed: :duration (seconds)'), compact('duration')));
|
||||
|
||||
$this->out("");
|
||||
|
||||
$this->out(String::insert(__d('debug_kit', 'Requests/Second: :rps req/sec'), array(
|
||||
'rps' => round($requests / $duration, 3)
|
||||
)));
|
||||
|
||||
$this->out(String::insert(__d('debug_kit', 'Average request time: :average-time seconds'), array(
|
||||
'average-time' => round($duration / $requests, 3)
|
||||
)));
|
||||
|
||||
$this->out(String::insert(__d('debug_kit', 'Standard deviation of average request time: :std-dev'), array(
|
||||
'std-dev' => round($this->_deviation($times, true), 3)
|
||||
)));
|
||||
|
||||
$this->out(String::insert(__d('debug_kit', 'Longest/shortest request: :longest sec/:shortest sec'), array(
|
||||
'longest' => round(max($times), 3),
|
||||
'shortest' => round(min($times), 3)
|
||||
)));
|
||||
|
||||
$this->out("");
|
||||
}
|
||||
|
||||
/**
|
||||
* One-pass, numerically stable calculation of population variance.
|
||||
*
|
||||
* Donald E. Knuth (1998).
|
||||
* The Art of Computer Programming, volume 2: Seminumerical Algorithms, 3rd edn.,
|
||||
* p. 232. Boston: Addison-Wesley.
|
||||
*
|
||||
* @param array $times Array of values
|
||||
* @param boolean $sample If true, calculates an unbiased estimate of the population
|
||||
* variance from a finite sample.
|
||||
* @return float Variance
|
||||
*/
|
||||
protected function _variance($times, $sample = true) {
|
||||
$n = $mean = $M2 = 0;
|
||||
|
||||
foreach ($times as $time) {
|
||||
$n += 1;
|
||||
$delta = $time - $mean;
|
||||
$mean = $mean + $delta / $n;
|
||||
$M2 = $M2 + $delta * ($time - $mean);
|
||||
}
|
||||
|
||||
if ($sample) {
|
||||
$n -= 1;
|
||||
}
|
||||
|
||||
return $M2 / $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the standard deviation.
|
||||
*
|
||||
* @param array $times Array of values
|
||||
* @param boolean $sample
|
||||
* @return float Standard deviation
|
||||
*/
|
||||
protected function _deviation($times, $sample = true) {
|
||||
return sqrt($this->_variance($times, $sample));
|
||||
}
|
||||
|
||||
public function getOptionParser() {
|
||||
$parser = parent::getOptionParser();
|
||||
$parser->description(__d('debug_kit',
|
||||
'Allows you to obtain some rough benchmarking statistics' .
|
||||
'about a fully qualified URL.'
|
||||
))
|
||||
->addArgument('url', array(
|
||||
'help' => __d('debug_kit', 'The URL to request.'),
|
||||
'required' => true
|
||||
))
|
||||
->addOption('n', array(
|
||||
'default' => 10,
|
||||
'help' => __d('debug_kit', 'Number of iterations to perform.')
|
||||
))
|
||||
->addOption('t', array(
|
||||
'default' => 100,
|
||||
'help' => __d('debug_kit', 'Maximum total time for all iterations, in seconds.' .
|
||||
'If a single iteration takes more than the timeout, only one request will be made'
|
||||
)
|
||||
))
|
||||
->epilog(__d('debug_kit',
|
||||
'Example Use: `cake benchmark --n 10 --t 100 http://localhost/testsite`. ' .
|
||||
'<info>Note:</info> this benchmark does not include browser render times.'
|
||||
));
|
||||
return $parser;
|
||||
}
|
||||
}
|
||||
|
||||
93
exp/Plugin/DebugKit/Console/Command/WhitespaceShell.php
Normal file
93
exp/Plugin/DebugKit/Console/Command/WhitespaceShell.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.3
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
App::uses('Folder', 'Utility');
|
||||
|
||||
/**
|
||||
* Whitespace shell. Helps find and trim whitespace from files.
|
||||
*
|
||||
* Based on jperras' shell found at http://bin.cakephp.org/view/626544881
|
||||
*
|
||||
* @since DebugKit 1.3
|
||||
*/
|
||||
class WhitespaceShell extends Shell {
|
||||
|
||||
/**
|
||||
* Will check files for whitespace and notify you
|
||||
* of any files containing leading or trailing whitespace.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function main() {
|
||||
$path = APP;
|
||||
if (!empty($this->params['path']) && strpos($this->params['path'], '/') === 0) {
|
||||
$path = $this->params['path'];
|
||||
} elseif (!empty($this->params['path'])) {
|
||||
$path .= $this->params['path'];
|
||||
}
|
||||
$folder = new Folder($path);
|
||||
|
||||
$r = $folder->findRecursive('.*\.php');
|
||||
$this->out("Checking *.php in " . $path);
|
||||
foreach ($r as $file) {
|
||||
$c = file_get_contents($file);
|
||||
if (preg_match('/^[\n\r|\n\r|\n|\r|\s]+\<\?php/', $c)) {
|
||||
$this->out('!!!contains leading whitespaces: ' . $this->shortPath($file));
|
||||
}
|
||||
if (preg_match('/\?\>[\n\r|\n\r|\n|\r|\s]+$/', $c)) {
|
||||
$this->out('!!!contains trailing whitespaces: ' . $this->shortPath($file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Much like main() except files are modified. Be sure to have
|
||||
* backups or use version control.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function trim() {
|
||||
$path = APP;
|
||||
if (!empty($this->params['path']) && strpos($this->params['path'], '/') === 0) {
|
||||
$path = $this->params['path'];
|
||||
} elseif (!empty($this->params['path'])) {
|
||||
$path .= $this->params['path'];
|
||||
}
|
||||
$folder = new Folder($path);
|
||||
|
||||
$r = $folder->findRecursive('.*\.php');
|
||||
$this->out("Checking *.php in " . $path);
|
||||
foreach ($r as $file) {
|
||||
$c = file_get_contents($file);
|
||||
if (preg_match('/^[\n\r|\n\r|\n|\r|\s]+\<\?php/', $c) || preg_match('/\?\>[\n\r|\n\r|\n|\r|\s]+$/', $c)) {
|
||||
$this->out('trimming' . $this->shortPath($file));
|
||||
$c = preg_replace('/^[\n\r|\n\r|\n|\r|\s]+\<\?php/', '<?php', $c);
|
||||
$c = preg_replace('/\?\>[\n\r|\n\r|\n|\r|\s]+$/', '?>', $c);
|
||||
file_put_contents($file, $c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the option parser
|
||||
*
|
||||
* @return ConsoleOptionParser
|
||||
*/
|
||||
public function getOptionParser() {
|
||||
$parser = parent::getOptionParser();
|
||||
return $parser->addOption('path', array(
|
||||
'short' => 'p',
|
||||
'help' => __d('cake_console', 'Absolute path or relative to APP.')
|
||||
));
|
||||
}
|
||||
}
|
||||
504
exp/Plugin/DebugKit/Controller/Component/ToolbarComponent.php
Normal file
504
exp/Plugin/DebugKit/Controller/Component/ToolbarComponent.php
Normal file
@@ -0,0 +1,504 @@
|
||||
<?php
|
||||
/**
|
||||
* DebugKit DebugToolbar Component
|
||||
*
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('CakeLog', 'Log');
|
||||
App::uses('CakeLogInterface', 'Log');
|
||||
App::uses('DebugTimer', 'DebugKit.Lib');
|
||||
App::uses('DebugMemory', 'DebugKit.Lib');
|
||||
App::uses('HelperCollection', 'View');
|
||||
App::uses('CakeEventManager', 'Event');
|
||||
App::uses('CakeEventListener', 'Event');
|
||||
|
||||
/**
|
||||
* Class ToolbarComponent
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class ToolbarComponent extends Component implements CakeEventListener {
|
||||
|
||||
/**
|
||||
* Settings for the Component
|
||||
*
|
||||
* - forceEnable - Force the toolbar to display even if debug == 0. Default = false
|
||||
* - autoRun - Automatically display the toolbar. If set to false, toolbar display can be triggered by adding
|
||||
* `?debug=true` to your URL.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $settings = array(
|
||||
'forceEnable' => false,
|
||||
'autoRun' => true
|
||||
);
|
||||
|
||||
/**
|
||||
* Controller instance reference
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $controller;
|
||||
|
||||
/**
|
||||
* Components used by DebugToolbar
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $components = array('RequestHandler', 'Session');
|
||||
|
||||
/**
|
||||
* The default panels the toolbar uses.
|
||||
* which panels are used can be configured when attaching the component
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_defaultPanels = array(
|
||||
'DebugKit.History',
|
||||
'DebugKit.Session',
|
||||
'DebugKit.Request',
|
||||
'DebugKit.SqlLog',
|
||||
'DebugKit.Timer',
|
||||
'DebugKit.Log',
|
||||
'DebugKit.Variables',
|
||||
'DebugKit.Environment',
|
||||
'DebugKit.Include'
|
||||
);
|
||||
|
||||
/**
|
||||
* Loaded panel objects.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $panels = array();
|
||||
|
||||
/**
|
||||
* javascript files component will be using
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $javascript = array(
|
||||
'libs' => 'DebugKit./js/js_debug_toolbar'
|
||||
);
|
||||
|
||||
/**
|
||||
* CSS files component will be using
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $css = array('DebugKit./css/debug_toolbar.css');
|
||||
|
||||
/**
|
||||
* CacheKey used for the cache file.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $cacheKey = 'toolbar_cache';
|
||||
|
||||
/**
|
||||
* Duration of the debug kit history cache
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $cacheDuration = '+4 hours';
|
||||
|
||||
/**
|
||||
* Status whether component is enable or disable
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $enabled = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* If debug is off the component will be disabled and not do any further time tracking
|
||||
* or load the toolbar helper.
|
||||
*
|
||||
* @param ComponentCollection $collection
|
||||
* @param array $settings
|
||||
* @return \ToolbarComponent
|
||||
*/
|
||||
public function __construct(ComponentCollection $collection, $settings = array()) {
|
||||
$settings = array_merge((array)Configure::read('DebugKit'), $settings);
|
||||
$panels = $this->_defaultPanels;
|
||||
if (isset($settings['panels'])) {
|
||||
$panels = $this->_makePanelList($settings['panels']);
|
||||
unset($settings['panels']);
|
||||
}
|
||||
$this->controller = $collection->getController();
|
||||
|
||||
parent::__construct($collection, array_merge($this->settings, (array)$settings));
|
||||
|
||||
if (
|
||||
!Configure::read('debug') &&
|
||||
empty($this->settings['forceEnable'])
|
||||
) {
|
||||
$this->enabled = false;
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
$this->settings['autoRun'] === false &&
|
||||
!isset($this->controller->request->query['debug'])
|
||||
) {
|
||||
$this->enabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->controller->getEventManager()->attach($this);
|
||||
|
||||
DebugMemory::record(__d('debug_kit', 'Component initialization'));
|
||||
|
||||
$this->cacheKey .= $this->Session->read('Config.userAgent');
|
||||
if (
|
||||
in_array('DebugKit.History', $panels) ||
|
||||
(isset($settings['history']) && $settings['history'] !== false)
|
||||
) {
|
||||
$this->_createCacheConfig();
|
||||
}
|
||||
|
||||
$this->_loadPanels($panels, $settings);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all the timing handlers for core events.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function implementedEvents() {
|
||||
$before = function ($name) {
|
||||
return function () use ($name) {
|
||||
DebugTimer::start($name, $name);
|
||||
};
|
||||
};
|
||||
$after = function ($name) {
|
||||
return function () use ($name) {
|
||||
DebugTimer::stop($name);
|
||||
};
|
||||
};
|
||||
|
||||
return array(
|
||||
'Controller.initialize' => array(
|
||||
array('priority' => 0, 'callable' => $before('Event: Controller.initialize')),
|
||||
array('priority' => 999, 'callable' => $after('Event: Controller.initialize'))
|
||||
),
|
||||
'Controller.startup' => array(
|
||||
array('priority' => 0, 'callable' => $before('Event: Controller.startup')),
|
||||
array('priority' => 999, 'callable' => $after('Event: Controller.startup'))
|
||||
),
|
||||
'Controller.beforeRender' => array(
|
||||
array('priority' => 0, 'callable' => $before('Event: Controller.beforeRender')),
|
||||
array('priority' => 999, 'callable' => $after('Event: Controller.beforeRender'))
|
||||
),
|
||||
'Controller.shutdown' => array(
|
||||
array('priority' => 0, 'callable' => $before('Event: Controller.shutdown')),
|
||||
array('priority' => 999, 'callable' => $after('Event: Controller.shutdown'))
|
||||
),
|
||||
'View.beforeRender' => array(
|
||||
array('priority' => 0, 'callable' => $before('Event: View.beforeRender')),
|
||||
array('priority' => 999, 'callable' => $after('Event: View.beforeRender'))
|
||||
),
|
||||
'View.afterRender' => array(
|
||||
array('priority' => 0, 'callable' => $before('Event: View.afterRender')),
|
||||
array('priority' => 999, 'callable' => $after('Event: View.afterRender'))
|
||||
),
|
||||
'View.beforeLayout' => array(
|
||||
array('priority' => 0, 'callable' => $before('Event: View.beforeLayout')),
|
||||
array('priority' => 999, 'callable' => $after('Event: View.beforeLayout'))
|
||||
),
|
||||
'View.afterLayout' => array(
|
||||
array('priority' => 0, 'callable' => $before('Event: View.afterLayout')),
|
||||
array('priority' => 999, 'callable' => $after('Event: View.afterLayout'))
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize callback.
|
||||
* If automatically disabled, tell component collection about the state.
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return boolean
|
||||
*/
|
||||
public function initialize(Controller $controller) {
|
||||
if (!$this->enabled) {
|
||||
$this->_Collection->disable('Toolbar');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through user panels and remove default panels as indicated.
|
||||
*
|
||||
* @param array $userPanels The list of panels ther user has added removed.
|
||||
* @return array Array of panels to use.
|
||||
*/
|
||||
protected function _makePanelList($userPanels) {
|
||||
$panels = $this->_defaultPanels;
|
||||
foreach ($userPanels as $key => $value) {
|
||||
if (is_numeric($key)) {
|
||||
$panels[] = $value;
|
||||
}
|
||||
if (is_string($key) && $value === false) {
|
||||
$index = array_search($key, $panels);
|
||||
if ($index !== false) {
|
||||
unset($panels[$index]);
|
||||
}
|
||||
// Compatibility for when panels were not
|
||||
// required to have a plugin prefix.
|
||||
$alternate = 'DebugKit.' . ucfirst($key);
|
||||
$index = array_search($alternate, $panels);
|
||||
if ($index !== false) {
|
||||
unset($panels[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $panels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component Startup
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return boolean
|
||||
*/
|
||||
public function startup(Controller $controller) {
|
||||
$panels = array_keys($this->panels);
|
||||
foreach ($panels as $panelName) {
|
||||
$this->panels[$panelName]->startup($controller);
|
||||
}
|
||||
DebugTimer::start(
|
||||
'controllerAction',
|
||||
__d('debug_kit', 'Controller action')
|
||||
);
|
||||
DebugMemory::record(
|
||||
__d('debug_kit', 'Controller action start')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* beforeRedirect callback
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @param $url
|
||||
* @param null $status
|
||||
* @param boolean $exit
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRedirect(Controller $controller, $url, $status = null, $exit = true) {
|
||||
if (!class_exists('DebugTimer')) {
|
||||
return null;
|
||||
}
|
||||
DebugTimer::stop('controllerAction');
|
||||
DebugTimer::start(
|
||||
'processToolbar',
|
||||
__d('debug_kit', 'Processing toolbar state')
|
||||
);
|
||||
$vars = $this->_gatherVars($controller);
|
||||
$this->_saveState($controller, $vars);
|
||||
DebugTimer::stop('processToolbar');
|
||||
}
|
||||
|
||||
/**
|
||||
* beforeRender callback
|
||||
*
|
||||
* Calls beforeRender on all the panels and set the aggregate to the controller.
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
if (!class_exists('DebugTimer')) {
|
||||
return null;
|
||||
}
|
||||
DebugTimer::stop('controllerAction');
|
||||
|
||||
DebugTimer::start(
|
||||
'processToolbar',
|
||||
__d('debug_kit', 'Processing toolbar data')
|
||||
);
|
||||
$vars = $this->_gatherVars($controller);
|
||||
$this->_saveState($controller, $vars);
|
||||
|
||||
$this->javascript = array_unique(array_merge($this->javascript, $vars['javascript']));
|
||||
$this->css = array_unique(array_merge($this->css, $vars['css']));
|
||||
unset($vars['javascript'], $vars['css']);
|
||||
|
||||
$controller->set(array(
|
||||
'debugToolbarPanels' => $vars,
|
||||
'debugToolbarJavascript' => $this->javascript,
|
||||
'debugToolbarCss' => $this->css
|
||||
));
|
||||
|
||||
$isHtml = (
|
||||
!isset($controller->request->params['ext']) ||
|
||||
$controller->request->params['ext'] === 'html'
|
||||
);
|
||||
|
||||
if (!$controller->request->is('ajax') && $isHtml) {
|
||||
$format = 'Html';
|
||||
} else {
|
||||
$format = 'FirePhp';
|
||||
}
|
||||
|
||||
$controller->helpers[] = 'DebugKit.DebugTimer';
|
||||
$controller->helpers['DebugKit.Toolbar'] = array(
|
||||
'output' => sprintf('DebugKit.%sToolbar', $format),
|
||||
'cacheKey' => $this->cacheKey,
|
||||
'cacheConfig' => 'debug_kit',
|
||||
'forceEnable' => $this->settings['forceEnable'],
|
||||
);
|
||||
|
||||
DebugTimer::stop('processToolbar');
|
||||
DebugMemory::record(__d('debug_kit', 'Controller render start'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a toolbar state from cache
|
||||
*
|
||||
* @param integer $key
|
||||
* @return array
|
||||
*/
|
||||
public function loadState($key) {
|
||||
$history = Cache::read($this->cacheKey, 'debug_kit');
|
||||
if (isset($history[$key])) {
|
||||
return $history[$key];
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the cache config for the history
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _createCacheConfig() {
|
||||
if (Configure::read('Cache.disable') === true || Cache::config('debug_kit')) {
|
||||
return;
|
||||
}
|
||||
$cache = array(
|
||||
'duration' => $this->cacheDuration,
|
||||
'engine' => 'File',
|
||||
'path' => CACHE
|
||||
);
|
||||
if (isset($this->settings['cache'])) {
|
||||
$cache = array_merge($cache, $this->settings['cache']);
|
||||
}
|
||||
Cache::config('debug_kit', $cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* collects the panel contents
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return array Array of all panel beforeRender()
|
||||
*/
|
||||
protected function _gatherVars(Controller $controller) {
|
||||
$vars = array('javascript' => array(), 'css' => array());
|
||||
$panels = array_keys($this->panels);
|
||||
|
||||
foreach ($panels as $panelName) {
|
||||
$panel = $this->panels[$panelName];
|
||||
$panelName = Inflector::underscore($panelName);
|
||||
$vars[$panelName]['content'] = $panel->beforeRender($controller);
|
||||
$elementName = Inflector::underscore($panelName) . '_panel';
|
||||
if (isset($panel->elementName)) {
|
||||
$elementName = $panel->elementName;
|
||||
}
|
||||
$vars[$panelName]['elementName'] = $elementName;
|
||||
$vars[$panelName]['plugin'] = $panel->plugin;
|
||||
$vars[$panelName]['title'] = $panel->title;
|
||||
$vars[$panelName]['disableTimer'] = true;
|
||||
|
||||
if (!empty($panel->javascript)) {
|
||||
$vars['javascript'] = array_merge($vars['javascript'], (array)$panel->javascript);
|
||||
}
|
||||
if (!empty($panel->css)) {
|
||||
$vars['css'] = array_merge($vars['css'], (array)$panel->css);
|
||||
}
|
||||
}
|
||||
return $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Panels used in the debug toolbar
|
||||
*
|
||||
* @param $panels
|
||||
* @param $settings
|
||||
* @return void
|
||||
*/
|
||||
protected function _loadPanels($panels, $settings) {
|
||||
foreach ($panels as $panel) {
|
||||
$className = ucfirst($panel) . 'Panel';
|
||||
list($plugin, $className) = pluginSplit($className, true);
|
||||
|
||||
App::uses($className, $plugin . 'Panel');
|
||||
if (!class_exists($className)) {
|
||||
trigger_error(__d('debug_kit', 'Could not load DebugToolbar panel %s', $panel), E_USER_WARNING);
|
||||
continue;
|
||||
}
|
||||
$panelObj = new $className($settings);
|
||||
if ($panelObj instanceof DebugPanel) {
|
||||
list(, $panel) = pluginSplit($panel);
|
||||
$this->panels[Inflector::underscore($panel)] = $panelObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current state of the toolbar varibles to the cache file.
|
||||
*
|
||||
* @param \Controller|object $controller Controller instance
|
||||
* @param array $vars Vars to save.
|
||||
* @return void
|
||||
*/
|
||||
protected function _saveState(Controller $controller, $vars) {
|
||||
$config = Cache::config('debug_kit');
|
||||
if (empty($config) || !isset($this->panels['history'])) {
|
||||
return;
|
||||
}
|
||||
$history = Cache::read($this->cacheKey, 'debug_kit');
|
||||
if (empty($history)) {
|
||||
$history = array();
|
||||
}
|
||||
if (count($history) == $this->panels['history']->history) {
|
||||
array_pop($history);
|
||||
}
|
||||
|
||||
if (isset($vars['variables']['content'])) {
|
||||
// Remove unserializable native objects.
|
||||
array_walk_recursive($vars['variables']['content'], function (&$item) {
|
||||
if (
|
||||
$item instanceof Closure ||
|
||||
$item instanceof PDO ||
|
||||
$item instanceof SimpleXmlElement
|
||||
) {
|
||||
$item = 'Unserializable object - ' . get_class($item);
|
||||
} elseif ($item instanceof Exception) {
|
||||
$item = sprintf(
|
||||
'Unserializable object - %s. Error: %s in %s, line %s',
|
||||
get_class($item),
|
||||
$item,
|
||||
$item->getMessage(),
|
||||
$item->getFile(),
|
||||
$item->getLine()
|
||||
);
|
||||
}
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
unset($vars['history']);
|
||||
array_unshift($history, $vars);
|
||||
Cache::write($this->cacheKey, $history, 'debug_kit');
|
||||
}
|
||||
|
||||
}
|
||||
25
exp/Plugin/DebugKit/Controller/DebugKitAppController.php
Normal file
25
exp/Plugin/DebugKit/Controller/DebugKitAppController.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('Controller', 'Controller');
|
||||
App::uses('AppController', 'Controller');
|
||||
|
||||
/**
|
||||
* Class DebugKitAppController
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class DebugKitAppController extends AppController {
|
||||
|
||||
}
|
||||
121
exp/Plugin/DebugKit/Controller/ToolbarAccessController.php
Normal file
121
exp/Plugin/DebugKit/Controller/ToolbarAccessController.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('Security', 'Utility');
|
||||
App::uses('DebugKitAppController', 'DebugKit.Controller');
|
||||
|
||||
/**
|
||||
* DebugKit ToolbarAccess Controller
|
||||
*
|
||||
* Allows retrieval of information from the debugKit internals.
|
||||
*
|
||||
* @since DebugKit 1.1
|
||||
*/
|
||||
class ToolbarAccessController extends DebugKitAppController {
|
||||
|
||||
/**
|
||||
* name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name = 'ToolbarAccess';
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $helpers = array(
|
||||
'DebugKit.Toolbar' => array('output' => 'DebugKit.HtmlToolbar'),
|
||||
'Js', 'Number', 'DebugKit.SimpleGraph'
|
||||
);
|
||||
|
||||
/**
|
||||
* Components
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $components = array('RequestHandler', 'DebugKit.Toolbar');
|
||||
|
||||
/**
|
||||
* Uses
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $uses = array('DebugKit.ToolbarAccess');
|
||||
|
||||
/**
|
||||
* beforeFilter callback
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
if (isset($this->Toolbar)) {
|
||||
$this->Components->disable('Toolbar');
|
||||
}
|
||||
$this->helpers['DebugKit.Toolbar']['cacheKey'] = $this->Toolbar->cacheKey;
|
||||
$this->helpers['DebugKit.Toolbar']['cacheConfig'] = 'debug_kit';
|
||||
|
||||
if (isset($this->Auth) && method_exists($this->Auth, 'mapActions')) {
|
||||
$this->Auth->mapActions(array(
|
||||
'read' => array('history_state', 'sql_explain')
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a stored history state from the toolbar cache.
|
||||
*
|
||||
* @param null $key
|
||||
* @return void
|
||||
*/
|
||||
public function history_state($key = null) {
|
||||
if (Configure::read('debug') == 0) {
|
||||
return $this->redirect($this->referer());
|
||||
}
|
||||
$oldState = $this->Toolbar->loadState($key);
|
||||
$this->set('toolbarState', $oldState);
|
||||
$this->set('debugKitInHistoryMode', true);
|
||||
$this->viewClass = null;
|
||||
$this->layout = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run SQL explain/profiling on queries. Checks the hash + the hashed queries,
|
||||
* if there is mismatch a 404 will be rendered. If debug == 0 a 404 will also be
|
||||
* rendered. No explain will be run if a 404 is made.
|
||||
*
|
||||
* @throws BadRequestException
|
||||
* @return void
|
||||
*/
|
||||
public function sql_explain() {
|
||||
if (
|
||||
!$this->request->is('post') ||
|
||||
empty($this->request->data['log']['sql']) ||
|
||||
empty($this->request->data['log']['ds']) ||
|
||||
empty($this->request->data['log']['hash']) ||
|
||||
Configure::read('debug') == 0
|
||||
) {
|
||||
throw new BadRequestException('Invalid parameters');
|
||||
}
|
||||
$hash = Security::hash($this->request->data['log']['sql'] . $this->request->data['log']['ds'], 'sha1', true);
|
||||
if ($hash !== $this->request->data['log']['hash']) {
|
||||
throw new BadRequestException('Invalid parameters');
|
||||
}
|
||||
$result = $this->ToolbarAccess->explainQuery($this->request->data['log']['ds'], $this->request->data['log']['sql']);
|
||||
$this->set(compact('result'));
|
||||
}
|
||||
|
||||
}
|
||||
28
exp/Plugin/DebugKit/LICENSE.txt
Normal file
28
exp/Plugin/DebugKit/LICENSE.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
The MIT License
|
||||
|
||||
CakePHP(tm) : The Rapid Development PHP Framework (http://cakephp.org)
|
||||
Copyright (c) 2005-2015, Cake Software Foundation, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Cake Software Foundation, Inc.
|
||||
1785 E. Sahara Avenue,
|
||||
Suite 490-204
|
||||
Las Vegas, Nevada 89104,
|
||||
United States of America.
|
||||
227
exp/Plugin/DebugKit/Lib/DebugKitDebugger.php
Normal file
227
exp/Plugin/DebugKit/Lib/DebugKitDebugger.php
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('Debugger', 'Utility');
|
||||
App::uses('FireCake', 'DebugKit.Lib');
|
||||
App::uses('DebugTimer', 'DebugKit.Lib');
|
||||
App::uses('DebugMemory', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* DebugKit Temporary Debugger Class
|
||||
*
|
||||
* Provides the future features that are planned. Yet not implemented in the 1.2 code base
|
||||
*
|
||||
* This file will not be needed in future version of CakePHP.
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class DebugKitDebugger extends Debugger {
|
||||
|
||||
/**
|
||||
* destruct method
|
||||
*
|
||||
* Allow timer info to be displayed if the code dies or is being debugged before rendering the view
|
||||
* Cheat and use the debug log class for formatting
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct() {
|
||||
$timers = DebugTimer::getAll();
|
||||
if (Configure::read('debug') < 2 || count($timers) > 0) {
|
||||
return;
|
||||
}
|
||||
$timers = array_values($timers);
|
||||
$end = end($timers);
|
||||
echo '<table class="cake-sql-log"><tbody>';
|
||||
echo '<caption>Debug timer info</caption>';
|
||||
echo '<tr><th>Message</th><th>Start Time (ms)</th><th>End Time (ms)</th><th>Duration (ms)</th></tr>';
|
||||
$i = 0;
|
||||
foreach ($timers as $timer) {
|
||||
$indent = 0;
|
||||
for ($j = 0; $j < $i; $j++) {
|
||||
if (($timers[$j]['end']) > ($timer['start']) && ($timers[$j]['end']) > ($timer['end'])) {
|
||||
$indent++;
|
||||
}
|
||||
}
|
||||
$indent = str_repeat(' » ', $indent);
|
||||
|
||||
extract($timer);
|
||||
$start = round($start * 1000, 0);
|
||||
$end = round($end * 1000, 0);
|
||||
$time = round($time * 1000, 0);
|
||||
echo "<tr><td>{$indent}$message</td><td>$start</td><td>$end</td><td>$time</td></tr>";
|
||||
$i++;
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an benchmarking timer.
|
||||
*
|
||||
* @param string $name The name of the timer to start.
|
||||
* @param string $message A message for your timer
|
||||
* @return boolean true
|
||||
* @deprecated use DebugTimer::start()
|
||||
*/
|
||||
public static function startTimer($name = null, $message = null) {
|
||||
return DebugTimer::start($name, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a benchmarking timer.
|
||||
*
|
||||
* $name should be the same as the $name used in startTimer().
|
||||
*
|
||||
* @param string $name The name of the timer to end.
|
||||
* @return boolean true if timer was ended, false if timer was not started.
|
||||
* @deprecated use DebugTimer::stop()
|
||||
*/
|
||||
public static function stopTimer($name = null) {
|
||||
return DebugTimer::stop($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all timers that have been started and stopped.
|
||||
* Calculates elapsed time for each timer. If clear is true, will delete existing timers
|
||||
*
|
||||
* @param boolean $clear false
|
||||
* @return array
|
||||
* @deprecated use DebugTimer::getAll()
|
||||
*/
|
||||
public static function getTimers($clear = false) {
|
||||
return DebugTimer::getAll($clear);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all existing timers
|
||||
*
|
||||
* @return boolean true
|
||||
* @deprecated use DebugTimer::clear()
|
||||
*/
|
||||
public static function clearTimers() {
|
||||
return DebugTimer::clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the difference in time between the timer start and timer end.
|
||||
*
|
||||
* @param $name string the name of the timer you want elapsed time for.
|
||||
* @param $precision int the number of decimal places to return, defaults to 5.
|
||||
* @return float number of seconds elapsed for timer name, 0 on missing key
|
||||
* @deprecated use DebugTimer::elapsedTime()
|
||||
*/
|
||||
public static function elapsedTime($name = 'default', $precision = 5) {
|
||||
return DebugTimer::elapsedTime($name, $precision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total execution time until this point
|
||||
*
|
||||
* @return float elapsed time in seconds since script start.
|
||||
* @deprecated use DebugTimer::requestTime()
|
||||
*/
|
||||
public static function requestTime() {
|
||||
return DebugTimer::requestTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the time the current request started.
|
||||
*
|
||||
* @return float time of request start
|
||||
* @deprecated use DebugTimer::requestStartTime()
|
||||
*/
|
||||
public static function requestStartTime() {
|
||||
return DebugTimer::requestStartTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* get current memory usage
|
||||
*
|
||||
* @return integer number of bytes ram currently in use. 0 if memory_get_usage() is not available.
|
||||
* @deprecated Use DebugMemory::getCurrent() instead.
|
||||
*/
|
||||
public static function getMemoryUse() {
|
||||
return DebugMemory::getCurrent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get peak memory use
|
||||
*
|
||||
* @return integer peak memory use (in bytes). Returns 0 if memory_get_peak_usage() is not available
|
||||
* @deprecated Use DebugMemory::getPeak() instead.
|
||||
*/
|
||||
public static function getPeakMemoryUse() {
|
||||
return DebugMemory::getPeak();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a memory point in the internal tracker.
|
||||
* Takes a optional message name which can be used to identify the memory point.
|
||||
* If no message is supplied a debug_backtrace will be done to identifty the memory point.
|
||||
* If you don't have memory_get_xx methods this will not work.
|
||||
*
|
||||
* @param string $message Message to identify this memory point.
|
||||
* @return boolean
|
||||
* @deprecated Use DebugMemory::getAll() instead.
|
||||
*/
|
||||
public static function setMemoryPoint($message = null) {
|
||||
return DebugMemory::record($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the stored memory points
|
||||
*
|
||||
* @param boolean $clear Whether you want to clear the memory points as well. Defaults to false.
|
||||
* @return array Array of memory marks stored so far.
|
||||
* @deprecated Use DebugMemory::getAll() instead.
|
||||
*/
|
||||
public static function getMemoryPoints($clear = false) {
|
||||
return DebugMemory::getAll($clear);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear out any existing memory points
|
||||
*
|
||||
* @return void
|
||||
* @deprecated Use DebugMemory::clear() instead.
|
||||
*/
|
||||
public static function clearMemoryPoints() {
|
||||
DebugMemory::clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FirePHP error message
|
||||
*
|
||||
* @param array $data Data of the error
|
||||
* @param array $links Links for the error
|
||||
* @return void
|
||||
*/
|
||||
public static function fireError($data, $links) {
|
||||
$name = $data['error'] . ' - ' . $data['description'];
|
||||
$message = "{$data['error']} {$data['code']} {$data['description']} on line: {$data['line']} in file: {$data['file']}";
|
||||
FireCake::group($name);
|
||||
FireCake::error($message, $name);
|
||||
if (isset($data['context'])) {
|
||||
FireCake::log($data['context'], 'Context');
|
||||
}
|
||||
if (isset($data['trace'])) {
|
||||
FireCake::log(preg_split('/[\r\n]+/', $data['trace']), 'Trace');
|
||||
}
|
||||
FireCake::groupEnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DebugKitDebugger::getInstance('DebugKitDebugger');
|
||||
Debugger::addFormat('fb', array('callback' => 'DebugKitDebugger::fireError'));
|
||||
98
exp/Plugin/DebugKit/Lib/DebugMemory.php
Normal file
98
exp/Plugin/DebugKit/Lib/DebugMemory.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 2.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('Debugger', 'Utility');
|
||||
|
||||
/**
|
||||
* Contains methods for Profiling memory usage.
|
||||
*
|
||||
*/
|
||||
class DebugMemory {
|
||||
|
||||
/**
|
||||
* An array of recorded memory use points.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $_points = array();
|
||||
|
||||
/**
|
||||
* Get current memory usage
|
||||
*
|
||||
* @return integer number of bytes ram currently in use. 0 if memory_get_usage() is not available.
|
||||
*/
|
||||
public static function getCurrent() {
|
||||
return memory_get_usage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get peak memory use
|
||||
*
|
||||
* @return integer peak memory use (in bytes). Returns 0 if memory_get_peak_usage() is not available
|
||||
*/
|
||||
public static function getPeak() {
|
||||
return memory_get_peak_usage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a memory point in the internal tracker.
|
||||
* Takes a optional message name which can be used to identify the memory point.
|
||||
* If no message is supplied a debug_backtrace will be done to identify the memory point.
|
||||
*
|
||||
* @param string $message Message to identify this memory point.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function record($message = null) {
|
||||
$memoryUse = self::getCurrent();
|
||||
if (!$message) {
|
||||
$named = false;
|
||||
$trace = debug_backtrace();
|
||||
$message = Debugger::trimpath($trace[0]['file']) . ' line ' . $trace[0]['line'];
|
||||
}
|
||||
if (isset(self::$_points[$message])) {
|
||||
$originalMessage = $message;
|
||||
$i = 1;
|
||||
while (isset(self::$_points[$message])) {
|
||||
$i++;
|
||||
$message = $originalMessage . ' #' . $i;
|
||||
}
|
||||
}
|
||||
self::$_points[$message] = $memoryUse;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the stored memory points
|
||||
*
|
||||
* @param boolean $clear Whether you want to clear the memory points as well. Defaults to false.
|
||||
* @return array Array of memory marks stored so far.
|
||||
*/
|
||||
public static function getAll($clear = false) {
|
||||
$marks = self::$_points;
|
||||
if ($clear) {
|
||||
self::$_points = array();
|
||||
}
|
||||
return $marks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear out any existing memory points
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clear() {
|
||||
self::$_points = array();
|
||||
}
|
||||
|
||||
}
|
||||
84
exp/Plugin/DebugKit/Lib/DebugPanel.php
Normal file
84
exp/Plugin/DebugKit/Lib/DebugPanel.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for debug panels.
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class DebugPanel {
|
||||
|
||||
/**
|
||||
* Defines which plugin this panel is from so the element can be located.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $plugin = 'DebugKit';
|
||||
|
||||
/**
|
||||
* Defines the title for displaying on the toolbar. If null, the class name will be used.
|
||||
* Overriding this allows you to define a custom name in the toolbar.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $title = null;
|
||||
|
||||
/**
|
||||
* Panel's css files
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $css = array();
|
||||
|
||||
/**
|
||||
* Panel's javascript files
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $javascript = array();
|
||||
|
||||
/**
|
||||
* Provide a custom element name for this panel. If null, the underscored version of the class
|
||||
* name will be used.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $elementName = null;
|
||||
|
||||
/**
|
||||
* Empty constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* startup the panel
|
||||
*
|
||||
* Pull information from the controller / request
|
||||
*
|
||||
* @param \Controller|object $controller Controller reference.
|
||||
* @return void
|
||||
*/
|
||||
public function startup(Controller $controller) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare output vars before Controller Rendering.
|
||||
*
|
||||
* @param \Controller|object $controller Controller reference.
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
}
|
||||
}
|
||||
201
exp/Plugin/DebugKit/Lib/DebugTimer.php
Normal file
201
exp/Plugin/DebugKit/Lib/DebugTimer.php
Normal file
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('Debugger', 'Utility');
|
||||
|
||||
/**
|
||||
* Contains methods for Profiling and creating timers.
|
||||
*
|
||||
*/
|
||||
class DebugTimer {
|
||||
|
||||
/**
|
||||
* Internal timers array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $_timers = array();
|
||||
|
||||
/**
|
||||
* Start an benchmarking timer.
|
||||
*
|
||||
* @param string $name The name of the timer to start.
|
||||
* @param string $message A message for your timer
|
||||
* @return boolean Always true
|
||||
*/
|
||||
public static function start($name = null, $message = null) {
|
||||
$start = microtime(true);
|
||||
|
||||
if (!$name) {
|
||||
$named = false;
|
||||
$calledFrom = debug_backtrace();
|
||||
$_name = $name = Debugger::trimpath($calledFrom[0]['file']) . ' line ' . $calledFrom[0]['line'];
|
||||
} else {
|
||||
$named = true;
|
||||
}
|
||||
|
||||
if (!$message) {
|
||||
$message = $name;
|
||||
}
|
||||
|
||||
$_name = $name;
|
||||
$i = 1;
|
||||
while (isset(self::$_timers[$name])) {
|
||||
$i++;
|
||||
$name = $_name . ' #' . $i;
|
||||
}
|
||||
|
||||
if ($i > 1) {
|
||||
$message .= ' #' . $i;
|
||||
}
|
||||
|
||||
self::$_timers[$name] = array(
|
||||
'start' => $start,
|
||||
'message' => $message,
|
||||
'named' => $named
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a benchmarking timer.
|
||||
*
|
||||
* $name should be the same as the $name used in startTimer().
|
||||
*
|
||||
* @param string $name The name of the timer to end.
|
||||
* @return boolean true if timer was ended, false if timer was not started.
|
||||
*/
|
||||
public static function stop($name = null) {
|
||||
$end = microtime(true);
|
||||
if (!$name) {
|
||||
$names = array_reverse(array_keys(self::$_timers));
|
||||
foreach ($names as $name) {
|
||||
if (!empty(self::$_timers[$name]['end'])) {
|
||||
continue;
|
||||
}
|
||||
if (empty(self::$_timers[$name]['named'])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$i = 1;
|
||||
$_name = $name;
|
||||
while (isset(self::$_timers[$name])) {
|
||||
if (empty(self::$_timers[$name]['end'])) {
|
||||
break;
|
||||
}
|
||||
$i++;
|
||||
$name = $_name . ' #' . $i;
|
||||
}
|
||||
}
|
||||
if (!isset(self::$_timers[$name])) {
|
||||
return false;
|
||||
}
|
||||
self::$_timers[$name]['end'] = $end;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all timers that have been started and stopped.
|
||||
* Calculates elapsed time for each timer. If clear is true, will delete existing timers
|
||||
*
|
||||
* @param boolean $clear false
|
||||
* @return array
|
||||
*/
|
||||
public static function getAll($clear = false) {
|
||||
$start = self::requestStartTime();
|
||||
$now = microtime(true);
|
||||
|
||||
$times = array();
|
||||
if (!empty(self::$_timers)) {
|
||||
$firstTimer = reset(self::$_timers);
|
||||
$_end = $firstTimer['start'];
|
||||
} else {
|
||||
$_end = $now;
|
||||
}
|
||||
$times['Core Processing (Derived from $_SERVER["REQUEST_TIME"])'] = array(
|
||||
'message' => __d('debug_kit', 'Core Processing (Derived from $_SERVER["REQUEST_TIME"])'),
|
||||
'start' => 0,
|
||||
'end' => $_end - $start,
|
||||
'time' => round($_end - $start, 6),
|
||||
'named' => null
|
||||
);
|
||||
foreach (self::$_timers as $name => $timer) {
|
||||
if (!isset($timer['end'])) {
|
||||
$timer['end'] = $now;
|
||||
}
|
||||
$times[$name] = array_merge($timer, array(
|
||||
'start' => $timer['start'] - $start,
|
||||
'end' => $timer['end'] - $start,
|
||||
'time' => self::elapsedTime($name)
|
||||
));
|
||||
}
|
||||
if ($clear) {
|
||||
self::$_timers = array();
|
||||
}
|
||||
return $times;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all existing timers
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
public static function clear() {
|
||||
self::$_timers = array();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the difference in time between the timer start and timer end.
|
||||
*
|
||||
* @param $name string the name of the timer you want elapsed time for.
|
||||
* @param $precision int the number of decimal places to return, defaults to 5.
|
||||
* @return float number of seconds elapsed for timer name, 0 on missing key
|
||||
*/
|
||||
public static function elapsedTime($name = 'default', $precision = 5) {
|
||||
if (!isset(self::$_timers[$name]['start']) || !isset(self::$_timers[$name]['end'])) {
|
||||
return 0;
|
||||
}
|
||||
return round(self::$_timers[$name]['end'] - self::$_timers[$name]['start'], $precision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total execution time until this point
|
||||
*
|
||||
* @return float elapsed time in seconds since script start.
|
||||
*/
|
||||
public static function requestTime() {
|
||||
$start = self::requestStartTime();
|
||||
$now = microtime(true);
|
||||
return ($now - $start);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the time the current request started.
|
||||
*
|
||||
* @return float time of request start
|
||||
*/
|
||||
public static function requestStartTime() {
|
||||
if (defined('TIME_START')) {
|
||||
$startTime = TIME_START;
|
||||
} elseif (isset($GLOBALS['TIME_START'])) {
|
||||
$startTime = $GLOBALS['TIME_START'];
|
||||
} else {
|
||||
$startTime = env('REQUEST_TIME');
|
||||
}
|
||||
return $startTime;
|
||||
}
|
||||
|
||||
}
|
||||
538
exp/Plugin/DebugKit/Lib/FireCake.php
Normal file
538
exp/Plugin/DebugKit/Lib/FireCake.php
Normal file
@@ -0,0 +1,538 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('Debugger', 'Utility');
|
||||
|
||||
if (!function_exists('firecake')) {
|
||||
|
||||
/**
|
||||
* Procedural version of FireCake::log()
|
||||
*
|
||||
* @param $message
|
||||
* @param null $label
|
||||
*/
|
||||
function firecake($message, $label = null) {
|
||||
FireCake::fb($message, $label, 'log');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* FirePHP Class for CakePHP
|
||||
*
|
||||
* Provides most of the functionality offered by FirePHPCore
|
||||
* Interoperates with FirePHP extension for Firefox
|
||||
*
|
||||
* For more information see: http://www.firephp.org/
|
||||
*
|
||||
*/
|
||||
class FireCake {
|
||||
|
||||
/**
|
||||
* Options for FireCake.
|
||||
*
|
||||
* @see _defaultOptions and setOptions();
|
||||
* @var string
|
||||
*/
|
||||
public $options = array();
|
||||
|
||||
/**
|
||||
* Default Options used in CakeFirePhp
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_defaultOptions = array(
|
||||
'maxObjectDepth' => 10,
|
||||
'maxArrayDepth' => 20,
|
||||
'useNativeJsonEncode' => true,
|
||||
'includeLineNumbers' => true,
|
||||
);
|
||||
|
||||
/**
|
||||
* Message Levels for messages sent via FirePHP
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_levels = array(
|
||||
'log' => 'LOG',
|
||||
'info' => 'INFO',
|
||||
'warn' => 'WARN',
|
||||
'error' => 'ERROR',
|
||||
'dump' => 'DUMP',
|
||||
'trace' => 'TRACE',
|
||||
'exception' => 'EXCEPTION',
|
||||
'table' => 'TABLE',
|
||||
'groupStart' => 'GROUP_START',
|
||||
'groupEnd' => 'GROUP_END',
|
||||
);
|
||||
|
||||
/**
|
||||
* Version number for X-Wf-1-Plugin-1 HTML header
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_version = '0.2.1';
|
||||
|
||||
/**
|
||||
* internal messageIndex counter
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $_messageIndex = 1;
|
||||
|
||||
/**
|
||||
* stack of objects encoded by stringEncode()
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_encodedObjects = array();
|
||||
|
||||
/**
|
||||
* methodIndex to include in tracebacks when using includeLineNumbers
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_methodIndex = array('info', 'log', 'warn', 'error', 'table', 'trace');
|
||||
|
||||
/**
|
||||
* FireCake output status
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_enabled = true;
|
||||
|
||||
/**
|
||||
* get Instance of the singleton
|
||||
*
|
||||
* @param string $class Class instance to store in the singleton. Used with subclasses and Tests.
|
||||
* @return FireCake
|
||||
*/
|
||||
public static function getInstance($class = null) {
|
||||
static $instance = array();
|
||||
if (!empty($class)) {
|
||||
if (!$instance || strtolower($class) !== strtolower(get_class($instance[0]))) {
|
||||
$instance[0] = new $class();
|
||||
$instance[0]->setOptions();
|
||||
}
|
||||
}
|
||||
if (!isset($instance[0]) || !$instance[0]) {
|
||||
$instance[0] = new FireCake();
|
||||
$instance[0]->setOptions();
|
||||
}
|
||||
return $instance[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* setOptions
|
||||
*
|
||||
* @param array $options Array of options to set.
|
||||
* @return void
|
||||
*/
|
||||
public static function setOptions($options = array()) {
|
||||
$_this = FireCake::getInstance();
|
||||
if (empty($_this->options)) {
|
||||
$_this->options = array_merge($_this->_defaultOptions, $options);
|
||||
} else {
|
||||
$_this->options = array_merge($_this->options, $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return boolean based on presence of FirePHP extension
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function detectClientExtension() {
|
||||
$ua = FireCake::getUserAgent();
|
||||
if (preg_match('/\sFirePHP\/([\.|\d]*)\s?/si', $ua, $match) && version_compare($match[1], '0.0.6', '>=')) {
|
||||
return true;
|
||||
}
|
||||
if (env('HTTP_X_FIREPHP_VERSION') && version_compare(env('HTTP_X_FIREPHP_VERSION'), '0.6', '>=')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Current UserAgent
|
||||
*
|
||||
* @return string UserAgent string of active client connection
|
||||
*/
|
||||
public static function getUserAgent() {
|
||||
return env('HTTP_USER_AGENT');
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable FireCake output
|
||||
* All subsequent output calls will not be run.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function disable() {
|
||||
$_this = FireCake::getInstance();
|
||||
$_this->_enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable FireCake output
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function enable() {
|
||||
$_this = FireCake::getInstance();
|
||||
$_this->_enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper for LOG messages
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param string $label Label for message (optional)
|
||||
* @return void
|
||||
*/
|
||||
public static function log($message, $label = null) {
|
||||
FireCake::fb($message, $label, 'log');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper for WARN messages
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param string $label Label for message (optional)
|
||||
* @return void
|
||||
*/
|
||||
public static function warn($message, $label = null) {
|
||||
FireCake::fb($message, $label, 'warn');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper for INFO messages
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param string $label Label for message (optional)
|
||||
* @return void
|
||||
*/
|
||||
public static function info($message, $label = null) {
|
||||
FireCake::fb($message, $label, 'info');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper for ERROR messages
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param string $label Label for message (optional)
|
||||
* @return void
|
||||
*/
|
||||
public static function error($message, $label = null) {
|
||||
FireCake::fb($message, $label, 'error');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper for TABLE messages
|
||||
*
|
||||
* @param string $label Label for message (optional)
|
||||
* @param string $message Message to log
|
||||
* @return void
|
||||
*/
|
||||
public static function table($label, $message) {
|
||||
FireCake::fb($message, $label, 'table');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper for DUMP messages
|
||||
*
|
||||
* @param string $label Unique label for message
|
||||
* @param string $message Message to log
|
||||
* @return void
|
||||
*/
|
||||
public static function dump($label, $message) {
|
||||
FireCake::fb($message, $label, 'dump');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper for TRACE messages
|
||||
*
|
||||
* @param string $label Label for message (optional)
|
||||
* @return void
|
||||
*/
|
||||
public static function trace($label) {
|
||||
FireCake::fb($label, 'trace');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper for GROUP messages
|
||||
* Messages following the group call will be nested in a group block
|
||||
*
|
||||
* @param string $label Label for group (optional)
|
||||
* @return void
|
||||
*/
|
||||
public static function group($label) {
|
||||
FireCake::fb(null, $label, 'groupStart');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper for GROUPEND messages
|
||||
* Closes a group block
|
||||
*
|
||||
* @internal param string $label Label for group (optional)
|
||||
* @return void
|
||||
*/
|
||||
public static function groupEnd() {
|
||||
FireCake::fb(null, null, 'groupEnd');
|
||||
}
|
||||
|
||||
/**
|
||||
* fb - Send messages with FireCake to FirePHP
|
||||
*
|
||||
* Much like FirePHP's fb() this method can be called with various parameter counts
|
||||
* fb($message) - Just send a message defaults to LOG type
|
||||
* fb($message, $type) - Send a message with a specific type
|
||||
* fb($message, $label, $type) - Send a message with a custom label and type.
|
||||
*
|
||||
* @param mixed $message Message to output. For other parameters see usage above.
|
||||
* @return boolean Success
|
||||
*/
|
||||
public static function fb($message) {
|
||||
$_this = FireCake::getInstance();
|
||||
|
||||
if (headers_sent($filename, $linenum)) {
|
||||
trigger_error(__d('debug_kit', 'Headers already sent in %s on line %s. Cannot send log data to FirePHP.', $filename, $linenum), E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
if (!$_this->_enabled || !$_this->detectClientExtension()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$args = func_get_args();
|
||||
$type = $label = null;
|
||||
switch (count($args)) {
|
||||
case 1:
|
||||
$type = $_this->_levels['log'];
|
||||
break;
|
||||
case 2:
|
||||
$type = $args[1];
|
||||
break;
|
||||
case 3:
|
||||
$type = $args[2];
|
||||
$label = $args[1];
|
||||
break;
|
||||
default:
|
||||
trigger_error(__d('debug_kit', 'Incorrect parameter count for FireCake::fb()'), E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
if (isset($_this->_levels[$type])) {
|
||||
$type = $_this->_levels[$type];
|
||||
} else {
|
||||
$type = $_this->_levels['log'];
|
||||
}
|
||||
|
||||
$meta = array();
|
||||
$skipFinalObjectEncode = false;
|
||||
if ($type == $_this->_levels['trace']) {
|
||||
$trace = debug_backtrace();
|
||||
if (!$trace) {
|
||||
return false;
|
||||
}
|
||||
$message = FireCake::_parseTrace($trace, $args[0]);
|
||||
$skipFinalObjectEncode = true;
|
||||
}
|
||||
|
||||
if ($_this->options['includeLineNumbers']) {
|
||||
if (!isset($meta['file']) || !isset($meta['line'])) {
|
||||
$trace = debug_backtrace();
|
||||
for ($i = 0, $len = count($trace); $i < $len; $i++) {
|
||||
$keySet = (isset($trace[$i]['class']) && isset($trace[$i]['function']));
|
||||
$selfCall = ($keySet &&
|
||||
strtolower($trace[$i]['class']) === 'firecake' &&
|
||||
in_array($trace[$i]['function'], $_this->_methodIndex)
|
||||
);
|
||||
if ($selfCall) {
|
||||
$meta['File'] = isset($trace[$i]['file']) ? Debugger::trimPath($trace[$i]['file']) : '';
|
||||
$meta['Line'] = isset($trace[$i]['line']) ? $trace[$i]['line'] : '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$structureIndex = 1;
|
||||
if ($type == $_this->_levels['dump']) {
|
||||
$structureIndex = 2;
|
||||
$_this->_sendHeader('X-Wf-1-Structure-2', 'http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
|
||||
} else {
|
||||
$_this->_sendHeader('X-Wf-1-Structure-1', 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
|
||||
}
|
||||
|
||||
$_this->_sendHeader('X-Wf-Protocol-1', 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
|
||||
$_this->_sendHeader('X-Wf-1-Plugin-1', 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/' . $_this->_version);
|
||||
if ($type == $_this->_levels['groupStart']) {
|
||||
$meta['Collapsed'] = 'true';
|
||||
}
|
||||
if ($type == $_this->_levels['dump']) {
|
||||
$dump = FireCake::jsonEncode($message);
|
||||
$msg = '{"' . $label . '":' . $dump . '}';
|
||||
} else {
|
||||
$meta['Type'] = $type;
|
||||
if ($label !== null) {
|
||||
$meta['Label'] = $label;
|
||||
}
|
||||
$msg = '[' . $_this->jsonEncode($meta) . ',' . $_this->jsonEncode($message, $skipFinalObjectEncode) . ']';
|
||||
}
|
||||
|
||||
$lines = explode("\n", chunk_split($msg, 5000, "\n"));
|
||||
|
||||
foreach ($lines as $i => $line) {
|
||||
if (empty($line)) {
|
||||
continue;
|
||||
}
|
||||
$header = 'X-Wf-1-' . $structureIndex . '-1-' . $_this->_messageIndex;
|
||||
if (count($lines) > 2) {
|
||||
$first = ($i == 0) ? strlen($msg) : '';
|
||||
$end = ($i < count($lines) - 2) ? '\\' : '';
|
||||
$message = $first . '|' . $line . '|' . $end;
|
||||
$_this->_sendHeader($header, $message);
|
||||
} else {
|
||||
$_this->_sendHeader($header, strlen($line) . '|' . $line . '|');
|
||||
}
|
||||
$_this->_messageIndex++;
|
||||
if ($_this->_messageIndex > 99999) {
|
||||
trigger_error(__d('debug_kit', 'Maximum number (99,999) of messages reached!'), E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
$_this->_sendHeader('X-Wf-1-Index', $_this->_messageIndex - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a debug backtrace
|
||||
*
|
||||
* @param array $trace Debug backtrace output
|
||||
* @param $messageName
|
||||
* @return array
|
||||
*/
|
||||
protected static function _parseTrace($trace, $messageName) {
|
||||
$message = array();
|
||||
for ($i = 0, $len = count($trace); $i < $len; $i++) {
|
||||
$keySet = (isset($trace[$i]['class']) && isset($trace[$i]['function']));
|
||||
$selfCall = ($keySet && $trace[$i]['class'] === 'FireCake');
|
||||
if (!$selfCall) {
|
||||
$message = array(
|
||||
'Class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : '',
|
||||
'Type' => isset($trace[$i]['type']) ? $trace[$i]['type'] : '',
|
||||
'Function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : '',
|
||||
'Message' => $messageName,
|
||||
'File' => isset($trace[$i]['file']) ? Debugger::trimPath($trace[$i]['file']) : '',
|
||||
'Line' => isset($trace[$i]['line']) ? $trace[$i]['line'] : '',
|
||||
'Args' => isset($trace[$i]['args']) ? FireCake::stringEncode($trace[$i]['args']) : '',
|
||||
'Trace' => FireCake::_escapeTrace(array_splice($trace, $i + 1))
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix a trace for use in output
|
||||
*
|
||||
* @param mixed $trace Trace to fix
|
||||
* @return string
|
||||
*/
|
||||
protected static function _escapeTrace($trace) {
|
||||
for ($i = 0, $len = count($trace); $i < $len; $i++) {
|
||||
if (isset($trace[$i]['file'])) {
|
||||
$trace[$i]['file'] = Debugger::trimPath($trace[$i]['file']);
|
||||
}
|
||||
if (isset($trace[$i]['args'])) {
|
||||
$trace[$i]['args'] = FireCake::stringEncode($trace[$i]['args']);
|
||||
}
|
||||
}
|
||||
return $trace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode non string objects to string.
|
||||
* Filter out recursion, so no errors are raised by json_encode or $javascript->object()
|
||||
*
|
||||
* @param mixed $object Object or variable to encode to string.
|
||||
* @param integer $objectDepth Current Depth in object chains.
|
||||
* @param integer $arrayDepth Current Depth in array chains.
|
||||
* @return string|Object
|
||||
*/
|
||||
public static function stringEncode($object, $objectDepth = 1, $arrayDepth = 1) {
|
||||
$_this = FireCake::getInstance();
|
||||
$return = array();
|
||||
if (is_resource($object)) {
|
||||
return '** ' . (string)$object . '**';
|
||||
}
|
||||
if (is_object($object)) {
|
||||
if ($objectDepth == $_this->options['maxObjectDepth']) {
|
||||
return '** Max Object Depth (' . $_this->options['maxObjectDepth'] . ') **';
|
||||
}
|
||||
foreach ($_this->_encodedObjects as $encoded) {
|
||||
if ($encoded === $object) {
|
||||
return '** Recursion (' . get_class($object) . ') **';
|
||||
}
|
||||
}
|
||||
$_this->_encodedObjects[] = $object;
|
||||
|
||||
$return['__className'] = $class = get_class($object);
|
||||
$properties = get_object_vars($object);
|
||||
foreach ($properties as $name => $property) {
|
||||
$return[$name] = FireCake::stringEncode($property, 1, $objectDepth + 1);
|
||||
}
|
||||
array_pop($_this->_encodedObjects);
|
||||
}
|
||||
if (is_array($object)) {
|
||||
if ($arrayDepth == $_this->options['maxArrayDepth']) {
|
||||
return '** Max Array Depth (' . $_this->options['maxArrayDepth'] . ') **';
|
||||
}
|
||||
foreach ($object as $key => $value) {
|
||||
$return[$key] = FireCake::stringEncode($value, 1, $arrayDepth + 1);
|
||||
}
|
||||
}
|
||||
if (is_string($object) || is_numeric($object) || is_bool($object) || $object === null) {
|
||||
return $object;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an object into JSON
|
||||
*
|
||||
* @param mixed $object Object or array to json encode
|
||||
* @param boolean $skipEncode
|
||||
* @internal param bool $doIt
|
||||
* @static
|
||||
* @return string
|
||||
*/
|
||||
public static function jsonEncode($object, $skipEncode = false) {
|
||||
$_this = FireCake::getInstance();
|
||||
if (!$skipEncode) {
|
||||
$object = FireCake::stringEncode($object);
|
||||
}
|
||||
return json_encode($object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Headers - write headers.
|
||||
*
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @return void
|
||||
*/
|
||||
protected function _sendHeader($name, $value) {
|
||||
header($name . ': ' . $value);
|
||||
}
|
||||
}
|
||||
50
exp/Plugin/DebugKit/Lib/Log/Engine/DebugKitLog.php
Normal file
50
exp/Plugin/DebugKit/Lib/Log/Engine/DebugKitLog.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* A CakeLog listener which saves having to munge files or other configured loggers.
|
||||
*
|
||||
*/
|
||||
class DebugKitLog implements CakeLogInterface {
|
||||
|
||||
/**
|
||||
* logs
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $logs = array();
|
||||
|
||||
/**
|
||||
* Makes the reverse link needed to get the logs later.
|
||||
*
|
||||
* @param $options
|
||||
* @return \DebugKitLog
|
||||
*/
|
||||
public function __construct($options) {
|
||||
$options['panel']->logger = $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures log messages in memory
|
||||
*
|
||||
* @param $type
|
||||
* @param $message
|
||||
* @return void
|
||||
*/
|
||||
public function write($type, $message) {
|
||||
if (!isset($this->logs[$type])) {
|
||||
$this->logs[$type] = array();
|
||||
}
|
||||
$this->logs[$type][] = array(date('Y-m-d H:i:s'), (string)$message);
|
||||
}
|
||||
}
|
||||
81
exp/Plugin/DebugKit/Lib/Panel/EnvironmentPanel.php
Normal file
81
exp/Plugin/DebugKit/Lib/Panel/EnvironmentPanel.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Provides information about your PHP and CakePHP environment to assist with debugging.
|
||||
*
|
||||
*/
|
||||
class EnvironmentPanel extends DebugPanel {
|
||||
|
||||
/**
|
||||
* beforeRender - Get necessary data about environment to pass back to controller
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return array
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
parent::beforeRender($controller);
|
||||
|
||||
$return = array();
|
||||
|
||||
// PHP Data
|
||||
$phpVer = phpversion();
|
||||
$return['php'] = array_merge(array('PHP_VERSION' => $phpVer), $_SERVER);
|
||||
unset($return['php']['argv']);
|
||||
|
||||
// CakePHP Data
|
||||
$return['cake'] = array(
|
||||
'APP' => APP,
|
||||
'APP_DIR' => APP_DIR,
|
||||
'APPLIBS' => APPLIBS,
|
||||
'CACHE' => CACHE,
|
||||
'CAKE' => CAKE,
|
||||
'CAKE_CORE_INCLUDE_PATH' => CAKE_CORE_INCLUDE_PATH,
|
||||
'CORE_PATH' => CORE_PATH,
|
||||
'CAKE_VERSION' => Configure::version(),
|
||||
'CSS' => CSS,
|
||||
'CSS_URL' => CSS_URL,
|
||||
'DS' => DS,
|
||||
'FULL_BASE_URL' => FULL_BASE_URL,
|
||||
'IMAGES' => IMAGES,
|
||||
'IMAGES_URL' => IMAGES_URL,
|
||||
'JS' => JS,
|
||||
'JS_URL' => JS_URL,
|
||||
'LOGS' => LOGS,
|
||||
'ROOT' => ROOT,
|
||||
'TESTS' => TESTS,
|
||||
'TMP' => TMP,
|
||||
'VENDORS' => VENDORS,
|
||||
'WEBROOT_DIR' => WEBROOT_DIR,
|
||||
'WWW_ROOT' => WWW_ROOT
|
||||
);
|
||||
|
||||
$cakeConstants = array_fill_keys(
|
||||
array(
|
||||
'DS', 'ROOT', 'FULL_BASE_URL', 'TIME_START', 'SECOND', 'MINUTE', 'HOUR', 'DAY', 'WEEK', 'MONTH', 'YEAR',
|
||||
'LOG_ERROR', 'FULL_BASE_URL'
|
||||
), ''
|
||||
);
|
||||
$var = get_defined_constants(true);
|
||||
$return['app'] = array_diff_key($var['user'], $return['cake'], $cakeConstants);
|
||||
|
||||
if (isset($var['hidef'])) {
|
||||
$return['hidef'] = $var['hidef'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
83
exp/Plugin/DebugKit/Lib/Panel/HistoryPanel.php
Normal file
83
exp/Plugin/DebugKit/Lib/Panel/HistoryPanel.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Provides debug information on previous requests.
|
||||
*
|
||||
*/
|
||||
class HistoryPanel extends DebugPanel {
|
||||
|
||||
/**
|
||||
* Number of history elements to keep
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $history = 5;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $settings Array of settings.
|
||||
* @return \HistoryPanel
|
||||
*/
|
||||
public function __construct($settings) {
|
||||
if (isset($settings['history'])) {
|
||||
$this->history = $settings['history'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* beforeRender callback function
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return array contents for panel
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
$cacheKey = $controller->Toolbar->cacheKey;
|
||||
$toolbarHistory = Cache::read($cacheKey, 'debug_kit');
|
||||
$historyStates = array();
|
||||
if (is_array($toolbarHistory) && !empty($toolbarHistory)) {
|
||||
$prefix = array();
|
||||
if (!empty($controller->request->params['prefix'])) {
|
||||
$prefix[$controller->request->params['prefix']] = false;
|
||||
}
|
||||
foreach ($toolbarHistory as $i => $state) {
|
||||
if (!isset($state['request']['content']['url'])) {
|
||||
continue;
|
||||
}
|
||||
$title = $state['request']['content']['url'];
|
||||
$query = @$state['request']['content']['query'];
|
||||
if (isset($query['url'])) {
|
||||
unset($query['url']);
|
||||
}
|
||||
if (!empty($query)) {
|
||||
$title .= '?' . urldecode(http_build_query($query));
|
||||
}
|
||||
$historyStates[] = array(
|
||||
'title' => $title,
|
||||
'url' => array_merge($prefix, array(
|
||||
'plugin' => 'debug_kit',
|
||||
'controller' => 'toolbar_access',
|
||||
'action' => 'history_state',
|
||||
$i + 1))
|
||||
);
|
||||
}
|
||||
}
|
||||
if (count($historyStates) >= $this->history) {
|
||||
array_pop($historyStates);
|
||||
}
|
||||
return $historyStates;
|
||||
}
|
||||
}
|
||||
160
exp/Plugin/DebugKit/Lib/Panel/IncludePanel.php
Normal file
160
exp/Plugin/DebugKit/Lib/Panel/IncludePanel.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Provides a list of included files for the current request
|
||||
*
|
||||
*/
|
||||
class IncludePanel extends DebugPanel {
|
||||
|
||||
/**
|
||||
* The list of plugins within the application
|
||||
*
|
||||
* @var <type>
|
||||
*/
|
||||
protected $_pluginPaths = array();
|
||||
|
||||
/**
|
||||
* File Types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_fileTypes = array(
|
||||
'Cache', 'Config', 'Configure', 'Console', 'Component', 'Controller',
|
||||
'Behavior', 'Datasource', 'Model', 'Plugin', 'Test', 'View', 'Utility',
|
||||
'Network', 'Routing', 'I18n', 'Log', 'Error'
|
||||
);
|
||||
|
||||
/**
|
||||
* Get a list of plugins on construct for later use
|
||||
*/
|
||||
public function __construct() {
|
||||
foreach (CakePlugin::loaded() as $plugin) {
|
||||
$this->_pluginPaths[$plugin] = CakePlugin::path($plugin);
|
||||
}
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of files that were included and split them out into the various parts of the app
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return array
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
$return = array('core' => array(), 'app' => array(), 'plugins' => array());
|
||||
|
||||
foreach (get_included_files() as $file) {
|
||||
$pluginName = $this->_isPluginFile($file);
|
||||
|
||||
if ($pluginName) {
|
||||
$return['plugins'][$pluginName][$this->_getFileType($file)][] = $this->_niceFileName($file, $pluginName);
|
||||
} elseif ($this->_isAppFile($file)) {
|
||||
$return['app'][$this->_getFileType($file)][] = $this->_niceFileName($file, 'app');
|
||||
} elseif ($this->_isCoreFile($file)) {
|
||||
$return['core'][$this->_getFileType($file)][] = $this->_niceFileName($file, 'core');
|
||||
}
|
||||
}
|
||||
|
||||
$return['paths'] = $this->_includePaths();
|
||||
|
||||
ksort($return['core']);
|
||||
ksort($return['plugins']);
|
||||
ksort($return['app']);
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the possible include paths
|
||||
* @return array
|
||||
*/
|
||||
protected function _includePaths() {
|
||||
$paths = array_flip(array_merge(explode(PATH_SEPARATOR, get_include_path()), array(CAKE)));
|
||||
|
||||
unset($paths['.']);
|
||||
return array_flip($paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a path is part of cake core
|
||||
* @param string $file
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _isCoreFile($file) {
|
||||
return strstr($file, CAKE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a path is from APP but not a plugin
|
||||
* @param string $file
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _isAppFile($file) {
|
||||
return strstr($file, APP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a path is from a plugin
|
||||
* @param string $file
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _isPluginFile($file) {
|
||||
foreach ($this->_pluginPaths as $plugin => $path) {
|
||||
if (strstr($file, $path)) {
|
||||
return $plugin;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the path with APP, CORE or the plugin name
|
||||
* @param string $file
|
||||
* @param string
|
||||
* - app for app files
|
||||
* - core for core files
|
||||
* - PluginName for the name of a plugin
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _niceFileName($file, $type) {
|
||||
switch ($type) {
|
||||
case 'app':
|
||||
return str_replace(APP, 'APP/', $file);
|
||||
|
||||
case 'core':
|
||||
return str_replace(CAKE, 'CORE/', $file);
|
||||
|
||||
default:
|
||||
return str_replace($this->_pluginPaths[$type], $type . '/', $file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of file (model, controller etc)
|
||||
* @param string $file
|
||||
* @return string
|
||||
*/
|
||||
protected function _getFileType($file) {
|
||||
foreach ($this->_fileTypes as $type) {
|
||||
if (stripos($file, '/' . $type . '/') !== false) {
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
|
||||
return 'Other';
|
||||
}
|
||||
}
|
||||
51
exp/Plugin/DebugKit/Lib/Panel/LogPanel.php
Normal file
51
exp/Plugin/DebugKit/Lib/Panel/LogPanel.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Log Panel - Reads log entries made this request.
|
||||
*
|
||||
*/
|
||||
class LogPanel extends DebugPanel {
|
||||
|
||||
/**
|
||||
* Constructor - sets up the log listener.
|
||||
*
|
||||
* @return \LogPanel
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$existing = CakeLog::configured();
|
||||
if (empty($existing)) {
|
||||
CakeLog::config('default', array(
|
||||
'engine' => 'FileLog'
|
||||
));
|
||||
}
|
||||
CakeLog::config('debug_kit_log_panel', array(
|
||||
'engine' => 'DebugKit.DebugKitLog',
|
||||
'panel' => $this
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* beforeRender Callback
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return array
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
$logger = $this->logger;
|
||||
return $logger;
|
||||
}
|
||||
}
|
||||
41
exp/Plugin/DebugKit/Lib/Panel/RequestPanel.php
Normal file
41
exp/Plugin/DebugKit/Lib/Panel/RequestPanel.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Provides debug information on the Current request params.
|
||||
*
|
||||
*/
|
||||
class RequestPanel extends DebugPanel {
|
||||
|
||||
/**
|
||||
* beforeRender callback - grabs request params
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return array
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
$out = array();
|
||||
$out['params'] = $controller->request->params;
|
||||
$out['url'] = $controller->request->url;
|
||||
$out['query'] = $controller->request->query;
|
||||
$out['data'] = $controller->request->data;
|
||||
if (isset($controller->Cookie)) {
|
||||
$out['cookie'] = $controller->Cookie->read();
|
||||
}
|
||||
$out['get'] = $_GET;
|
||||
$out['currentRoute'] = Router::currentRoute();
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
32
exp/Plugin/DebugKit/Lib/Panel/SessionPanel.php
Normal file
32
exp/Plugin/DebugKit/Lib/Panel/SessionPanel.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Provides debug information on the Session contents.
|
||||
*
|
||||
*/
|
||||
class SessionPanel extends DebugPanel {
|
||||
|
||||
/**
|
||||
* beforeRender callback
|
||||
*
|
||||
* @param \Controller|object $controller
|
||||
* @return array
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
$sessions = $controller->Toolbar->Session->read();
|
||||
return $sessions;
|
||||
}
|
||||
}
|
||||
64
exp/Plugin/DebugKit/Lib/Panel/SqlLogPanel.php
Normal file
64
exp/Plugin/DebugKit/Lib/Panel/SqlLogPanel.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Provides debug information on the SQL logs and provides links to an ajax explain interface.
|
||||
*
|
||||
*/
|
||||
class SqlLogPanel extends DebugPanel {
|
||||
|
||||
/**
|
||||
* Minimum number of Rows Per Millisecond that must be returned by a query before an explain
|
||||
* is done.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $slowRate = 20;
|
||||
|
||||
/**
|
||||
* Gets the connection names that should have logs + dumps generated.
|
||||
*
|
||||
* @param \Controller|string $controller
|
||||
* @return array
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
if (!class_exists('ConnectionManager')) {
|
||||
return array();
|
||||
}
|
||||
$connections = array();
|
||||
|
||||
$dbConfigs = ConnectionManager::sourceList();
|
||||
foreach ($dbConfigs as $configName) {
|
||||
$driver = null;
|
||||
$db = ConnectionManager::getDataSource($configName);
|
||||
if (
|
||||
(empty($db->config['driver']) && empty($db->config['datasource'])) ||
|
||||
!method_exists($db, 'getLog')
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (isset($db->config['datasource'])) {
|
||||
$driver = $db->config['datasource'];
|
||||
}
|
||||
$explain = false;
|
||||
$isExplainable = (preg_match('/(Mysql|Postgres)$/', $driver));
|
||||
if ($isExplainable) {
|
||||
$explain = true;
|
||||
}
|
||||
$connections[$configName] = $explain;
|
||||
}
|
||||
return array('connections' => $connections, 'threshold' => $this->slowRate);
|
||||
}
|
||||
}
|
||||
36
exp/Plugin/DebugKit/Lib/Panel/TimerPanel.php
Normal file
36
exp/Plugin/DebugKit/Lib/Panel/TimerPanel.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Provides debug information on all timers used in a request.
|
||||
*
|
||||
*/
|
||||
class TimerPanel extends DebugPanel {
|
||||
|
||||
/**
|
||||
* startup - add in necessary helpers
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return void
|
||||
*/
|
||||
public function startup(Controller $controller) {
|
||||
if (!in_array('Number', array_keys(HelperCollection::normalizeObjectArray($controller->helpers)))) {
|
||||
$controller->helpers[] = 'Number';
|
||||
}
|
||||
if (!in_array('SimpleGraph', array_keys(HelperCollection::normalizeObjectArray($controller->helpers)))) {
|
||||
$controller->helpers[] = 'DebugKit.SimpleGraph';
|
||||
}
|
||||
}
|
||||
}
|
||||
31
exp/Plugin/DebugKit/Lib/Panel/VariablesPanel.php
Normal file
31
exp/Plugin/DebugKit/Lib/Panel/VariablesPanel.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Provides debug information on the View variables.
|
||||
*
|
||||
*/
|
||||
class VariablesPanel extends DebugPanel {
|
||||
|
||||
/**
|
||||
* beforeRender callback
|
||||
*
|
||||
* @param Controller $controller
|
||||
* @return array
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
return array_merge($controller->viewVars, array('$request->data' => $controller->request->data));
|
||||
}
|
||||
}
|
||||
138
exp/Plugin/DebugKit/Locale/debug_kit.pot
Normal file
138
exp/Plugin/DebugKit/Locale/debug_kit.pot
Normal file
@@ -0,0 +1,138 @@
|
||||
# LANGUAGE translation of Debug Kit Application
|
||||
# Copyright 2008 Andy Dawson <andydawson76@yahoo.co.uk>
|
||||
# No version information was available in the source files.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: debug_kit-\n"
|
||||
"POT-Creation-Date: 2009-05-27 09:47+0200\n"
|
||||
"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
|
||||
"Last-Translator: Andy Dawson <andydawson76@yahoo.co.uk>\n"
|
||||
"Language-Team:\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Poedit-Basepath: ../../../\n"
|
||||
|
||||
#: controllers/components/toolbar.php:91
|
||||
msgid "Component initialization and startup"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:140
|
||||
msgid "Controller Action"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:167
|
||||
msgid "Render Controller Action"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:231
|
||||
msgid "Could not load DebugToolbar panel %s"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/debug_toolbar.ctp:25
|
||||
msgid "There are no active panels. You must enable a panel to see its output."
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:21
|
||||
msgid "Request History"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:23
|
||||
msgid "No previous requests logged."
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:25
|
||||
msgid "previous requests available"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:27
|
||||
msgid "Restore to current request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:21
|
||||
msgid "Logs"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:28
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:28
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Message"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:37
|
||||
msgid "There were no log entries made this request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/request_panel.ctp:21
|
||||
msgid "Request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/request_panel.ctp:35
|
||||
msgid "Current Route"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/session_panel.ctp:21
|
||||
msgid "Session"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:21
|
||||
msgid "Sql Logs"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:31
|
||||
msgid "toggle (%s) query explains for %s"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:39
|
||||
msgid "No slow queries!, or your database does not support EXPLAIN"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:44
|
||||
msgid "No active database connections"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:33
|
||||
msgid "Memory"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:35
|
||||
msgid "Current Memory Use"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:39
|
||||
msgid "Peak Memory Use"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:43
|
||||
msgid "Timers"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:45
|
||||
msgid "%s (ms)"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:46
|
||||
msgid "Total Request Time:"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Time in ms"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Graph"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/variables_panel.ctp:21
|
||||
msgid "View Variables"
|
||||
msgstr ""
|
||||
|
||||
#: views/helpers/simple_graph.php:79
|
||||
msgid "Starting %sms into the request, taking %sms"
|
||||
msgstr ""
|
||||
|
||||
135
exp/Plugin/DebugKit/Locale/eng/LC_MESSAGES/debug_kit.po
Normal file
135
exp/Plugin/DebugKit/Locale/eng/LC_MESSAGES/debug_kit.po
Normal file
@@ -0,0 +1,135 @@
|
||||
# LANGUAGE translation of CakePHP Application
|
||||
# Copyright YEAR NAME <EMAIL@ADDRESS>
|
||||
# No version information was available in the source files.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr "Project-Id-Version: PROJECT VERSION\n"
|
||||
"POT-Creation-Date: 2009-05-27 09:47+0200\n"
|
||||
"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
|
||||
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
||||
|
||||
#: controllers/components/toolbar.php:91
|
||||
msgid "Component initialization and startup"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:140
|
||||
msgid "Controller Action"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:167
|
||||
msgid "Render Controller Action"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:231
|
||||
msgid "Could not load DebugToolbar panel %s"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/debug_toolbar.ctp:25
|
||||
msgid "There are no active panels. You must enable a panel to see its output."
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:21
|
||||
msgid "Request History"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:23
|
||||
msgid "No previous requests logged."
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:25
|
||||
msgid "previous requests available"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:27
|
||||
msgid "Restore to current request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:21
|
||||
msgid "Logs"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:28
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:28 views/elements/timer_panel.ctp:54
|
||||
msgid "Message"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:37
|
||||
msgid "There were no log entries made this request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/request_panel.ctp:21
|
||||
msgid "Request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/request_panel.ctp:35
|
||||
msgid "Current Route"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/session_panel.ctp:21
|
||||
msgid "Session"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:21
|
||||
msgid "Sql Logs"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:31
|
||||
msgid "toggle (%s) query explains for %s"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:39
|
||||
msgid "No slow queries!, or your database does not support EXPLAIN"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:44
|
||||
msgid "No active database connections"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:33
|
||||
msgid "Memory"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:35
|
||||
msgid "Current Memory Use"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:39
|
||||
msgid "Peak Memory Use"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:43
|
||||
msgid "Timers"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:45
|
||||
msgid "%s (ms)"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:46
|
||||
msgid "Total Request Time:"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Time in ms"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Graph"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/variables_panel.ctp:21
|
||||
msgid "View Variables"
|
||||
msgstr ""
|
||||
|
||||
#: views/helpers/simple_graph.php:79
|
||||
msgid "Starting %sms into the request, taking %sms"
|
||||
msgstr ""
|
||||
135
exp/Plugin/DebugKit/Locale/fra/LC_MESSAGES/debug_kit.po
Normal file
135
exp/Plugin/DebugKit/Locale/fra/LC_MESSAGES/debug_kit.po
Normal file
@@ -0,0 +1,135 @@
|
||||
# LANGUAGE translation of CakePHP Application
|
||||
# Copyright YEAR NAME <EMAIL@ADDRESS>
|
||||
# No version information was available in the source files.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr "Project-Id-Version: PROJECT VERSION\n"
|
||||
"POT-Creation-Date: 2013-06-04 12:00+0200\n"
|
||||
"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
|
||||
"Last-Translator: cake17 <gvmail76-inscription@yahoo.fr>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n>1;\n"
|
||||
|
||||
#: controllers/components/toolbar.php:91
|
||||
msgid "Component initialization and startup"
|
||||
msgstr "Initialisation du component et démarrage"
|
||||
|
||||
#: controllers/components/toolbar.php:140
|
||||
msgid "Controller Action"
|
||||
msgstr "Action du Controller"
|
||||
|
||||
#: controllers/components/toolbar.php:167
|
||||
msgid "Render Controller Action"
|
||||
msgstr "Rendu de l'Action du Controller"
|
||||
|
||||
#: controllers/components/toolbar.php:231
|
||||
msgid "Could not load DebugToolbar panel %s"
|
||||
msgstr "Ne peut charger le panel %s de DebugToolbar"
|
||||
|
||||
#: views/elements/debug_toolbar.ctp:25
|
||||
msgid "There are no active panels. You must enable a panel to see its output."
|
||||
msgstr "Il n'y a pas de panels actifs. Vous devez activer le panel pour voir sa sortie."
|
||||
|
||||
#: views/elements/history_panel.ctp:21
|
||||
msgid "Request History"
|
||||
msgstr "Historique des Requêtes"
|
||||
|
||||
#: views/elements/history_panel.ctp:23
|
||||
msgid "No previous requests logged."
|
||||
msgstr "Pas de demandes antérieures enregistrées."
|
||||
|
||||
#: views/elements/history_panel.ctp:25
|
||||
msgid "previous requests available"
|
||||
msgstr "Des requêtes antérieures sont disponibles"
|
||||
|
||||
#: views/elements/history_panel.ctp:27
|
||||
msgid "Restore to current request"
|
||||
msgstr "Restaure la requête actuelle"
|
||||
|
||||
#: views/elements/log_panel.ctp:21
|
||||
msgid "Logs"
|
||||
msgstr "Logs"
|
||||
|
||||
#: views/elements/log_panel.ctp:28
|
||||
msgid "Time"
|
||||
msgstr "Date"
|
||||
|
||||
#: views/elements/log_panel.ctp:28 views/elements/timer_panel.ctp:54
|
||||
msgid "Message"
|
||||
msgstr "Message"
|
||||
|
||||
#: views/elements/log_panel.ctp:37
|
||||
msgid "There were no log entries made this request"
|
||||
msgstr "Il n'y avait pas d'entrées de log faîtes pour cette requête"
|
||||
|
||||
#: views/elements/request_panel.ctp:21
|
||||
msgid "Request"
|
||||
msgstr "Requête"
|
||||
|
||||
#: views/elements/request_panel.ctp:35
|
||||
msgid "Current Route"
|
||||
msgstr "Route actuelle"
|
||||
|
||||
#: views/elements/session_panel.ctp:21
|
||||
msgid "Session"
|
||||
msgstr "Session"
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:21
|
||||
msgid "Sql Logs"
|
||||
msgstr "Logs Sql"
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:31
|
||||
msgid "toggle (%s) query explains for %s"
|
||||
msgstr "bascule (%s) requêtes expliquées pour %s"
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:39
|
||||
msgid "No slow queries!, or your database does not support EXPLAIN"
|
||||
msgstr "Pas de requêtes lentes!, ou votre base de données ne supporte pas EXPLAIN"
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:44
|
||||
msgid "No active database connections"
|
||||
msgstr "Pas de connections actives de la base de données"
|
||||
|
||||
#: views/elements/timer_panel.ctp:33
|
||||
msgid "Memory"
|
||||
msgstr "Mémoire"
|
||||
|
||||
#: views/elements/timer_panel.ctp:35
|
||||
msgid "Current Memory Use"
|
||||
msgstr "Utilisation de la Mémoire Actuelle"
|
||||
|
||||
#: views/elements/timer_panel.ctp:39
|
||||
msgid "Peak Memory Use"
|
||||
msgstr "Utilisation de la Mémoire au niveau maximum"
|
||||
|
||||
#: views/elements/timer_panel.ctp:43
|
||||
msgid "Timers"
|
||||
msgstr "Timers"
|
||||
|
||||
#: views/elements/timer_panel.ctp:45
|
||||
msgid "%s (ms)"
|
||||
msgstr "%s (ms)"
|
||||
|
||||
#: views/elements/timer_panel.ctp:46
|
||||
msgid "Total Request Time:"
|
||||
msgstr "Total du Temps de Requête"
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Time in ms"
|
||||
msgstr "Temps en ms"
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Graph"
|
||||
msgstr "Graph"
|
||||
|
||||
#: views/elements/variables_panel.ctp:21
|
||||
msgid "View Variables"
|
||||
msgstr "Variables du View"
|
||||
|
||||
#: views/helpers/simple_graph.php:79
|
||||
msgid "Starting %sms into the request, taking %sms"
|
||||
msgstr "Début en %sms de la requête, et prend %sms"
|
||||
136
exp/Plugin/DebugKit/Locale/lim/LC_MESSAGES/debug_kit.po
Normal file
136
exp/Plugin/DebugKit/Locale/lim/LC_MESSAGES/debug_kit.po
Normal file
@@ -0,0 +1,136 @@
|
||||
# LANGUAGE translation of Debug Kit Application
|
||||
# Copyright 2008 Andy Dawson <andydawson76@yahoo.co.uk>
|
||||
# No version information was available in the source files.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: debug_kit-\n"
|
||||
"POT-Creation-Date: 2009-05-27 09:47+0200\n"
|
||||
"PO-Revision-Date: 2009-05-27 09:47+0200\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team:none\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Poedit-Basepath: ../../../\n"
|
||||
"Language: lim\n"
|
||||
|
||||
#: controllers/components/toolbar.php:91
|
||||
msgid "Component initialization and startup"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:140
|
||||
msgid "Controller Action"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:167
|
||||
msgid "Render Controller Action"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:231
|
||||
msgid "Could not load DebugToolbar panel %s"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/debug_toolbar.ctp:25
|
||||
msgid "There are no active panels. You must enable a panel to see its output."
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:21
|
||||
msgid "Request History"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:23
|
||||
msgid "No previous requests logged."
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:25
|
||||
msgid "previous requests available"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:27
|
||||
msgid "Restore to current request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:21
|
||||
msgid "Logs"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:28
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:28 views/elements/timer_panel.ctp:54
|
||||
msgid "Message"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:37
|
||||
msgid "There were no log entries made this request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/request_panel.ctp:21
|
||||
msgid "Request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/request_panel.ctp:35
|
||||
msgid "Current Route"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/session_panel.ctp:21
|
||||
msgid "Session"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:21
|
||||
msgid "Sql Logs"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:31
|
||||
msgid "toggle (%s) query explains for %s"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:39
|
||||
msgid "No slow queries!, or your database does not support EXPLAIN"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:44
|
||||
msgid "No active database connections"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:33
|
||||
msgid "Memory"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:35
|
||||
msgid "Current Memory Use"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:39
|
||||
msgid "Peak Memory Use"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:43
|
||||
msgid "Timers"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:45
|
||||
msgid "%s (ms)"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:46
|
||||
msgid "Total Request Time:"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Time in ms"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Graph"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/variables_panel.ctp:21
|
||||
msgid "View Variables"
|
||||
msgstr ""
|
||||
|
||||
#: views/helpers/simple_graph.php:79
|
||||
msgid "Starting %sms into the request, taking %sms"
|
||||
msgstr ""
|
||||
141
exp/Plugin/DebugKit/Locale/nld/LC_MESSAGES/debug_kit.po
Normal file
141
exp/Plugin/DebugKit/Locale/nld/LC_MESSAGES/debug_kit.po
Normal file
@@ -0,0 +1,141 @@
|
||||
# LANGUAGE translation of Debug Kit Application
|
||||
# Copyright 2008 Andy Dawson <andydawson76@yahoo.co.uk>
|
||||
# No version information was available in the source files.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: debug_kit-\n"
|
||||
"POT-Creation-Date: 2009-05-27 09:47+0200\n"
|
||||
"PO-Revision-Date: 2014-07-17 17:04+0200\n"
|
||||
"Last-Translator: Marlin Cremers <m.cremers@cvo-technologies.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: nld\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 1.9\n"
|
||||
"X-Poedit-Basepath: ../../../\n"
|
||||
|
||||
#: controllers/components/toolbar.php:91
|
||||
msgid "Component initialization and startup"
|
||||
msgstr "Component initializatie en opstarten"
|
||||
|
||||
#: controllers/components/toolbar.php:140
|
||||
msgid "Controller Action"
|
||||
msgstr "Controller Actie"
|
||||
|
||||
#: controllers/components/toolbar.php:167
|
||||
msgid "Render Controller Action"
|
||||
msgstr "Produceer Controller Actie"
|
||||
|
||||
#: controllers/components/toolbar.php:231
|
||||
msgid "Could not load DebugToolbar panel %s"
|
||||
msgstr "Kon DebugToolbar paneel %s niet laden"
|
||||
|
||||
#: views/elements/debug_toolbar.ctp:25
|
||||
msgid "There are no active panels. You must enable a panel to see its output."
|
||||
msgstr ""
|
||||
"Er zijn geen actieve panelen. Je moet een paneel aanzetten om de uitvoer te "
|
||||
"zien."
|
||||
|
||||
#: views/elements/history_panel.ctp:21
|
||||
msgid "Request History"
|
||||
msgstr "Aanvraag Geschiedenis"
|
||||
|
||||
#: views/elements/history_panel.ctp:23
|
||||
msgid "No previous requests logged."
|
||||
msgstr "Geen vorige aanvragen gelogged."
|
||||
|
||||
#: views/elements/history_panel.ctp:25
|
||||
msgid "previous requests available"
|
||||
msgstr "vorige aanvraag beschikbaar"
|
||||
|
||||
#: views/elements/history_panel.ctp:27
|
||||
msgid "Restore to current request"
|
||||
msgstr "Herstel naar actuele aanvraag"
|
||||
|
||||
#: views/elements/log_panel.ctp:21
|
||||
msgid "Logs"
|
||||
msgstr "Logs"
|
||||
|
||||
#: views/elements/log_panel.ctp:28
|
||||
msgid "Time"
|
||||
msgstr "Tijd"
|
||||
|
||||
#: views/elements/log_panel.ctp:28
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Message"
|
||||
msgstr "Bericht"
|
||||
|
||||
#: views/elements/log_panel.ctp:37
|
||||
msgid "There were no log entries made this request"
|
||||
msgstr "Er zijn geen log vermeldingen gemaakt in deze aanvraag"
|
||||
|
||||
#: views/elements/request_panel.ctp:21
|
||||
msgid "Request"
|
||||
msgstr "Aanvraag"
|
||||
|
||||
#: views/elements/request_panel.ctp:35
|
||||
msgid "Current Route"
|
||||
msgstr "Huide Route"
|
||||
|
||||
#: views/elements/session_panel.ctp:21
|
||||
msgid "Session"
|
||||
msgstr "Sessie"
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:21
|
||||
msgid "Sql Logs"
|
||||
msgstr "Sql Logs"
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:31
|
||||
msgid "toggle (%s) query explains for %s"
|
||||
msgstr "schakel (%s) aanvraag uitleg voor %s"
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:39
|
||||
msgid "No slow queries!, or your database does not support EXPLAIN"
|
||||
msgstr "Geen langzame vragen!, of je database ondersteund geen EXPLAIN"
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:44
|
||||
msgid "No active database connections"
|
||||
msgstr "Geen actieve database verbindingen"
|
||||
|
||||
#: views/elements/timer_panel.ctp:33
|
||||
msgid "Memory"
|
||||
msgstr "Geheugen"
|
||||
|
||||
#: views/elements/timer_panel.ctp:35
|
||||
msgid "Current Memory Use"
|
||||
msgstr "Actueel Geheugen Gebruik"
|
||||
|
||||
#: views/elements/timer_panel.ctp:39
|
||||
msgid "Peak Memory Use"
|
||||
msgstr "Hoogste Geheugen Gebruik"
|
||||
|
||||
#: views/elements/timer_panel.ctp:43
|
||||
msgid "Timers"
|
||||
msgstr "Timers"
|
||||
|
||||
#: views/elements/timer_panel.ctp:45
|
||||
msgid "%s (ms)"
|
||||
msgstr "%s (ms)"
|
||||
|
||||
#: views/elements/timer_panel.ctp:46
|
||||
msgid "Total Request Time:"
|
||||
msgstr "Totale Aanvraag Tijd:"
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Time in ms"
|
||||
msgstr "Tijd in ms"
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Graph"
|
||||
msgstr "Diagram"
|
||||
|
||||
#: views/elements/variables_panel.ctp:21
|
||||
msgid "View Variables"
|
||||
msgstr "View Variabelen"
|
||||
|
||||
#: views/helpers/simple_graph.php:79
|
||||
msgid "Starting %sms into the request, taking %sms"
|
||||
msgstr "Starten %sms in de aanvraag, neemt %sms"
|
||||
135
exp/Plugin/DebugKit/Locale/spa/LC_MESSAGES/debug_kit.po
Normal file
135
exp/Plugin/DebugKit/Locale/spa/LC_MESSAGES/debug_kit.po
Normal file
@@ -0,0 +1,135 @@
|
||||
# LANGUAGE translation of CakePHP Application
|
||||
# Copyright YEAR NAME <EMAIL@ADDRESS>
|
||||
# No version information was available in the source files.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr "Project-Id-Version: PROJECT VERSION\n"
|
||||
"POT-Creation-Date: 2009-05-27 09:47+0200\n"
|
||||
"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
|
||||
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
||||
|
||||
#: controllers/components/toolbar.php:91
|
||||
msgid "Component initialization and startup"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:140
|
||||
msgid "Controller Action"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:167
|
||||
msgid "Render Controller Action"
|
||||
msgstr ""
|
||||
|
||||
#: controllers/components/toolbar.php:231
|
||||
msgid "Could not load DebugToolbar panel %s"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/debug_toolbar.ctp:25
|
||||
msgid "There are no active panels. You must enable a panel to see its output."
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:21
|
||||
msgid "Request History"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:23
|
||||
msgid "No previous requests logged."
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:25
|
||||
msgid "previous requests available"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/history_panel.ctp:27
|
||||
msgid "Restore to current request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:21
|
||||
msgid "Logs"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:28
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:28 views/elements/timer_panel.ctp:54
|
||||
msgid "Message"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/log_panel.ctp:37
|
||||
msgid "There were no log entries made this request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/request_panel.ctp:21
|
||||
msgid "Request"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/request_panel.ctp:35
|
||||
msgid "Current Route"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/session_panel.ctp:21
|
||||
msgid "Session"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:21
|
||||
msgid "Sql Logs"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:31
|
||||
msgid "toggle (%s) query explains for %s"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:39
|
||||
msgid "No slow queries!, or your database does not support EXPLAIN"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:44
|
||||
msgid "No active database connections"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:33
|
||||
msgid "Memory"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:35
|
||||
msgid "Current Memory Use"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:39
|
||||
msgid "Peak Memory Use"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:43
|
||||
msgid "Timers"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:45
|
||||
msgid "%s (ms)"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:46
|
||||
msgid "Total Request Time:"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Time in ms"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Graph"
|
||||
msgstr ""
|
||||
|
||||
#: views/elements/variables_panel.ctp:21
|
||||
msgid "View Variables"
|
||||
msgstr ""
|
||||
|
||||
#: views/helpers/simple_graph.php:79
|
||||
msgid "Starting %sms into the request, taking %sms"
|
||||
msgstr ""
|
||||
102
exp/Plugin/DebugKit/Model/Behavior/TimedBehavior.php
Normal file
102
exp/Plugin/DebugKit/Model/Behavior/TimedBehavior.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.3
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugKitDebugger', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Class TimedBehavior
|
||||
*
|
||||
* @since DebugKit 1.3
|
||||
*/
|
||||
class TimedBehavior extends ModelBehavior {
|
||||
|
||||
/**
|
||||
* Behavior settings
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $settings = array();
|
||||
|
||||
/**
|
||||
* Default setting values
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_defaults = array();
|
||||
|
||||
/**
|
||||
* Setup the behavior and import required classes.
|
||||
*
|
||||
* @param \Model|object $Model Model using the behavior
|
||||
* @param array $settings Settings to override for model.
|
||||
* @return void
|
||||
*/
|
||||
public function setup(Model $Model, $settings = null) {
|
||||
if (is_array($settings)) {
|
||||
$this->settings[$Model->alias] = array_merge($this->_defaults, $settings);
|
||||
} else {
|
||||
$this->settings[$Model->alias] = $this->_defaults;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* beforeFind, starts a timer for a find operation.
|
||||
*
|
||||
* @param Model $Model
|
||||
* @param array $queryData Array of query data (not modified)
|
||||
* @return boolean true
|
||||
*/
|
||||
public function beforeFind(Model $Model, $queryData) {
|
||||
DebugKitDebugger::startTimer($Model->alias . '_find', $Model->alias . '->find()');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* afterFind, stops a timer for a find operation.
|
||||
*
|
||||
* @param Model $Model
|
||||
* @param array $results Array of results
|
||||
* @param $primary
|
||||
* @return boolean true.
|
||||
*/
|
||||
public function afterFind(Model $Model, $results, $primary = false) {
|
||||
DebugKitDebugger::stopTimer($Model->alias . '_find');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* beforeSave, starts a time before a save is initiated.
|
||||
*
|
||||
* @param Model $Model
|
||||
* @param array $options
|
||||
* @return boolean true
|
||||
*/
|
||||
public function beforeSave(Model $Model, $options = array()) {
|
||||
DebugKitDebugger::startTimer($Model->alias . '_save', $Model->alias . '->save()');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* afterSave, stop the timer started from a save.
|
||||
*
|
||||
* @param \Model $Model
|
||||
* @param string $created
|
||||
* @return boolean Always true
|
||||
*/
|
||||
public function afterSave(Model $Model, $created, $options = array()) {
|
||||
DebugKitDebugger::stopTimer($Model->alias . '_save');
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
24
exp/Plugin/DebugKit/Model/DebugKitAppModel.php
Normal file
24
exp/Plugin/DebugKit/Model/DebugKitAppModel.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('AppModel', 'Model');
|
||||
|
||||
/**
|
||||
* Class DebugKitAppModel
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class DebugKitAppModel extends AppModel {
|
||||
|
||||
}
|
||||
56
exp/Plugin/DebugKit/Model/ToolbarAccess.php
Normal file
56
exp/Plugin/DebugKit/Model/ToolbarAccess.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.3
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('ConnectionManager', 'Model');
|
||||
|
||||
/**
|
||||
* Class ToolbarAccess
|
||||
*
|
||||
* Contains logic for accessing DebugKit specific information.
|
||||
*/
|
||||
class ToolbarAccess extends Object {
|
||||
|
||||
/**
|
||||
* Runs an explain on a query if the connection supports EXPLAIN.
|
||||
* currently only PostgreSQL and MySQL are supported.
|
||||
*
|
||||
* @param string $connection Connection name
|
||||
* @param string $query SQL query to explain / find query plan for.
|
||||
* @return array Array of explain information or empty array if connection is unsupported.
|
||||
*/
|
||||
public function explainQuery($connection, $query) {
|
||||
$db = ConnectionManager::getDataSource($connection);
|
||||
$datasource = $db->config['datasource'];
|
||||
|
||||
$return = array();
|
||||
if (preg_match('/(Mysql|Postgres)$/', $datasource)) {
|
||||
$explained = $db->query('EXPLAIN ' . $query);
|
||||
if (preg_match('/Postgres$/', $datasource)) {
|
||||
$queryPlan = array();
|
||||
foreach ($explained as $postgreValue) {
|
||||
$queryPlan[] = array($postgreValue[0]['QUERY PLAN']);
|
||||
}
|
||||
$return = array_merge(array(array('')), $queryPlan);
|
||||
} else {
|
||||
$keys = array_keys($explained[0][0]);
|
||||
foreach ($explained as $mysqlValue) {
|
||||
$queryPlan[] = array_values($mysqlValue[0]);
|
||||
}
|
||||
$return = array_merge(array($keys), $queryPlan);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
}
|
||||
299
exp/Plugin/DebugKit/README.md
Normal file
299
exp/Plugin/DebugKit/README.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# CakePHP DebugKit [](http://travis-ci.org/cakephp/debug_kit)
|
||||
|
||||
DebugKit provides a debugging toolbar and enhanced debugging tools for CakePHP applications.
|
||||
|
||||
## Requirements
|
||||
|
||||
The master branch has the following requirements:
|
||||
|
||||
* CakePHP 2.2.0 or greater.
|
||||
* PHP 5.3.0 or greater.
|
||||
|
||||
## Installation
|
||||
|
||||
_[Using [Composer](http://getcomposer.org/)]_
|
||||
|
||||
Add the plugin to your project's `composer.json` - something like this:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"require": {
|
||||
"cakephp/debug_kit": "2.2.*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Because this plugin has the type `cakephp-plugin` set in it's own `composer.json`, composer knows to install it inside your `/Plugin` directory, rather than in the usual vendors file. It is recommended that you add `/Plugin/DebugKit` to your .gitignore file. (Why? [read this](http://getcomposer.org/doc/faqs/should-i-commit-the-dependencies-in-my-vendor-directory.md).)
|
||||
|
||||
> Consider using "require-dev" if you only want to include DebugKit for your development environment.
|
||||
|
||||
_[Manual]_
|
||||
|
||||
* Download the [DebugKit archive](https://github.com/cakephp/debug_kit/zipball/2.2).
|
||||
* Unzip that download.
|
||||
* Rename the resulting folder to `DebugKit`
|
||||
* Then copy this folder into `app/Plugin/`
|
||||
|
||||
_[GIT Submodule]_
|
||||
|
||||
In your app directory type:
|
||||
|
||||
```bash
|
||||
git submodule add --branch 2.2 git://github.com/cakephp/debug_kit.git Plugin/DebugKit
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
_[GIT Clone]_
|
||||
|
||||
In your plugin directory type
|
||||
|
||||
```bash
|
||||
git clone --single-branch --branch 2.2 git://github.com/cakephp/debug_kit.git DebugKit
|
||||
```
|
||||
|
||||
### Enable plugin
|
||||
|
||||
* In 2.x you need to enable the plugin your `app/Config/bootstrap.php` file. If you are already using `CakePlugin::loadAll();`, then the following is not necessary.:
|
||||
```php
|
||||
CakePlugin::load('DebugKit');
|
||||
```
|
||||
* Include the toolbar component in your `app/Controller/AppController.php`:
|
||||
```php
|
||||
class AppController extends Controller {
|
||||
public $components = array('DebugKit.Toolbar');
|
||||
}
|
||||
```
|
||||
* Set `Configure::write('debug', 1);` in `app/Config/core.php`.
|
||||
* Make sure to remove the 'sql_dump' element from your layout (usually
|
||||
`app/View/Layouts/default.ctp`), if you want to experience the awesome that is
|
||||
the DebugKit SQL log.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
If you have a problem with DebugKit please open an issue on [GitHub](https://github.com/cakephp/debug_kit/issues).
|
||||
|
||||
## Contributing
|
||||
|
||||
If you'd like to contribute to DebugKit, check out the
|
||||
[roadmap](https://github.com/cakephp/debug_kit/wiki/roadmap) for any
|
||||
planned features. You can [fork](https://help.github.com/articles/fork-a-repo)
|
||||
the project, add features, and send [pull
|
||||
requests](https://help.github.com/articles/using-pull-requests) or open
|
||||
[issues](https://github.com/cakephp/debug_kit/issues).
|
||||
|
||||
## Versions
|
||||
|
||||
DebugKit has several releases, each compatible with different releases of
|
||||
CakePHP. Use the appropriate version by downloading a tag, or checking out the
|
||||
correct branch.
|
||||
|
||||
* `1.0, 1.1, 1.2` are compatible with CakePHP 1.2.x. These releases of DebugKit
|
||||
will not work with CakePHP 1.3. You can also use the `1.2-branch` for the mos
|
||||
recent updates and bugfixes.
|
||||
* `1.3.0` is compatible with CakePHP 1.3.x only. It will not work with CakePHP
|
||||
1.2. You can also use the `1.3` branch to get the most recent updates and
|
||||
bugfixes.
|
||||
* `2.0.0` is compatible with CakePHP 2.0.x only. It will not work with previous
|
||||
CakePHP versions.
|
||||
* `2.2.0` is compatible with CakePHP 2.2.0 and greater. It will not work with
|
||||
older versions of CakePHP as this release uses new API's available in 2.2.
|
||||
You can also use the `master` branch to get the most recent updates.
|
||||
* `2.2.x` are compatible with CakePHP 2.2.0 and greater. It is a necessary
|
||||
upgrade for people using CakePHP 2.4 as the naming conventions around loggers
|
||||
changed in that release.
|
||||
|
||||
# Documentation
|
||||
|
||||
## Toolbar Panels
|
||||
|
||||
The DebugKit Toolbar is comprised of several panels, which are shown by clicking the
|
||||
CakePHP icon in the upper right-hand corner of your browser after DebugKit has been
|
||||
installed and loaded. Each panel is comprised of a panel class and view element.
|
||||
Typically, a panel handles the collection and display of a single type of information
|
||||
such as Logs or Request information. You can choose to panels from the toolbar or add
|
||||
your own custom panels.
|
||||
|
||||
### Built-in Panels
|
||||
|
||||
There are several built-in panels, they are:
|
||||
|
||||
* **History** Allows access to previous request information, useful when
|
||||
debugging actions with redirects.
|
||||
* **Request** Displays information about the current request, GET, POST, Cake
|
||||
Parameters, Current Route information and Cookies if the `CookieComponent`
|
||||
is in you controller's components.
|
||||
* **Session** Display the information currently in the Session.
|
||||
* **Timer** Display any timers that were set during the request see
|
||||
`DebugKitDebugger` for more information. Also displays
|
||||
memory use at component callbacks as well as peak memory used.
|
||||
* **Sql Logs** Displays sql logs for each database connection.
|
||||
* **Log** Display any entries made to the log files this request.
|
||||
* **Variables** Display View variables set in controller.
|
||||
* **Environment** Display environment variables related to PHP + CakePHP.
|
||||
|
||||
## Configuration
|
||||
|
||||
The toolbar has a few configuration settings. Settings are passed in the component declaration like normal component configuration.
|
||||
|
||||
```php
|
||||
public $components = array(
|
||||
'DebugKit.Toolbar' => array(/* array of settings */)
|
||||
);
|
||||
```
|
||||
|
||||
### Configuring Panels
|
||||
|
||||
You can customize the toolbar to show your custom panels or hide any built-in panel when adding it toolbar to your components.
|
||||
```php
|
||||
public $components = array('DebugKit.Toolbar' => array(
|
||||
'panels' => array('MyCustom', 'timer'=>false)
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
Would display your custom panel and all built-in panels except the 'Timer' panel.
|
||||
|
||||
#### Controlling Panels
|
||||
|
||||
Using the panels key you can specify which panels you want to load, as well as the order in which you want the panels loaded.
|
||||
```php
|
||||
public $components = array(
|
||||
'DebugKit.Toolbar' => array('panels' => array('MyCustom', 'timer' => false))
|
||||
);
|
||||
```
|
||||
|
||||
Would add your custom panel `MyCustomPanel` to the toolbar and exclude the default `Timer` panel. In addition to choosing which panels you want, you can pass options into the `__construct` of the panels. For example the built-in `History` panel uses the `history` key to set the number of historical requests to track.
|
||||
```php
|
||||
public $components = array(
|
||||
'DebugKit.Toolbar' => array('history' => 10)
|
||||
);
|
||||
```
|
||||
|
||||
Would load the `History` panel and set its history level to 10. The `panels` key is not passed to the Panel constructor.
|
||||
|
||||
#### forceEnable
|
||||
|
||||
The `forceEnable` setting is new in DebugKit 1.1. It allows you to force the toolbar to display regardless of the value of `Configure::read('debug');`. This is useful when profiling an application with debug kit as you can enable the toolbar even when running the application in production mode.
|
||||
|
||||
#### autoRun
|
||||
|
||||
autoRun is a new configuration setting for DebugKit 1.2. It allows you to control whether or not the toolbar is displayed automatically or whether you would like to use a query string parameter to enable it. Set this configuration key to false to use query string parameter toggling of the toolbar.
|
||||
```php
|
||||
public $components = array(
|
||||
'DebugKit.Toolbar' => array('autoRun' => false)
|
||||
);
|
||||
```
|
||||
|
||||
When visiting a page you can add `?debug=true` to the url and the toolbar will be visible. Otherwise it will stay hidden and not execute.
|
||||
|
||||
## Developing Your Own Panels
|
||||
|
||||
You can create your own custom panels for DebugKit to help in debugging your applications.
|
||||
|
||||
### Panel Classes
|
||||
|
||||
Panel Classes simply need to be placed in`Panel` directory inside a `Lib` path. The filename should match the classname, so the class `MyCustomPanel` would be expected to have a filename of `app/Lib/Panel/MyCustomPanel.php`.
|
||||
```php
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* My Custom Panel
|
||||
*/
|
||||
class MyCustomPanel extends DebugPanel {
|
||||
...
|
||||
}
|
||||
```
|
||||
See also the example `Test/test_app/Plugin/DebugkitTestPlugin/Lib/Panel/PluginTestPanel.php`.
|
||||
|
||||
Notice that custom panels are required to subclass the `DebugPanel` class. Panels can define the
|
||||
`css` and `javascript` properties to include additional CSS or javascript on the page. Both
|
||||
properties should be an array.
|
||||
```php
|
||||
class MyCustomPanel extends DebugPanel {
|
||||
public $javascript = array(
|
||||
'/my_plugin/js/custom_panel.js'
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Callbacks
|
||||
|
||||
Panel objects have 2 callbacks, that allow them to hook into and introspect on the current request.
|
||||
```php
|
||||
startup(Controller $controller)
|
||||
```
|
||||
|
||||
Each panel's `startup()` method is called during component `startup()` process. `$controller` is a reference to the current controller object.
|
||||
```php
|
||||
beforeRender(Controller $controller)
|
||||
```
|
||||
|
||||
Much like `startup()` `beforeRender()` is called during the Component beforeRender() process. Again `$controller` is a reference to the current controller. Normally at this point you could do additional introspection on the controller. The return of a panels `beforeRender()` is automatically passed to the View by the Toolbar Component. Therefore, under normal use you do not need to explicitly set variables to the controller.
|
||||
|
||||
#### Example of beforeRender Callback
|
||||
```php
|
||||
/**
|
||||
* beforeRender callback - grabs request params
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function beforeRender(Controller $controller) {
|
||||
return $controller->params;
|
||||
}
|
||||
```
|
||||
|
||||
This would return cake's internal params array. The return of a panel's `beforeRender()` is available in you Panel element as `$content`
|
||||
|
||||
### Panel Elements
|
||||
|
||||
Each Panel is expected to have a view element that renders the content from the panel. The element name must be the underscored inflection of the class name. For example `SessionPanel` has an element named `session_panel.ctp`, and sqllogPanel has an element named `sqllog_panel.ctp`. These elements should be located in the root of your `View/Elements` directory.
|
||||
|
||||
#### Custom Titles and Elements
|
||||
|
||||
Panels should pick up their title and element name by convention. However, if you need to choose a custom element name or title, there are properties to allow that configuration.
|
||||
|
||||
- `$title` - Set a custom title for use in the toolbar. This title will be used as the panels button.
|
||||
- `$elementName` - Set a custom element name to be used to render the panel.
|
||||
|
||||
### Panels as Cake Plugins
|
||||
|
||||
Panels provided by [Cake Plugins](http://book.cakephp.org/2.0/en/plugins.html) work almost entirely the same as other plugins, with one minor difference: You must set `public $plugin` to be the name of the plugin directory, so that the panel's Elements can be located at render time.
|
||||
```php
|
||||
class MyCustomPanel extends DebugPanel {
|
||||
public $plugin = 'MyPlugin';
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
To use a plugin panel, use the common CakePHP dot notation for plugins.
|
||||
```php
|
||||
public $components = array('DebugKit.Toolbar' => array(
|
||||
'panels' => array('MyPlugin.MyCustom')
|
||||
));
|
||||
```
|
||||
The above would load all the default panels as well as the custom panel from `MyPlugin`.
|
||||
|
||||
## Cache Engine
|
||||
|
||||
By default, DebugKit uses File as the engine for internal caching, but if you want to use another cache engine you can customize it by simply adding a cache key inside the components config array.
|
||||
```php
|
||||
public $components = array('DebugKit.Toolbar' => array(
|
||||
'cache' => array('engine' => 'Memcache', 'servers' => array('127.0.0.1:11211'))
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
You can use any cache engine supported by CakePHP, the same way you set in both core.php and bootstrap.php files with the Cache::config() method.
|
||||
|
||||
## Viewing the Toolbar for AJAX Requests
|
||||
|
||||
When doing AJAX requests, you will not be able to see an HTML version of the toolbar. However, if you have a browser extension that supports FirePHP, you can view
|
||||
the toolbar in your browser:
|
||||
|
||||
- [FirePHP 4 chrome](https://chrome.google.com/webstore/detail/firephp4chrome/gpgbmonepdpnacijbbdijfbecmgoojma)
|
||||
- [FirePHP for chrome](https://chrome.google.com/webstore/detail/firephp-for-chrome/goajlbdffkligccnfgibeilhdnnpaead)
|
||||
- [FirePHP for firefox](https://addons.mozilla.org/en-US/firefox/addon/firephp/)
|
||||
|
||||
Once you have installed the correct extension, you should see the toolbar data output on each AJAX request.
|
||||
40
exp/Plugin/DebugKit/Test/Case/AllDebugKitTest.php
Normal file
40
exp/Plugin/DebugKit/Test/Case/AllDebugKitTest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* View Group Test for DebugKit
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . DS . 'DebugkitGroupTestCase.php';
|
||||
|
||||
/**
|
||||
* DebugKitViewTestSuite class
|
||||
*
|
||||
* @since DebugKit 1.0
|
||||
*/
|
||||
class AllDebugKitTest extends DebugKitGroupTestCase {
|
||||
|
||||
/**
|
||||
* Assemble Test Suite
|
||||
*
|
||||
* @return PHPUnit_Framework_TestSuite the instance of PHPUnit_Framework_TestSuite
|
||||
*/
|
||||
public static function suite() {
|
||||
$suite = new self;
|
||||
$files = $suite->getTestFiles();
|
||||
$suite->addTestFiles($files);
|
||||
|
||||
return $suite;
|
||||
}
|
||||
}
|
||||
40
exp/Plugin/DebugKit/Test/Case/AllDebugKitViewTest.php
Normal file
40
exp/Plugin/DebugKit/Test/Case/AllDebugKitViewTest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* View Group Test for DebugKit
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . DS . 'DebugkitGroupTestCase.php';
|
||||
|
||||
/**
|
||||
* DebugKitViewTestSuite class
|
||||
*
|
||||
* @since DebugKit 1.0
|
||||
*/
|
||||
class AllDebugKitViewTest extends DebugkitGroupTestCase {
|
||||
|
||||
/**
|
||||
* Assemble Test Suite
|
||||
*
|
||||
* @return PHPUnit_Framework_TestSuite the instance of PHPUnit_Framework_TestSuite
|
||||
*/
|
||||
public static function suite() {
|
||||
$suite = new self;
|
||||
$files = $suite->getTestFiles('View');
|
||||
$suite->addTestFiles($files);
|
||||
|
||||
return $suite;
|
||||
}
|
||||
}
|
||||
40
exp/Plugin/DebugKit/Test/Case/AllDebugKitWithoutViewTest.php
Normal file
40
exp/Plugin/DebugKit/Test/Case/AllDebugKitWithoutViewTest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* View Group Test for DebugKit
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . DS . 'DebugkitGroupTestCase.php';
|
||||
|
||||
/**
|
||||
* DebugKitViewTestSuite class
|
||||
*
|
||||
* @since DebugKit 1.0
|
||||
*/
|
||||
class AllDebugKitWithoutViewTest extends DebugkitGroupTestCase {
|
||||
|
||||
/**
|
||||
* Assemble Test Suite
|
||||
*
|
||||
* @return PHPUnit_Framework_TestSuite the instance of PHPUnit_Framework_TestSuite
|
||||
*/
|
||||
public static function suite() {
|
||||
$suite = new self;
|
||||
$files = $suite->getTestFiles(null, 'View');
|
||||
$suite->addTestFiles($files);
|
||||
|
||||
return $suite;
|
||||
}
|
||||
}
|
||||
40
exp/Plugin/DebugKit/Test/Case/AllTestsTest.php
Normal file
40
exp/Plugin/DebugKit/Test/Case/AllTestsTest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* AllTestsTest For DebugKit
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . DS . 'DebugkitGroupTestCase.php';
|
||||
|
||||
/**
|
||||
* AllTestsTest class
|
||||
*
|
||||
* @since DebugKit 1.0
|
||||
*/
|
||||
class AllTestsTest extends DebugkitGroupTestCase {
|
||||
|
||||
/**
|
||||
* Assemble Test Suite
|
||||
*
|
||||
* @return PHPUnit_Framework_TestSuite the instance of PHPUnit_Framework_TestSuite
|
||||
*/
|
||||
public static function suite() {
|
||||
$suite = new self;
|
||||
$files = $suite->getTestFiles();
|
||||
$suite->addTestFiles($files);
|
||||
|
||||
return $suite;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,524 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 2.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('Router', 'Routing');
|
||||
App::uses('Controller', 'Controller');
|
||||
App::uses('AppController', 'Controller');
|
||||
App::uses('Component', 'Controller');
|
||||
App::uses('ToolbarComponent', 'DebugKit.Controller/Component');
|
||||
App::uses('DebugMemory', 'DebugKit.Lib');
|
||||
App::uses('DebugTimer', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Class TestToolbarComponent
|
||||
*
|
||||
* @since DebugKit 2.1
|
||||
*/
|
||||
class TestToolbarComponent extends ToolbarComponent {
|
||||
|
||||
/**
|
||||
* Load Panels of Toolbar
|
||||
*
|
||||
* @param $panels
|
||||
* @param array $settings
|
||||
*/
|
||||
public function loadPanels($panels, $settings = array()) {
|
||||
$this->_loadPanels($panels, $settings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ToolbarComponentTestCase Test case
|
||||
*
|
||||
*/
|
||||
class ToolbarComponentTestCase extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* fixtures
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $fixtures = array('core.article');
|
||||
|
||||
/**
|
||||
* url for test
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $url;
|
||||
|
||||
/**
|
||||
* Start test callback
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||
$this->_server = $_SERVER;
|
||||
$this->_get = $_GET;
|
||||
$this->_paths = array();
|
||||
$this->_paths['plugins'] = App::path('plugins');
|
||||
$this->_paths['views'] = App::path('views');
|
||||
$this->_paths['vendors'] = App::path('vendors');
|
||||
$this->_paths['controllers'] = App::path('controllers');
|
||||
Configure::write('Cache.disable', false);
|
||||
|
||||
$this->url = '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* endTest
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
$_SERVER = $this->_server;
|
||||
$_GET = $this->_get;
|
||||
|
||||
parent::tearDown();
|
||||
|
||||
App::build(array(
|
||||
'plugins' => $this->_paths['plugins'],
|
||||
'views' => $this->_paths['views'],
|
||||
'controllers' => $this->_paths['controllers'],
|
||||
'vendors' => $this->_paths['vendors']
|
||||
), true);
|
||||
Configure::write('Cache.disable', true);
|
||||
|
||||
unset($this->Controller);
|
||||
ClassRegistry::flush();
|
||||
if (class_exists('DebugMemory')) {
|
||||
DebugMemory::clear();
|
||||
}
|
||||
if (class_exists('DebugTimer')) {
|
||||
DebugTimer::clear();
|
||||
}
|
||||
Router::reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* loading test controller
|
||||
*
|
||||
* @param array $settings
|
||||
* @return Controller
|
||||
*/
|
||||
protected function _loadController($settings = array()) {
|
||||
$request = new CakeRequest($this->url);
|
||||
$request->addParams(Router::parse($this->url));
|
||||
$this->Controller = new Controller($request);
|
||||
$this->Controller->uses = null;
|
||||
$this->Controller->components = array('Toolbar' => $settings + array('className' => 'TestToolbar'));
|
||||
$this->Controller->constructClasses();
|
||||
$this->Controller->Components->trigger('initialize', array($this->Controller));
|
||||
return $this->Controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* test Loading of panel classes
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLoadPanels() {
|
||||
$this->_loadController();
|
||||
|
||||
$this->Controller->Toolbar->loadPanels(array('session', 'request'));
|
||||
$this->assertInstanceOf('SessionPanel', $this->Controller->Toolbar->panels['session']);
|
||||
$this->assertInstanceOf('RequestPanel', $this->Controller->Toolbar->panels['request']);
|
||||
|
||||
$this->Controller->Toolbar->loadPanels(array('history'), array('history' => 10));
|
||||
$this->assertEquals($this->Controller->Toolbar->panels['history']->history, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test exceptions on bad panel names
|
||||
*
|
||||
* @expectedException PHPUnit_Framework_Error
|
||||
* @return void
|
||||
*/
|
||||
public function testLoadPanelsError() {
|
||||
$this->Controller->Toolbar->loadPanels(array('randomNonExisting', 'request'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test Loading of panel classes from a plugin
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLoadPluginPanels() {
|
||||
$debugKitPath = App::pluginPath('DebugKit');
|
||||
$noDir = (empty($debugKitPath) || !file_exists($debugKitPath));
|
||||
if ($noDir) {
|
||||
$this->markTestAsSkipped('Could not find DebugKit in plugin paths');
|
||||
}
|
||||
|
||||
App::build(array(
|
||||
'Plugin' => array($debugKitPath . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
|
||||
));
|
||||
|
||||
CakePlugin::load('DebugkitTestPlugin');
|
||||
$this->_loadController();
|
||||
$this->Controller->Toolbar->loadPanels(array('DebugkitTestPlugin.PluginTest'));
|
||||
$this->assertInstanceOf(
|
||||
'PluginTestPanel',
|
||||
$this->Controller->Toolbar->panels['plugin_test']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* test loading of vendor panels from test_app folder
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLibPanels() {
|
||||
$debugKitPath = App::pluginPath('DebugKit');
|
||||
$noDir = (empty($debugKitPath) || !file_exists($debugKitPath));
|
||||
if ($noDir) {
|
||||
$this->markTestAsSkipped('Could not find DebugKit in plugin paths');
|
||||
}
|
||||
|
||||
App::build(array(
|
||||
'Lib' => array($debugKitPath . 'Test' . DS . 'test_app' . DS . 'Lib' . DS)
|
||||
));
|
||||
$this->_loadController(array(
|
||||
'panels' => array('test'),
|
||||
'className' => 'DebugKit.Toolbar',
|
||||
));
|
||||
$this->assertTrue(isset($this->Controller->Toolbar->panels['test']));
|
||||
$this->assertInstanceOf('TestPanel', $this->Controller->Toolbar->panels['test']);
|
||||
}
|
||||
|
||||
/**
|
||||
* test construct
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConstruct() {
|
||||
$this->_loadController();
|
||||
|
||||
$this->assertFalse(empty($this->Controller->Toolbar->panels));
|
||||
|
||||
$memory = DebugMemory::getAll();
|
||||
$this->assertTrue(isset($memory['Component initialization']));
|
||||
|
||||
$events = $this->Controller->getEventManager();
|
||||
$this->assertNotEmpty($events->listeners('Controller.initialize'));
|
||||
$this->assertNotEmpty($events->listeners('Controller.startup'));
|
||||
$this->assertNotEmpty($events->listeners('Controller.beforeRender'));
|
||||
$this->assertNotEmpty($events->listeners('Controller.shutdown'));
|
||||
$this->assertNotEmpty($events->listeners('View.beforeRender'));
|
||||
$this->assertNotEmpty($events->listeners('View.afterRender'));
|
||||
$this->assertNotEmpty($events->listeners('View.beforeLayout'));
|
||||
$this->assertNotEmpty($events->listeners('View.afterLayout'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test initialize w/ custom panels and defaults
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInitializeCustomPanelsWithDefaults() {
|
||||
$this->_loadController(array(
|
||||
'panels' => array('test'),
|
||||
));
|
||||
|
||||
$expected = array(
|
||||
'history', 'session', 'request', 'sql_log', 'timer',
|
||||
'log', 'variables', 'environment', 'include', 'test'
|
||||
);
|
||||
$this->assertEquals($expected, array_keys($this->Controller->Toolbar->panels));
|
||||
}
|
||||
|
||||
/**
|
||||
* test syntax for removing panels
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInitializeRemovingPanels() {
|
||||
$this->_loadController(array(
|
||||
'panels' => array(
|
||||
'session' => false,
|
||||
'history' => false,
|
||||
)
|
||||
));
|
||||
|
||||
$expected = array('request', 'sql_log', 'timer', 'log', 'variables', 'environment', 'include');
|
||||
$this->assertEquals($expected, array_keys($this->Controller->Toolbar->panels));
|
||||
}
|
||||
|
||||
/**
|
||||
* ensure that Toolbar is not enabled when debug == 0 on initialize
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDebugDisableOnInitialize() {
|
||||
$_debug = Configure::read('debug');
|
||||
Configure::write('debug', 0);
|
||||
$this->_loadController();
|
||||
Configure::write('debug', $_debug);
|
||||
|
||||
$this->assertFalse($this->Controller->Components->enabled('Toolbar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test that passing in forceEnable will enable the toolbar even if debug = 0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testForceEnable() {
|
||||
$_debug = Configure::read('debug');
|
||||
Configure::write('debug', 0);
|
||||
$this->_loadController(array(
|
||||
'forceEnable' => true,
|
||||
));
|
||||
Configure::write('debug', $_debug);
|
||||
|
||||
$this->assertTrue($this->Controller->Components->enabled('Toolbar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test disabling autoRunning of toolbar
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAutoRunSettingFalse() {
|
||||
$this->_loadController(array(
|
||||
'autoRun' => false,
|
||||
));
|
||||
$this->assertFalse($this->Controller->Components->enabled('Toolbar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test autorun = false with query string param
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAutoRunSettingWithQueryString() {
|
||||
$this->url = '/?debug=1';
|
||||
$_GET['debug'] = 1;
|
||||
$this->_loadController(array(
|
||||
'autoRun' => false,
|
||||
));
|
||||
$this->assertTrue($this->Controller->Components->enabled('Toolbar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test startup
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testStartup() {
|
||||
$this->_loadController(array(
|
||||
'panels' => array('timer'),
|
||||
));
|
||||
$MockPanel = $this->getMock('DebugPanel');
|
||||
$MockPanel->expects($this->once())->method('startup');
|
||||
$this->Controller->Toolbar->panels['timer'] = $MockPanel;
|
||||
|
||||
$this->Controller->Toolbar->startup($this->Controller);
|
||||
|
||||
$timers = DebugTimer::getAll();
|
||||
$this->assertTrue(isset($timers['controllerAction']));
|
||||
$memory = DebugMemory::getAll();
|
||||
$this->assertTrue(isset($memory['Controller action start']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that cache config generation works.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCacheConfigGeneration() {
|
||||
$this->_loadController();
|
||||
$this->Controller->Components->trigger('startup', array($this->Controller));
|
||||
|
||||
$results = Cache::config('debug_kit');
|
||||
$this->assertTrue(is_array($results));
|
||||
}
|
||||
|
||||
/**
|
||||
* test state saving of toolbar
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testStateSaving() {
|
||||
$this->_loadController();
|
||||
$configName = 'debug_kit';
|
||||
$this->Controller->Toolbar->cacheKey = 'toolbar_history';
|
||||
|
||||
$this->Controller->Components->trigger('startup', array($this->Controller));
|
||||
$this->Controller->set('test', 'testing');
|
||||
$this->Controller->Components->trigger('beforeRender', array($this->Controller));
|
||||
|
||||
$result = Cache::read('toolbar_history', $configName);
|
||||
$this->assertEquals($result[0]['variables']['content']['test'], 'testing');
|
||||
Cache::delete('toolbar_history', $configName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Before Render callback
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBeforeRender() {
|
||||
$this->_loadController(array(
|
||||
'panels' => array('timer', 'session'),
|
||||
));
|
||||
$MockPanel = $this->getMock('DebugPanel');
|
||||
$MockPanel->expects($this->once())->method('beforeRender');
|
||||
$this->Controller->Toolbar->panels['timer'] = $MockPanel;
|
||||
$this->Controller->Toolbar->beforeRender($this->Controller);
|
||||
|
||||
$this->assertTrue(isset($this->Controller->helpers['DebugKit.Toolbar']));
|
||||
$this->assertEquals($this->Controller->helpers['DebugKit.Toolbar']['output'], 'DebugKit.HtmlToolbar');
|
||||
$this->assertEquals($this->Controller->helpers['DebugKit.Toolbar']['cacheConfig'], 'debug_kit');
|
||||
$this->assertTrue(isset($this->Controller->helpers['DebugKit.Toolbar']['cacheKey']));
|
||||
|
||||
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarPanels']));
|
||||
$vars = $this->Controller->viewVars['debugToolbarPanels'];
|
||||
|
||||
$expected = array(
|
||||
'plugin' => 'DebugKit',
|
||||
'elementName' => 'session_panel',
|
||||
'content' => $this->Controller->Toolbar->Session->read(),
|
||||
'disableTimer' => true,
|
||||
'title' => ''
|
||||
);
|
||||
$this->assertEquals($expected, $vars['session']);
|
||||
|
||||
$memory = DebugMemory::getAll();
|
||||
$this->assertTrue(isset($memory['Controller render start']));
|
||||
}
|
||||
|
||||
/**
|
||||
* test that vars are gathered and state is saved on beforeRedirect
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBeforeRedirect() {
|
||||
$this->_loadController(array(
|
||||
'panels' => array('session', 'history'),
|
||||
));
|
||||
|
||||
$configName = 'debug_kit';
|
||||
$this->Controller->Toolbar->cacheKey = 'toolbar_history';
|
||||
Cache::delete('toolbar_history', $configName);
|
||||
|
||||
DebugTimer::start('controllerAction', 'testing beforeRedirect');
|
||||
$MockPanel = $this->getMock('DebugPanel');
|
||||
$MockPanel->expects($this->once())->method('beforeRender');
|
||||
$this->Controller->Toolbar->panels['session'] = $MockPanel;
|
||||
$this->Controller->Toolbar->beforeRedirect($this->Controller, '/another/url');
|
||||
|
||||
$result = Cache::read('toolbar_history', $configName);
|
||||
$this->assertTrue(isset($result[0]['session']));
|
||||
$this->assertFalse(isset($result[0]['history']));
|
||||
|
||||
$timers = DebugTimer::getAll();
|
||||
$this->assertTrue(isset($timers['controllerAction']));
|
||||
}
|
||||
|
||||
/**
|
||||
* test that loading state (accessing cache) works.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLoadState() {
|
||||
$this->_loadController();
|
||||
$this->Controller->Toolbar->cacheKey = 'toolbar_history';
|
||||
|
||||
$data = array(0 => array('my data'));
|
||||
Cache::write('toolbar_history', $data, 'debug_kit');
|
||||
$result = $this->Controller->Toolbar->loadState(0);
|
||||
$this->assertEquals($result, $data[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that history state urls set prefix = null and admin = null so generated urls do not
|
||||
* adopt these params.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testHistoryUrlGenerationWithPrefixes() {
|
||||
$this->url = '/debugkit_url_with_prefixes_test';
|
||||
Router::connect($this->url, array(
|
||||
'controller' => 'posts',
|
||||
'action' => 'edit',
|
||||
'admin' => 1,
|
||||
'prefix' => 'admin',
|
||||
'plugin' => 'cms',
|
||||
));
|
||||
$this->_loadController();
|
||||
$this->Controller->Toolbar->cacheKey = 'url_test';
|
||||
$this->Controller->Components->trigger('startup', array($this->Controller));
|
||||
$this->Controller->Components->trigger('beforeRender', array($this->Controller));
|
||||
|
||||
$result = $this->Controller->Toolbar->panels['history']->beforeRender($this->Controller);
|
||||
$expected = array(
|
||||
'plugin' => 'debug_kit',
|
||||
'controller' => 'toolbar_access',
|
||||
'action' => 'history_state',
|
||||
0 => 1,
|
||||
'admin' => false,
|
||||
);
|
||||
$this->assertEquals($result[0]['url'], $expected);
|
||||
Cache::delete('url_test', 'debug_kit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the FireCake toolbar is used on AJAX requests
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAjaxToolbar() {
|
||||
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
|
||||
$this->_loadController();
|
||||
$this->Controller->Components->trigger('startup', array($this->Controller));
|
||||
$this->Controller->Components->trigger('beforeRender', array($this->Controller));
|
||||
$this->assertEquals($this->Controller->helpers['DebugKit.Toolbar']['output'], 'DebugKit.FirePhpToolbar');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the toolbar does not interfere with requestAction
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNoRequestActionInterference() {
|
||||
$debugKitPath = App::pluginPath('DebugKit');
|
||||
$noDir = (empty($debugKitPath) || !file_exists($debugKitPath));
|
||||
if ($noDir) {
|
||||
$this->markTestAsSkipped('Could not find DebugKit in plugin paths');
|
||||
}
|
||||
|
||||
App::build(array(
|
||||
'Controller' => $debugKitPath . 'Test' . DS . 'test_app' . DS . 'Controller' . DS,
|
||||
'View' => array(
|
||||
$debugKitPath . 'Test' . DS . 'test_app' . DS . 'View' . DS,
|
||||
CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'View' . DS
|
||||
),
|
||||
'plugins' => $this->_paths['plugins']
|
||||
));
|
||||
Router::reload();
|
||||
$this->_loadController();
|
||||
|
||||
$result = $this->Controller->requestAction('/debug_kit_test/request_action_return', array('return'));
|
||||
$this->assertEquals($result, 'I am some value from requestAction.');
|
||||
|
||||
$result = $this->Controller->requestAction('/debug_kit_test/request_action_render', array('return'));
|
||||
$this->assertEquals($result, 'I have been rendered.');
|
||||
}
|
||||
}
|
||||
79
exp/Plugin/DebugKit/Test/Case/DebugkitGroupTestCase.php
Normal file
79
exp/Plugin/DebugKit/Test/Case/DebugkitGroupTestCase.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* DebugKit Group Test Case
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class DebugKitGroupTestCase
|
||||
*
|
||||
*/
|
||||
class DebugKitGroupTestCase extends PHPUnit_Framework_TestSuite {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
$label = Inflector::humanize(Inflector::underscore(get_class($this)));
|
||||
parent::__construct($label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Test Files
|
||||
*
|
||||
* @param null $directory
|
||||
* @param null $excludes
|
||||
* @return array
|
||||
*/
|
||||
public static function getTestFiles($directory = null, $excludes = null) {
|
||||
if (is_array($directory)) {
|
||||
$files = array();
|
||||
foreach ($directory as $d) {
|
||||
$files = array_merge($files, self::getTestFiles($d, $excludes));
|
||||
}
|
||||
return array_unique($files);
|
||||
}
|
||||
|
||||
if ($excludes !== null) {
|
||||
$excludes = self::getTestFiles((array)$excludes);
|
||||
}
|
||||
if ($directory === null || $directory !== realpath($directory)) {
|
||||
$basePath = App::pluginPath('DebugKit') . 'Test' . DS . 'Case' . DS;
|
||||
$directory = str_replace(DS . DS, DS, $basePath . $directory);
|
||||
}
|
||||
|
||||
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
|
||||
|
||||
$files = array();
|
||||
while ($it->valid()) {
|
||||
|
||||
if (!$it->isDot()) {
|
||||
$file = $it->key();
|
||||
|
||||
if (
|
||||
preg_match('|Test\.php$|', $file) &&
|
||||
$file !== __FILE__ &&
|
||||
!preg_match('|^All.+?\.php$|', basename($file)) &&
|
||||
($excludes === null || !in_array($file, $excludes))
|
||||
) {
|
||||
$files[] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
$it->next();
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
}
|
||||
76
exp/Plugin/DebugKit/Test/Case/Lib/DebugKitDebuggerTest.php
Normal file
76
exp/Plugin/DebugKit/Test/Case/Lib/DebugKitDebuggerTest.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* DebugKit Debugger Test Case File
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since debug_kit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
**/
|
||||
|
||||
App::uses('DebugKitDebugger', 'DebugKit.Lib');
|
||||
require_once CakePlugin::path('DebugKit') . 'Test' . DS . 'Case' . DS . 'TestFireCake.php';
|
||||
|
||||
/**
|
||||
* Test case for the DebugKitDebugger
|
||||
*
|
||||
* @since debug_kit 0.1
|
||||
*/
|
||||
class DebugKitDebuggerTest extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* setUp method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
Configure::write('log', false);
|
||||
$this->firecake = FireCake::getInstance('TestFireCake');
|
||||
TestFireCake::reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* tearDown method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
Configure::write('log', true);
|
||||
DebugKitDebugger::clearTimers();
|
||||
TestFireCake::reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* test output switch to firePHP
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testOutput() {
|
||||
Debugger::getInstance('DebugKitDebugger');
|
||||
Debugger::addFormat('fb', array('callback' => 'DebugKitDebugger::fireError'));
|
||||
Debugger::outputAs('fb');
|
||||
|
||||
set_error_handler('ErrorHandler::handleError');
|
||||
$foo .= '';
|
||||
restore_error_handler();
|
||||
|
||||
$result = $this->firecake->sentHeaders;
|
||||
|
||||
$this->assertRegExp('/GROUP_START/', $result['X-Wf-1-1-1-1']);
|
||||
$this->assertRegExp('/ERROR/', $result['X-Wf-1-1-1-2']);
|
||||
$this->assertRegExp('/GROUP_END/', $result['X-Wf-1-1-1-5']);
|
||||
|
||||
Debugger::getInstance('Debugger');
|
||||
Debugger::outputAs('html');
|
||||
}
|
||||
}
|
||||
65
exp/Plugin/DebugKit/Test/Case/Lib/DebugMemoryTest.php
Normal file
65
exp/Plugin/DebugKit/Test/Case/Lib/DebugMemoryTest.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* DebugKit Debug Memory Test Cases
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
**/
|
||||
|
||||
App::uses('DebugMemory', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Class DebugMemoryTest
|
||||
*
|
||||
*/
|
||||
class DebugMemoryTest extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* test memory usage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMemoryUsage() {
|
||||
$result = DebugMemory::getCurrent();
|
||||
$this->assertTrue(is_int($result));
|
||||
|
||||
$result = DebugMemory::getPeak();
|
||||
$this->assertTrue(is_int($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* test making memory use markers.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMemorySettingAndGetting() {
|
||||
DebugMemory::clear();
|
||||
$result = DebugMemory::record('test marker');
|
||||
$this->assertTrue($result);
|
||||
|
||||
$result = DebugMemory::getAll(true);
|
||||
$this->assertEquals(count($result), 1);
|
||||
$this->assertTrue(isset($result['test marker']));
|
||||
$this->assertTrue(is_numeric($result['test marker']));
|
||||
|
||||
$result = DebugMemory::getAll();
|
||||
$this->assertTrue(empty($result));
|
||||
|
||||
DebugMemory::record('test marker');
|
||||
DebugMemory::record('test marker');
|
||||
$result = DebugMemory::getAll();
|
||||
|
||||
$this->assertEquals(count($result), 2);
|
||||
$this->assertTrue(isset($result['test marker']));
|
||||
$this->assertTrue(isset($result['test marker #2']));
|
||||
}
|
||||
}
|
||||
169
exp/Plugin/DebugKit/Test/Case/Lib/DebugTimerTest.php
Normal file
169
exp/Plugin/DebugKit/Test/Case/Lib/DebugTimerTest.php
Normal file
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
/**
|
||||
* DebugTimer Test Case
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since debug_kit 2.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugTimer', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Class DebugTimerTest
|
||||
*
|
||||
* @since debug_kit 2.0
|
||||
*/
|
||||
class DebugTimerTest extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* tearDown method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
DebugTimer::clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Timer test
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTimers() {
|
||||
$this->assertTrue(DebugTimer::start('test1', 'this is my first test'));
|
||||
usleep(5000);
|
||||
$this->assertTrue(DebugTimer::stop('test1'));
|
||||
$elapsed = DebugTimer::elapsedTime('test1');
|
||||
$this->assertTrue($elapsed > 0.0050);
|
||||
|
||||
$this->assertTrue(DebugTimer::start('test2', 'this is my second test'));
|
||||
sleep(1);
|
||||
$this->assertTrue(DebugTimer::stop('test2'));
|
||||
$elapsed = DebugTimer::elapsedTime('test2');
|
||||
$expected = stripos(PHP_OS, 'win') === false ? 0.999: 0.95; // Windows timer's precision is bad
|
||||
$this->assertTrue($elapsed >= $expected);
|
||||
|
||||
DebugTimer::start('test3');
|
||||
$this->assertIdentical(DebugTimer::elapsedTime('test3'), 0);
|
||||
$this->assertFalse(DebugTimer::stop('wrong'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test timers with no names.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAnonymousTimers() {
|
||||
$this->assertTrue(DebugTimer::start());
|
||||
usleep(2000);
|
||||
$this->assertTrue(DebugTimer::stop());
|
||||
$timers = DebugTimer::getAll();
|
||||
|
||||
$this->assertEquals(2, count($timers));
|
||||
end($timers);
|
||||
$key = key($timers);
|
||||
$lineNo = __LINE__ - 8;
|
||||
|
||||
$file = Debugger::trimPath(__FILE__);
|
||||
$expected = $file . ' line ' . $lineNo;
|
||||
$this->assertEquals($expected, $key);
|
||||
|
||||
$timer = $timers[$expected];
|
||||
$this->assertTrue($timer['time'] > 0.0020);
|
||||
$this->assertEquals($expected, $timers[$expected]['message']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that nested anonymous timers don't get mixed up.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNestedAnonymousTimers() {
|
||||
$this->assertTrue(DebugTimer::start());
|
||||
usleep(100);
|
||||
$this->assertTrue(DebugTimer::start());
|
||||
usleep(100);
|
||||
$this->assertTrue(DebugTimer::stop());
|
||||
$this->assertTrue(DebugTimer::stop());
|
||||
|
||||
$timers = DebugTimer::getAll();
|
||||
$this->assertEquals(3, count($timers), 'incorrect number of timers %s');
|
||||
$firstTimerLine = __LINE__ - 9;
|
||||
$secondTimerLine = __LINE__ - 8;
|
||||
$file = Debugger::trimPath(__FILE__);
|
||||
|
||||
$this->assertTrue(isset($timers[$file . ' line ' . $firstTimerLine]), 'first timer is not set %s');
|
||||
$this->assertTrue(isset($timers[$file . ' line ' . $secondTimerLine]), 'second timer is not set %s');
|
||||
|
||||
$firstTimer = $timers[$file . ' line ' . $firstTimerLine];
|
||||
$secondTimer = $timers[$file . ' line ' . $secondTimerLine];
|
||||
$this->assertTrue($firstTimer['time'] > $secondTimer['time']);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that calling start with the same name does not overwrite previous timers
|
||||
* and instead adds new ones.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testRepeatTimers() {
|
||||
DebugTimer::start('my timer', 'This is the first call');
|
||||
usleep(100);
|
||||
DebugTimer::start('my timer', 'This is the second call');
|
||||
usleep(100);
|
||||
|
||||
DebugTimer::stop('my timer');
|
||||
DebugTimer::stop('my timer');
|
||||
|
||||
$timers = DebugTimer::getAll();
|
||||
$this->assertEquals(3, count($timers), 'wrong timer count %s');
|
||||
|
||||
$this->assertTrue(isset($timers['my timer']));
|
||||
$this->assertTrue(isset($timers['my timer #2']));
|
||||
|
||||
$this->assertTrue($timers['my timer']['time'] > $timers['my timer #2']['time'], 'timer 2 is longer? %s');
|
||||
$this->assertEquals('This is the first call', $timers['my timer']['message']);
|
||||
$this->assertEquals('This is the second call #2', $timers['my timer #2']['message']);
|
||||
}
|
||||
|
||||
/**
|
||||
* testRequestTime
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testRequestTime() {
|
||||
$result1 = DebugTimer::requestTime();
|
||||
usleep(50);
|
||||
$result2 = DebugTimer::requestTime();
|
||||
$this->assertTrue($result1 < $result2);
|
||||
}
|
||||
|
||||
/**
|
||||
* test getting all the set timers.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetTimers() {
|
||||
DebugTimer::start('test1', 'this is my first test');
|
||||
DebugTimer::stop('test1');
|
||||
usleep(50);
|
||||
DebugTimer::start('test2');
|
||||
DebugTimer::stop('test2');
|
||||
$timers = DebugTimer::getAll();
|
||||
|
||||
$this->assertEquals(3, count($timers));
|
||||
$this->assertTrue(is_float($timers['test1']['time']));
|
||||
$this->assertTrue(isset($timers['test1']['message']));
|
||||
$this->assertTrue(isset($timers['test2']['message']));
|
||||
}
|
||||
}
|
||||
345
exp/Plugin/DebugKit/Test/Case/Lib/FireCakeTest.php
Normal file
345
exp/Plugin/DebugKit/Test/Case/Lib/FireCakeTest.php
Normal file
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
/**
|
||||
* CakeFirePHP Test Case
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
**/
|
||||
|
||||
App::uses('FireCake', 'DebugKit.Lib');
|
||||
require_once CakePlugin::path('DebugKit') . 'Test' . DS . 'Case' . DS . 'TestFireCake.php';
|
||||
|
||||
/**
|
||||
* Test Case For FireCake
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class FireCakeTestCase extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* setup test
|
||||
*
|
||||
* Fill FireCake with TestFireCake instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
$this->firecake = FireCake::getInstance('TestFireCake');
|
||||
TestFireCake::reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the FireCake counters and headers.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
TestFireCake::reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getInstance cheat.
|
||||
*
|
||||
* If this fails the rest of the test is going to fail too.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetInstanceOverride() {
|
||||
$instance = FireCake::getInstance();
|
||||
$instance2 = FireCake::getInstance();
|
||||
$this->assertReference($instance, $instance2);
|
||||
$this->assertIsA($instance, 'FireCake');
|
||||
$this->assertIsA($instance, 'TestFireCake', 'Stored instance is not a copy of TestFireCake, test case is broken.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setOptions
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetOptions() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
$this->assertEquals($this->firecake->options['includeLineNumbers'], false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Log()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLog() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::log('Testing');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '26|[{"Type":"LOG"},"Testing"]|');
|
||||
|
||||
FireCake::log('Testing', 'log-info');
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '45|[{"Type":"LOG","Label":"log-info"},"Testing"]|');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test info()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInfo() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::info('I have information');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '38|[{"Type":"INFO"},"I have information"]|');
|
||||
|
||||
FireCake::info('I have information', 'info-label');
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '59|[{"Type":"INFO","Label":"info-label"},"I have information"]|');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test info()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testWarn() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::warn('A Warning');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '29|[{"Type":"WARN"},"A Warning"]|');
|
||||
|
||||
FireCake::warn('A Warning', 'Bzzz');
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '44|[{"Type":"WARN","Label":"Bzzz"},"A Warning"]|');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test error()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testError() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::error('An error');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '29|[{"Type":"ERROR"},"An error"]|');
|
||||
|
||||
FireCake::error('An error', 'wonky');
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '45|[{"Type":"ERROR","Label":"wonky"},"An error"]|');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test dump()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDump() {
|
||||
FireCake::dump('mydump', array('one' => 1, 'two' => 2));
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-2-1-1'], '28|{"mydump":{"one":1,"two":2}}|');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-2']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test table() generation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTable() {
|
||||
$table[] = array('Col 1 Heading','Col 2 Heading');
|
||||
$table[] = array('Row 1 Col 1','Row 1 Col 2');
|
||||
$table[] = array('Row 2 Col 1','Row 2 Col 2');
|
||||
$table[] = array('Row 3 Col 1','Row 3 Col 2');
|
||||
FireCake::table('myTrace', $table);
|
||||
$expected = '162|[{"Type":"TABLE","Label":"myTrace"},[["Col 1 Heading","Col 2 Heading"],["Row 1 Col 1","Row 1 Col 2"],["Row 2 Col 1","Row 2 Col 2"],["Row 3 Col 1","Row 3 Col 2"]]]|';
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-1'], $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* TestStringEncoding
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testStringEncode() {
|
||||
$vars = array(1,2,3);
|
||||
$result = $this->firecake->stringEncode($vars);
|
||||
$this->assertEquals($result, array(1,2,3));
|
||||
|
||||
$this->firecake->setOptions(array('maxArrayDepth' => 3));
|
||||
$deep = array(1 => array(2 => array(3)));
|
||||
$result = $this->firecake->stringEncode($deep);
|
||||
$this->assertEquals($result, array(1 => array(2 => '** Max Array Depth (3) **')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test object encoding
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testStringEncodeObjects() {
|
||||
$obj = FireCake::getInstance();
|
||||
$result = $this->firecake->stringEncode($obj);
|
||||
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertEquals($result['_defaultOptions']['useNativeJsonEncode'], true);
|
||||
$this->assertEquals($result['_encodedObjects'][0], '** Recursion (TestFireCake) **');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test trace()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTrace() {
|
||||
FireCake::trace('myTrace');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||
$dump = $this->firecake->sentHeaders['X-Wf-1-1-1-1'];
|
||||
$this->assertPattern('/"Message":"myTrace"/', $dump);
|
||||
$this->assertPattern('/"Trace":\[/', $dump);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test enabling and disabling of FireCake output
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testEnableDisable() {
|
||||
FireCake::disable();
|
||||
FireCake::trace('myTrace');
|
||||
$this->assertTrue(empty($this->firecake->sentHeaders));
|
||||
|
||||
FireCake::enable();
|
||||
FireCake::trace('myTrace');
|
||||
$this->assertFalse(empty($this->firecake->sentHeaders));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test correct line continuation markers on multi line headers.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMultiLineOutput() {
|
||||
FireCake::trace('myTrace');
|
||||
$this->assertGreaterThan(1, $this->firecake->sentHeaders['X-Wf-1-Index']);
|
||||
$header = $this->firecake->sentHeaders['X-Wf-1-1-1-1'];
|
||||
$this->assertEquals(substr($header, -2), '|\\');
|
||||
|
||||
$endIndex = $this->firecake->sentHeaders['X-Wf-1-Index'];
|
||||
$header = $this->firecake->sentHeaders['X-Wf-1-1-1-' . $endIndex];
|
||||
$this->assertEquals(substr($header, -1), '|');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test inclusion of line numbers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIncludeLineNumbers() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => true));
|
||||
FireCake::info('Testing');
|
||||
$result = $this->firecake->sentHeaders['X-Wf-1-1-1-1'];
|
||||
$this->assertPattern('/"File"\:".*FireCakeTest.php/', $result);
|
||||
$this->assertPattern('/"Line"\:\d+/', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Group messages
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGroup() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::group('test');
|
||||
FireCake::info('my info');
|
||||
FireCake::groupEnd();
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '63|[{"Collapsed":"true","Type":"GROUP_START","Label":"test"},null]|');
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-3'], '27|[{"Type":"GROUP_END"},null]|');
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-Index'], 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test fb() parameter parsing
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFbParameterParsing() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::fb('Test');
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '23|[{"Type":"LOG"},"Test"]|');
|
||||
|
||||
FireCake::fb('Test', 'warn');
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '24|[{"Type":"WARN"},"Test"]|');
|
||||
|
||||
FireCake::fb('Test', 'Custom label', 'warn');
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-3'], '47|[{"Type":"WARN","Label":"Custom label"},"Test"]|');
|
||||
|
||||
$this->expectError('PHPUnit_Framework_Error');
|
||||
$this->assertFalse(FireCake::fb('Test', 'Custom label', 'warn', 'more parameters'));
|
||||
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-Index'], 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test defaulting to log if incorrect message type is used
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIncorrectMessageType() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::fb('Hello World', 'foobared');
|
||||
$this->assertEquals($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '30|[{"Type":"LOG"},"Hello World"]|');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test DetectClientExtension.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDetectClientExtension() {
|
||||
$back = env('HTTP_USER_AGENT');
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4 FirePHP/0.2.1';
|
||||
$this->assertTrue(FireCake::detectClientExtension());
|
||||
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4 FirePHP/0.0.4';
|
||||
$this->assertFalse(FireCake::detectClientExtension());
|
||||
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4';
|
||||
$this->assertFalse(FireCake::detectClientExtension());
|
||||
$_SERVER['HTTP_USER_AGENT'] = $back;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of Non Native JSON encoding.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNonNativeEncoding() {
|
||||
FireCake::setOptions(array('useNativeJsonEncode' => false));
|
||||
$json = FireCake::jsonEncode(array('one' => 1, 'two' => 2));
|
||||
$this->assertEquals($json, '{"one":1,"two":2}');
|
||||
|
||||
$json = FireCake::jsonEncode(array(1,2,3));
|
||||
$this->assertEquals($json, '[1,2,3]');
|
||||
|
||||
$json = FireCake::jsonEncode(FireCake::getInstance());
|
||||
$this->assertPattern('/"options"\:\{"maxObjectDepth"\:\d*,/', $json);
|
||||
}
|
||||
|
||||
}
|
||||
63
exp/Plugin/DebugKit/Test/Case/Lib/Panel/LogPanelTest.php
Normal file
63
exp/Plugin/DebugKit/Test/Case/Lib/Panel/LogPanelTest.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* DebugKit Log Panel Test Cases
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
**/
|
||||
|
||||
App::uses('LogPanel', 'DebugKit.Lib/Panel');
|
||||
App::uses('Controller', 'Controller');
|
||||
|
||||
/**
|
||||
* Class LogPanelTest
|
||||
*
|
||||
*/
|
||||
class LogPanelTest extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* set up
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->panel = new LogPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that logging configs are created.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConstructor() {
|
||||
$result = CakeLog::configured();
|
||||
$this->assertContains('debug_kit_log_panel', $result);
|
||||
$this->assertTrue(count($result) > 1, 'Default loggers were not added.');
|
||||
}
|
||||
|
||||
/**
|
||||
* testBeforeRender
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBeforeRender() {
|
||||
$controller = new Controller();
|
||||
|
||||
CakeLog::write('error', 'Test');
|
||||
|
||||
$result = $this->panel->beforeRender($controller);
|
||||
$this->assertInstanceOf('DebugKitLog', $result);
|
||||
$this->assertTrue(isset($result->logs));
|
||||
$this->assertCount(1, $result->logs['error']);
|
||||
}
|
||||
}
|
||||
59
exp/Plugin/DebugKit/Test/Case/Lib/Panel/SqlLogPanelTest.php
Normal file
59
exp/Plugin/DebugKit/Test/Case/Lib/Panel/SqlLogPanelTest.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* SqlLogPanelTest
|
||||
*
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 2.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('SqlLogPanel', 'DebugKit.Lib/Panel');
|
||||
App::uses('Model', 'Model');
|
||||
App::uses('Controller', 'Controller');
|
||||
|
||||
/**
|
||||
* Class SqlLogPanelTest
|
||||
*
|
||||
* @since DebugKit 2.1
|
||||
*/
|
||||
class SqlLogPanelTest extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* fixtures.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $fixtures = array('core.article');
|
||||
|
||||
/**
|
||||
* Setup
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->panel = new SqlLogPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* test the parsing of source list.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBeforeRender() {
|
||||
$Article = ClassRegistry::init('Article');
|
||||
$Article->find('first', array('conditions' => array('Article.id' => 1)));
|
||||
|
||||
$controller = new Controller();
|
||||
$result = $this->panel->beforeRender($controller);
|
||||
|
||||
$this->assertTrue(isset($result['connections'][$Article->useDbConfig]));
|
||||
$this->assertTrue(isset($result['threshold']));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* DebugKit TimedBehavior Test Case
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.3
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugKitDebugger', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Class TimedBehaviorTestCase
|
||||
*
|
||||
* @since DebugKit 1.3
|
||||
*/
|
||||
class TimedBehaviorTestCase extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* Fixtures
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $fixtures = array('core.article');
|
||||
|
||||
/**
|
||||
* Start Test callback
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->Article = ClassRegistry::init('Article');
|
||||
$this->Article->Behaviors->attach('DebugKit.Timed');
|
||||
}
|
||||
|
||||
/**
|
||||
* End a test
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
unset($this->Article);
|
||||
ClassRegistry::flush();
|
||||
DebugKitDebugger::clearTimers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test find timers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFindTimers() {
|
||||
$timers = DebugKitDebugger::getTimers(false);
|
||||
$this->assertEquals(count($timers), 1);
|
||||
|
||||
$this->Article->find('all');
|
||||
$result = DebugKitDebugger::getTimers(false);
|
||||
$this->assertEquals(count($result), 2);
|
||||
|
||||
$this->Article->find('all');
|
||||
$result = DebugKitDebugger::getTimers(false);
|
||||
$this->assertEquals(count($result), 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test save timers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSaveTimers() {
|
||||
$timers = DebugKitDebugger::getTimers(false);
|
||||
$this->assertEquals(count($timers), 1);
|
||||
|
||||
$this->Article->save(array('user_id' => 1, 'title' => 'test', 'body' => 'test'));
|
||||
$result = DebugKitDebugger::getTimers(false);
|
||||
$this->assertEquals(count($result), 2);
|
||||
}
|
||||
}
|
||||
69
exp/Plugin/DebugKit/Test/Case/Model/ToolbarAccessTest.php
Normal file
69
exp/Plugin/DebugKit/Test/Case/Model/ToolbarAccessTest.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* DebugKit ToolbarAccess Model Test case
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.3
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
**/
|
||||
|
||||
App::uses('ToolbarAccess', 'DebugKit.Model');
|
||||
|
||||
/**
|
||||
* Test case for ToolbarAccess model
|
||||
*
|
||||
* @since DebugKit 1.3
|
||||
*/
|
||||
class ToolbarAccessTestCase extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* Included fixtures
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $fixtures = array('core.post');
|
||||
|
||||
/**
|
||||
* setUp method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->Model = new ToolbarAccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* tearDown
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
unset($this->Model);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that explain query returns arrays of query information.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testExplainQuery() {
|
||||
$Post = new CakeTestModel(array('table' => 'posts', 'alias' => 'Post'));
|
||||
$db = $Post->getDataSource();
|
||||
$sql = 'SELECT * FROM ' . $db->fullTableName('posts') . ';';
|
||||
$result = $this->Model->explainQuery($Post->useDbConfig, $sql);
|
||||
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertFalse(empty($result));
|
||||
}
|
||||
}
|
||||
65
exp/Plugin/DebugKit/Test/Case/TestFireCake.php
Normal file
65
exp/Plugin/DebugKit/Test/Case/TestFireCake.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* Common test objects used in DebugKit tests
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('FireCake', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* TestFireCake class allows for testing of FireCake
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class TestFireCake extends FireCake {
|
||||
|
||||
/**
|
||||
* Headers that were sent
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $sentHeaders = array();
|
||||
|
||||
/**
|
||||
* Send header
|
||||
*
|
||||
* @param $name
|
||||
* @param $value
|
||||
*/
|
||||
protected function _sendHeader($name, $value) {
|
||||
$_this = FireCake::getInstance();
|
||||
$_this->sentHeaders[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip client detection as headers are not being sent.
|
||||
*
|
||||
* @return boolean Always true
|
||||
*/
|
||||
public static function detectClientExtension() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset FireCake
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function reset() {
|
||||
$_this = FireCake::getInstance();
|
||||
$_this->sentHeaders = array();
|
||||
$_this->_messageIndex = 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/**
|
||||
* Toolbar Abstract Helper Test Case
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
**/
|
||||
|
||||
$path = CakePlugin::path('DebugKit');
|
||||
|
||||
App::uses('View', 'View');
|
||||
App::uses('Controller', 'Controller');
|
||||
App::uses('CakeResponse', 'Network');
|
||||
App::uses('Router', 'Routing');
|
||||
App::uses('ToolbarHelper', 'DebugKit.View/Helper');
|
||||
App::uses('FirePhpToolbarHelper', 'DebugKit.View/Helper');
|
||||
|
||||
require_once $path . 'Test' . DS . 'Case' . DS . 'TestFireCake.php';
|
||||
|
||||
/**
|
||||
* Class FirePhpToolbarHelperTestCase
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class FirePhpToolbarHelperTestCase extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* setUp
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
Router::connect('/:controller/:action');
|
||||
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||
Router::parse('/');
|
||||
|
||||
$this->Controller = new Controller($this->getMock('CakeRequest'), new CakeResponse());
|
||||
$this->View = new View($this->Controller);
|
||||
$this->Toolbar = new ToolbarHelper($this->View, array('output' => 'DebugKit.FirePhpToolbar'));
|
||||
$this->Toolbar->FirePhpToolbar = new FirePhpToolbarHelper($this->View);
|
||||
|
||||
$this->firecake = FireCake::getInstance('TestFireCake');
|
||||
TestFireCake::reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start test - switch view paths
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public static function setupBeforeClass() {
|
||||
App::build(array(
|
||||
'View' => array(
|
||||
CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'View' . DS,
|
||||
APP . 'Plugin' . DS . 'DebugKit' . DS . 'View' . DS,
|
||||
CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'View' . DS
|
||||
)), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* End Test
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function tearDownAfterClass() {
|
||||
App::build();
|
||||
}
|
||||
|
||||
/**
|
||||
* TearDown
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
unset($this->Toolbar, $this->Controller);
|
||||
TestFireCake::reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test neat array (dump)creation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMakeNeatArray() {
|
||||
$this->Toolbar->makeNeatArray(array(1,2,3));
|
||||
$result = $this->firecake->sentHeaders;
|
||||
$this->assertTrue(isset($result['X-Wf-1-1-1-1']));
|
||||
$this->assertRegexp('/\[1,2,3\]/', $result['X-Wf-1-1-1-1']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test afterlayout element rendering
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAfterLayout() {
|
||||
$this->Controller->viewPath = 'Posts';
|
||||
$request = new CakeRequest('/posts/index');
|
||||
$request->addParams(Router::parse($request->url));
|
||||
$request->addPaths(array(
|
||||
'webroot' => '/',
|
||||
'base' => '/',
|
||||
'here' => '/posts/index',
|
||||
));
|
||||
$this->Controller->setRequest($request);
|
||||
$this->Controller->layout = 'default';
|
||||
$this->Controller->uses = null;
|
||||
$this->Controller->components = array('DebugKit.Toolbar');
|
||||
$this->Controller->constructClasses();
|
||||
$this->Controller->Components->trigger('startup', array($this->Controller));
|
||||
$this->Controller->Components->trigger('beforeRender', array($this->Controller));
|
||||
$result = $this->Controller->render();
|
||||
$this->assertNotRegExp('/debug-toolbar/', (string)$result);
|
||||
$result = $this->firecake->sentHeaders;
|
||||
$this->assertTrue(is_array($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* test starting a panel
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function testPanelStart() {
|
||||
$this->Toolbar->panelStart('My Panel', 'my_panel');
|
||||
$result = $this->firecake->sentHeaders;
|
||||
$this->assertPattern('/GROUP_START.+My Panel/', $result['X-Wf-1-1-1-1']);
|
||||
}
|
||||
|
||||
/**
|
||||
* test ending a panel
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function testPanelEnd() {
|
||||
$this->Toolbar->panelEnd();
|
||||
$result = $this->firecake->sentHeaders;
|
||||
$this->assertPattern('/GROUP_END/', $result['X-Wf-1-1-1-1']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,452 @@
|
||||
<?php
|
||||
/**
|
||||
* Toolbar HTML Helper Test Case
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('View', 'View');
|
||||
App::uses('Controller', 'Controller');
|
||||
App::uses('Router', 'Routing');
|
||||
App::uses('CakeResponse', 'Network');
|
||||
App::uses('ToolbarHelper', 'DebugKit.View/Helper');
|
||||
App::uses('HtmlToolbarHelper', 'DebugKit.View/Helper');
|
||||
App::uses('HtmlHelper', 'View/Helper');
|
||||
App::uses('FormHelper', 'View/Helper');
|
||||
|
||||
/**
|
||||
* Class HtmlToolbarHelperTestCase
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class HtmlToolbarHelperTestCase extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* Setup Test Case
|
||||
*/
|
||||
public static function setupBeforeClass() {
|
||||
App::build(array(
|
||||
'View' => array(
|
||||
CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'View' . DS,
|
||||
APP . 'Plugin' . DS . 'DebugKit' . DS . 'View' . DS,
|
||||
CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'View' . DS
|
||||
)
|
||||
), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear Down Test Case
|
||||
*/
|
||||
public static function tearDownAfterClass() {
|
||||
App::build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
Router::connect('/:controller/:action');
|
||||
|
||||
$request = new CakeRequest();
|
||||
$request->addParams(array('controller' => 'pages', 'action' => 'display'));
|
||||
|
||||
$this->Controller = new Controller($request, new CakeResponse());
|
||||
$this->View = new View($this->Controller);
|
||||
$this->Toolbar = new ToolbarHelper($this->View, array('output' => 'DebugKit.HtmlToolbar'));
|
||||
$this->Toolbar->HtmlToolbar = new HtmlToolbarHelper($this->View);
|
||||
$this->Toolbar->HtmlToolbar->Html = new HtmlHelper($this->View);
|
||||
$this->Toolbar->HtmlToolbar->Form = new FormHelper($this->View);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear Down
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
unset($this->Toolbar, $this->Controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test makeNeatArray with basic types.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMakeNeatArrayBasic() {
|
||||
$in = false;
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', '0' , '/strong', '(false)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = null;
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', '0' , '/strong', '(null)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = true;
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', '0' , '/strong', '(true)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array();
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', '0' , '/strong', '(empty)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that cyclic references can be printed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMakeNeatArrayCyclicObjects() {
|
||||
$a = new StdClass;
|
||||
$b = new StdClass;
|
||||
$a->child = $b;
|
||||
$b->parent = $a;
|
||||
|
||||
$in = array('obj' => $a);
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
array('ul' => array('class' => 'neat-array depth-0')),
|
||||
'<li', '<strong', 'obj', '/strong', '(object)',
|
||||
array('ul' => array('class' => 'neat-array depth-1')),
|
||||
'<li', '<strong', 'child', '/strong', '(object)',
|
||||
array('ul' => array('class' => 'neat-array depth-2')),
|
||||
'<li', '<strong', 'parent', '/strong',
|
||||
'(object) - recursion',
|
||||
'/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Neat Array formatting
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMakeNeatArray() {
|
||||
$in = array('key' => 'value');
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array('key' => null);
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', 'key', '/strong', '(null)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array('key' => 'value', 'foo' => 'bar');
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'foo', '/strong', 'bar', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array(
|
||||
'key' => 'value',
|
||||
'foo' => array(
|
||||
'this' => 'deep',
|
||||
'another' => 'value'
|
||||
)
|
||||
);
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'foo', '/strong',
|
||||
'(array)',
|
||||
array('ul' => array('class' => 'neat-array depth-1')),
|
||||
'<li', '<strong', 'this', '/strong', 'deep', '/li',
|
||||
'<li', '<strong', 'another', '/strong', 'value', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array(
|
||||
'key' => 'value',
|
||||
'foo' => array(
|
||||
'this' => 'deep',
|
||||
'another' => 'value'
|
||||
),
|
||||
'lotr' => array(
|
||||
'gandalf' => 'wizard',
|
||||
'bilbo' => 'hobbit'
|
||||
)
|
||||
);
|
||||
$result = $this->Toolbar->makeNeatArray($in, 1);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0 expanded'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'foo', '/strong',
|
||||
'(array)',
|
||||
array('ul' => array('class' => 'neat-array depth-1')),
|
||||
'<li', '<strong', 'this', '/strong', 'deep', '/li',
|
||||
'<li', '<strong', 'another', '/strong', 'value', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'<li', '<strong', 'lotr', '/strong',
|
||||
'(array)',
|
||||
array('ul' => array('class' => 'neat-array depth-1')),
|
||||
'<li', '<strong', 'gandalf', '/strong', 'wizard', '/li',
|
||||
'<li', '<strong', 'bilbo', '/strong', 'hobbit', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$result = $this->Toolbar->makeNeatArray($in, 2);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0 expanded'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'foo', '/strong',
|
||||
'(array)',
|
||||
array('ul' => array('class' => 'neat-array depth-1 expanded')),
|
||||
'<li', '<strong', 'this', '/strong', 'deep', '/li',
|
||||
'<li', '<strong', 'another', '/strong', 'value', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'<li', '<strong', 'lotr', '/strong',
|
||||
'(array)',
|
||||
array('ul' => array('class' => 'neat-array depth-1 expanded')),
|
||||
'<li', '<strong', 'gandalf', '/strong', 'wizard', '/li',
|
||||
'<li', '<strong', 'bilbo', '/strong', 'hobbit', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array('key' => 'value', 'array' => array());
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'array', '/strong', '(empty)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test makeNeatArray with object inputs.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMakeNeatArrayObjects() {
|
||||
$in = new StdClass();
|
||||
$in->key = 'value';
|
||||
$in->nested = new StdClass();
|
||||
$in->nested->name = 'mark';
|
||||
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
array('ul' => array('class' => 'neat-array depth-0')),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'nested', '/strong',
|
||||
'(object)',
|
||||
array('ul' => array('class' => 'neat-array depth-1')),
|
||||
'<li', '<strong', 'name', '/strong', 'mark', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test injection of toolbar
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInjectToolbar() {
|
||||
$this->Controller->viewPath = 'Posts';
|
||||
$request = new CakeRequest('/posts/index');
|
||||
$request->addParams(Router::parse($request->url));
|
||||
$request->addPaths(array(
|
||||
'webroot' => '/',
|
||||
'base' => '/',
|
||||
'here' => '/posts/index',
|
||||
));
|
||||
$this->Controller->setRequest($request);
|
||||
$this->Controller->helpers = array('Html', 'Js', 'Session', 'DebugKit.Toolbar');
|
||||
$this->Controller->layout = 'default';
|
||||
$this->Controller->uses = null;
|
||||
$this->Controller->components = array('DebugKit.Toolbar');
|
||||
$this->Controller->constructClasses();
|
||||
$this->Controller->Components->trigger('startup', array($this->Controller));
|
||||
$this->Controller->Components->trigger('beforeRender', array($this->Controller));
|
||||
$result = $this->Controller->render();
|
||||
$result = str_replace(array("\n", "\r"), '', $result);
|
||||
$this->assertPattern('#<div id\="debug-kit-toolbar">.+</div>.*</body>#', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test injection of javascript
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testJavascriptInjection() {
|
||||
$this->Controller->viewPath = 'Posts';
|
||||
$this->Controller->uses = null;
|
||||
$request = new CakeRequest('/posts/index');
|
||||
$request->addParams(Router::parse($request->url));
|
||||
$request->addPaths(array(
|
||||
'webroot' => '/',
|
||||
'base' => '/',
|
||||
'here' => '/posts/index',
|
||||
));
|
||||
$this->Controller->setRequest($request);
|
||||
$this->Controller->helpers = array('Js', 'Html', 'Session');
|
||||
$this->Controller->components = array('DebugKit.Toolbar');
|
||||
$this->Controller->layout = 'default';
|
||||
$this->Controller->constructClasses();
|
||||
$this->Controller->Components->trigger('startup', array($this->Controller));
|
||||
$this->Controller->Components->trigger('beforeRender', array($this->Controller));
|
||||
$result = $this->Controller->render();
|
||||
$result = str_replace(array("\n", "\r"), '', $result);
|
||||
$this->assertPattern('#<script\s*type="text/javascript"\s*src="/debug_kit/js/js_debug_toolbar.js(?:\?\d*?)?"\s*>\s?</script>#', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test message creation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMessage() {
|
||||
$result = $this->Toolbar->message('test', 'one, two');
|
||||
$expected = array(
|
||||
'<p',
|
||||
'<strong', 'test', '/strong',
|
||||
' one, two',
|
||||
'/p',
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Table generation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTable() {
|
||||
$rows = array(
|
||||
array(1,2),
|
||||
array(3,4),
|
||||
);
|
||||
$result = $this->Toolbar->table($rows);
|
||||
$expected = array(
|
||||
'table' => array('class' => 'debug-table'),
|
||||
array('tr' => array('class' => 'odd')),
|
||||
'<td', '1', '/td',
|
||||
'<td', '2', '/td',
|
||||
'/tr',
|
||||
array('tr' => array('class' => 'even')),
|
||||
'<td', '3', '/td',
|
||||
'<td', '4', '/td',
|
||||
'/tr',
|
||||
'/table'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* test starting a panel
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testStartPanel() {
|
||||
$result = $this->Toolbar->panelStart('My Panel', 'my_panel');
|
||||
$expected = array(
|
||||
'a' => array('href' => '#my_panel'),
|
||||
'My Panel',
|
||||
'/a'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* test ending a panel
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPanelEnd() {
|
||||
$result = $this->Toolbar->panelEnd();
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test generating links for query explains.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testExplainLink() {
|
||||
$sql = 'SELECT * FROM tasks';
|
||||
$result = $this->Toolbar->explainLink($sql, 'default');
|
||||
$expected = array(
|
||||
'form' => array('action' => '/debug_kit/toolbar_access/sql_explain', 'method' => 'post',
|
||||
'accept-charset' => 'utf-8', 'id'),
|
||||
array('div' => array('style' => 'display:none;')),
|
||||
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
|
||||
'/div',
|
||||
array('input' => array('type' => 'hidden', 'id', 'name' => 'data[log][ds]', 'value' => 'default')),
|
||||
array('input' => array('type' => 'hidden', 'id', 'name' => 'data[log][sql]', 'value' => $sql)),
|
||||
array('input' => array('type' => 'hidden', 'id', 'name' => 'data[log][hash]', 'value')),
|
||||
array('input' => array('class' => 'sql-explain-link', 'type' => 'submit', 'value' => 'Explain')),
|
||||
'/form',
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
}
|
||||
179
exp/Plugin/DebugKit/Test/Case/View/Helper/ToolbarHelperTest.php
Normal file
179
exp/Plugin/DebugKit/Test/Case/View/Helper/ToolbarHelperTest.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
/**
|
||||
* Toolbar facade tests.
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('View', 'View');
|
||||
App::uses('Controller', 'Controller');
|
||||
App::uses('Helper', 'View');
|
||||
App::uses('ToolbarHelper', 'DebugKit.View/Helper');
|
||||
App::uses('ConnectionManager', 'Manager');
|
||||
|
||||
/**
|
||||
* Class MockBackendHelper
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class MockBackendHelper extends Helper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ToolbarHelperTestCase
|
||||
*
|
||||
*/
|
||||
class ToolbarHelperTestCase extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* Fixtures
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $fixtures = array('core.post');
|
||||
|
||||
/**
|
||||
* setUp
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$db = ConnectionManager::getDatasource('test');
|
||||
$db->fullDebug = true;
|
||||
|
||||
Configure::write('Cache.disable', false);
|
||||
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||
Router::parse('/');
|
||||
|
||||
$this->Controller = new Controller(null);
|
||||
$this->View = new View($this->Controller);
|
||||
$this->Toolbar = new ToolbarHelper($this->View, array(
|
||||
'output' => 'MockBackendHelper',
|
||||
'cacheKey' => 'debug_kit_toolbar_test_case',
|
||||
'cacheConfig' => 'default'
|
||||
));
|
||||
$this->Toolbar->MockBackend = $this->getMock('Helper', array('testMethod'), array($this->View));
|
||||
|
||||
$this->_viewPaths = App::path('views');
|
||||
App::build(array(
|
||||
'View' => array(
|
||||
CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'View' . DS,
|
||||
APP . 'Plugin' . DS . 'DebugKit' . DS . 'View' . DS,
|
||||
CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'View' . DS
|
||||
)), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* tearDown
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
Cache::delete('debug_kit_toolbar_test_case', 'default');
|
||||
unset($this->Toolbar, $this->Controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* test cache writing for views.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCacheWrite() {
|
||||
$result = $this->Toolbar->writeCache('test', array('stuff', 'to', 'cache'));
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the cache writing only affects the
|
||||
* top most level of the history stack. As this is where the current request is stored.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testOnlyWritingToFirstElement() {
|
||||
$values = array(
|
||||
array('test' => array('content' => array('first', 'values'))),
|
||||
array('test' => array('content' => array('second', 'values'))),
|
||||
);
|
||||
Cache::write('debug_kit_toolbar_test_case', $values, 'default');
|
||||
$this->Toolbar->writeCache('test', array('new', 'values'));
|
||||
|
||||
$result = $this->Toolbar->readCache('test');
|
||||
$this->assertEquals($result, array('new', 'values'));
|
||||
|
||||
$result = $this->Toolbar->readCache('test', 1);
|
||||
$this->assertEquals($result, array('second', 'values'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test cache reading for views
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCacheRead() {
|
||||
$result = $this->Toolbar->writeCache('test', array('stuff', 'to', 'cache'));
|
||||
$this->assertTrue($result, 'Cache write failed %s');
|
||||
|
||||
$result = $this->Toolbar->readCache('test');
|
||||
$this->assertEquals($result, array('stuff', 'to', 'cache'), 'Cache value is wrong %s');
|
||||
|
||||
$result = $this->Toolbar->writeCache('test', array('new', 'stuff'));
|
||||
$this->assertTrue($result, 'Cache write failed %s');
|
||||
|
||||
$result = $this->Toolbar->readCache('test');
|
||||
$this->assertEquals($result, array('new', 'stuff'), 'Cache value is wrong %s');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that reading/writing doesn't work with no cache config.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNoCacheConfigPresent() {
|
||||
$this->Toolbar = new ToolbarHelper($this->View, array('output' => 'MockBackendHelper'));
|
||||
|
||||
$result = $this->Toolbar->writeCache('test', array('stuff', 'to', 'cache'));
|
||||
$this->assertFalse($result, 'Writing to cache succeeded with no cache config %s');
|
||||
|
||||
$result = $this->Toolbar->readCache('test');
|
||||
$this->assertFalse($result, 'Reading cache succeeded with no cache config %s');
|
||||
}
|
||||
|
||||
/**
|
||||
* ensure that getQueryLogs works and writes to the cache so the history panel will
|
||||
* work.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetQueryLogs() {
|
||||
$model = new CakeTestModel(array('table' => 'posts', 'alias' => 'Post'));
|
||||
$model->find('all');
|
||||
$model->find('first');
|
||||
|
||||
$result = $this->Toolbar->getQueryLogs($model->useDbConfig, array('cache' => false));
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(count($result) >= 2, 'Should be more than 2 queries in the log %s');
|
||||
$this->assertTrue(isset($result['queries'][0]['actions']));
|
||||
|
||||
$model->find('first');
|
||||
Cache::delete('debug_kit_toolbar_test_case', 'default');
|
||||
$result = $this->Toolbar->getQueryLogs($model->useDbConfig, array('cache' => true));
|
||||
|
||||
$cached = $this->Toolbar->readCache('sql_log');
|
||||
$this->assertTrue(isset($cached[$model->useDbConfig]));
|
||||
$this->assertEquals($cached[$model->useDbConfig]['queries'][0], $result['queries'][0]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* DebugKit TestController of test_app
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
**/
|
||||
|
||||
/**
|
||||
* Class DebugKitTestController
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class DebugKitTestController extends Controller {
|
||||
|
||||
/**
|
||||
* Mame of the Controller
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name = 'DebugKitTest';
|
||||
|
||||
/**
|
||||
* Uses no Models
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $uses = array();
|
||||
|
||||
/**
|
||||
* Uses only DebugKit Toolbar Component
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $components = array('DebugKit.Toolbar');
|
||||
|
||||
/**
|
||||
* Return Request Action Value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function request_action_return() {
|
||||
$this->autoRender = false;
|
||||
return 'I am some value from requestAction.';
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Request Action
|
||||
*/
|
||||
public function request_action_render() {
|
||||
$this->set('test', 'I have been rendered.');
|
||||
}
|
||||
}
|
||||
37
exp/Plugin/DebugKit/Test/test_app/Lib/Panel/TestPanel.php
Normal file
37
exp/Plugin/DebugKit/Test/test_app/Lib/Panel/TestPanel.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Test Panel of test_app
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Class TestPanel
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class TestPanel extends DebugPanel {
|
||||
|
||||
/**
|
||||
* Startup
|
||||
*
|
||||
* @param Controller $controller
|
||||
*/
|
||||
public function startup(Controller $controller) {
|
||||
$controller->testPanel = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Test Panel of test_app
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugPanel', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* Class PluginTestPanel
|
||||
*
|
||||
*/
|
||||
|
||||
class PluginTestPanel extends DebugPanel {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* Request Action Render template
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<?php echo $test; ?>
|
||||
1
exp/Plugin/DebugKit/VERSION.txt
Normal file
1
exp/Plugin/DebugKit/VERSION.txt
Normal file
@@ -0,0 +1 @@
|
||||
2.2.6
|
||||
59
exp/Plugin/DebugKit/View/Elements/debug_toolbar.ctp
Normal file
59
exp/Plugin/DebugKit/View/Elements/debug_toolbar.ctp
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Debug Toolbar Element
|
||||
*
|
||||
* Renders all of the other panel elements.
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<div id="debug-kit-toolbar">
|
||||
<?php if (empty($debugToolbarPanels)) :?>
|
||||
<p class="warning"><?php echo __d('debug_kit', 'There are no active panels. You must enable a panel to see its output.'); ?></p>
|
||||
<?php else: ?>
|
||||
<ul id="panel-tabs">
|
||||
<li class="panel-tab icon">
|
||||
<a href="#hide" id="hide-toolbar">
|
||||
<?php echo $this->Html->image('/debug_kit/img/cake.icon.png', array('alt' => 'CakePHP')); ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php foreach ($debugToolbarPanels as $panelName => $panelInfo): ?>
|
||||
<?php $panelUnderscore = Inflector::underscore($panelName);?>
|
||||
<li class="panel-tab">
|
||||
<?php
|
||||
$title = (empty($panelInfo['title'])) ? Inflector::humanize($panelUnderscore) : $panelInfo['title'];
|
||||
echo $this->Toolbar->panelStart($title, $panelUnderscore);
|
||||
?>
|
||||
<div class="panel-content" id="<?php echo $panelUnderscore ?>-tab">
|
||||
<a href="#" class="panel-toggle ui-control ui-button">+</a>
|
||||
<div class="panel-resize-region">
|
||||
<div class="panel-content-data">
|
||||
<?php
|
||||
echo $this->element($panelInfo['elementName'], $panelInfo, array(
|
||||
'plugin' => (empty($panelInfo['plugin'])) ? null : Inflector::camelize($panelInfo['plugin'])
|
||||
));
|
||||
?>
|
||||
</div>
|
||||
<div class="panel-content-data panel-history" id="<?php echo $panelUnderscore; ?>-history">
|
||||
<!-- content here -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-resize-handle ui-control">====</div>
|
||||
</div>
|
||||
<?php $this->Toolbar->panelEnd(); ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
84
exp/Plugin/DebugKit/View/Elements/environment_panel.ctp
Normal file
84
exp/Plugin/DebugKit/View/Elements/environment_panel.ctp
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* Environment Panel Element
|
||||
*
|
||||
* Shows information about the current app environment
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<h2><?php echo __d('debug_kit', 'App Constants'); ?></h2>
|
||||
<?php
|
||||
if (!empty($content['app'])) {
|
||||
$cakeRows = array();
|
||||
foreach ($content['app'] as $key => $val) {
|
||||
$cakeRows[] = array(
|
||||
$key,
|
||||
$val
|
||||
);
|
||||
}
|
||||
$headers = array('Constant', 'Value');
|
||||
echo $this->Toolbar->table($cakeRows, $headers, array('title' => 'Application Environment Vars'));
|
||||
} else {
|
||||
echo "No application environment available.";
|
||||
} ?>
|
||||
|
||||
<h2><?php echo __d('debug_kit', 'CakePHP Constants'); ?></h2>
|
||||
<?php
|
||||
if (!empty($content['cake'])) {
|
||||
$cakeRows = array();
|
||||
foreach ($content['cake'] as $key => $val) {
|
||||
$cakeRows[] = array(
|
||||
h($key),
|
||||
h($val)
|
||||
);
|
||||
}
|
||||
$headers = array('Constant', 'Value');
|
||||
echo $this->Toolbar->table($cakeRows, $headers, array('title' => 'CakePHP Environment Vars'));
|
||||
} else {
|
||||
echo "CakePHP environment unavailable.";
|
||||
} ?>
|
||||
|
||||
<h2><?php echo __d('debug_kit', 'PHP Environment');?></h2>
|
||||
<?php
|
||||
$headers = array('Environment Variable', 'Value');
|
||||
|
||||
if (!empty($content['php'])) {
|
||||
$phpRows = array();
|
||||
foreach ($content['php'] as $key => $val) {
|
||||
$phpRows[] = array(
|
||||
h(Inflector::humanize(strtolower($key))),
|
||||
h($val)
|
||||
);
|
||||
}
|
||||
echo $this->Toolbar->table($phpRows, $headers, array('title' => 'CakePHP Environment Vars'));
|
||||
} else {
|
||||
echo "PHP environment unavailable.";
|
||||
}
|
||||
|
||||
if (isset($content['hidef'])) {
|
||||
echo '<h2>' . __d('debug_kit', 'Hidef Environment') . '</h2>';
|
||||
if (!empty($content['hidef'])) {
|
||||
$cakeRows = array();
|
||||
foreach ($content['hidef'] as $key => $val) {
|
||||
$cakeRows[] = array(
|
||||
h($key),
|
||||
h($val)
|
||||
);
|
||||
}
|
||||
$headers = array('Constant', 'Value');
|
||||
echo $this->Toolbar->table($cakeRows, $headers, array('title' => 'Hidef Environment Vars'));
|
||||
} else {
|
||||
echo "No Hidef environment available.";
|
||||
}
|
||||
}
|
||||
32
exp/Plugin/DebugKit/View/Elements/history_panel.ctp
Normal file
32
exp/Plugin/DebugKit/View/Elements/history_panel.ctp
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* View Variables Panel Element
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<h2> <?php echo __d('debug_kit', 'Request History'); ?></h2>
|
||||
<?php if (empty($content)): ?>
|
||||
<p class="warning"><?php echo __d('debug_kit', 'No previous requests logged.'); ?></p>
|
||||
<?php else: ?>
|
||||
<?php echo count($content); ?> <?php echo __d('debug_kit', 'previous requests available') ?>
|
||||
<ul class="history-list">
|
||||
<li><?php echo $this->Html->link(__d('debug_kit', 'Restore to current request'),
|
||||
'#', array('class' => 'history-link', 'id' => 'history-restore-current')); ?>
|
||||
</li>
|
||||
<?php foreach ($content as $previous): ?>
|
||||
<li><?php echo $this->Html->link($previous['title'], $previous['url'], array('class' => 'history-link')); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif;
|
||||
34
exp/Plugin/DebugKit/View/Elements/include_panel.ctp
Normal file
34
exp/Plugin/DebugKit/View/Elements/include_panel.ctp
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* Included Files Element
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 2.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
**/
|
||||
?>
|
||||
<h2> <?php echo __d('debug_kit', 'Included Files'); ?></h2>
|
||||
|
||||
<h4>Include Paths</h4>
|
||||
<?php
|
||||
foreach ($content['paths'] as $i => $path) {
|
||||
if (strstr($path, CAKE)) {
|
||||
$content['paths'][$i] = '-> ' . $path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
echo $this->Toolbar->makeNeatArray(array_filter($content['paths']));
|
||||
unset($content['paths']);
|
||||
?>
|
||||
|
||||
<h4>Included Files</h4>
|
||||
<?php echo $this->Toolbar->makeNeatArray($content);
|
||||
41
exp/Plugin/DebugKit/View/Elements/log_panel.ctp
Normal file
41
exp/Plugin/DebugKit/View/Elements/log_panel.ctp
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Log Panel Element
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<h2><?php echo __d('debug_kit', 'Logs') ?></h2>
|
||||
<div class="code-table">
|
||||
<?php if ($content instanceof DebugKitLog): ?>
|
||||
<?php foreach ($content->logs as $logName => $logs): ?>
|
||||
<h3><?php echo $logName ?></h3>
|
||||
<?php
|
||||
$len = count($logs);
|
||||
if ($len > 0):
|
||||
$headers = array(__d('debug_kit', 'Time'), __d('debug_kit', 'Message'));
|
||||
$rows = array();
|
||||
for ($i = 0; $i < $len; $i++):
|
||||
$rows[] = array(
|
||||
$logs[$i][0], h($logs[$i][1])
|
||||
);
|
||||
endfor;
|
||||
echo $this->Toolbar->table($rows, $headers, array('title' => $logName));
|
||||
endif; ?>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($content->logs)): ?>
|
||||
<p class="info"><?php echo __d('debug_kit', 'There were no log entries made this request'); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
50
exp/Plugin/DebugKit/View/Elements/request_panel.ctp
Normal file
50
exp/Plugin/DebugKit/View/Elements/request_panel.ctp
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Request Panel Element
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<h2> <?php echo __d('debug_kit', 'Request'); ?></h2>
|
||||
|
||||
<h4>Cake Params</h4>
|
||||
<?php echo $this->Toolbar->makeNeatArray($content['params']); ?>
|
||||
|
||||
<h4>Post data</h4>
|
||||
<?php
|
||||
if (empty($content['data'])):
|
||||
echo '<p class="info">' . __d('debug_kit', 'No post data.') . '</p>';
|
||||
else:
|
||||
echo $this->Toolbar->makeNeatArray($content['data']);
|
||||
endif;
|
||||
?>
|
||||
|
||||
<h4>Query string</h4>
|
||||
<?php
|
||||
if (empty($content['query'])):
|
||||
echo '<p class="info">' . __d('debug_kit', 'No querystring data.') . '</p>';
|
||||
else:
|
||||
echo $this->Toolbar->makeNeatArray($content['query']);
|
||||
endif;
|
||||
?>
|
||||
|
||||
<h4>Cookie</h4>
|
||||
<?php if (isset($content['cookie'])): ?>
|
||||
<?php echo $this->Toolbar->makeNeatArray($content['cookie']); ?>
|
||||
<?php else: ?>
|
||||
<p class="info">To view Cookies, add CookieComponent to Controller</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<h4><?php echo __d('debug_kit', 'Current Route') ?></h4>
|
||||
<?php echo $this->Toolbar->makeNeatArray($content['currentRoute']);
|
||||
20
exp/Plugin/DebugKit/View/Elements/session_panel.ctp
Normal file
20
exp/Plugin/DebugKit/View/Elements/session_panel.ctp
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Session Panel Element
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<h2><?php echo __d('debug_kit', 'Session'); ?></h2>
|
||||
<?php echo $this->Toolbar->makeNeatArray($content);
|
||||
80
exp/Plugin/DebugKit/View/Elements/sql_log_panel.ctp
Normal file
80
exp/Plugin/DebugKit/View/Elements/sql_log_panel.ctp
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* SQL Log Panel Element
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
$headers = array('Query', 'Affected', 'Num. rows', 'Took (ms)', 'Actions');
|
||||
if (isset($debugKitInHistoryMode)) {
|
||||
$content = $this->Toolbar->readCache('sql_log', $this->request->params['pass'][0]);
|
||||
}
|
||||
?>
|
||||
<h2><?php echo __d('debug_kit', 'Sql Logs')?></h2>
|
||||
<?php if (!empty($content)) : ?>
|
||||
<?php foreach ($content['connections'] as $dbName => $explain): ?>
|
||||
<div class="sql-log-panel-query-log">
|
||||
<h4><?php echo $dbName ?></h4>
|
||||
<?php
|
||||
if (!isset($debugKitInHistoryMode)):
|
||||
$queryLog = $this->Toolbar->getQueryLogs($dbName, array(
|
||||
'explain' => $explain, 'threshold' => $content['threshold']
|
||||
));
|
||||
else:
|
||||
$queryLog = $content[$dbName];
|
||||
endif;
|
||||
if (empty($queryLog['queries'])):
|
||||
if (Configure::read('debug') < 2):
|
||||
echo ' ' . __d('debug_kit', 'No query logs when debug < 2.');
|
||||
else:
|
||||
echo ' ' . __d('debug_kit', 'No query logs.');
|
||||
endif;
|
||||
else:
|
||||
$hashes = array();
|
||||
$duplicate = 0;
|
||||
foreach ($queryLog['queries'] as $key => $val) {
|
||||
$hash = sha1($val['query']);
|
||||
if (!isset($hashes[$hash]) || $hashes[$hash] !== $val['affected']) {
|
||||
$hashes[$hash] = $val['affected'];
|
||||
continue;
|
||||
}
|
||||
$duplicate++;
|
||||
|
||||
$queryLog['queries'][$key]['query'] = '<span class="alert-duplicate">' . $val['query'] . '</span>';
|
||||
}
|
||||
|
||||
echo '<h5>';
|
||||
echo __d(
|
||||
'debug_kit',
|
||||
'Total Time: %s ms <br />Total Queries: %s queries',
|
||||
$queryLog['time'],
|
||||
$queryLog['count']
|
||||
);
|
||||
echo '</h5>';
|
||||
echo $this->Toolbar->table($queryLog['queries'], $headers, array('title' => 'SQL Log ' . $dbName));
|
||||
if ($duplicate) {
|
||||
echo '<p class="alert alert-warning">' . __d('debug_kit', '%s duplicate queries run.', $duplicate) . '</p>';
|
||||
}
|
||||
?>
|
||||
<h4><?php echo __d('debug_kit', 'Query Explain:'); ?></h4>
|
||||
<div id="sql-log-explain-<?php echo $dbName ?>">
|
||||
<a id="debug-kit-explain-<?php echo $dbName ?>"> </a>
|
||||
<p><?php echo __d('debug_kit', 'Click an "Explain" link above, to see the query explanation.'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php else:
|
||||
echo $this->Toolbar->message('Warning', __d('debug_kit', 'No active database connections'));
|
||||
endif;
|
||||
110
exp/Plugin/DebugKit/View/Elements/timer_panel.ctp
Normal file
110
exp/Plugin/DebugKit/View/Elements/timer_panel.ctp
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
* Timer Panel Element
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
$this->Number = $this->Helpers->load('Number');
|
||||
$this->SimpleGraph = $this->Helpers->load('DebugKit.SimpleGraph');
|
||||
|
||||
if (!isset($debugKitInHistoryMode)):
|
||||
$timers = DebugTimer::getAll(true);
|
||||
$currentMemory = DebugKitDebugger::getMemoryUse();
|
||||
$peakMemory = DebugKitDebugger::getPeakMemoryUse();
|
||||
$requestTime = DebugTimer::requestTime();
|
||||
else:
|
||||
$content = $this->Toolbar->readCache('timer', $this->request->params['pass'][0]);
|
||||
if (is_array($content)):
|
||||
extract($content);
|
||||
endif;
|
||||
endif;
|
||||
?>
|
||||
<div class="debug-info">
|
||||
<h2><?php echo __d('debug_kit', 'Memory'); ?></h2>
|
||||
<div class="peak-mem-use">
|
||||
<?php
|
||||
echo $this->Toolbar->message(__d('debug_kit', 'Peak Memory Use'), $this->Number->toReadableSize($peakMemory)); ?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$headers = array(__d('debug_kit', 'Message'), __d('debug_kit', 'Memory use'));
|
||||
$memoryPoints = DebugKitDebugger::getMemoryPoints();
|
||||
|
||||
$rows = array();
|
||||
foreach ($memoryPoints as $key => $value):
|
||||
$rows[] = array($key, $this->Number->toReadableSize($value));
|
||||
endforeach;
|
||||
|
||||
echo $this->Toolbar->table($rows, $headers);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="debug-info debug-timers">
|
||||
<h2><?php echo __d('debug_kit', 'Timers'); ?></h2>
|
||||
<div class="request-time">
|
||||
<?php $totalTime = __d('debug_kit', '%s (ms)', $this->Number->precision($requestTime * 1000, 0)); ?>
|
||||
<?php echo $this->Toolbar->message(__d('debug_kit', 'Total Request Time:'), $totalTime)?>
|
||||
</div>
|
||||
<?php
|
||||
$rows = array();
|
||||
$end = end($timers);
|
||||
$maxTime = $end['end'];
|
||||
|
||||
$headers = array(
|
||||
__d('debug_kit', 'Message'),
|
||||
__d('debug_kit', 'Time in ms'),
|
||||
__d('debug_kit', 'Graph')
|
||||
);
|
||||
|
||||
$i = 0;
|
||||
$values = array_values($timers);
|
||||
|
||||
foreach ($timers as $timerName => $timeInfo):
|
||||
$indent = 0;
|
||||
for ($j = 0; $j < $i; $j++) {
|
||||
if (($values[$j]['end'] > $timeInfo['start']) && ($values[$j]['end']) > ($timeInfo['end'])) {
|
||||
$indent++;
|
||||
}
|
||||
}
|
||||
$indent = str_repeat(' » ', $indent);
|
||||
$rows[] = array(
|
||||
$indent . $timeInfo['message'],
|
||||
$this->Number->precision($timeInfo['time'] * 1000, 2),
|
||||
$this->SimpleGraph->bar(
|
||||
$this->Number->precision($timeInfo['time'] * 1000, 2),
|
||||
$this->Number->precision($timeInfo['start'] * 1000, 2),
|
||||
array(
|
||||
'max' => $maxTime * 1000,
|
||||
'requestTime' => $requestTime * 1000,
|
||||
)
|
||||
)
|
||||
);
|
||||
$i++;
|
||||
endforeach;
|
||||
|
||||
if (strtolower($this->Toolbar->getName()) === 'firephptoolbar'):
|
||||
for ($i = 0, $len = count($rows); $i < $len; $i++):
|
||||
unset($rows[$i][2]);
|
||||
endfor;
|
||||
unset($headers[2]);
|
||||
endif;
|
||||
|
||||
echo $this->Toolbar->table($rows, $headers, array('title' => 'Timers'));
|
||||
|
||||
if (!isset($debugKitInHistoryMode)):
|
||||
$this->Toolbar->writeCache('timer', compact('timers', 'currentMemory', 'peakMemory', 'requestTime'));
|
||||
endif;
|
||||
?>
|
||||
</div>
|
||||
23
exp/Plugin/DebugKit/View/Elements/variables_panel.ctp
Normal file
23
exp/Plugin/DebugKit/View/Elements/variables_panel.ctp
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* View Variables Panel Element
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<h2> <?php echo __d('debug_kit', 'View Variables'); ?></h2>
|
||||
<?php
|
||||
$content['$this->validationErrors'] = $this->validationErrors;
|
||||
$content['Loaded Helpers'] = $this->Helpers->attached();
|
||||
echo $this->Toolbar->makeNeatArray($content);
|
||||
90
exp/Plugin/DebugKit/View/Helper/DebugTimerHelper.php
Normal file
90
exp/Plugin/DebugKit/View/Helper/DebugTimerHelper.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 2.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugTimer', 'DebugKit.Lib');
|
||||
App::uses('DebugMemory', 'DebugKit.Lib');
|
||||
App::uses('Helper', 'View');
|
||||
|
||||
/**
|
||||
* Class DebugTimerHelper
|
||||
*
|
||||
* Tracks time and memory usage while rendering view.
|
||||
*
|
||||
*/
|
||||
class DebugTimerHelper extends Helper {
|
||||
|
||||
/**
|
||||
* Set to true when rendering is complete.
|
||||
* Used to not add timers for rendering the toolbar.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_renderComplete = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param View $View
|
||||
* @param array $settings
|
||||
*/
|
||||
public function __construct(View $View, $settings = array()) {
|
||||
parent::__construct($View, $settings);
|
||||
DebugTimer::start(
|
||||
'viewRender',
|
||||
__d('debug_kit', 'Rendering View')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a timer point before rendering a file.
|
||||
*
|
||||
* @param string $viewFile The view being rendered
|
||||
*/
|
||||
public function beforeRenderFile($viewFile) {
|
||||
if ($this->_renderComplete) {
|
||||
return;
|
||||
}
|
||||
DebugTimer::start(
|
||||
'render_' . basename($viewFile),
|
||||
__d('debug_kit', 'Rendering %s',
|
||||
Debugger::trimPath($viewFile))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the timer point before rendering a file.
|
||||
*
|
||||
* @param string $viewFile The view being rendered
|
||||
* @param string $content The contents of the view.
|
||||
*/
|
||||
public function afterRenderFile($viewFile, $content) {
|
||||
if ($this->_renderComplete) {
|
||||
return;
|
||||
}
|
||||
DebugTimer::stop('render_' . basename($viewFile));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop timers for rendering.
|
||||
*
|
||||
* @param string $layoutFile
|
||||
*/
|
||||
public function afterLayout($layoutFile) {
|
||||
DebugTimer::stop('viewRender');
|
||||
DebugTimer::stop('controllerRender');
|
||||
DebugMemory::record(__d('debug_kit', 'View render complete'));
|
||||
$this->_renderComplete = true;
|
||||
}
|
||||
|
||||
}
|
||||
106
exp/Plugin/DebugKit/View/Helper/FirePhpToolbarHelper.php
Normal file
106
exp/Plugin/DebugKit/View/Helper/FirePhpToolbarHelper.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('ToolbarHelper', 'DebugKit.View/Helper');
|
||||
App::uses('FireCake', 'DebugKit.Lib');
|
||||
|
||||
/**
|
||||
* FirePHP Toolbar Helper
|
||||
*
|
||||
* Injects the toolbar elements into non-HTML layouts via FireCake.
|
||||
*
|
||||
*/
|
||||
class FirePhpToolbarHelper extends ToolbarHelper {
|
||||
|
||||
/**
|
||||
* settings property
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $settings = array('format' => 'firePHP', 'forceEnable' => false);
|
||||
|
||||
/**
|
||||
* send method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function send() {
|
||||
$view = $this->_View;
|
||||
$view->element('debug_toolbar', array('disableTimer' => true), array('plugin' => 'DebugKit'));
|
||||
}
|
||||
|
||||
/**
|
||||
* makeNeatArray.
|
||||
*
|
||||
* wraps FireCake::dump() allowing panel elements to continue functioning
|
||||
*
|
||||
* @param string $values
|
||||
* @return void
|
||||
*/
|
||||
public function makeNeatArray($values) {
|
||||
FireCake::info($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a simple message
|
||||
*
|
||||
* @param string $label Label of message
|
||||
* @param string $message Message content
|
||||
* @return void
|
||||
*/
|
||||
public function message($label, $message) {
|
||||
FireCake::log($message, $label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a table with FireCake
|
||||
*
|
||||
* @param array $rows Rows to print
|
||||
* @param array $headers Headers for table
|
||||
* @param array $options Additional options and params
|
||||
* @return void
|
||||
*/
|
||||
public function table($rows, $headers, $options = array()) {
|
||||
$title = $headers[0];
|
||||
if (isset($options['title'])) {
|
||||
$title = $options['title'];
|
||||
}
|
||||
foreach ($rows as $i => $row) {
|
||||
$rows[$i] = array_values($row);
|
||||
}
|
||||
array_unshift($rows, $headers);
|
||||
FireCake::table($title, $rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a panel which is a 'Group' in FirePHP
|
||||
*
|
||||
* @param $title
|
||||
* @param $anchor
|
||||
* @return void
|
||||
*/
|
||||
public function panelStart($title, $anchor) {
|
||||
FireCake::group($title);
|
||||
}
|
||||
|
||||
/**
|
||||
* End a panel (Group)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function panelEnd() {
|
||||
FireCake::groupEnd();
|
||||
}
|
||||
|
||||
}
|
||||
238
exp/Plugin/DebugKit/View/Helper/HtmlToolbarHelper.php
Normal file
238
exp/Plugin/DebugKit/View/Helper/HtmlToolbarHelper.php
Normal file
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('ToolbarHelper', 'DebugKit.View/Helper');
|
||||
App::uses('Security', 'Utility');
|
||||
|
||||
/**
|
||||
* Html Toolbar Helper
|
||||
*
|
||||
* Injects the toolbar elements into HTML layouts.
|
||||
* Contains helper methods for
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class HtmlToolbarHelper extends ToolbarHelper {
|
||||
|
||||
/**
|
||||
* helpers property
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $helpers = array('Html', 'Form');
|
||||
|
||||
/**
|
||||
* settings property
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $settings = array('format' => 'html', 'forceEnable' => false);
|
||||
|
||||
/**
|
||||
* Recursively goes through an array and makes neat HTML out of it.
|
||||
*
|
||||
* @param mixed $values Array to make pretty.
|
||||
* @param integer $openDepth Depth to add open class
|
||||
* @param integer $currentDepth current depth.
|
||||
* @param boolean $doubleEncode
|
||||
* @return string
|
||||
*/
|
||||
public function makeNeatArray($values, $openDepth = 0, $currentDepth = 0, $doubleEncode = false) {
|
||||
static $printedObjects = null;
|
||||
if ($currentDepth === 0) {
|
||||
$printedObjects = new SplObjectStorage();
|
||||
}
|
||||
$className = "neat-array depth-$currentDepth";
|
||||
if ($openDepth > $currentDepth) {
|
||||
$className .= ' expanded';
|
||||
}
|
||||
$nextDepth = $currentDepth + 1;
|
||||
$out = "<ul class=\"$className\">";
|
||||
if (!is_array($values)) {
|
||||
if (is_bool($values)) {
|
||||
$values = array($values);
|
||||
}
|
||||
if ($values === null) {
|
||||
$values = array(null);
|
||||
}
|
||||
}
|
||||
if (empty($values)) {
|
||||
$values[] = '(empty)';
|
||||
}
|
||||
foreach ($values as $key => $value) {
|
||||
$out .= '<li><strong>' . h($key, $doubleEncode) . '</strong>';
|
||||
if (is_array($value) && count($value) > 0) {
|
||||
$out .= '(array)';
|
||||
} elseif (is_object($value)) {
|
||||
$out .= '(object)';
|
||||
}
|
||||
if ($value === null) {
|
||||
$value = '(null)';
|
||||
}
|
||||
if ($value === false) {
|
||||
$value = '(false)';
|
||||
}
|
||||
if ($value === true) {
|
||||
$value = '(true)';
|
||||
}
|
||||
if (empty($value) && $value != 0) {
|
||||
$value = '(empty)';
|
||||
}
|
||||
if ($value instanceof Closure) {
|
||||
$value = 'function';
|
||||
}
|
||||
|
||||
$isObject = is_object($value);
|
||||
if ($isObject && $printedObjects->contains($value)) {
|
||||
$isObject = false;
|
||||
$value = ' - recursion';
|
||||
}
|
||||
|
||||
if ($isObject) {
|
||||
$printedObjects->attach($value);
|
||||
}
|
||||
|
||||
if (
|
||||
(
|
||||
$value instanceof ArrayAccess ||
|
||||
$value instanceof Iterator ||
|
||||
is_array($value) ||
|
||||
$isObject
|
||||
) && !empty($value)
|
||||
) {
|
||||
$out .= $this->makeNeatArray($value, $openDepth, $nextDepth, $doubleEncode);
|
||||
} else {
|
||||
$out .= h($value, $doubleEncode);
|
||||
}
|
||||
$out .= '</li>';
|
||||
}
|
||||
$out .= '</ul>';
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an HTML message
|
||||
*
|
||||
* @param string $label label content
|
||||
* @param string $message message content
|
||||
* @return string
|
||||
*/
|
||||
public function message($label, $message) {
|
||||
return sprintf('<p><strong>%s</strong> %s</p>', $label, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a panel.
|
||||
* Make a link and anchor.
|
||||
*
|
||||
* @param $title
|
||||
* @param $anchor
|
||||
* @return string
|
||||
*/
|
||||
public function panelStart($title, $anchor) {
|
||||
$link = $this->Html->link($title, '#' . $anchor);
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a table.
|
||||
*
|
||||
* @param array $rows Rows to make.
|
||||
* @param array $headers Optional header row.
|
||||
* @return string
|
||||
*/
|
||||
public function table($rows, $headers = array()) {
|
||||
$out = '<table class="debug-table">';
|
||||
if (!empty($headers)) {
|
||||
$out .= $this->Html->tableHeaders($headers);
|
||||
}
|
||||
$out .= $this->Html->tableCells($rows, array('class' => 'odd'), array('class' => 'even'), false, false);
|
||||
$out .= '</table>';
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function send() {
|
||||
if (!$this->settings['forceEnable'] && Configure::read('debug') == 0) {
|
||||
return;
|
||||
}
|
||||
$view = $this->_View;
|
||||
$head = '';
|
||||
if (isset($view->viewVars['debugToolbarCss']) && !empty($view->viewVars['debugToolbarCss'])) {
|
||||
$head .= $this->Html->css($view->viewVars['debugToolbarCss']);
|
||||
}
|
||||
|
||||
$js = sprintf('window.DEBUGKIT_JQUERY_URL = "%s";', $this->webroot('/debug_kit/js/jquery.js'));
|
||||
$head .= $this->Html->scriptBlock($js);
|
||||
|
||||
if (isset($view->viewVars['debugToolbarJavascript'])) {
|
||||
foreach ($view->viewVars['debugToolbarJavascript'] as $script) {
|
||||
if ($script) {
|
||||
$head .= $this->Html->script($script);
|
||||
}
|
||||
}
|
||||
}
|
||||
$search = '</head>';
|
||||
$pos = strpos($view->output, $search);
|
||||
if ($pos !== false) {
|
||||
$view->output = substr_replace($view->output, $head . "\n</head>", $pos, strlen($search));
|
||||
}
|
||||
$toolbar = $view->element('debug_toolbar', array('disableTimer' => true), array('plugin' => 'DebugKit'));
|
||||
$search = '</body>';
|
||||
$pos = strrpos($view->output, $search);
|
||||
if ($pos !== false) {
|
||||
$view->output = substr_replace($view->output, $toolbar . "\n</body>", $pos, strlen($search));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a SQL explain link for a given query
|
||||
*
|
||||
* @param string $sql SQL query string you want an explain link for.
|
||||
* @param $connection
|
||||
* @return string Rendered Html link or '' if the query is not a select/describe
|
||||
*/
|
||||
public function explainLink($sql, $connection) {
|
||||
if (!preg_match('/^[\s()]*SELECT/i', $sql)) {
|
||||
return '';
|
||||
}
|
||||
$sql = str_replace(array("\n", "\t"), ' ', $sql);
|
||||
$hash = Security::hash($sql . $connection, 'sha1', true);
|
||||
$url = array(
|
||||
'plugin' => 'debug_kit',
|
||||
'controller' => 'toolbar_access',
|
||||
'action' => 'sql_explain'
|
||||
);
|
||||
foreach (Router::prefixes() as $prefix) {
|
||||
$url[$prefix] = false;
|
||||
}
|
||||
$this->explainLinkUid = (isset($this->explainLinkUid) ? $this->explainLinkUid + 1 : 0);
|
||||
$uid = $this->explainLinkUid . '_' . rand(0, 10000);
|
||||
$form = $this->Form->create('log', array('url' => $url, 'id' => "logForm{$uid}"));
|
||||
$form .= $this->Form->hidden('log.ds', array('id' => "logDs{$uid}", 'value' => $connection));
|
||||
$form .= $this->Form->hidden('log.sql', array('id' => "logSql{$uid}", 'value' => $sql));
|
||||
$form .= $this->Form->hidden('log.hash', array('id' => "logHash{$uid}", 'value' => $hash));
|
||||
$form .= $this->Form->submit(__d('debug_kit', 'Explain'), array(
|
||||
'div' => false,
|
||||
'class' => 'sql-explain-link'
|
||||
));
|
||||
$form .= $this->Form->end();
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
88
exp/Plugin/DebugKit/View/Helper/SimpleGraphHelper.php
Normal file
88
exp/Plugin/DebugKit/View/Helper/SimpleGraphHelper.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('AppHelper', 'View/Helper');
|
||||
App::uses('HtmlHelper', 'View/Helper');
|
||||
|
||||
/**
|
||||
* Class SimpleGraphHelper
|
||||
*
|
||||
* Allows creation and display of extremely simple graphing elements
|
||||
*
|
||||
* @since DebugKit 1.0
|
||||
*/
|
||||
class SimpleGraphHelper extends AppHelper {
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $helpers = array('Html');
|
||||
|
||||
/**
|
||||
* Default settings to be applied to each Simple Graph
|
||||
*
|
||||
* Allowed options:
|
||||
*
|
||||
* - max => (int) Maximum value in the graphs
|
||||
* - width => (int)
|
||||
* - valueType => string (value, percentage)
|
||||
* - style => array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_defaultSettings = array(
|
||||
'max' => 100,
|
||||
'width' => 350,
|
||||
'valueType' => 'value',
|
||||
);
|
||||
|
||||
/**
|
||||
* bar method
|
||||
*
|
||||
* @param $value Value to be graphed
|
||||
* @param $offset how much indentation
|
||||
* @param array|\Graph $options Graph options
|
||||
* @return string Html graph
|
||||
*/
|
||||
public function bar($value, $offset, $options = array()) {
|
||||
$settings = array_merge($this->_defaultSettings, $options);
|
||||
extract($settings);
|
||||
|
||||
$graphValue = ($value / $max) * $width;
|
||||
$graphValue = max(round($graphValue), 1);
|
||||
|
||||
if ($valueType === 'percentage') {
|
||||
$graphOffset = 0;
|
||||
} else {
|
||||
$graphOffset = ($offset / $max) * $width;
|
||||
$graphOffset = round($graphOffset);
|
||||
}
|
||||
return $this->Html->div(
|
||||
'debug-kit-graph-bar',
|
||||
$this->Html->div(
|
||||
'debug-kit-graph-bar-value',
|
||||
' ',
|
||||
array(
|
||||
'style' => "margin-left: {$graphOffset}px; width: {$graphValue}px",
|
||||
'title' => __d('debug_kit', "Starting %sms into the request, taking %sms", $offset, $value),
|
||||
)
|
||||
),
|
||||
array('style' => "width: {$width}px;"),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
171
exp/Plugin/DebugKit/View/Helper/TidyHelper.php
Normal file
171
exp/Plugin/DebugKit/View/Helper/TidyHelper.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since v 1.0 (22-Jun-2009)
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('File', 'Utility');
|
||||
|
||||
/**
|
||||
* TidyHelper class
|
||||
*
|
||||
* Passes html through tidy on the command line, and reports markup errors
|
||||
*
|
||||
* @uses AppHelper
|
||||
* @since v 1.0 (22-Jun-2009)
|
||||
*/
|
||||
class TidyHelper extends AppHelper {
|
||||
|
||||
/**
|
||||
* helpers property
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $helpers = array('DebugKit.Toolbar');
|
||||
|
||||
/**
|
||||
* results property
|
||||
*
|
||||
* @var mixed null
|
||||
*/
|
||||
public $results = null;
|
||||
|
||||
/**
|
||||
* Return a nested array of errors for the passed html string
|
||||
* Fudge the markup slightly so that the tag which is invalid is highlighted
|
||||
*
|
||||
* @param string $html ''
|
||||
* @param string $out ''
|
||||
* @return array
|
||||
*/
|
||||
public function process($html = '', &$out = '') {
|
||||
$errors = $this->tidyErrors($html, $out);
|
||||
|
||||
if (!$errors) {
|
||||
return array();
|
||||
}
|
||||
$result = array('Error' => array(), 'Warning' => array(), 'Misc' => array());
|
||||
$errors = explode("\n", $errors);
|
||||
$markup = explode("\n", $out);
|
||||
foreach ($errors as $error) {
|
||||
preg_match('@line (\d+) column (\d+) - (\w+): (.*)@', $error, $matches);
|
||||
if ($matches) {
|
||||
list($original, $line, $column, $type, $message) = $matches;
|
||||
$line = $line - 1;
|
||||
|
||||
$string = '</strong>';
|
||||
if (isset($markup[$line - 1])) {
|
||||
$string .= h($markup[$line - 1]);
|
||||
}
|
||||
$string .= '<strong>' . h(@$markup[$line]) . '</strong>';
|
||||
if (isset($markup[$line + 1])) {
|
||||
$string .= h($markup[$line + 1]);
|
||||
}
|
||||
$string .= '</strong>';
|
||||
|
||||
$result[$type][$string][] = h($message);
|
||||
} elseif ($error) {
|
||||
$message = $error;
|
||||
$result['Misc'][h($message)][] = h($message);
|
||||
}
|
||||
}
|
||||
$this->results = $result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* report method
|
||||
*
|
||||
* Call process if a string is passed, or no prior results exist - and return the results using
|
||||
* the toolbar helper to generate a nested navigatable array
|
||||
*
|
||||
* @param mixed $html null
|
||||
* @return string
|
||||
*/
|
||||
public function report($html = null) {
|
||||
if ($html) {
|
||||
$this->process($html);
|
||||
} elseif ($this->results === null) {
|
||||
$this->process($this->_View->output);
|
||||
}
|
||||
if (!$this->results) {
|
||||
return '<p>' . __d('debug_kit', 'No markup errors found') . '</p>';
|
||||
}
|
||||
foreach ($this->results as &$results) {
|
||||
foreach ($results as $type => &$messages) {
|
||||
foreach ($messages as &$message) {
|
||||
$message = html_entity_decode($message, ENT_COMPAT, Configure::read('App.encoding'));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->Toolbar->makeNeatArray(array_filter($this->results), 0, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the html string through tidy, and return the (raw) errors. pass back a reference to the
|
||||
* normalized string so that the error messages can be linked to the line that caused them.
|
||||
*
|
||||
* @param string $in ''
|
||||
* @param string $out ''
|
||||
* @return string
|
||||
*/
|
||||
public function tidyErrors($in = '', &$out = '') {
|
||||
$out = preg_replace('@>\s*<@s', ">\n<", $in);
|
||||
|
||||
// direct access? windows etc
|
||||
if (function_exists('tidy_parse_string')) {
|
||||
$tidy = tidy_parse_string($out, array(), 'UTF8');
|
||||
$tidy->cleanRepair();
|
||||
$errors = $tidy->errorBuffer . "\n";
|
||||
return $errors;
|
||||
}
|
||||
|
||||
// cli
|
||||
$File = new File(rtrim(TMP, DS) . DS . rand() . '.html', true);
|
||||
$File->write($out);
|
||||
$path = $File->pwd();
|
||||
$errors = $path . '.err';
|
||||
$this->_exec("tidy -eq -utf8 -f $errors $path");
|
||||
$File->delete();
|
||||
|
||||
if (!file_exists($errors)) {
|
||||
return '';
|
||||
}
|
||||
$Error = new File($errors);
|
||||
$errors = $Error->read();
|
||||
$Error->delete();
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* exec method
|
||||
*
|
||||
* @param mixed $cmd
|
||||
* @param mixed $out null
|
||||
* @return boolean True if successful
|
||||
*/
|
||||
protected function _exec($cmd, &$out = null) {
|
||||
if (DS === '/') {
|
||||
$_out = exec($cmd . ' 2>&1', $out, $return);
|
||||
} else {
|
||||
$_out = exec($cmd, $out, $return);
|
||||
}
|
||||
|
||||
if (Configure::read('debug')) {
|
||||
$source = Debugger::trace(array('depth' => 1, 'start' => 2)) . "\n";
|
||||
//CakeLog::write('system_calls_' . date('Y-m-d'), "\n" . $source . Debugger::exportVar(compact('cmd','out','return')));
|
||||
//CakeLog::write('system_calls', "\n" . $source . Debugger::exportVar(compact('cmd','out','return')));
|
||||
}
|
||||
if ($return) {
|
||||
return false;
|
||||
}
|
||||
return $_out ? $_out : true;
|
||||
}
|
||||
}
|
||||
226
exp/Plugin/DebugKit/View/Helper/ToolbarHelper.php
Normal file
226
exp/Plugin/DebugKit/View/Helper/ToolbarHelper.php
Normal file
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('DebugKitDebugger', 'DebugKit.Lib');
|
||||
App::uses('AppHelper', 'View/Helper');
|
||||
App::uses('ConnectionManager', 'Model');
|
||||
|
||||
/**
|
||||
* Provides Base methods for content specific debug toolbar helpers.
|
||||
* Acts as a facade for other toolbars helpers as well.
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class ToolbarHelper extends AppHelper {
|
||||
|
||||
/**
|
||||
* settings property to be overloaded. Subclasses should specify a format
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $settings = array();
|
||||
|
||||
/**
|
||||
* flag for whether or not cache is enabled.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_cacheEnabled = false;
|
||||
|
||||
/**
|
||||
* Construct the helper and make the backend helper.
|
||||
*
|
||||
* @param $View
|
||||
* @param array|string $options
|
||||
* @return \ToolbarHelper
|
||||
*/
|
||||
public function __construct($View, $options = array()) {
|
||||
$this->_myName = strtolower(get_class($this));
|
||||
$this->settings = array_merge($this->settings, $options);
|
||||
|
||||
if ($this->_myName !== 'toolbarhelper') {
|
||||
parent::__construct($View, $options);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($options['output'])) {
|
||||
$options['output'] = 'DebugKit.HtmlToolbar';
|
||||
}
|
||||
$className = $options['output'];
|
||||
if (strpos($options['output'], '.') !== false) {
|
||||
list($plugin, $className) = explode('.', $options['output']);
|
||||
}
|
||||
$this->_backEndClassName = $className;
|
||||
$this->helpers[$options['output']] = $options;
|
||||
if (isset($options['cacheKey']) && isset($options['cacheConfig'])) {
|
||||
$this->_cacheKey = $options['cacheKey'];
|
||||
$this->_cacheConfig = $options['cacheConfig'];
|
||||
$this->_cacheEnabled = true;
|
||||
}
|
||||
|
||||
parent::__construct($View, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* afterLayout callback
|
||||
*
|
||||
* @param string $layoutFile
|
||||
* @return void
|
||||
*/
|
||||
public function afterLayout($layoutFile) {
|
||||
if (!$this->request->is('requested')) {
|
||||
$this->send();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the backend Helper
|
||||
* used to conditionally trigger toolbar output
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->_backEndClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* call__
|
||||
*
|
||||
* Allows method calls on backend helper
|
||||
*
|
||||
* @param string $method
|
||||
* @param mixed $params
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function __call($method, $params) {
|
||||
if (method_exists($this->{$this->_backEndClassName}, $method)) {
|
||||
return $this->{$this->_backEndClassName}->dispatchMethod($method, $params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows for writing to panel cache from view.
|
||||
* Some panels generate all variables in the view by
|
||||
* necessity ie. Timer. Using this method, will allow you to replace in full
|
||||
* the content for a panel.
|
||||
*
|
||||
* @param string $name Name of the panel you are replacing.
|
||||
* @param string $content Content to write to the panel.
|
||||
* @return boolean Success of write.
|
||||
*/
|
||||
public function writeCache($name, $content) {
|
||||
if (!$this->_cacheEnabled) {
|
||||
return false;
|
||||
}
|
||||
$existing = (array)Cache::read($this->_cacheKey, $this->_cacheConfig);
|
||||
$existing[0][$name]['content'] = $content;
|
||||
return Cache::write($this->_cacheKey, $existing, $this->_cacheConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the toolbar
|
||||
*
|
||||
* @param string $name Name of the panel you want cached data for
|
||||
* @param integer $index
|
||||
* @return mixed Boolean false on failure, array of data otherwise.
|
||||
*/
|
||||
public function readCache($name, $index = 0) {
|
||||
if (!$this->_cacheEnabled) {
|
||||
return false;
|
||||
}
|
||||
$existing = (array)Cache::read($this->_cacheKey, $this->_cacheConfig);
|
||||
if (!isset($existing[$index][$name]['content'])) {
|
||||
return false;
|
||||
}
|
||||
return $existing[$index][$name]['content'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the query logs for the given connection names.
|
||||
*
|
||||
* ### Options
|
||||
*
|
||||
* - explain - Whether explain links should be generated for this connection.
|
||||
* - cache - Whether the toolbar_state Cache should be updated.
|
||||
* - threshold - The threshold at which a visual 'maybe slow' flag should be added.
|
||||
* results with rows/ms lower than $threshold will be marked.
|
||||
*
|
||||
* @param string $connection Connection name to get logs for.
|
||||
* @param array $options Options for the query log retrieval.
|
||||
* @return array Array of data to be converted into a table.
|
||||
*/
|
||||
public function getQueryLogs($connection, $options = array()) {
|
||||
$options += array('explain' => false, 'cache' => true, 'threshold' => 20);
|
||||
$db = ConnectionManager::getDataSource($connection);
|
||||
|
||||
if (!method_exists($db, 'getLog')) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$log = $db->getLog();
|
||||
|
||||
$out = array(
|
||||
'queries' => array(),
|
||||
'count' => $log['count'],
|
||||
'time' => $log['time']
|
||||
);
|
||||
foreach ($log['log'] as $i => $query) {
|
||||
$query += array('query' => null);
|
||||
$isSlow = (
|
||||
$query['took'] > 0 &&
|
||||
$query['numRows'] / $query['took'] != 1 &&
|
||||
$query['numRows'] / $query['took'] <= $options['threshold']
|
||||
);
|
||||
$query['actions'] = '';
|
||||
$isHtml = ($this->getName() === 'HtmlToolbar');
|
||||
if ($isSlow && $isHtml) {
|
||||
$query['actions'] = sprintf(
|
||||
'<span class="slow-query">%s</span>',
|
||||
__d('debug_kit', 'maybe slow')
|
||||
);
|
||||
} elseif ($isSlow) {
|
||||
$query['actions'] = '*';
|
||||
}
|
||||
if ($options['explain'] && $isHtml) {
|
||||
$query['actions'] .= $this->explainLink($query['query'], $connection);
|
||||
}
|
||||
if ($isHtml) {
|
||||
$query['query'] = h($query['query']);
|
||||
if (!empty($query['params']) && is_array($query['params'])) {
|
||||
$bindParam = $bindType = null;
|
||||
if (preg_match('/.+ :.+/', $query['query'])) {
|
||||
$bindType = true;
|
||||
}
|
||||
foreach ($query['params'] as $bindKey => $bindVal) {
|
||||
if ($bindType === true) {
|
||||
$bindParam .= h($bindKey) . " => " . h($bindVal) . ", ";
|
||||
} else {
|
||||
$bindParam .= h($bindVal) . ", ";
|
||||
}
|
||||
}
|
||||
$query['query'] .= " [ " . rtrim($bindParam, ', ') . " ]";
|
||||
}
|
||||
}
|
||||
unset($query['params']);
|
||||
$out['queries'][] = $query;
|
||||
}
|
||||
if ($options['cache']) {
|
||||
$existing = $this->readCache('sql_log');
|
||||
$existing[$connection] = $out;
|
||||
$this->writeCache('sql_log', $existing);
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
||||
30
exp/Plugin/DebugKit/View/ToolbarAccess/history_state.ctp
Normal file
30
exp/Plugin/DebugKit/View/ToolbarAccess/history_state.ctp
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* Toolbar history state view.
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 1.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
$panels = array();
|
||||
foreach ($toolbarState as $panelName => $panel) {
|
||||
if (!empty($panel) && !empty($panel['elementName'])) {
|
||||
$panels[$panelName] = $this->element($panel['elementName'], array(
|
||||
'content' => $panel['content']
|
||||
), array(
|
||||
'plugin' => Inflector::camelize($panel['plugin'])
|
||||
));
|
||||
}
|
||||
}
|
||||
echo json_encode($panels);
|
||||
Configure::write('debug', 0);
|
||||
11
exp/Plugin/DebugKit/View/ToolbarAccess/sql_explain.ctp
Normal file
11
exp/Plugin/DebugKit/View/ToolbarAccess/sql_explain.ctp
Normal file
@@ -0,0 +1,11 @@
|
||||
<table class="sql-log-query-explain debug-table">
|
||||
<?php
|
||||
$headers = array_shift($result);
|
||||
|
||||
echo $this->Html->tableHeaders($headers);
|
||||
echo $this->Html->tableCells($result);
|
||||
?>
|
||||
</table>
|
||||
<?php
|
||||
// Consume and toss out the timers
|
||||
$timers = DebugKitDebugger::getTimers(true);
|
||||
35
exp/Plugin/DebugKit/composer.json
Normal file
35
exp/Plugin/DebugKit/composer.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "cakephp/debug_kit",
|
||||
"description": "CakePHP Debug Kit",
|
||||
"type": "cakephp-plugin",
|
||||
"keywords": ["cakephp", "debug", "kit"],
|
||||
"homepage": "https://github.com/cakephp/debug_kit",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mark Story",
|
||||
"homepage": "http://mark-story.com",
|
||||
"role": "Author"
|
||||
},
|
||||
{
|
||||
"name": "CakePHP Community",
|
||||
"homepage": "https://github.com/cakephp/debug_kit/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/cakephp/debug_kit/issues",
|
||||
"forum": "http://stackoverflow.com/tags/cakephp",
|
||||
"irc": "irc://irc.freenode.org/cakephp",
|
||||
"source": "https://github.com/cakephp/debug_kit"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"composer/installers": "*"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2.x-dev"
|
||||
},
|
||||
"installer-name": "DebugKit"
|
||||
}
|
||||
}
|
||||
382
exp/Plugin/DebugKit/webroot/css/debug_toolbar.css
Normal file
382
exp/Plugin/DebugKit/webroot/css/debug_toolbar.css
Normal file
@@ -0,0 +1,382 @@
|
||||
/* @override http://localhost/mark_story/site/debug_kit/css/debug_toolbar.css */
|
||||
#debug-kit-toolbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right:0px;
|
||||
width: 100%;
|
||||
height: 1%;
|
||||
overflow: visible;
|
||||
z-index:10000;
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
font-size: 12px;
|
||||
direction: ltr;
|
||||
}
|
||||
#debug-kit-toolbar img {
|
||||
border:0;
|
||||
outline:0;
|
||||
}
|
||||
|
||||
/* panel tabs */
|
||||
#debug-kit-toolbar #panel-tabs {
|
||||
float: right;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-shadow: 0 5px 6px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 8px 0 0 8px;
|
||||
}
|
||||
#debug-kit-toolbar .panel-tab {
|
||||
clear: none;
|
||||
float: left;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
#debug-kit-toolbar .panel-tab > a {
|
||||
float: left;
|
||||
clear: none;
|
||||
background: #efefef;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#cacaca));
|
||||
background: -moz-linear-gradient(top, #efefef, #cacaca);
|
||||
color: #222;
|
||||
padding: 6px;
|
||||
border-right: 1px solid #ccc;
|
||||
border-bottom: 1px solid #aaa;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
margin: 0;
|
||||
display: block;
|
||||
text-decoration:none;
|
||||
text-shadow:1px 1px #eee;
|
||||
-moz-text-shadow:1px 1px #eee;
|
||||
-webkit-text-shadow:1px 1px #eee;
|
||||
}
|
||||
#debug-kit-toolbar .panel-tab .active {
|
||||
background: #fff;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#fff));
|
||||
background: -moz-linear-gradient(top, #f5f5f5, #fff);
|
||||
}
|
||||
#debug-kit-toolbar .panel-tab > a:hover {
|
||||
background: #fff;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#fff));
|
||||
background: -moz-linear-gradient(top, #f5f5f5, #fff);
|
||||
text-decoration:underline;
|
||||
}
|
||||
#debug-kit-toolbar .panel-tab.icon a {
|
||||
padding: 4px;
|
||||
}
|
||||
#debug-kit-toolbar .panel-tab a.edit-value {
|
||||
float: none;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#debug-kit-toolbar .panel-tab.icon a {
|
||||
border-radius: 8px 0 0 8px;
|
||||
}
|
||||
#debug-kit-toolbar .panel-tab.icon img {
|
||||
display:block;
|
||||
}
|
||||
|
||||
/* panel content */
|
||||
#debug-kit-toolbar .panel-content {
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
width: auto;
|
||||
top:28px;
|
||||
right:0px;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
width:100%;
|
||||
box-shadow:0px 5px 6px rgba(0, 0, 0, 0.5);
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#debug-kit-toolbar .panel-resize-region {
|
||||
padding:15px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 14px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#debug-kit-toolbar .ui-control {
|
||||
background:#ccc;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#d6d6d6), to(#c2c2c2));
|
||||
background: -moz-linear-gradient(top, #d6d6d6, #c2c2c2);
|
||||
text-align:center;
|
||||
border-top:1px solid #afafaf;
|
||||
border-bottom:1px solid #7c7c7c;
|
||||
color:#666;
|
||||
text-shadow: 1px 1px #eee;
|
||||
-webkit-text-shadow: 1px 1px #eee;
|
||||
-moz-text-shadow: 1px 1px #eee;
|
||||
}
|
||||
#debug-kit-toolbar .ui-button {
|
||||
border-radius: 5px;
|
||||
}
|
||||
#debug-kit-toolbar .ui-button:hover {
|
||||
text-decoration: none;
|
||||
background:#ccc;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#c2c2c2), to(#d6d6d6));
|
||||
background: -moz-linear-gradient(top, #c2c2c2, #d6d6d6);
|
||||
}
|
||||
#debug-kit-toolbar .panel-resize-handle {
|
||||
cursor: row-resize;
|
||||
height:14px;
|
||||
line-height: 14px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
#debug-kit-toolbar .panel-toggle {
|
||||
float: right;
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
line-height: 14px;
|
||||
border-left: 1px solid #afafaf;
|
||||
border-right: 1px solid #7c7c7c;
|
||||
text-decoration: none;
|
||||
margin: 10px 20px 0 0;
|
||||
z-index: 999;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Hide panel content by default */
|
||||
#debug-kit-toolbar .panel-content {
|
||||
display: none;
|
||||
}
|
||||
#debug-kit-toolbar .panel-content p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
#debug-kit-toolbar .panel-content h2 {
|
||||
padding: 0;
|
||||
margin-top:0;
|
||||
}
|
||||
#debug-kit-toolbar .panel-content h3 {
|
||||
padding: 0;
|
||||
margin-top: 1em;
|
||||
}
|
||||
#debug-kit-toolbar .panel-content .info {
|
||||
padding: 4px;
|
||||
border-top: 1px dashed #6c6cff;
|
||||
border-bottom: 1px dashed #6c6cff;
|
||||
}
|
||||
#debug-kit-toolbar h1,
|
||||
#debug-kit-toolbar h2,
|
||||
#debug-kit-toolbar h3,
|
||||
#debug-kit-toolbar h4,
|
||||
#debug-kit-toolbar h5,
|
||||
#debug-kit-toolbar th {
|
||||
color: #5d1717;
|
||||
font-family: Arial, sans-serif;
|
||||
margin-bottom:0.6em;
|
||||
background:none;
|
||||
}
|
||||
#debug-kit-toolbar h1 {
|
||||
font-size: 18px;
|
||||
}
|
||||
#debug-kit-toolbar h2 {
|
||||
font-size: 16px;
|
||||
}
|
||||
#debug-kit-toolbar h4 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
||||
/* panel tables */
|
||||
#debug-kit-toolbar .debug-table {
|
||||
width: 100%;
|
||||
border: 1px solid #eee;
|
||||
border-left: 0;
|
||||
clear:both;
|
||||
margin-bottom: 20px;
|
||||
border-spacing: 0;
|
||||
}
|
||||
#debug-kit-toolbar .debug-table td,
|
||||
#debug-kit-toolbar .debug-table th {
|
||||
text-align: left;
|
||||
border: 0;
|
||||
border-left: 1px solid #eee;
|
||||
padding: 3px;
|
||||
margin: 0;
|
||||
}
|
||||
#debug-kit-toolbar table.debug-table th {
|
||||
border-bottom: 1px solid #bbb;
|
||||
border-left: 1px solid #bbb;
|
||||
background: -webkit-linear-gradient(top, #d4d4d4, #c1c1c1);
|
||||
background: -moz-linear-gradient(top, #d4d4d4, #c1c1c1);
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
line-height: 16px;
|
||||
}
|
||||
#debug-kit-toolbar .debug-table tr:nth-child(2n) td {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
#debug-kit-toolbar .debug-timers .debug-table td:nth-child(2),
|
||||
#debug-kit-toolbar .debug-timers .debug-table th:nth-child(2) {
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
/** code tables **/
|
||||
#debug-kit-toolbar .code-table td {
|
||||
white-space: pre;
|
||||
font-family: monaco, Consolas, "courier new", courier, monospaced;
|
||||
}
|
||||
#debug-kit-toolbar .code-table td:first-child {
|
||||
width: 15%;
|
||||
}
|
||||
#debug-kit-toolbar .code-table td:last-child {
|
||||
width: 80%;
|
||||
}
|
||||
#debug-kit-toolbar .panel-content.request {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/** Neat Array styles **/
|
||||
#debug-kit-toolbar .neat-array,
|
||||
#debug-kit-toolbar .neat-array li {
|
||||
list-style:none;
|
||||
list-style-image:none;
|
||||
}
|
||||
#debug-kit-toolbar .neat-array {
|
||||
padding: 1px 2px 1px 20px;
|
||||
background: #CE9E23;
|
||||
list-style: none;
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
#debug-kit-toolbar .neat-array .neat-array {
|
||||
padding: 0 0 0 20px;
|
||||
margin: 0;
|
||||
border-top:1px solid #CE9E23;
|
||||
}
|
||||
#debug-kit-toolbar .neat-array li {
|
||||
background: #FEF6E5;
|
||||
border-top: 1px solid #CE9E23;
|
||||
border-bottom: 1px solid #CE9E23;
|
||||
margin: 0;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
#debug-kit-toolbar .neat-array li:hover {
|
||||
background: #fff;
|
||||
}
|
||||
#debug-kit-toolbar .neat-array li strong {
|
||||
padding: 0 8px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
/* expandable sections */
|
||||
#debug-kit-toolbar .neat-array li.expandable {
|
||||
cursor: pointer;
|
||||
}
|
||||
#debug-kit-toolbar .neat-array .expanded {
|
||||
border-bottom:0;
|
||||
}
|
||||
#debug-kit-toolbar .neat-array li.expandable.expanded > strong:before {
|
||||
content: 'v ';
|
||||
}
|
||||
#debug-kit-toolbar .neat-array li.expandable.collapsed > strong:before,
|
||||
#debug-kit-toolbar .neat-array li.expandable.expanded .expandable.collapsed > strong:before {
|
||||
content: '> ';
|
||||
}
|
||||
#debug-kit-toolbar .neat-array li {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#debug-kit-toolbar .debug-kit-graph-bar,
|
||||
#debug-kit-toolbar .debug-kit-graph-bar-value {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: 10px;
|
||||
}
|
||||
#debug-kit-toolbar .debug-kit-graph-bar {
|
||||
background: #ddd;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
height: 12px;
|
||||
}
|
||||
#debug-kit-toolbar .debug-kit-graph-bar-value {
|
||||
background: -webkit-linear-gradient(top, #77D124, #4B9406);
|
||||
background: -moz-linear-gradient(top, #77D124, #4B9406);
|
||||
border-radius: 3px;
|
||||
border: 1px solid #4B9406;
|
||||
}
|
||||
|
||||
/* Sql Log */
|
||||
#sqllog-tab td,
|
||||
#sqllog-tab .slow-query-container p {
|
||||
font-family: Monaco, 'Consolas', "Courier New", Courier, monospaced;
|
||||
}
|
||||
#debug-kit-toolbar #sqllog-tab a.show-slow {
|
||||
display:block;
|
||||
margin: 3px;
|
||||
float:none;
|
||||
}
|
||||
#sqllog-tab .slow-query-container p {
|
||||
display:block;
|
||||
clear:both;
|
||||
margin: 20px 0 5px;
|
||||
}
|
||||
#debug-kit-toolbar #sqllog-tab .panel-content-data a {
|
||||
background: none;
|
||||
border:none;
|
||||
}
|
||||
#sqllog-tab .slow-query {
|
||||
background:#e79302;
|
||||
font-size:9px;
|
||||
color:#fff;
|
||||
padding: 2px;
|
||||
white-space:nowrap;
|
||||
}
|
||||
#sqllog-tab input[type=submit] {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
font-family: Monaco, 'Consolas', "Courier New", Courier, monospaced;
|
||||
}
|
||||
#sqllog-tab input[type=submit]:hover {
|
||||
color: darkred;
|
||||
}
|
||||
#debug-kit-toolbar .alert-duplicate {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* previous panels */
|
||||
#debug-kit-toolbar .panel-history {
|
||||
display: none;
|
||||
background:#eeffff;
|
||||
}
|
||||
#debug-kit-toolbar #history-tab ul {
|
||||
margin: 20px 0 0 20px;
|
||||
}
|
||||
#debug-kit-toolbar #history-tab li {
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
#debug-kit-toolbar #history-tab .panel-content-data a {
|
||||
float: none;
|
||||
display:block;
|
||||
}
|
||||
#debug-kit-toolbar #history-tab a.active {
|
||||
background: #FEF6E5;
|
||||
}
|
||||
#debug-kit-toolbar #history-tab a.loading:after {
|
||||
content : ' Loading...';
|
||||
font-style:italic;
|
||||
}
|
||||
|
||||
/* Minimized mode */
|
||||
#debug-kit-toolbar.minimized {
|
||||
opacity: 0.75;
|
||||
}
|
||||
#debug-kit-toolbar.minimized:hover {
|
||||
opacity: inherit;
|
||||
}
|
||||
BIN
exp/Plugin/DebugKit/webroot/img/cake.icon.png
Normal file
BIN
exp/Plugin/DebugKit/webroot/img/cake.icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 943 B |
4
exp/Plugin/DebugKit/webroot/js/jquery.js
vendored
Normal file
4
exp/Plugin/DebugKit/webroot/js/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
936
exp/Plugin/DebugKit/webroot/js/js_debug_toolbar.js
Normal file
936
exp/Plugin/DebugKit/webroot/js/js_debug_toolbar.js
Normal file
@@ -0,0 +1,936 @@
|
||||
/**
|
||||
* Debug Toolbar Javascript.
|
||||
*
|
||||
* Creates the DEBUGKIT namespace and provides methods for extending
|
||||
* and enhancing the Html toolbar. Includes library agnostic Event, Element,
|
||||
* Cookie and Request wrappers.
|
||||
*
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/* jshint jquery: true */
|
||||
|
||||
var DEBUGKIT = function () {
|
||||
var undef;
|
||||
return {
|
||||
module: function (newmodule) {
|
||||
if (this[newmodule] === undef) {
|
||||
this[newmodule] = {};
|
||||
return this[newmodule];
|
||||
}
|
||||
return this[newmodule];
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
(function () {
|
||||
function versionGTE(a, b) {
|
||||
var len = Math.min(a.length, b.length);
|
||||
for (var i = 0; i < len; i++) {
|
||||
a[i] = parseInt(a[i], 10);
|
||||
b[i] = parseInt(b[i], 10);
|
||||
if (a[i] > b[i]) {
|
||||
return true;
|
||||
}
|
||||
if (a[i] < b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function versionWithin(version, min, max) {
|
||||
version = version.split('.');
|
||||
min = min.split('.');
|
||||
max = max.split('.');
|
||||
return versionGTE(version, min) && versionGTE(max, version);
|
||||
}
|
||||
|
||||
function initOnReady() {
|
||||
DEBUGKIT.$(document).ready(function () {
|
||||
DEBUGKIT.registerModules(DEBUGKIT.$);
|
||||
DEBUGKIT.loader.init();
|
||||
});
|
||||
}
|
||||
|
||||
// Push checking for jQuery at the end of the stack.
|
||||
// This will catch JS included at the bottom of a page.
|
||||
setTimeout(function() {
|
||||
// Look for existing jQuery that matches the requirements.
|
||||
if (window.jQuery && versionWithin(jQuery.fn.jquery, "1.8", "2.1")) {
|
||||
DEBUGKIT.$ = window.jQuery;
|
||||
initOnReady();
|
||||
} else {
|
||||
var req = new XMLHttpRequest();
|
||||
req.onload = function () {
|
||||
eval(this.responseText);
|
||||
// Restore both $ and jQuery to the original values.
|
||||
DEBUGKIT.$ = jQuery.noConflict(true);
|
||||
initOnReady();
|
||||
};
|
||||
req.open('get', window.DEBUGKIT_JQUERY_URL, true);
|
||||
req.send();
|
||||
}
|
||||
}, 0);
|
||||
})();
|
||||
|
||||
DEBUGKIT.loader = function () {
|
||||
return {
|
||||
// List of methods to run on startup.
|
||||
_startup: [],
|
||||
|
||||
// Register a new method to be run on dom ready.
|
||||
register: function (method) {
|
||||
this._startup.push(method);
|
||||
},
|
||||
|
||||
init: function () {
|
||||
for (var i = 0, callback; callback = this._startup[i]; i++) {
|
||||
callback.init();
|
||||
}
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
|
||||
DEBUGKIT.registerModules = function($) {
|
||||
|
||||
|
||||
DEBUGKIT.module('sqlLog');
|
||||
DEBUGKIT.sqlLog = function () {
|
||||
|
||||
return {
|
||||
init : function () {
|
||||
var sqlPanel = $('#sql_log-tab');
|
||||
var buttons = sqlPanel.find('input');
|
||||
|
||||
// Button handling code for explain links.
|
||||
// Performs XHR request to get explain query.
|
||||
var handleButton = function (event) {
|
||||
event.preventDefault();
|
||||
var form = $(this.form),
|
||||
data = form.serialize(),
|
||||
dbName = form.find('input[name*=ds]').val() || 'default';
|
||||
|
||||
var fetch = $.ajax({
|
||||
url: this.form.action,
|
||||
data: data,
|
||||
type: 'POST',
|
||||
success : function (response) {
|
||||
$('#sql-log-explain-' + dbName).html(response);
|
||||
},
|
||||
error : function () {
|
||||
alert('Could not fetch EXPLAIN for query.');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
buttons.filter('.sql-explain-link').on('click', handleButton);
|
||||
}
|
||||
};
|
||||
}();
|
||||
DEBUGKIT.loader.register(DEBUGKIT.sqlLog);
|
||||
|
||||
//
|
||||
// NOTE DEBUGKIT.Util.Element is Deprecated.
|
||||
//
|
||||
// Util module and Element utility class.
|
||||
DEBUGKIT.module('Util');
|
||||
DEBUGKIT.Util.Element = {
|
||||
|
||||
// Test if an element is a name node.
|
||||
nodeName: function (element, name) {
|
||||
return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();
|
||||
},
|
||||
|
||||
// Return a boolean if the element has the classname
|
||||
hasClass: function (element, className) {
|
||||
if (!element.className) {
|
||||
return false;
|
||||
}
|
||||
return element.className.indexOf(className) > -1;
|
||||
},
|
||||
|
||||
addClass: function (element, className) {
|
||||
if (!element.className) {
|
||||
element.className = className;
|
||||
return;
|
||||
}
|
||||
element.className = element.className.replace(/^(.*)$/, '$1 ' + className);
|
||||
},
|
||||
|
||||
removeClass: function (element, className) {
|
||||
if (DEBUGKIT.Util.isArray(element)) {
|
||||
DEBUGKIT.Util.Collection.apply(element, function (element) {
|
||||
DEBUGKIT.Util.Element.removeClass(element, className);
|
||||
});
|
||||
}
|
||||
if (!element.className) {
|
||||
return false;
|
||||
}
|
||||
element.className = element.className.replace(new RegExp(' ?(' + className + ') ?'), '');
|
||||
},
|
||||
|
||||
swapClass: function (element, removeClass, addClass) {
|
||||
if (!element.className) {
|
||||
return false;
|
||||
}
|
||||
element.className = element.className.replace(removeClass, addClass);
|
||||
},
|
||||
|
||||
show: function (element) {
|
||||
element.style.display = 'block';
|
||||
},
|
||||
|
||||
hide: function (element) {
|
||||
element.style.display = 'none';
|
||||
},
|
||||
|
||||
// Go between hide() and show() depending on element.style.display
|
||||
toggle: function (element) {
|
||||
if (element.style.display === 'none') {
|
||||
this.show(element);
|
||||
return;
|
||||
}
|
||||
this.hide(element);
|
||||
},
|
||||
|
||||
_walk: function (element, walk) {
|
||||
var sibling = element[walk];
|
||||
while (true) {
|
||||
if (sibling.nodeType == 1) {
|
||||
break;
|
||||
}
|
||||
sibling = sibling[walk];
|
||||
}
|
||||
return sibling;
|
||||
},
|
||||
|
||||
getNext: function (element) {
|
||||
return this._walk(element, 'nextSibling');
|
||||
},
|
||||
|
||||
getPrevious: function (element) {
|
||||
return this._walk(element, 'previousSibling');
|
||||
},
|
||||
|
||||
// Get or set an element's height, omit value to get, add value (integer) to set.
|
||||
height: function (element, value) {
|
||||
// Get value
|
||||
if (value === undefined) {
|
||||
return parseInt(this.getStyle(element, 'height'), 10);
|
||||
}
|
||||
element.style.height = value + 'px';
|
||||
},
|
||||
|
||||
// Gets the style in css format for property
|
||||
getStyle: function (element, property) {
|
||||
if (element.currentStyle) {
|
||||
property = property.replace(/-[a-z]/g, function (match) {
|
||||
return match.charAt(1).toUpperCase();
|
||||
});
|
||||
return element.currentStyle[property];
|
||||
}
|
||||
if (window.getComputedStyle) {
|
||||
return document.defaultView.getComputedStyle(element, null).getPropertyValue(property);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// NOTE DEBUGKIT.Util.Collection is Deprecated.
|
||||
//
|
||||
DEBUGKIT.Util.Collection = {
|
||||
/**
|
||||
* Apply the passed function to each item in the collection.
|
||||
* The current element in the collection will be `this` in the callback
|
||||
* The callback is also passed the element and the index as arguments.
|
||||
* Optionally you can supply a binding parameter to change `this` in the callback.
|
||||
*/
|
||||
apply: function (collection, callback, binding) {
|
||||
var name, thisVar, i = 0, len = collection.length;
|
||||
|
||||
if (len === undefined) {
|
||||
for (name in collection) {
|
||||
thisVar = (binding === undefined) ? collection[name] : binding;
|
||||
callback.apply(thisVar, [collection[name], name]);
|
||||
}
|
||||
} else {
|
||||
for (; i < len; i++) {
|
||||
thisVar = (binding === undefined) ? collection[i] : binding;
|
||||
callback.apply(thisVar, [collection[i], i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// NOTE DEBUGKIT.Util.Event is Deprecated.
|
||||
//
|
||||
// Event binding
|
||||
DEBUGKIT.Util.Event = function () {
|
||||
var _listeners = {},
|
||||
_eventId = 0;
|
||||
|
||||
var preventDefault = function () {
|
||||
this.returnValue = false;
|
||||
};
|
||||
|
||||
var stopPropagation = function () {
|
||||
this.cancelBubble = true;
|
||||
};
|
||||
|
||||
// Fixes IE's broken event object, adds in common methods + properties.
|
||||
var fixEvent = function (event) {
|
||||
if (!event.preventDefault) {
|
||||
event.preventDefault = preventDefault;
|
||||
}
|
||||
if (!event.stopPropagation) {
|
||||
event.stopPropagation = stopPropagation;
|
||||
}
|
||||
if (!event.target) {
|
||||
event.target = event.srcElement || document;
|
||||
}
|
||||
if (event.pageX === null && event.clientX !== null) {
|
||||
var doc = document.body;
|
||||
event.pageX = event.clientX + (doc.scrollLeft || 0) - (doc.clientLeft || 0);
|
||||
event.pageY = event.clientY + (doc.scrollTop || 0) - (doc.clientTop || 0);
|
||||
}
|
||||
return event;
|
||||
};
|
||||
|
||||
return {
|
||||
// Bind an event listener of type to element, handler is your method.
|
||||
addEvent: function (element, type, handler, capture) {
|
||||
capture = (capture === undefined) ? false : capture;
|
||||
|
||||
var callback = function (event) {
|
||||
event = fixEvent(event || window.event);
|
||||
handler.apply(element, [event]);
|
||||
};
|
||||
|
||||
if (element.addEventListener) {
|
||||
element.addEventListener(type, callback, capture);
|
||||
} else if (element.attachEvent) {
|
||||
type = 'on' + type;
|
||||
element.attachEvent(type, callback);
|
||||
} else {
|
||||
type = 'on' + type;
|
||||
element[type] = callback;
|
||||
}
|
||||
_listeners[++_eventId] = {element: element, type: type, handler: callback};
|
||||
},
|
||||
|
||||
// Destroy an event listener. requires the exact same function as was used for attaching
|
||||
// the event.
|
||||
removeEvent: function (element, type, handler) {
|
||||
if (element.removeEventListener) {
|
||||
element.removeEventListener(type, handler, false);
|
||||
} else if (element.detachEvent) {
|
||||
type = 'on' + type;
|
||||
element.detachEvent(type, handler);
|
||||
} else {
|
||||
type = 'on' + type;
|
||||
element[type] = null;
|
||||
}
|
||||
},
|
||||
|
||||
// Bind an event to the DOMContentLoaded or other similar event.
|
||||
domready: function (callback) {
|
||||
if (document.addEventListener) {
|
||||
return document.addEventListener('DOMContentLoaded', callback, false);
|
||||
}
|
||||
|
||||
if (document.all && !window.opera) {
|
||||
// Define a "blank" external JavaScript tag
|
||||
document.write(
|
||||
'<script type="text/javascript" id="__domreadywatcher" defer="defer" src="javascript:void(0)"><\/script>'
|
||||
);
|
||||
var contentloadtag = document.getElementById('__domreadywatcher');
|
||||
contentloadtag.onreadystatechange = function () {
|
||||
if (this.readyState === 'complete') {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
contentloadtag = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (/Webkit/i.test(navigator.userAgent)) {
|
||||
var _timer = setInterval(function () {
|
||||
if (/loaded|complete/.test(document.readyState)) {
|
||||
clearInterval(_timer);
|
||||
callback();
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
},
|
||||
|
||||
// Unload all the events attached by DebugKit. Fix any memory leaks.
|
||||
unload: function () {
|
||||
var listener;
|
||||
for (var i in _listeners) {
|
||||
listener = _listeners[i];
|
||||
try {
|
||||
this.removeEvent(listener.element, listener.type, listener.handler);
|
||||
} catch (e) {}
|
||||
delete _listeners[i];
|
||||
}
|
||||
delete _listeners;
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
// Cookie utility
|
||||
DEBUGKIT.Util.Cookie = function () {
|
||||
var cookieLife = 60;
|
||||
|
||||
// Public methods
|
||||
return {
|
||||
/**
|
||||
* Write to cookie.
|
||||
*
|
||||
* @param [string] name Name of cookie to write.
|
||||
* @param [mixed] value Value to write to cookie.
|
||||
*/
|
||||
write: function (name, value) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (cookieLife * 24 * 60 * 60 * 1000));
|
||||
var expires = '; expires=' + date.toGMTString();
|
||||
document.cookie = name + '=' + value + expires + '; path=/';
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Read from the cookie.
|
||||
*
|
||||
* @param [string] name Name of cookie to read.
|
||||
*/
|
||||
read: function (name) {
|
||||
name = name + '=';
|
||||
var cookieJar = document.cookie.split(';');
|
||||
var cookieJarLength = cookieJar.length;
|
||||
for (var i = 0; i < cookieJarLength; i++) {
|
||||
var chips = cookieJar[i];
|
||||
// Trim leading spaces
|
||||
while (chips.charAt(0) === ' ') {
|
||||
chips = chips.substring(1, chips.length);
|
||||
}
|
||||
if (chips.indexOf(name) === 0) {
|
||||
return chips.substring(name.length, chips.length);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete a cookie by name.
|
||||
*
|
||||
* @param [string] name of cookie to delete.
|
||||
*/
|
||||
del: function (name) {
|
||||
var date = new Date();
|
||||
date.setFullYear(2000, 0, 1);
|
||||
var expires = ' ; expires=' + date.toGMTString();
|
||||
document.cookie = name + '=' + expires + '; path=/';
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
//
|
||||
// NOTE DEBUGKIT.Util.merge is Deprecated.
|
||||
//
|
||||
|
||||
/**
|
||||
* Object merge takes any number of arguments and glues them together.
|
||||
*
|
||||
* @param [Object] one first object
|
||||
* @return object
|
||||
*/
|
||||
DEBUGKIT.Util.merge = function () {
|
||||
var out = {};
|
||||
var argumentsLength = arguments.length;
|
||||
for (var i = 0; i < argumentsLength; i++) {
|
||||
var current = arguments[i];
|
||||
for (var prop in current) {
|
||||
if (current[prop] !== undefined) {
|
||||
out[prop] = current[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
//
|
||||
// NOTE DEBUGKIT.Util.isArray is Deprecated.
|
||||
//
|
||||
|
||||
/**
|
||||
* Check if the given object is an array.
|
||||
*/
|
||||
DEBUGKIT.Util.isArray = function (test) {
|
||||
return Object.prototype.toString.call(test) === '[object Array]';
|
||||
};
|
||||
|
||||
//
|
||||
// NOTE DEBUGKIT.Util.Request is Deprecated.
|
||||
//
|
||||
// Simple wrapper for XmlHttpRequest objects.
|
||||
DEBUGKIT.Util.Request = function (options) {
|
||||
var _defaults = {
|
||||
onComplete : function () {},
|
||||
onRequest : function () {},
|
||||
onFail : function () {},
|
||||
method : 'GET',
|
||||
async : true,
|
||||
headers : {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
|
||||
}
|
||||
};
|
||||
|
||||
var self = this;
|
||||
this.options = DEBUGKIT.Util.merge(_defaults, options);
|
||||
this.options.method = this.options.method.toUpperCase();
|
||||
|
||||
var ajax = this.createObj();
|
||||
this.transport = ajax;
|
||||
|
||||
// Event assignment
|
||||
this.onComplete = this.options.onComplete;
|
||||
this.onRequest = this.options.onRequest;
|
||||
this.onFail = this.options.onFail;
|
||||
|
||||
this.send = function (url, data) {
|
||||
if (this.options.method === 'GET' && data) {
|
||||
url = url + ((url.charAt(url.length - 1) === '?') ? '&' : '?') + data; //check for ? at the end of the string
|
||||
data = null;
|
||||
}
|
||||
// Open connection
|
||||
this.transport.open(this.options.method, url, this.options.async);
|
||||
|
||||
// Set statechange and pass the active XHR object to it. From here it handles all status changes.
|
||||
this.transport.onreadystatechange = function () {
|
||||
self.onReadyStateChange.apply(self, arguments);
|
||||
};
|
||||
for (var key in this.options.headers) {
|
||||
this.transport.setRequestHeader(key, this.options.headers[key]);
|
||||
}
|
||||
if (typeof data === 'object') {
|
||||
data = this.serialize(data);
|
||||
}
|
||||
if (data) {
|
||||
this.transport.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
this.onRequest();
|
||||
this.transport.send(data);
|
||||
};
|
||||
};
|
||||
|
||||
DEBUGKIT.Util.Request.prototype.onReadyStateChange = function () {
|
||||
if (this.transport.readyState !== 4) {
|
||||
return;
|
||||
}
|
||||
if (this.transport.status === 200 || this.transport.status > 300 && this.transport.status < 400) {
|
||||
this.response = {
|
||||
xml: this.transport.responseXML,
|
||||
text: this.transport.responseText
|
||||
};
|
||||
|
||||
if (typeof this.onComplete === 'function') {
|
||||
this.onComplete.apply(this, [this, this.response]);
|
||||
} else {
|
||||
return this.response;
|
||||
}
|
||||
} else if (this.transport.status > 400) {
|
||||
if (typeof this.onFail === 'function') {
|
||||
this.onFail.apply(this, []);
|
||||
} else {
|
||||
console.error('Request failed');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates cross-broswer XHR object used for requests.
|
||||
* Tries using the standard XmlHttpRequest, then IE's wacky ActiveX Objects.
|
||||
*/
|
||||
DEBUGKIT.Util.Request.prototype.createObj = function () {
|
||||
var request = null;
|
||||
try {
|
||||
request = new XMLHttpRequest();
|
||||
} catch (MS) {
|
||||
try {
|
||||
request = new ActiveXObject('Msxml2.XMLHTTP');
|
||||
} catch (old_MS) {
|
||||
try {
|
||||
request = new ActiveXObject('Microsoft.XMLHTTP');
|
||||
} catch (failure) {
|
||||
request = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return request;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serializes an object literal into a querystring.
|
||||
*/
|
||||
DEBUGKIT.Util.Request.prototype.serialize = function (data) {
|
||||
var out = '';
|
||||
for (var name in data) {
|
||||
if (data.hasOwnProperty(name)) {
|
||||
out += name + '=' + data[name] + '&';
|
||||
}
|
||||
}
|
||||
return out.substring(0, out.length - 1);
|
||||
};
|
||||
|
||||
|
||||
// Basic toolbar module.
|
||||
DEBUGKIT.toolbar = function () {
|
||||
// Shortcuts
|
||||
var Cookie = DEBUGKIT.Util.Cookie,
|
||||
toolbarHidden = false;
|
||||
|
||||
return {
|
||||
elements: {},
|
||||
panels: {},
|
||||
|
||||
init: function () {
|
||||
var i, element, lists, index, _this = this;
|
||||
|
||||
this.elements.toolbar = $('#debug-kit-toolbar');
|
||||
|
||||
if (this.elements.toolbar.length === 0) {
|
||||
throw new Error('Toolbar not found, make sure you loaded it.');
|
||||
}
|
||||
|
||||
this.elements.panel = $('#panel-tabs');
|
||||
this.elements.panel.find('.panel-tab').each(function (i, panel) {
|
||||
_this.addPanel(panel);
|
||||
});
|
||||
|
||||
lists = this.elements.toolbar.find('.depth-0');
|
||||
|
||||
this.makeNeatArray(lists);
|
||||
this.deactivatePanel(true);
|
||||
},
|
||||
|
||||
// Add a panel to the toolbar
|
||||
addPanel: function (tab) {
|
||||
var button, content, _this = this;
|
||||
var panel = {
|
||||
id : false,
|
||||
element : tab,
|
||||
button : undefined,
|
||||
content : undefined,
|
||||
active : false
|
||||
};
|
||||
tab = $(tab);
|
||||
button = tab.children('a');
|
||||
|
||||
panel.id = button.attr('href').replace(/^#/, '');
|
||||
panel.button = button;
|
||||
panel.content = tab.find('.panel-content');
|
||||
|
||||
if (!panel.id || panel.content.length === 0) {
|
||||
return false;
|
||||
}
|
||||
this.makePanelDraggable(panel);
|
||||
this.makePanelMinMax(panel);
|
||||
|
||||
button.on('click', function (event) {
|
||||
event.preventDefault();
|
||||
_this.togglePanel(panel.id);
|
||||
});
|
||||
|
||||
this.panels[panel.id] = panel;
|
||||
return panel.id;
|
||||
},
|
||||
|
||||
// Find the handle element and make the panel drag resizable.
|
||||
makePanelDraggable: function (panel) {
|
||||
|
||||
// Create a variable in the enclosing scope, for scope tricks.
|
||||
var currentElement = null;
|
||||
|
||||
// Use the elements startHeight stored Event.pageY and current Event.pageY to
|
||||
// resize the panel.
|
||||
var mouseMoveHandler = function (event) {
|
||||
event.preventDefault();
|
||||
if (!currentElement) {
|
||||
return;
|
||||
}
|
||||
var newHeight = currentElement.data('startHeight') + (event.pageY - currentElement.data('startY'));
|
||||
currentElement.parent().height(newHeight);
|
||||
};
|
||||
|
||||
// Handle the mouseup event, remove the other listeners so the panel
|
||||
// doesn't continue to resize.
|
||||
var mouseUpHandler = function (event) {
|
||||
currentElement = null;
|
||||
$(document).off('mousemove', mouseMoveHandler).off('mouseup', mouseUpHandler);
|
||||
};
|
||||
|
||||
var mouseDownHandler = function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
currentElement = $(this);
|
||||
currentElement.data('startY', event.pageY);
|
||||
currentElement.data('startHeight', currentElement.parent().height());
|
||||
|
||||
// Attach to document so mouse doesn't have to stay precisely on the 'handle'.
|
||||
$(document).on('mousemove', mouseMoveHandler)
|
||||
.on('mouseup', mouseUpHandler);
|
||||
};
|
||||
|
||||
panel.content.find('.panel-resize-handle').on('mousedown', mouseDownHandler);
|
||||
},
|
||||
|
||||
// Make the maximize button work on the panels.
|
||||
makePanelMinMax: function (panel) {
|
||||
var _oldHeight;
|
||||
|
||||
var maximize = function () {
|
||||
if (!_oldHeight) {
|
||||
_oldHeight = this.parentNode.offsetHeight;
|
||||
}
|
||||
var windowHeight = window.innerHeight;
|
||||
var panelHeight = windowHeight - this.parentNode.offsetTop;
|
||||
$(this.parentNode).height(panelHeight);
|
||||
$(this).text('-');
|
||||
};
|
||||
|
||||
var minimize = function () {
|
||||
$(this.parentNode).height(_oldHeight);
|
||||
$(this).text('+');
|
||||
_oldHeight = null;
|
||||
};
|
||||
|
||||
var state = 1;
|
||||
var toggle = function (event) {
|
||||
event.preventDefault();
|
||||
if (state === 1) {
|
||||
maximize.call(this);
|
||||
state = 0;
|
||||
} else {
|
||||
state = 1;
|
||||
minimize.call(this);
|
||||
}
|
||||
};
|
||||
|
||||
panel.content.find('.panel-toggle').on('click', toggle);
|
||||
},
|
||||
|
||||
// Toggle a panel
|
||||
togglePanel: function (id) {
|
||||
if (this.panels[id] && this.panels[id].active) {
|
||||
this.deactivatePanel(true);
|
||||
} else {
|
||||
this.deactivatePanel(true);
|
||||
this.activatePanel(id);
|
||||
}
|
||||
},
|
||||
|
||||
// Make a panel active.
|
||||
activatePanel: function (id, unique) {
|
||||
if (this.panels[id] !== undefined && !this.panels[id].active) {
|
||||
var panel = this.panels[id];
|
||||
if (panel.content.length > 0) {
|
||||
panel.content.show();
|
||||
}
|
||||
|
||||
var contentHeight = panel.content.find('.panel-content-data').height() + 70;
|
||||
if (contentHeight <= (window.innerHeight / 2)) {
|
||||
panel.content.height(contentHeight);
|
||||
}
|
||||
|
||||
panel.button.addClass('active');
|
||||
panel.active = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// Deactivate a panel. use true to hide all panels.
|
||||
deactivatePanel: function (id) {
|
||||
if (id === true) {
|
||||
for (var i in this.panels) {
|
||||
this.deactivatePanel(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (this.panels[id] !== undefined) {
|
||||
var panel = this.panels[id];
|
||||
if (panel.content !== undefined) {
|
||||
panel.content.hide();
|
||||
}
|
||||
panel.button.removeClass('active');
|
||||
panel.active = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// Bind events for all the collapsible arrays.
|
||||
makeNeatArray: function (lists) {
|
||||
lists.find('ul').hide()
|
||||
.parent().addClass('expandable collapsed');
|
||||
|
||||
lists.on('click', 'li', function (event) {
|
||||
event.stopPropagation();
|
||||
$(this).children('ul').toggle().toggleClass('expanded collapsed');
|
||||
});
|
||||
}
|
||||
};
|
||||
}();
|
||||
DEBUGKIT.loader.register(DEBUGKIT.toolbar);
|
||||
|
||||
DEBUGKIT.module('historyPanel');
|
||||
DEBUGKIT.historyPanel = function () {
|
||||
var toolbar = DEBUGKIT.toolbar,
|
||||
historyLinks;
|
||||
|
||||
// Private methods to handle JSON response and insertion of
|
||||
// new content.
|
||||
var switchHistory = function (response) {
|
||||
|
||||
historyLinks.removeClass('loading');
|
||||
|
||||
$.each(toolbar.panels, function (id, panel) {
|
||||
if (panel.content === undefined || response[id] === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
var regionDiv = panel.content.find('.panel-resize-region');
|
||||
if (!regionDiv.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var regionDivs = regionDiv.children();
|
||||
|
||||
regionDivs.filter('div').hide();
|
||||
regionDivs.filter('.panel-history').each(function (i, panelContent) {
|
||||
var panelId = panelContent.id.replace('-history', '');
|
||||
if (response[panelId]) {
|
||||
panelContent = $(panelContent);
|
||||
panelContent.html(response[panelId]);
|
||||
var lists = panelContent.find('.depth-0');
|
||||
toolbar.makeNeatArray(lists);
|
||||
}
|
||||
panelContent.show();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Private method to handle restoration to current request.
|
||||
var restoreCurrentState = function () {
|
||||
var id, i, panelContent, tag;
|
||||
|
||||
historyLinks.removeClass('loading');
|
||||
|
||||
$.each(toolbar.panels, function (panel, id) {
|
||||
if (panel.content === undefined) {
|
||||
return;
|
||||
}
|
||||
var regionDiv = panel.content.find('.panel-resize-region');
|
||||
if (!regionDiv.length) {
|
||||
return;
|
||||
}
|
||||
var regionDivs = regionDiv.children();
|
||||
regionDivs.filter('div').show()
|
||||
.end()
|
||||
.filter('.panel-history').hide();
|
||||
});
|
||||
};
|
||||
|
||||
function handleHistoryLink(event) {
|
||||
event.preventDefault();
|
||||
|
||||
historyLinks.removeClass('active');
|
||||
$(this).addClass('active loading');
|
||||
|
||||
if (this.id === 'history-restore-current') {
|
||||
restoreCurrentState();
|
||||
return false;
|
||||
}
|
||||
|
||||
var xhr = $.ajax({
|
||||
url: this.href,
|
||||
type: 'GET',
|
||||
dataType: 'json'
|
||||
});
|
||||
xhr.success(switchHistory).fail(function () {
|
||||
alert('History retrieval failed');
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init : function () {
|
||||
if (toolbar.panels.history === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
historyLinks = toolbar.panels.history.content.find('.history-link');
|
||||
historyLinks.on('click', handleHistoryLink);
|
||||
}
|
||||
};
|
||||
}();
|
||||
DEBUGKIT.loader.register(DEBUGKIT.historyPanel);
|
||||
|
||||
//Add events + behaviors for toolbar collapser.
|
||||
DEBUGKIT.toolbarToggle = function () {
|
||||
var toolbar = DEBUGKIT.toolbar,
|
||||
Cookie = DEBUGKIT.Util.Cookie,
|
||||
toolbarHidden = false;
|
||||
|
||||
return {
|
||||
init: function () {
|
||||
var button = $('#hide-toolbar'),
|
||||
self = this;
|
||||
|
||||
button.on('click', function (event) {
|
||||
event.preventDefault();
|
||||
self.toggleToolbar();
|
||||
});
|
||||
|
||||
var toolbarState = Cookie.read('toolbarDisplay');
|
||||
if (toolbarState !== 'show') {
|
||||
toolbarHidden = false;
|
||||
this.toggleToolbar();
|
||||
}
|
||||
},
|
||||
|
||||
toggleToolbar: function () {
|
||||
var display = toolbarHidden ? 'show' : 'hide';
|
||||
$.each(toolbar.panels, function (i, panel) {
|
||||
$(panel.element)[display]();
|
||||
Cookie.write('toolbarDisplay', display);
|
||||
});
|
||||
toolbarHidden = !toolbarHidden;
|
||||
|
||||
if (toolbarHidden) {
|
||||
$('#debug-kit-toolbar').addClass('minimized');
|
||||
} else {
|
||||
$('#debug-kit-toolbar').removeClass('minimized');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}();
|
||||
DEBUGKIT.loader.register(DEBUGKIT.toolbarToggle);
|
||||
|
||||
|
||||
}; // DEBUGKIT.registerModules
|
||||
Reference in New Issue
Block a user