Initial commit: apps.prometeysev.ru
This commit is contained in:
commit
96ccabcd8b
6561 files changed
+1270349
No files matched your search
@@ -0,0 +1,317 @@
|
||||
<?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
|
||||
*
|
||||
*/
|
||||
namespace DebugKit\Cache\Engine;
|
||||
|
||||
use Cake\Cache\CacheEngine;
|
||||
use Cake\Cache\CacheRegistry;
|
||||
use DebugKit\DebugTimer;
|
||||
|
||||
/**
|
||||
* A spying proxy for cache engines.
|
||||
*
|
||||
* Used by the CachePanel to wrap and track metrics related to caching.
|
||||
*/
|
||||
class DebugEngine extends CacheEngine
|
||||
{
|
||||
|
||||
/**
|
||||
* Proxied cache engine config.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_config;
|
||||
|
||||
/**
|
||||
* Proxied engine
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_engine;
|
||||
|
||||
/**
|
||||
* Hit/miss metrics.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_metrics = [
|
||||
'write' => 0,
|
||||
'delete' => 0,
|
||||
'read' => 0,
|
||||
'hit' => 0,
|
||||
'miss' => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param mixed $config Config data or the proxied adapter.
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->_config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the proxied Cache Engine
|
||||
*
|
||||
* @param array $config Array of setting for the engine.
|
||||
* @return bool True, this engine cannot fail to initialize.
|
||||
*/
|
||||
public function init(array $config = [])
|
||||
{
|
||||
if (is_object($this->_config)) {
|
||||
$this->_engine = $this->_config;
|
||||
|
||||
return true;
|
||||
}
|
||||
$registry = new CacheRegistry();
|
||||
$this->_engine = $registry->load('spies', $this->_config);
|
||||
unset($registry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the internal engine
|
||||
*
|
||||
* @return \Cake\Cache\CacheEngine
|
||||
*/
|
||||
public function engine()
|
||||
{
|
||||
return $this->_engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the metrics for this object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function metrics()
|
||||
{
|
||||
return $this->_metrics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Track a metric.
|
||||
*
|
||||
* @param string $metric The metric to increment.
|
||||
* @return void
|
||||
*/
|
||||
protected function _track($metric)
|
||||
{
|
||||
$this->_metrics[$metric]++;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function write($key, $value)
|
||||
{
|
||||
$this->_track('write');
|
||||
DebugTimer::start('Cache.write ' . $key);
|
||||
$result = $this->_engine->write($key, $value);
|
||||
DebugTimer::stop('Cache.write ' . $key);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function writeMany($data)
|
||||
{
|
||||
$this->_track('write');
|
||||
DebugTimer::start('Cache.writeMany');
|
||||
$result = $this->_engine->writeMany($data);
|
||||
DebugTimer::stop('Cache.writeMany');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function read($key)
|
||||
{
|
||||
$this->_track('read');
|
||||
DebugTimer::start('Cache.read ' . $key);
|
||||
$result = $this->_engine->read($key);
|
||||
DebugTimer::stop('Cache.read ' . $key);
|
||||
$metric = 'hit';
|
||||
if ($result === false) {
|
||||
$metric = 'miss';
|
||||
}
|
||||
$this->_track($metric);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function readMany($data)
|
||||
{
|
||||
$this->_track('read');
|
||||
DebugTimer::start('Cache.readMany');
|
||||
$result = $this->_engine->readMany($data);
|
||||
DebugTimer::stop('Cache.readMany');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function increment($key, $offset = 1)
|
||||
{
|
||||
$this->_track('write');
|
||||
DebugTimer::start('Cache.increment ' . $key);
|
||||
$result = $this->_engine->increment($key, $offset);
|
||||
DebugTimer::stop('Cache.increment ' . $key);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function decrement($key, $offset = 1)
|
||||
{
|
||||
$this->_track('write');
|
||||
DebugTimer::start('Cache.decrement ' . $key);
|
||||
$result = $this->_engine->decrement($key, $offset);
|
||||
DebugTimer::stop('Cache.decrement ' . $key);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function delete($key)
|
||||
{
|
||||
$this->_track('delete');
|
||||
DebugTimer::start('Cache.delete ' . $key);
|
||||
$result = $this->_engine->delete($key);
|
||||
DebugTimer::stop('Cache.delete ' . $key);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function deleteMany($data)
|
||||
{
|
||||
$this->_track('delete');
|
||||
DebugTimer::start('Cache.deleteMany');
|
||||
$result = $this->_engine->deleteMany($data);
|
||||
DebugTimer::stop('Cache.deleteMany');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function clear($check)
|
||||
{
|
||||
$this->_track('delete');
|
||||
DebugTimer::start('Cache.clear');
|
||||
$result = $this->_engine->clear($check);
|
||||
DebugTimer::stop('Cache.clear');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function groups()
|
||||
{
|
||||
return $this->_engine->groups();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the proxied configuration data.
|
||||
*
|
||||
* This method uses func_get_args() as not doing so confuses the
|
||||
* proxied class.
|
||||
*
|
||||
* @deprecated 3.6.0 use setConfig()/getConfig() instead.
|
||||
* @param string $key The key to set/read.
|
||||
* @param mixed $value The value to set.
|
||||
* @param bool $merge Whether or not configuration should be merged.
|
||||
* @return mixed
|
||||
*/
|
||||
public function config($key = null, $value = null, $merge = true)
|
||||
{
|
||||
return call_user_func_array([$this->_engine, 'config'], func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the config.
|
||||
*
|
||||
* @param string|null $key The key to get or null for the whole config.
|
||||
* @param mixed $default The return value when the key does not exist.
|
||||
* @return mixed Config value being read.
|
||||
*/
|
||||
public function getConfig($key = null, $default = null)
|
||||
{
|
||||
return $this->_engine->getConfig($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the config.
|
||||
*
|
||||
* @param string|array $key The key to set, or a complete array of configs.
|
||||
* @param mixed|null $value The value to set.
|
||||
* @param bool $merge Whether to recursively merge or overwrite existing config, defaults to true.
|
||||
* @return $this
|
||||
* @throws \Cake\Core\Exception\Exception When trying to set a key that is invalid.
|
||||
*/
|
||||
public function setConfig($key, $value = null, $merge = true)
|
||||
{
|
||||
return $this->_engine->setConfig($key, $value, $merge);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function clearGroup($group)
|
||||
{
|
||||
$this->_track('delete');
|
||||
DebugTimer::start('Cache.clearGroup ' . $group);
|
||||
$result = $this->_engine->clearGroup($group);
|
||||
DebugTimer::stop('Cache.clearGroup ' . $group);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic __toString() method to get the CacheEngine's name
|
||||
*
|
||||
* @return string Returns the CacheEngine's name
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
if (!empty($this->_engine)) {
|
||||
list($ns, $class) = namespaceSplit(get_class($this->_engine));
|
||||
|
||||
return str_replace('Engine', '', $class);
|
||||
}
|
||||
|
||||
return $this->_config['className'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Controller\Component;
|
||||
|
||||
use Cake\Controller\Component;
|
||||
use Cake\Controller\ComponentRegistry;
|
||||
|
||||
/**
|
||||
* Class ToolbarComponent
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
* @deprecated
|
||||
*/
|
||||
class ToolbarComponent extends Component
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* If debug is off the component will be disabled and not do any further time tracking
|
||||
* or load the toolbar helper.
|
||||
*
|
||||
* @param \Cake\Controller\ComponentRegistry $registry The ComponentRegistry
|
||||
* @param array $settings An array of config
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __construct(ComponentRegistry $registry, $settings = [])
|
||||
{
|
||||
parent::__construct($registry, $settings);
|
||||
|
||||
$msg = __d('debug_kit', "{0} is now loaded through plugin bootstrapping. Make sure you have {1} in your application's {2}.", 'DebugKit', '`Plugin::load("DebugKit", ["bootstrap" => true, "routes" => true]);`', 'bootstrap.php');
|
||||
throw new \RuntimeException($msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?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 3.6.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\Controller;
|
||||
|
||||
use Cake\View\JsonView;
|
||||
use Composer\Console\Application;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
|
||||
/**
|
||||
* Provides utility features need by the toolbar.
|
||||
*/
|
||||
class ComposerController extends DebugKitController
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
$this->loadComponent('RequestHandler');
|
||||
$this->viewBuilder()->setClassName(JsonView::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check outdated composer dependencies
|
||||
*
|
||||
* @return void
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function checkDependencies()
|
||||
{
|
||||
$this->request->allowMethod('post');
|
||||
|
||||
$input = new ArrayInput([
|
||||
'command' => 'outdated',
|
||||
'--no-interaction' => true,
|
||||
'--direct' => filter_var($this->request->getData('direct'), FILTER_VALIDATE_BOOLEAN),
|
||||
]);
|
||||
|
||||
$output = $this->executeComposerCommand($input);
|
||||
$dependencies = array_filter(explode("\n", $output->fetch()));
|
||||
$packages = [];
|
||||
foreach ($dependencies as $dependency) {
|
||||
if (strpos($dependency, 'php_network_getaddresses') !== false) {
|
||||
throw new \RuntimeException(__d('debug_kit', 'You have to be connected to the internet'));
|
||||
}
|
||||
if (strpos($dependency, '<highlight>') !== false) {
|
||||
$packages['semverCompatible'][] = $dependency;
|
||||
continue;
|
||||
}
|
||||
$packages['bcBreaks'][] = $dependency;
|
||||
}
|
||||
if (!empty($packages['semverCompatible'])) {
|
||||
$packages['semverCompatible'] = trim(implode("\n", $packages['semverCompatible']));
|
||||
}
|
||||
if (!empty($packages['bcBreaks'])) {
|
||||
$packages['bcBreaks'] = trim(implode("\n", $packages['bcBreaks']));
|
||||
}
|
||||
|
||||
$this->set([
|
||||
'_serialize' => ['packages'],
|
||||
'packages' => $packages,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ArrayInput $input An array describing the command input
|
||||
* @return BufferedOutput Aa Console command buffered result
|
||||
*/
|
||||
private function executeComposerCommand(ArrayInput $input)
|
||||
{
|
||||
$bin = implode(DIRECTORY_SEPARATOR, [ROOT, 'vendor', 'bin', 'composer']);
|
||||
putenv('COMPOSER_HOME=' . $bin);
|
||||
putenv('COMPOSER_CACHE_DIR=' . CACHE);
|
||||
|
||||
$dir = getcwd();
|
||||
chdir(ROOT);
|
||||
$timeLimit = ini_get('max_execution_time');
|
||||
set_time_limit(300);
|
||||
$memoryLimit = ini_get('memory_limit');
|
||||
ini_set('memory_limit', '512M');
|
||||
|
||||
$output = new BufferedOutput();
|
||||
$application = new Application();
|
||||
$application->setAutoExit(false);
|
||||
$application->run($input, $output);
|
||||
|
||||
// Restore environment
|
||||
chdir($dir);
|
||||
set_time_limit($timeLimit);
|
||||
ini_set('memory_limit', $memoryLimit);
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
|
||||
/**
|
||||
* Dashboard and common DebugKit backend.
|
||||
*/
|
||||
class DashboardController extends DebugKitController
|
||||
{
|
||||
/**
|
||||
* Before filter handler.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The event.
|
||||
* @return void
|
||||
*/
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
|
||||
$this->viewBuilder()->setLayout('dashboard');
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Cake\Network\Exception\NotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->loadModel('DebugKit.Requests');
|
||||
|
||||
$data = [
|
||||
'driver' => get_class($this->Requests->getConnection()->getDriver()),
|
||||
'rows' => $this->Requests->find()->count(),
|
||||
];
|
||||
|
||||
$this->set('connection', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SQLite DB.
|
||||
*
|
||||
* @return \Cake\Http\Response
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->request->allowMethod('post');
|
||||
$this->loadModel('DebugKit.Requests');
|
||||
|
||||
$this->Requests->Panels->deleteAll('1=1');
|
||||
$this->Requests->deleteAll('1=1');
|
||||
|
||||
return $this->redirect(['action' => 'index']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Controller;
|
||||
|
||||
use Cake\Controller\Controller;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\Http\Exception\NotFoundException;
|
||||
use Cake\Log\Log;
|
||||
|
||||
/**
|
||||
* DebugKit Controller.
|
||||
*/
|
||||
class DebugKitController extends Controller
|
||||
{
|
||||
/**
|
||||
* Before filter handler.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The event.
|
||||
* @return void
|
||||
* @throws \Cake\Http\Exception\NotFoundException
|
||||
*/
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
if (!Configure::read('debug')) {
|
||||
throw new NotFoundException('Not available without debug mode on.');
|
||||
}
|
||||
|
||||
// If CakePHP Authorization\Authorization plugin is enabled,
|
||||
// ignore it, only if `DebugKit.ignoreAuthorization` is set to true
|
||||
$authorizationService = $this->getRequest()->getAttribute('authorization');
|
||||
if ($authorizationService instanceof \Authorization\AuthorizationService) {
|
||||
if (Configure::read('DebugKit.ignoreAuthorization')) {
|
||||
$authorizationService->skipAuthorization();
|
||||
} else {
|
||||
Log::info(
|
||||
"Cake Authorization plugin is enabled. If you would like " .
|
||||
"to force DebugKit to ignore it, set `DebugKit.ignoreAuthorization` " .
|
||||
" Configure option to true."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
<?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 3.3
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\Controller;
|
||||
|
||||
use Cake\Collection\CollectionInterface;
|
||||
use Cake\Core\App;
|
||||
use Cake\Core\Plugin as CorePlugin;
|
||||
use Cake\Event\Event;
|
||||
use Cake\Http\Exception\NotFoundException;
|
||||
use Cake\Routing\Router;
|
||||
use Cake\Utility\Inflector;
|
||||
use DebugKit\Mailer\AbstractResult;
|
||||
use DebugKit\Mailer\PreviewResult;
|
||||
use DebugKit\Mailer\SentMailResult;
|
||||
use PDOException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Provides access to the MailPreview classes for visually debugging email sending
|
||||
*
|
||||
* @property \DebugKit\Model\Table\PanelsTable $Panels
|
||||
*/
|
||||
class MailPreviewController extends DebugKitController
|
||||
{
|
||||
/**
|
||||
* Before render handler.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The event.
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRender(Event $event)
|
||||
{
|
||||
$this->viewBuilder()->setLayout('DebugKit.mailer');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles mail-preview/index
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->set('mailPreviews', $this->getMailPreviews()->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the viewing of an already sent email that was logged in the Mail panel
|
||||
* for DebugKit
|
||||
*
|
||||
* @param string $panelId The Mail panel id where the email data is stored.
|
||||
* @param string $number The email number as stored in the logs.
|
||||
* @return \Psr\Http\Message\ResponseInterface|null.
|
||||
*/
|
||||
public function sent($panelId, $number)
|
||||
{
|
||||
$this->loadModel('DebugKit.Panels');
|
||||
$panel = $this->Panels->get($panelId);
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
$content = @unserialize($panel->content);
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
if (empty($content['emails'][$number])) {
|
||||
throw new NotFoundException(__d('debug_kit', 'No emails found in this request'));
|
||||
}
|
||||
|
||||
$email = $content['emails'][$number];
|
||||
$email = new SentMailResult(array_filter($email['headers']), $email['message']);
|
||||
|
||||
$partType = $this->request->getQuery('part');
|
||||
if ($partType) {
|
||||
return $this->respondWithPart($email, $partType);
|
||||
}
|
||||
|
||||
$this->set('noHeader', true);
|
||||
$this->set('email', $email);
|
||||
$this->set('plugin', '');
|
||||
$this->set('part', $this->findPreferredPart($email, $this->request->getQuery('part')));
|
||||
$this->viewBuilder()->setTemplate('email');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles mail-preview/email
|
||||
*
|
||||
* @param string $name The Mailer name
|
||||
* @param string $method The mailer preview method
|
||||
* @return \Psr\Http\Message\ResponseInterface|null
|
||||
*/
|
||||
public function email($name, $method)
|
||||
{
|
||||
// Clear the plugin attribute from the request instance
|
||||
// Router is holding onto so that we can render mail previews
|
||||
// in a plugin less request context.
|
||||
Router::pushRequest($this->request->withParam('plugin', null));
|
||||
|
||||
$plugin = $this->request->getQuery('plugin');
|
||||
$email = $this->findPreview($name, $method, $plugin);
|
||||
$partType = $this->request->getQuery('part');
|
||||
|
||||
$this->viewBuilder()->setLayout(false);
|
||||
|
||||
if ($partType) {
|
||||
return $this->respondWithPart($email, $partType);
|
||||
}
|
||||
|
||||
$humanName = Inflector::humanize(Inflector::underscore($name) . "_$method");
|
||||
$this->set('title', $humanName);
|
||||
$this->set('email', $email);
|
||||
$this->set('plugin', $plugin);
|
||||
$this->set('part', $this->findPreferredPart($email, $this->request->getQuery('part')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a response object with the requested part type for the
|
||||
* email or throws an exception, if no such part exists.
|
||||
*
|
||||
* @param \Debugkit\Mailer\AbstractResult $email the email to preview
|
||||
* @param string $partType The email part to retrieve
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
protected function respondWithPart($email, $partType)
|
||||
{
|
||||
$part = $this->findPart($email, $partType);
|
||||
|
||||
if ($part === false) {
|
||||
throw new NotFoundException(__d('debug_kit', "Email part ''{0}'' not found in email", $partType));
|
||||
}
|
||||
|
||||
$response = $this->response->withType($partType);
|
||||
if ($part === 'text') {
|
||||
$part = '<pre>' . $part . "</pre>";
|
||||
}
|
||||
$response = $response->withStringBody($part);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an array of MailPreview objects
|
||||
*
|
||||
* @return \Cake\Core\CollectionInterface
|
||||
*/
|
||||
protected function getMailPreviews()
|
||||
{
|
||||
return $this->getMailPreviewClasses()->groupBy('plugin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of MailPreview class names for the app and plugins
|
||||
*
|
||||
* @return \Cake\Core\CollectionInterface
|
||||
*/
|
||||
protected function getMailPreviewClasses()
|
||||
{
|
||||
$pluginPaths = collection(CorePlugin::loaded())
|
||||
->reject(function ($plugin) {
|
||||
return $plugin === 'DebugKit';
|
||||
})
|
||||
->map(function ($plugin) {
|
||||
return [App::path('Mailer/Preview', $plugin), "$plugin."];
|
||||
});
|
||||
|
||||
$appPaths = [App::path('Mailer/Preview'), ''];
|
||||
|
||||
return collection([$appPaths])
|
||||
->append($pluginPaths)
|
||||
->unfold(function ($pairs) {
|
||||
list($paths, $plugin) = $pairs;
|
||||
foreach ($paths as $path) {
|
||||
yield $plugin => $path;
|
||||
}
|
||||
})
|
||||
->unfold(function ($path, $plugin) {
|
||||
foreach (glob($path . "*Preview.php") as $file) {
|
||||
$base = str_replace(".php", "", basename($file));
|
||||
$class = App::className($plugin . $base, 'Mailer/Preview');
|
||||
if ($class) {
|
||||
yield ['plugin' => trim($plugin, '.'), 'class' => new $class()];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a specified email part
|
||||
*
|
||||
* @param \DebugKit\Mailer\AbstractResult $email The result of the email preview
|
||||
* @param string $partType The name of a part
|
||||
* @return null|string
|
||||
*/
|
||||
protected function findPart(AbstractResult $email, $partType)
|
||||
{
|
||||
foreach ($email->getParts() as $part => $content) {
|
||||
if ($part === $partType) {
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a specified email part or the first part available
|
||||
*
|
||||
* @param \DebugKit\Mailer\AbstractResult $email The result of the email preview
|
||||
* @param string $partType The name of a part
|
||||
* @return null|string
|
||||
*/
|
||||
protected function findPreferredPart(AbstractResult $email, $partType)
|
||||
{
|
||||
$parts = $email->getParts();
|
||||
|
||||
if (empty($partType) && !empty($parts['html'])) {
|
||||
return 'html';
|
||||
}
|
||||
|
||||
if (empty($partType)) {
|
||||
foreach ($email->getParts() as $part => $content) {
|
||||
return $part;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->findPart($email, $partType) ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a matching MailPreview object with name
|
||||
*
|
||||
* @param string $previewName The Mailer name
|
||||
* @param string $emailName The mailer preview method
|
||||
* @param string|null $plugin The plugin where the mailer preview should be found
|
||||
* @return \DebugKit\Mailer\PreviewResult The result of the email preview
|
||||
* @throws \Cake\Http\Exception\NotFoundException
|
||||
*/
|
||||
protected function findPreview($previewName, $emailName, $plugin = null)
|
||||
{
|
||||
if ($plugin) {
|
||||
$plugin = "$plugin.";
|
||||
}
|
||||
|
||||
$realClass = App::className($plugin . $previewName, "Mailer/Preview");
|
||||
if (!$realClass) {
|
||||
throw new NotFoundException("Mailer preview ${previewName} not found");
|
||||
}
|
||||
$mailPreview = new $realClass();
|
||||
|
||||
$email = $mailPreview->find($emailName);
|
||||
if (!$email) {
|
||||
throw new NotFoundException(__d('debug_kit', "Mailer preview {0}::{1} not found", $previewName, $emailName));
|
||||
}
|
||||
|
||||
return new PreviewResult($mailPreview->$email(), $email);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\Http\Exception\NotFoundException;
|
||||
|
||||
/**
|
||||
* Provides access to panel data.
|
||||
*
|
||||
* @property \DebugKit\Model\Table\PanelsTable $Panels
|
||||
*/
|
||||
class PanelsController extends DebugKitController
|
||||
{
|
||||
/**
|
||||
* components
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $components = ['RequestHandler', 'Cookie'];
|
||||
|
||||
/**
|
||||
* Before render handler.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The event.
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRender(Event $event)
|
||||
{
|
||||
$this->viewBuilder()
|
||||
->setHelpers([
|
||||
'Form', 'Html', 'Number', 'Url', 'DebugKit.Toolbar',
|
||||
'DebugKit.Credentials', 'DebugKit.SimpleGraph',
|
||||
])
|
||||
->setLayout('DebugKit.toolbar');
|
||||
|
||||
if (!$this->request->is('json')) {
|
||||
$this->viewBuilder()->setClassName('DebugKit.Ajax');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Index method that lets you get requests by panelid.
|
||||
*
|
||||
* @param string $requestId Request id
|
||||
* @return void
|
||||
* @throws \Cake\Http\Exception\NotFoundException
|
||||
*/
|
||||
public function index($requestId = null)
|
||||
{
|
||||
$query = $this->Panels->find('byRequest', ['requestId' => $requestId]);
|
||||
$panels = $query->toArray();
|
||||
if (empty($panels)) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
$this->set([
|
||||
'_serialize' => ['panels'],
|
||||
'panels' => $panels,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* View a panel's data.
|
||||
*
|
||||
* @param string $id The id.
|
||||
* @return void
|
||||
*/
|
||||
public function view($id = null)
|
||||
{
|
||||
$this->Cookie->configKey('debugKit_sort', 'encryption', false);
|
||||
$this->set('sort', $this->Cookie->read('debugKit_sort'));
|
||||
$panel = $this->Panels->get($id);
|
||||
|
||||
$this->set('panel', $panel);
|
||||
// @codingStandardsIgnoreStart
|
||||
$this->set(@unserialize($panel->content));
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
|
||||
/**
|
||||
* Provides access to panel data.
|
||||
*
|
||||
* @property \DebugKit\Model\Table\RequestsTable $Requests
|
||||
*/
|
||||
class RequestsController extends DebugKitController
|
||||
{
|
||||
/**
|
||||
* Before filter handler.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The event.
|
||||
* @return void
|
||||
*/
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
|
||||
$this->response = $this->response->withHeader('Content-Security-Policy', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Before render handler.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The event.
|
||||
* @return void
|
||||
*/
|
||||
public function beforeRender(Event $event)
|
||||
{
|
||||
$this->viewBuilder()
|
||||
->setLayout('DebugKit.toolbar')
|
||||
->setClassName('DebugKit.Ajax');
|
||||
}
|
||||
|
||||
/**
|
||||
* View a request's data.
|
||||
*
|
||||
* @param string $id The id.
|
||||
* @return void
|
||||
*/
|
||||
public function view($id = null)
|
||||
{
|
||||
$toolbar = $this->Requests->get($id, ['contain' => 'Panels']);
|
||||
$this->set('toolbar', $toolbar);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Controller;
|
||||
|
||||
use Cake\Cache\Cache;
|
||||
use Cake\Http\Exception\NotFoundException;
|
||||
|
||||
/**
|
||||
* Provides utility features need by the toolbar.
|
||||
*/
|
||||
class ToolbarController extends DebugKitController
|
||||
{
|
||||
/**
|
||||
* components
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $components = ['RequestHandler'];
|
||||
|
||||
/**
|
||||
* View class
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $viewClass = 'Cake\View\JsonView';
|
||||
|
||||
/**
|
||||
* Clear a named cache.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Cake\Http\Exception\NotFoundException
|
||||
*/
|
||||
public function clearCache()
|
||||
{
|
||||
$this->request->allowMethod('post');
|
||||
if (!$this->request->getData('name')) {
|
||||
throw new NotFoundException(__d('debug_kit', 'Invalid cache engine name.'));
|
||||
}
|
||||
$result = Cache::clear(false, $this->request->getData('name'));
|
||||
$this->set([
|
||||
'_serialize' => ['success'],
|
||||
'success' => $result,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
<?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 3.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\Database\Log;
|
||||
|
||||
use Cake\Database\Log\LoggedQuery;
|
||||
use Cake\Database\Log\QueryLogger;
|
||||
use Psr\Log\AbstractLogger as PsrAbstractLogger;
|
||||
|
||||
/**
|
||||
* DebugKit Query logger.
|
||||
*
|
||||
* This logger decorates the existing logger if it exists,
|
||||
* and stores log messages internally so they can be displayed
|
||||
* or stored for future use.
|
||||
*/
|
||||
class DebugLog extends QueryLogger
|
||||
{
|
||||
|
||||
/**
|
||||
* Logs from the current request.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_queries = [];
|
||||
|
||||
/**
|
||||
* Decorated logger.
|
||||
*
|
||||
* @var \Cake\Database\Log\LoggedQuery
|
||||
*/
|
||||
protected $_logger;
|
||||
|
||||
/**
|
||||
* Name of the connection being logged.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_connectionName;
|
||||
|
||||
/**
|
||||
* Total time (ms) of all queries
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_totalTime = 0;
|
||||
|
||||
/**
|
||||
* Total rows of all queries
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_totalRows = 0;
|
||||
|
||||
/**
|
||||
* Set to true to capture schema reflection queries
|
||||
* in the SQL log panel.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_includeSchema = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \Cake\Database\Log\QueryLogger $logger The logger to decorate and spy on.
|
||||
* @param string $name The name of the connection being logged.
|
||||
* @param bool $includeSchema Whether or not schema reflection should be included.
|
||||
*/
|
||||
public function __construct($logger, $name, $includeSchema = false)
|
||||
{
|
||||
$this->_logger = $logger;
|
||||
$this->_connectionName = $name;
|
||||
$this->_includeSchema = $includeSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the schema include flag.
|
||||
*
|
||||
* @param bool $value Set
|
||||
* @return $this
|
||||
*/
|
||||
public function setIncludeSchema($value)
|
||||
{
|
||||
$this->_includeSchema = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the connection name.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function name()
|
||||
{
|
||||
return $this->_connectionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stored logs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function queries()
|
||||
{
|
||||
return $this->_queries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total time
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function totalTime()
|
||||
{
|
||||
return $this->_totalTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total rows
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function totalRows()
|
||||
{
|
||||
return $this->_totalRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log queries
|
||||
*
|
||||
* @param \Cake\Database\Log\LoggedQuery $query The query being logged.
|
||||
* @return void
|
||||
*/
|
||||
public function log(LoggedQuery $query)
|
||||
{
|
||||
if ($this->_logger) {
|
||||
if ($this->_logger instanceof PsrAbstractLogger) {
|
||||
$this->_logger->log($query, $query->error);
|
||||
} else {
|
||||
$this->_logger->log($query);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->_includeSchema === false && $this->isSchemaQuery($query)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($query->params)) {
|
||||
$query->query = $this->_interpolate($query);
|
||||
}
|
||||
$this->_totalTime += $query->took;
|
||||
$this->_totalRows += $query->numRows;
|
||||
|
||||
$this->_queries[] = [
|
||||
'query' => $query->query,
|
||||
'took' => $query->took,
|
||||
'rows' => $query->numRows,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sniff SQL statements for things only found in schema reflection.
|
||||
*
|
||||
* @param \Cake\Database\Log\LoggedQuery $query The query to check.
|
||||
* @return bool
|
||||
*/
|
||||
protected function isSchemaQuery(LoggedQuery $query)
|
||||
{
|
||||
$querystring = $query->query;
|
||||
|
||||
return (
|
||||
// Multiple engines
|
||||
strpos($querystring, 'FROM information_schema') !== false ||
|
||||
// Postgres
|
||||
strpos($querystring, 'FROM pg_catalog') !== false ||
|
||||
// MySQL
|
||||
strpos($querystring, 'SHOW TABLE') === 0 ||
|
||||
strpos($querystring, 'SHOW FULL COLUMNS') === 0 ||
|
||||
strpos($querystring, 'SHOW INDEXES') === 0 ||
|
||||
// Sqlite
|
||||
strpos($querystring, 'FROM sqlite_master') !== false ||
|
||||
strpos($querystring, 'PRAGMA') === 0 ||
|
||||
// Sqlserver
|
||||
strpos($querystring, 'FROM INFORMATION_SCHEMA') !== false ||
|
||||
strpos($querystring, 'FROM sys.') !== false
|
||||
);
|
||||
}
|
||||
}
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit;
|
||||
|
||||
use Cake\Core\Plugin as CorePlugin;
|
||||
use Cake\Event\Event;
|
||||
use Cake\Utility\Hash;
|
||||
use Composer\Json\JsonFile;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* Contains methods for Providing list of files.
|
||||
*
|
||||
*/
|
||||
class DebugInclude
|
||||
{
|
||||
|
||||
/**
|
||||
* The list of plugins within the application
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $_pluginPaths = [];
|
||||
|
||||
/**
|
||||
* The list of Composer packages
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $_composerPaths = [];
|
||||
|
||||
/**
|
||||
* File Types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_fileTypes = [
|
||||
'Auth', 'Cache', 'Collection', 'Config', 'Configure', 'Console', 'Component', 'Controller',
|
||||
'Behavior', 'Database', 'Datasource', 'Model', 'Template', 'View', 'Utility',
|
||||
'Network', 'Routing', 'I18n', 'Log', 'Error', 'Event', 'Form', 'Filesystem',
|
||||
'ORM', 'Filter', 'Validation',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get a list of plugins on construct for later use
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
foreach (CorePlugin::loaded() as $plugin) {
|
||||
$this->_pluginPaths[$plugin] = str_replace('/', DIRECTORY_SEPARATOR, CorePlugin::path($plugin));
|
||||
}
|
||||
|
||||
$lockFile = new JsonFile(ROOT . DIRECTORY_SEPARATOR . 'composer.lock');
|
||||
if ($lockFile->exists()) {
|
||||
$lockContent = $lockFile->read();
|
||||
|
||||
$vendorDir = ROOT . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR;
|
||||
$packages = array_merge($lockContent['packages'], $lockContent['packages-dev']);
|
||||
|
||||
foreach ($packages as $package) {
|
||||
$this->_composerPaths[$package['name']] = $vendorDir . str_replace('/', DIRECTORY_SEPARATOR, $package['name']) . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the possible include paths
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function includePaths()
|
||||
{
|
||||
$paths = explode(PATH_SEPARATOR, get_include_path());
|
||||
$paths = array_filter($paths, function ($path) {
|
||||
if ($path === '.' || strlen($path) === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return array_values($paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a path is part of CakePHP
|
||||
*
|
||||
* @param string $file File to check
|
||||
* @return bool
|
||||
*/
|
||||
public function isCakeFile($file)
|
||||
{
|
||||
return strpos($file, CAKE) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a path is from APP but not a plugin
|
||||
*
|
||||
* @param string $file File to check
|
||||
* @return bool
|
||||
*/
|
||||
public function isAppFile($file)
|
||||
{
|
||||
return strpos($file, APP) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect plugin the file belongs to
|
||||
*
|
||||
* @param string $file File to check
|
||||
* @return string|bool plugin name, or false if not plugin
|
||||
*/
|
||||
public function getPluginName($file)
|
||||
{
|
||||
foreach ($this->_pluginPaths as $plugin => $path) {
|
||||
if (strpos($file, $path) === 0) {
|
||||
return $plugin;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect Composer package the file belongs to
|
||||
*
|
||||
* @param string $file File to check
|
||||
* @return string|bool package name, or false if not Composer package
|
||||
*/
|
||||
public function getComposerPackageName($file)
|
||||
{
|
||||
foreach ($this->_composerPaths as $package => $path) {
|
||||
if (strpos($file, $path) === 0) {
|
||||
return $package;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the path with APP, CAKE, ROOT or the plugin name
|
||||
*
|
||||
* @param string $file File to check
|
||||
* @param string $type The file type
|
||||
* @param string|null $name plugin name or composer package
|
||||
* @return string Path with replaced prefix
|
||||
*/
|
||||
public function niceFileName($file, $type, $name = null)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'app':
|
||||
return str_replace(APP, 'APP' . DIRECTORY_SEPARATOR, $file);
|
||||
|
||||
case 'cake':
|
||||
return str_replace(CAKE, 'CAKE' . DIRECTORY_SEPARATOR, $file);
|
||||
|
||||
case 'root':
|
||||
return str_replace(ROOT, 'ROOT', $file);
|
||||
|
||||
case 'plugin':
|
||||
return str_replace($this->_pluginPaths[$name], $name . DIRECTORY_SEPARATOR, $file);
|
||||
|
||||
case 'vendor':
|
||||
return str_replace($this->_composerPaths[$name], '', $file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of file (model, controller etc)
|
||||
*
|
||||
* @param string $file File to check.
|
||||
* @return string
|
||||
*/
|
||||
public function getFileType($file)
|
||||
{
|
||||
foreach ($this->_fileTypes as $type) {
|
||||
if (stripos($file, DIRECTORY_SEPARATOR . $type . DIRECTORY_SEPARATOR) !== false) {
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
|
||||
return 'other';
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit;
|
||||
|
||||
use Cake\Error\Debugger;
|
||||
|
||||
/**
|
||||
* Contains methods for Profiling memory usage.
|
||||
*
|
||||
*/
|
||||
class DebugMemory
|
||||
{
|
||||
|
||||
/**
|
||||
* An array of recorded memory use points.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $_points = [];
|
||||
|
||||
/**
|
||||
* Get current memory usage
|
||||
*
|
||||
* @return int 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 int 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 bool
|
||||
*/
|
||||
public static function record($message = null)
|
||||
{
|
||||
$memoryUse = self::getCurrent();
|
||||
if (!$message) {
|
||||
$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 bool $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 = [];
|
||||
}
|
||||
|
||||
return $marks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear out any existing memory points
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clear()
|
||||
{
|
||||
self::$_points = [];
|
||||
}
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\Event\EventListenerInterface;
|
||||
use Cake\Utility\Inflector;
|
||||
|
||||
/**
|
||||
* Base class for debug panels.
|
||||
*
|
||||
* @since DebugKit 0.1
|
||||
*/
|
||||
class DebugPanel implements EventListenerInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Defines which plugin this panel is from so the element can be located.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $plugin = 'DebugKit';
|
||||
|
||||
/**
|
||||
* The data collected about a given request.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data = [];
|
||||
|
||||
/**
|
||||
* Get the title for the panel.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function title()
|
||||
{
|
||||
list($ns, $name) = namespaceSplit(get_class($this));
|
||||
$name = substr($name, 0, strlen('Panel') * -1);
|
||||
|
||||
return Inflector::humanize(Inflector::underscore($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element name for the panel.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function elementName()
|
||||
{
|
||||
list($ns, $name) = namespaceSplit(get_class($this));
|
||||
if ($this->plugin) {
|
||||
return $this->plugin . '.' . Inflector::underscore($name);
|
||||
}
|
||||
|
||||
return Inflector::underscore($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data a panel has collected.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the summary data for a panel.
|
||||
*
|
||||
* This data is displayed in the toolbar even when the panel is collapsed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize hook method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown callback
|
||||
*
|
||||
* @param \Cake\Event\Event $event The event.
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(Event $event)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the events this panels supports.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function implementedEvents()
|
||||
{
|
||||
return [
|
||||
'Controller.shutdown' => 'shutdown',
|
||||
];
|
||||
}
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
<?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 3.11.4
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Database\Query;
|
||||
use Cake\Error\Debugger;
|
||||
use SqlFormatter;
|
||||
|
||||
/**
|
||||
* Contains methods for dumping well formatted SQL queries.
|
||||
*/
|
||||
class DebugSql
|
||||
{
|
||||
/**
|
||||
* Template used for HTML output.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $templateHtml = <<<HTML
|
||||
<div class="cake-debug-output">
|
||||
%s
|
||||
<pre class="cake-debug">
|
||||
%s
|
||||
</pre>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
/**
|
||||
* Template used for CLI and text output.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $templateText = <<<TEXT
|
||||
%s
|
||||
########## DEBUG ##########
|
||||
%s
|
||||
###########################
|
||||
|
||||
TEXT;
|
||||
|
||||
/**
|
||||
* Prints out the SQL statements generated by a Query object.
|
||||
*
|
||||
* This function returns the same variable that was passed.
|
||||
* Only runs if debug mode is enabled.
|
||||
*
|
||||
* @param Query $query Query to show SQL statements for.
|
||||
* @param bool $showValues Renders the SQL statement with bound variables.
|
||||
* @param bool|null $showHtml If set to true, the method prints the debug
|
||||
* data in a browser-friendly way.
|
||||
* @param int $stackDepth Provides a hint as to which file in the call stack to reference.
|
||||
* @return Query
|
||||
*/
|
||||
public static function sql(Query $query, $showValues = true, $showHtml = null, $stackDepth = 0)
|
||||
{
|
||||
if (!Configure::read('debug')) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
$sql = (string)$query;
|
||||
if ($showValues) {
|
||||
$sql = method_exists($query, 'getValueBinder')
|
||||
? static::interpolate($sql, $query->getValueBinder()->bindings())
|
||||
: static::interpolate($sql, $query->valueBinder()->bindings());
|
||||
}
|
||||
|
||||
$trace = Debugger::trace(['start' => 1, 'depth' => $stackDepth + 2, 'format' => 'array']);
|
||||
$file = isset($trace[$stackDepth]) ? $trace[$stackDepth]['file'] : 'n/a';
|
||||
$line = isset($trace[$stackDepth]) ? $trace[$stackDepth]['line'] : 0;
|
||||
$lineInfo = '';
|
||||
if ($file) {
|
||||
$search = [];
|
||||
if (defined('ROOT')) {
|
||||
$search = [ROOT];
|
||||
}
|
||||
if (defined('CAKE_CORE_INCLUDE_PATH')) {
|
||||
array_unshift($search, CAKE_CORE_INCLUDE_PATH);
|
||||
}
|
||||
$file = str_replace($search, '', $file);
|
||||
}
|
||||
|
||||
$template = static::$templateHtml;
|
||||
$sqlHighlight = true;
|
||||
if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') || $showHtml === false) {
|
||||
$template = static::$templateText;
|
||||
$sqlHighlight = false;
|
||||
if ($file && $line) {
|
||||
$lineInfo = sprintf('%s (line %s)', $file, $line);
|
||||
}
|
||||
}
|
||||
if ($showHtml === null && $template !== static::$templateText) {
|
||||
$showHtml = true;
|
||||
}
|
||||
|
||||
$var = $showHtml ? SqlFormatter::format($sql, $sqlHighlight) : $sql;
|
||||
$var = str_replace(
|
||||
'<span >:</span> <span style="color: #333;">',
|
||||
'<span >:</span><span style="color: #333;">',
|
||||
$var
|
||||
);
|
||||
|
||||
if ($showHtml) {
|
||||
$template = static::$templateHtml;
|
||||
if ($file && $line) {
|
||||
$lineInfo = sprintf('<span><strong>%s</strong> (line <strong>%s</strong>)</span>', $file, $line);
|
||||
}
|
||||
}
|
||||
|
||||
printf($template, $lineInfo, $var);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints out the SQL statements generated by a Query object and dies.
|
||||
*
|
||||
* Only runs if debug mode is enabled.
|
||||
* It will otherwise just continue code execution and ignore this function.
|
||||
*
|
||||
* @param Query $query Query to show SQL statements for.
|
||||
* @param bool $showValues Renders the SQL statement with bound variables.
|
||||
* @param bool|null $showHtml If set to true, the method prints the debug
|
||||
* data in a browser-friendly way.
|
||||
* @param int $stackDepth Provides a hint as to which file in the call stack to reference.
|
||||
* @return void
|
||||
*/
|
||||
public static function sqld(Query $query, $showValues = true, $showHtml = null, $stackDepth = 1)
|
||||
{
|
||||
static::sql($query, $showValues, $showHtml, $stackDepth);
|
||||
die(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function used to replace query placeholders by the real
|
||||
* params used to execute the query.
|
||||
*
|
||||
* @param string $sql The SQL statement
|
||||
* @param array $bindings The Query bindings
|
||||
* @return string
|
||||
*/
|
||||
private static function interpolate($sql, array $bindings)
|
||||
{
|
||||
$params = array_map(function ($binding) {
|
||||
$p = $binding['value'];
|
||||
|
||||
if ($p === null) {
|
||||
return 'NULL';
|
||||
}
|
||||
if (is_bool($p)) {
|
||||
return $p ? '1' : '0';
|
||||
}
|
||||
|
||||
if (is_string($p)) {
|
||||
$replacements = [
|
||||
'$' => '\\$',
|
||||
'\\' => '\\\\\\\\',
|
||||
"'" => "''",
|
||||
];
|
||||
|
||||
$p = strtr($p, $replacements);
|
||||
|
||||
return "'$p'";
|
||||
}
|
||||
|
||||
return $p;
|
||||
}, $bindings);
|
||||
|
||||
$keys = [];
|
||||
$limit = is_int(key($params)) ? 1 : -1;
|
||||
foreach ($params as $key => $param) {
|
||||
$keys[] = is_string($key) ? "/$key\b/" : '/[?]/';
|
||||
}
|
||||
|
||||
return preg_replace($keys, $params, $sql, $limit);
|
||||
}
|
||||
}
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit;
|
||||
|
||||
use Cake\Error\Debugger;
|
||||
|
||||
/**
|
||||
* Contains methods for Profiling and creating timers.
|
||||
*
|
||||
*/
|
||||
class DebugTimer
|
||||
{
|
||||
|
||||
/**
|
||||
* Internal timers array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $_timers = [];
|
||||
|
||||
/**
|
||||
* Start an benchmarking timer.
|
||||
*
|
||||
* @param string $name The name of the timer to start.
|
||||
* @param string $message A message for your timer
|
||||
* @return bool Always true
|
||||
*/
|
||||
public static function start($name = null, $message = null)
|
||||
{
|
||||
$start = microtime(true);
|
||||
|
||||
if (!$name) {
|
||||
$named = false;
|
||||
$calledFrom = debug_backtrace();
|
||||
$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] = [
|
||||
'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 bool 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 bool $clear false
|
||||
* @return array
|
||||
*/
|
||||
public static function getAll($clear = false)
|
||||
{
|
||||
$start = self::requestStartTime();
|
||||
$now = microtime(true);
|
||||
|
||||
$times = [];
|
||||
if (!empty(self::$_timers)) {
|
||||
$firstTimer = reset(self::$_timers);
|
||||
$_end = $firstTimer['start'];
|
||||
} else {
|
||||
$_end = $now;
|
||||
}
|
||||
$times['Core Processing (Derived from $_SERVER["REQUEST_TIME"])'] = [
|
||||
'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, [
|
||||
'start' => $timer['start'] - $start,
|
||||
'end' => $timer['end'] - $start,
|
||||
'time' => self::elapsedTime($name),
|
||||
]);
|
||||
}
|
||||
if ($clear) {
|
||||
self::$_timers = [];
|
||||
}
|
||||
|
||||
return $times;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all existing timers
|
||||
*
|
||||
* @return bool true
|
||||
*/
|
||||
public static function clear()
|
||||
{
|
||||
self::$_timers = [];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the difference in time between the timer start and timer end.
|
||||
*
|
||||
* @param string $name the name of the timer you want elapsed time for.
|
||||
* @param int $precision 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;
|
||||
}
|
||||
}
|
||||
+138
@@ -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 ""
|
||||
|
||||
@@ -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 ""
|
||||
@@ -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"
|
||||
@@ -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 ""
|
||||
@@ -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"
|
||||
@@ -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: 2014-01-23 08:29+0200\n"
|
||||
"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
|
||||
"Last-Translator: Lincoln Brito <lincoln.sbrito@gmail.com>\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=2; plural=n>1;\n"
|
||||
|
||||
#: controllers/components/toolbar.php:91
|
||||
msgid "Component initialization and startup"
|
||||
msgstr "Inicialização de componente"
|
||||
|
||||
#: controllers/components/toolbar.php:140
|
||||
msgid "Controller Action"
|
||||
msgstr "Action do Controller"
|
||||
|
||||
#: controllers/components/toolbar.php:167
|
||||
msgid "Render Controller Action"
|
||||
msgstr "Renderizar Action do Controller"
|
||||
|
||||
#: controllers/components/toolbar.php:231
|
||||
msgid "Could not load DebugToolbar panel %s"
|
||||
msgstr "Não foi possível carregar o painel %s do DebugToolbar"
|
||||
|
||||
#: views/elements/debug_toolbar.ctp:25
|
||||
msgid "There are no active panels. You must enable a panel to see its output."
|
||||
msgstr "Não existem painéis ativos. Você deve habilitar um painel para visualizar sua saída."
|
||||
|
||||
#: views/elements/history_panel.ctp:21
|
||||
msgid "Request History"
|
||||
msgstr "Histórico de requisições"
|
||||
|
||||
#: views/elements/history_panel.ctp:23
|
||||
msgid "No previous requests logged."
|
||||
msgstr "Sem requisições anteriores logadas."
|
||||
|
||||
#: views/elements/history_panel.ctp:25
|
||||
msgid "previous requests available"
|
||||
msgstr "requisições anteriores disponíveis"
|
||||
|
||||
#: views/elements/history_panel.ctp:27
|
||||
msgid "Restore to current request"
|
||||
msgstr "Restaurar para requisição atual"
|
||||
|
||||
#: views/elements/log_panel.ctp:21
|
||||
msgid "Logs"
|
||||
msgstr "Logs"
|
||||
|
||||
#: views/elements/log_panel.ctp:28
|
||||
msgid "Time"
|
||||
msgstr "Tempo"
|
||||
|
||||
#: views/elements/log_panel.ctp:28 views/elements/timer_panel.ctp:54
|
||||
msgid "Message"
|
||||
msgstr "Mensagem"
|
||||
|
||||
#: views/elements/log_panel.ctp:37
|
||||
msgid "There were no log entries made this request"
|
||||
msgstr "Não houveram entradas no log para essa requisição "
|
||||
|
||||
#: views/elements/request_panel.ctp:21
|
||||
msgid "Request"
|
||||
msgstr "Requisição"
|
||||
|
||||
#: views/elements/request_panel.ctp:35
|
||||
msgid "Current Route"
|
||||
msgstr "Rota Atual"
|
||||
|
||||
#: views/elements/session_panel.ctp:21
|
||||
msgid "Session"
|
||||
msgstr "Sessão"
|
||||
|
||||
#: 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 "alternar (%s) query explains por %s"
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:39
|
||||
msgid "No slow queries!, or your database does not support EXPLAIN"
|
||||
msgstr "Sem consultas lentas!, ou o seu banco de dados não suporta EXPLAIN"
|
||||
|
||||
#: views/elements/sql_log_panel.ctp:44
|
||||
msgid "No active database connections"
|
||||
msgstr "Sem conexões ativas de banco de dados"
|
||||
|
||||
#: views/elements/timer_panel.ctp:33
|
||||
msgid "Memory"
|
||||
msgstr "Memória"
|
||||
|
||||
#: views/elements/timer_panel.ctp:35
|
||||
msgid "Current Memory Use"
|
||||
msgstr "Uso atual de memória"
|
||||
|
||||
#: views/elements/timer_panel.ctp:39
|
||||
msgid "Peak Memory Use"
|
||||
msgstr "Pico de uso de memória"
|
||||
|
||||
#: views/elements/timer_panel.ctp:43
|
||||
msgid "Timers"
|
||||
msgstr "Tempos"
|
||||
|
||||
#: views/elements/timer_panel.ctp:45
|
||||
msgid "%s (ms)"
|
||||
msgstr "%s (ms)"
|
||||
|
||||
#: views/elements/timer_panel.ctp:46
|
||||
msgid "Total Request Time:"
|
||||
msgstr "Tempo Total de Requisição"
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Time in ms"
|
||||
msgstr "Tempo em ms"
|
||||
|
||||
#: views/elements/timer_panel.ctp:54
|
||||
msgid "Graph"
|
||||
msgstr "Gráfico"
|
||||
|
||||
#: views/elements/variables_panel.ctp:21
|
||||
msgid "View Variables"
|
||||
msgstr "Visualizar Variáveis"
|
||||
|
||||
#: views/helpers/simple_graph.php:79
|
||||
msgid "Starting %sms into the request, taking %sms"
|
||||
msgstr "Começando %sms na requisição, levando %sms"
|
||||
@@ -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 ""
|
||||
@@ -0,0 +1,78 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Log\Engine;
|
||||
|
||||
use Cake\Log\Engine\BaseLog;
|
||||
|
||||
/**
|
||||
* A CakeLog listener which saves having to munge files or other configured loggers.
|
||||
*
|
||||
*/
|
||||
class DebugKitLog extends BaseLog
|
||||
{
|
||||
|
||||
/**
|
||||
* logs
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_logs = [];
|
||||
|
||||
/**
|
||||
* Captures log messages in memory
|
||||
*
|
||||
* @param string $type The type of message being logged.
|
||||
* @param string $message The message being logged.
|
||||
* @param array $context Additional context data
|
||||
* @return void
|
||||
*/
|
||||
public function log($type, $message, array $context = [])
|
||||
{
|
||||
if (!isset($this->_logs[$type])) {
|
||||
$this->_logs[$type] = [];
|
||||
}
|
||||
$this->_logs[$type][] = [date('Y-m-d H:i:s'), $this->_format($message)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return $this->_logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of log entries.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return array_reduce($this->_logs, function ($sum, $v) {
|
||||
return $sum + count($v);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are no logs.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function noLogs()
|
||||
{
|
||||
return empty($this->_logs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Mailer;
|
||||
|
||||
/**
|
||||
* A simple structure for representing the results of a sent email
|
||||
*/
|
||||
abstract class AbstractResult
|
||||
{
|
||||
|
||||
/**
|
||||
* The list of headers included in the email
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $headers = [];
|
||||
|
||||
/**
|
||||
* The rendered parts of the email (for example text and html)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $parts = [];
|
||||
|
||||
/**
|
||||
* Returns the list of headers included in th email
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rendered parts in th email
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getParts()
|
||||
{
|
||||
return $this->parts;
|
||||
}
|
||||
}
|
||||
+102
@@ -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
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\Mailer;
|
||||
|
||||
use Cake\Datasource\ModelAwareTrait;
|
||||
use Cake\Mailer\MailerAwareTrait;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionMethod;
|
||||
|
||||
/**
|
||||
* Base class for Mailer Previews.
|
||||
*/
|
||||
class MailPreview
|
||||
{
|
||||
use MailerAwareTrait;
|
||||
use ModelAwareTrait;
|
||||
|
||||
/**
|
||||
* Returns the name of an email if it is valid
|
||||
*
|
||||
* @param string $email Email name
|
||||
* @return null|string
|
||||
*/
|
||||
public function find($email)
|
||||
{
|
||||
if ($this->validEmail($email)) {
|
||||
return $email;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of valid emails
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEmails()
|
||||
{
|
||||
$emails = [];
|
||||
foreach (get_class_methods($this) as $methodName) {
|
||||
if (!$this->validEmail($methodName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$emails[] = $methodName;
|
||||
}
|
||||
|
||||
return $emails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this preview
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function name()
|
||||
{
|
||||
$classname = get_class($this);
|
||||
$pos = strrpos($classname, '\\');
|
||||
|
||||
return substr($classname, $pos + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not a specified email is valid
|
||||
* for this MailPreview instance
|
||||
*
|
||||
* @param string $email Name of email
|
||||
* @return bool
|
||||
*/
|
||||
protected function validEmail($email)
|
||||
{
|
||||
if (empty($email)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$baseClass = new ReflectionClass(get_class());
|
||||
if ($baseClass->hasMethod($email)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$method = new ReflectionMethod($this, $email);
|
||||
} catch (ReflectionException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $method->isPublic();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Mailer;
|
||||
|
||||
use Cake\Mailer\Mailer;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Represents the result of a preview for a given mailer
|
||||
*/
|
||||
class PreviewResult extends AbstractResult
|
||||
{
|
||||
|
||||
/**
|
||||
* Processes the mailer to extract the headers and parts
|
||||
*
|
||||
* @param Mailer $mailer The mailer instance to execute and extract the email data from
|
||||
* @param string $method The method to execute in the mailer
|
||||
*/
|
||||
public function __construct(Mailer $mailer, $method)
|
||||
{
|
||||
$this->processMailer(clone $mailer, $method);
|
||||
$mailer->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the mailer and extracts the relevant information from the generated email
|
||||
*
|
||||
* @param Mailer $mailer The mailer instance to execute and extract the email data from
|
||||
* @param string $method The method to execute in the mailer
|
||||
* @return void
|
||||
*/
|
||||
protected function processMailer(Mailer $mailer, $method)
|
||||
{
|
||||
$reflection = new ReflectionClass($mailer);
|
||||
$prop = $reflection->getProperty('_email');
|
||||
$prop->setAccessible(true);
|
||||
$email = $prop->getValue($mailer);
|
||||
|
||||
if (!$email->viewBuilder()->getTemplate()) {
|
||||
$email->viewBuilder()->setTemplate($method);
|
||||
}
|
||||
|
||||
$render = (new ReflectionClass($email))
|
||||
->getMethod('_renderTemplates')
|
||||
->getClosure($email);
|
||||
|
||||
$this->parts = $render('');
|
||||
|
||||
$extra = ['from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'subject'];
|
||||
$this->headers = array_filter($email->getHeaders($extra));
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
namespace DebugKit\Mailer;
|
||||
|
||||
use Cake\Mailer\Mailer;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Represents the result of an already sent email
|
||||
*
|
||||
*/
|
||||
class SentMailResult extends AbstractResult
|
||||
{
|
||||
|
||||
/**
|
||||
* Processes the mailer to extract the headers and parts
|
||||
*
|
||||
* @param array $headers The headers included in the email
|
||||
* @param array $parts The rendered parts in the email
|
||||
*/
|
||||
public function __construct(array $headers, array $parts)
|
||||
{
|
||||
$this->headers = $headers;
|
||||
$this->parts = $parts;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
namespace DebugKit\Mailer\Transport;
|
||||
|
||||
use Cake\Core\App;
|
||||
use Cake\Mailer\AbstractTransport;
|
||||
use Cake\Mailer\Email;
|
||||
|
||||
/**
|
||||
* Debug Transport class, useful for emulating the email sending process and inspecting
|
||||
* the resulting email message before actually sending it during development
|
||||
*/
|
||||
class DebugKitTransport extends AbstractTransport
|
||||
{
|
||||
/**
|
||||
* The transport object this class is decorating
|
||||
*
|
||||
* @var AbstractTransport
|
||||
*/
|
||||
protected $originalTransport;
|
||||
|
||||
/**
|
||||
* A reference to the object were emails will be pushed to
|
||||
* for logging.
|
||||
*
|
||||
* @var \ArrayObject
|
||||
*/
|
||||
protected $emailLog;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $config Configuration options.
|
||||
* @param AbstractTransport|null $originalTransport The transport that is to be decorated
|
||||
*/
|
||||
public function __construct($config = [], AbstractTransport $originalTransport = null)
|
||||
{
|
||||
$this->emailLog = $config['debugKitLog'];
|
||||
|
||||
if ($originalTransport !== null) {
|
||||
$this->originalTransport = $originalTransport;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$className = false;
|
||||
if (!empty($config['originalClassName'])) {
|
||||
$className = App::className(
|
||||
$config['originalClassName'],
|
||||
'Mailer/Transport',
|
||||
'Transport'
|
||||
);
|
||||
}
|
||||
|
||||
if ($className) {
|
||||
unset($config['originalClassName'], $config['debugKitLog']);
|
||||
$this->originalTransport = new $className($config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail
|
||||
*
|
||||
* @param \Cake\Mailer\Email $email Cake Email
|
||||
* @return array
|
||||
*/
|
||||
public function send(Email $email)
|
||||
{
|
||||
$headers = $email->getHeaders(['from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc']);
|
||||
$parts = [
|
||||
'text' => $email->message(Email::MESSAGE_TEXT),
|
||||
'html' => $email->message(Email::MESSAGE_HTML),
|
||||
];
|
||||
|
||||
$headers['Subject'] = $email->getOriginalSubject();
|
||||
$result = ['headers' => $headers, 'message' => $parts];
|
||||
$this->emailLog[] = $result;
|
||||
|
||||
if ($this->originalTransport !== null) {
|
||||
return $this->originalTransport->send($email);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy unknown methods to the wrapped object
|
||||
*
|
||||
* @param string $method The method to call
|
||||
* @param array $args The args to call $method with.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, array $args)
|
||||
{
|
||||
return call_user_func_array([$this->originalTransport, $method], $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy property reads to the wrapped object
|
||||
*
|
||||
* @param string $name The property to read.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->originalTransport->{$name};
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy property changes to the wrapped object
|
||||
*
|
||||
* @param string $name The property to read.
|
||||
* @param mixed $value The property value.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
return $this->originalTransport->{$name} = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy property changes to the wrapped object
|
||||
*
|
||||
* @param string $name The property to read.
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return isset($this->originalTransport->{$name});
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy property changes to the wrapped object
|
||||
*
|
||||
* @param string $name The property to delete.
|
||||
* @return void
|
||||
*/
|
||||
public function __unset($name)
|
||||
{
|
||||
unset($this->originalTransport->{$name});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?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
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\Middleware;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\EventManager;
|
||||
use DebugKit\ToolbarService;
|
||||
|
||||
/**
|
||||
* PSR-7 Middleware that enables DebugKit for the layers below.
|
||||
*/
|
||||
class DebugKitMiddleware
|
||||
{
|
||||
/**
|
||||
* @var \DebugKit\ToolbarService
|
||||
*/
|
||||
protected $service;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DebugKit\ToolbarService $service The configured service, or null.
|
||||
*/
|
||||
public function __construct(ToolbarService $service = null)
|
||||
{
|
||||
$service = $service ?: new ToolbarService(EventManager::instance(), (array)Configure::read('DebugKit'));
|
||||
$this->service = $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the middleware.
|
||||
*
|
||||
* DebugKit will augment the response and add the toolbar if possible.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
|
||||
* @param \Psr\Http\Message\ResponseInterface $response The response.
|
||||
* @param callable $next Callback to invoke the next middleware.
|
||||
* @return \Psr\Http\Message\ResponseInterface A response
|
||||
*/
|
||||
public function __invoke($request, $response, $next)
|
||||
{
|
||||
$this->service->loadPanels();
|
||||
$this->service->initializePanels();
|
||||
$response = $next($request, $response);
|
||||
$row = $this->service->saveData($request, $response);
|
||||
if (!$row) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->service->injectScripts($row, $response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Model\Behavior;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\Behavior;
|
||||
use DebugKit\DebugTimer;
|
||||
|
||||
/**
|
||||
* Class TimedBehavior
|
||||
*/
|
||||
class TimedBehavior extends Behavior
|
||||
{
|
||||
|
||||
/**
|
||||
* beforeFind, starts a timer for a find operation.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The beforeFind event
|
||||
* @param \Cake\ORM\Query $query Query
|
||||
* @return \Cake\ORM\Query
|
||||
*/
|
||||
public function beforeFind(Event $event, $query)
|
||||
{
|
||||
$alias = $event->getSubject()->getAlias();
|
||||
DebugTimer::start($alias . '_find', $alias . '->find()');
|
||||
|
||||
return $query->formatResults(function ($results) use ($alias) {
|
||||
DebugTimer::stop($alias . '_find');
|
||||
|
||||
return $results;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* beforeSave, starts a time before a save is initiated.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The beforeSave event
|
||||
* @return void
|
||||
*/
|
||||
public function beforeSave(Event $event)
|
||||
{
|
||||
$alias = $event->getSubject()->getAlias();
|
||||
DebugTimer::start($alias . '_save', $alias . '->save()');
|
||||
}
|
||||
|
||||
/**
|
||||
* afterSave, stop the timer started from a save.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The afterSave event
|
||||
* @return void
|
||||
*/
|
||||
public function afterSave(Event $event)
|
||||
{
|
||||
$alias = $event->getSubject()->getAlias();
|
||||
DebugTimer::stop($alias . '_save');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?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
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\Model\Entity;
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
|
||||
/**
|
||||
* Panel entity class.
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $request_id
|
||||
* @property string $title
|
||||
* @property string $element
|
||||
* @property string $content
|
||||
*/
|
||||
class Panel extends Entity
|
||||
{
|
||||
|
||||
/**
|
||||
* Some fields should not be in JSON/array exports.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_hidden = ['content'];
|
||||
|
||||
/**
|
||||
* Read the stream contents.
|
||||
*
|
||||
* Over certain sizes PDO will return file handles.
|
||||
* For backwards compatibility and consistency we smooth over that difference here.
|
||||
*
|
||||
* @param mixed $content Content
|
||||
* @return string
|
||||
*/
|
||||
protected function _getContent($content)
|
||||
{
|
||||
if (is_resource($content)) {
|
||||
return stream_get_contents($content);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace DebugKit\Model\Entity;
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
|
||||
/**
|
||||
* Request entity class.
|
||||
*
|
||||
* @property int $id
|
||||
* @property array $panels
|
||||
*/
|
||||
class Request extends Entity
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* 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
|
||||
*/
|
||||
namespace DebugKit\Model\Table;
|
||||
|
||||
use Cake\Core\App;
|
||||
use PDOException;
|
||||
|
||||
/**
|
||||
* A set of methods for building a database table when it is missing.
|
||||
*
|
||||
* Because the debugkit doesn't come with a pre-built SQLite database,
|
||||
* we'll need to make it as we need it.
|
||||
*
|
||||
* This trait lets us dump fixture schema into a given database at runtime.
|
||||
*/
|
||||
trait LazyTableTrait
|
||||
{
|
||||
/**
|
||||
* Ensures the tables for the given fixtures exist in the schema.
|
||||
*
|
||||
* If the tables do not exist, they will be created on the current model's connection.
|
||||
*
|
||||
* @param array $fixtures The fixture names to check and/or insert.
|
||||
* @return void
|
||||
* @throws \RuntimeException When fixtures are missing/unknown/fail.
|
||||
*/
|
||||
public function ensureTables(array $fixtures)
|
||||
{
|
||||
/** @var \Cake\Database\Connection $connection */
|
||||
$connection = $this->getConnection();
|
||||
$schema = $connection->getSchemaCollection();
|
||||
|
||||
try {
|
||||
$existing = $schema->listTables();
|
||||
} catch (PDOException $e) {
|
||||
// Handle errors when SQLite blows up if the schema has changed.
|
||||
if (strpos($e->getMessage(), 'schema has changed') !== false) {
|
||||
$existing = $schema->listTables();
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($fixtures as $name) {
|
||||
$class = App::className($name, 'Test/Fixture', 'Fixture');
|
||||
if ($class === false) {
|
||||
throw new \RuntimeException("Unknown fixture '$name'.");
|
||||
}
|
||||
/** @var \Cake\Datasource\FixtureInterface $fixture */
|
||||
$fixture = new $class($connection->configName());
|
||||
if (in_array($fixture->table, $existing)) {
|
||||
continue;
|
||||
}
|
||||
$fixture->create($connection);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
if (strpos($e->getMessage(), 'unable to open')) {
|
||||
throw new RuntimeException(
|
||||
'Could not create a SQLite database. ' .
|
||||
'Ensure that your webserver has write access to the database file and folder it is in.'
|
||||
);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Model\Table;
|
||||
|
||||
use Cake\ORM\Query;
|
||||
use Cake\ORM\Table;
|
||||
use DebugKit\Model\Entity\Panel;
|
||||
|
||||
/**
|
||||
* The panels table collects the information for each panel on
|
||||
* each request.
|
||||
*
|
||||
* @method Panel get($primaryKey, $options = [])
|
||||
* @method Panel newEntity($data = null, array $options = [])
|
||||
* @method Panel[] newEntities(array $data, array $options = [])
|
||||
* @method Panel save(\Cake\Datasource\EntityInterface $entity, $options = [])
|
||||
* @method Panel patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
|
||||
* @method Panel[] patchEntities($entities, array $data, array $options = [])
|
||||
* @method Panel findOrCreate($search, callable $callback = null)
|
||||
*/
|
||||
class PanelsTable extends Table
|
||||
{
|
||||
use LazyTableTrait;
|
||||
|
||||
/**
|
||||
* initialize method
|
||||
*
|
||||
* @param array $config Config data.
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(array $config)
|
||||
{
|
||||
$this->belongsTo('DebugKit.Requests');
|
||||
$this->ensureTables(['DebugKit.Requests', 'DebugKit.Panels']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find panels by requestid
|
||||
*
|
||||
* @param \Cake\ORM\Query $query The query
|
||||
* @param array $options The options to use.
|
||||
* @return \Cake\ORM\Query The query.
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function findByRequest(Query $query, array $options)
|
||||
{
|
||||
if (empty($options['requestId'])) {
|
||||
throw new \RuntimeException(__d('debug_kit', 'Missing request id in {0}.', 'findByRequest()'));
|
||||
}
|
||||
|
||||
return $query->where(['Panels.request_id' => $options['requestId']])
|
||||
->order(['Panels.title' => 'ASC']);
|
||||
}
|
||||
|
||||
/**
|
||||
* DebugKit tables are special.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function defaultConnectionName()
|
||||
{
|
||||
return 'debug_kit';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Model\Table;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Database\Driver\Sqlite;
|
||||
use Cake\ORM\Query;
|
||||
use Cake\ORM\Table;
|
||||
use DebugKit\Model\Entity\Request;
|
||||
|
||||
/**
|
||||
* The requests table tracks basic information about each request.
|
||||
*
|
||||
* @method Request get($primaryKey, $options = [])
|
||||
* @method Request newEntity($data = null, array $options = [])
|
||||
* @method Request[] newEntities(array $data, array $options = [])
|
||||
* @method Request save(\Cake\Datasource\EntityInterface $entity, $options = [])
|
||||
* @method Request patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
|
||||
* @method Request[] patchEntities($entities, array $data, array $options = [])
|
||||
* @method Request findOrCreate($search, callable $callback = null)
|
||||
*/
|
||||
class RequestsTable extends Table
|
||||
{
|
||||
use LazyTableTrait;
|
||||
|
||||
/**
|
||||
* initialize method
|
||||
*
|
||||
* @param array $config Config data.
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(array $config)
|
||||
{
|
||||
$this->hasMany('DebugKit.Panels', [
|
||||
'sort' => ['Panels.title' => 'ASC'],
|
||||
]);
|
||||
$this->addBehavior('Timestamp', [
|
||||
'events' => [
|
||||
'Model.beforeSave' => ['requested_at' => 'new'],
|
||||
],
|
||||
]);
|
||||
$this->ensureTables(['DebugKit.Requests', 'DebugKit.Panels']);
|
||||
}
|
||||
|
||||
/**
|
||||
* DebugKit tables are special.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function defaultConnectionName()
|
||||
{
|
||||
return 'debug_kit';
|
||||
}
|
||||
|
||||
/**
|
||||
* Finder method to get recent requests as a simple array
|
||||
*
|
||||
* @param \Cake\ORM\Query $query The query
|
||||
* @param array $options The options
|
||||
* @return Query The query.
|
||||
*/
|
||||
public function findRecent(Query $query, array $options)
|
||||
{
|
||||
return $query->order(['Requests.requested_at' => 'DESC'])
|
||||
->limit(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if garbage collection should be run
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldGc()
|
||||
{
|
||||
return time() % 100 === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collect old request data.
|
||||
*
|
||||
* Delete request data that is older than latest 20 requests.
|
||||
* You can use the `DebugKit.requestCount` config to change this limit.
|
||||
* This method will only trigger periodically.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function gc()
|
||||
{
|
||||
if (!$this->shouldGc()) {
|
||||
return;
|
||||
}
|
||||
$noPurge = $this->find()
|
||||
->select(['id'])
|
||||
->enableHydration(false)
|
||||
->order(['requested_at' => 'desc'])
|
||||
->limit(Configure::read('DebugKit.requestCount') ?: 20)
|
||||
->extract('id')
|
||||
->toArray();
|
||||
|
||||
$query = $this->Panels->query()
|
||||
->delete()
|
||||
->where(['request_id NOT IN' => $noPurge]);
|
||||
$statement = $query->execute();
|
||||
$statement->closeCursor();
|
||||
|
||||
$query = $this->query()
|
||||
->delete()
|
||||
->where(['id NOT IN' => $noPurge]);
|
||||
|
||||
$statement = $query->execute();
|
||||
$statement->closeCursor();
|
||||
|
||||
$conn = $this->getConnection();
|
||||
if ($conn->getDriver() instanceof Sqlite) {
|
||||
$conn->execute('VACUUM;');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?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
|
||||
*
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Cache\Cache;
|
||||
use DebugKit\Cache\Engine\DebugEngine;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* A panel for spying on cache engines.
|
||||
*/
|
||||
class CachePanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* The cache spy instances used.
|
||||
*
|
||||
* @var DebugEngine[]
|
||||
*/
|
||||
protected $_instances = [];
|
||||
|
||||
/**
|
||||
* Initialize - install cache spies.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
foreach (Cache::configured() as $name) {
|
||||
$config = Cache::getConfig($name);
|
||||
if (isset($config['className']) && $config['className'] instanceof DebugEngine) {
|
||||
$instance = $config['className'];
|
||||
} elseif (isset($config['className'])) {
|
||||
Cache::drop($name);
|
||||
$instance = new DebugEngine($config);
|
||||
Cache::setConfig($name, $instance);
|
||||
}
|
||||
if (isset($instance)) {
|
||||
$this->_instances[$name] = $instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data for this panel
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data()
|
||||
{
|
||||
$metrics = [];
|
||||
foreach ($this->_instances as $name => $instance) {
|
||||
$metrics[$name] = $instance->metrics();
|
||||
}
|
||||
|
||||
return [
|
||||
'metrics' => $metrics,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\Utility\Hash;
|
||||
use Composer\Json\JsonFile;
|
||||
use DebugKit\DebugInclude;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* Provides a list of deprecated methods for the current request
|
||||
*
|
||||
*/
|
||||
class DeprecationsPanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* The list of depreated errors.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $deprecatedErrors = [];
|
||||
|
||||
/**
|
||||
* instance of DebugInclude
|
||||
*
|
||||
* @var \DebugKit\DebugInclude
|
||||
*/
|
||||
protected $_debug;
|
||||
|
||||
/**
|
||||
* construct
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->_debug = new DebugInclude();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of files that were deprecated and split them out into the various parts of the app
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _prepare()
|
||||
{
|
||||
$errors = static::$deprecatedErrors;
|
||||
$return = ['cake' => [], 'app' => [], 'plugins' => [], 'vendor' => [], 'other' => []];
|
||||
|
||||
foreach ($errors as $error) {
|
||||
$file = $error['file'];
|
||||
$line = $error['line'];
|
||||
if (isset($error['context']['frame'])) {
|
||||
$file = $error['context']['frame']['file'];
|
||||
$line = $error['context']['frame']['line'];
|
||||
}
|
||||
|
||||
$errorData = [
|
||||
'file' => $file,
|
||||
'line' => $line,
|
||||
'message' => $error['message'],
|
||||
];
|
||||
|
||||
$pluginName = $this->_debug->getPluginName($file);
|
||||
if ($pluginName) {
|
||||
$errorData['niceFile'] = $this->_debug->niceFileName($file, 'plugin', $pluginName);
|
||||
$return['plugins'][$pluginName][] = $errorData;
|
||||
} elseif ($this->_debug->isAppFile($file)) {
|
||||
$errorData['niceFile'] = $this->_debug->niceFileName($file, 'app');
|
||||
$return['app'][] = $errorData;
|
||||
} elseif ($this->_debug->isCakeFile($file)) {
|
||||
$errorData['niceFile'] = $this->_debug->niceFileName($file, 'cake');
|
||||
$return['cake'][] = $errorData;
|
||||
} else {
|
||||
$vendorName = $this->_debug->getComposerPackageName($file);
|
||||
|
||||
if ($vendorName) {
|
||||
$errorData['niceFile'] = $this->_debug->niceFileName($file, 'vendor', $vendorName);
|
||||
$return['vendor'][$vendorName][] = $errorData;
|
||||
} else {
|
||||
$errorData['niceFile'] = $this->_debug->niceFileName($file, 'root');
|
||||
$return['other'][] = $errorData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ksort($return['app']);
|
||||
ksort($return['cake']);
|
||||
ksort($return['plugins']);
|
||||
ksort($return['vendor']);
|
||||
|
||||
foreach ($return['plugins'] as &$plugin) {
|
||||
ksort($plugin);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a error
|
||||
*
|
||||
* @param array $error The deprecated error
|
||||
* @return void
|
||||
*/
|
||||
public static function addDeprecatedError($error)
|
||||
{
|
||||
static::$deprecatedErrors[] = $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the tracked errors.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clearDeprecatedErrors()
|
||||
{
|
||||
static::$deprecatedErrors = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of files deprecated in this request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary()
|
||||
{
|
||||
$data = $this->_data;
|
||||
if (empty($data)) {
|
||||
$data = $this->_prepare();
|
||||
}
|
||||
|
||||
return array_reduce($data, function ($carry, $item) {
|
||||
if (empty($item)) {
|
||||
return $carry;
|
||||
}
|
||||
// app, cake, or other groups
|
||||
if (Hash::dimensions($item) == 2) {
|
||||
return $carry + count($item);
|
||||
}
|
||||
|
||||
// plugin and vendor groups
|
||||
foreach ($item as $group) {
|
||||
$carry += count($group);
|
||||
}
|
||||
|
||||
return $carry;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown callback
|
||||
*
|
||||
* @param \Cake\Event\Event $event Event
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(Event $event)
|
||||
{
|
||||
$this->_data = $this->_prepare();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?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
|
||||
*
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Controller\Controller;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* Provides information about your PHP and CakePHP environment to assist with debugging.
|
||||
*
|
||||
*/
|
||||
class EnvironmentPanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* Get necessary data about environment to pass back to controller
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _prepare()
|
||||
{
|
||||
$return = [];
|
||||
// PHP Data
|
||||
$phpVer = phpversion();
|
||||
$return['php'] = array_merge(
|
||||
['PHP_VERSION' => $phpVer],
|
||||
$_SERVER
|
||||
);
|
||||
unset($return['php']['argv']);
|
||||
|
||||
// ini Data
|
||||
$return['ini'] = [
|
||||
'intl.default_locale' => ini_get('intl.default_locale'),
|
||||
'memory_limit' => ini_get('memory_limit'),
|
||||
'error_reporting' => ini_get('error_reporting'),
|
||||
'upload_max_filesize' => ini_get('upload_max_filesize'),
|
||||
'post_max_size' => ini_get('post_max_size'),
|
||||
];
|
||||
|
||||
// CakePHP Data
|
||||
$return['cake'] = [
|
||||
'APP' => APP,
|
||||
'APP_DIR' => APP_DIR,
|
||||
'CACHE' => CACHE,
|
||||
'CAKE' => CAKE,
|
||||
'CAKE_CORE_INCLUDE_PATH' => CAKE_CORE_INCLUDE_PATH,
|
||||
'CONFIG' => CONFIG,
|
||||
'CORE_PATH' => CORE_PATH,
|
||||
'CAKE_VERSION' => Configure::version(),
|
||||
'DS' => DS,
|
||||
'LOGS' => LOGS,
|
||||
'ROOT' => ROOT,
|
||||
'TESTS' => TESTS,
|
||||
'TMP' => TMP,
|
||||
'WWW_ROOT' => WWW_ROOT,
|
||||
];
|
||||
|
||||
$hiddenCakeConstants = array_fill_keys(
|
||||
[
|
||||
'TIME_START', 'SECOND', 'MINUTE', 'HOUR', 'DAY', 'WEEK', 'MONTH', 'YEAR',
|
||||
],
|
||||
''
|
||||
);
|
||||
$var = get_defined_constants(true);
|
||||
$return['app'] = array_diff_key($var['user'], $return['cake'], $hiddenCakeConstants);
|
||||
|
||||
if (isset($var['hidef'])) {
|
||||
$return['hidef'] = $var['hidef'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown callback
|
||||
*
|
||||
* @param \Cake\Event\Event $event Event
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(Event $event)
|
||||
{
|
||||
$this->_data = $this->_prepare();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\ORM\TableRegistry;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* Provides debug information on previous requests.
|
||||
*
|
||||
*/
|
||||
class HistoryPanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* Get the data for the panel.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data()
|
||||
{
|
||||
$table = TableRegistry::get('DebugKit.Requests');
|
||||
$recent = $table->find('recent');
|
||||
|
||||
return [
|
||||
'requests' => $recent->toArray(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the initial text for the history summary
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary()
|
||||
{
|
||||
return '0 xhr';
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\Utility\Hash;
|
||||
use Composer\Json\JsonFile;
|
||||
use DebugKit\DebugInclude;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* Provides a list of included files for the current request
|
||||
*
|
||||
*/
|
||||
class IncludePanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* instance of DebugInclude
|
||||
*
|
||||
* @var \DebugKit\DebugInclude
|
||||
*/
|
||||
protected $_debug;
|
||||
|
||||
/**
|
||||
* construct
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->_debug = new DebugInclude();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of files that were included and split them out into the various parts of the app
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _prepare()
|
||||
{
|
||||
$return = ['cake' => [], 'app' => [], 'plugins' => [], 'vendor' => [], 'other' => []];
|
||||
|
||||
foreach (get_included_files() as $file) {
|
||||
$pluginName = $this->_debug->getPluginName($file);
|
||||
|
||||
if ($pluginName) {
|
||||
$return['plugins'][$pluginName][$this->_debug->getFileType($file)][] = $this->_debug->niceFileName($file, 'plugin', $pluginName);
|
||||
} elseif ($this->_debug->isAppFile($file)) {
|
||||
$return['app'][$this->_debug->getFileType($file)][] = $this->_debug->niceFileName($file, 'app');
|
||||
} elseif ($this->_debug->isCakeFile($file)) {
|
||||
$return['cake'][$this->_debug->getFileType($file)][] = $this->_debug->niceFileName($file, 'cake');
|
||||
} else {
|
||||
$vendorName = $this->_debug->getComposerPackageName($file);
|
||||
|
||||
if ($vendorName) {
|
||||
$return['vendor'][$vendorName][] = $this->_debug->niceFileName($file, 'vendor', $vendorName);
|
||||
} else {
|
||||
$return['other'][] = $this->_debug->niceFileName($file, 'root');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$return['paths'] = $this->_debug->includePaths();
|
||||
|
||||
ksort($return['app']);
|
||||
ksort($return['cake']);
|
||||
ksort($return['plugins']);
|
||||
ksort($return['vendor']);
|
||||
|
||||
foreach ($return['plugins'] as &$plugin) {
|
||||
ksort($plugin);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of files included in this request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary()
|
||||
{
|
||||
$data = $this->_data;
|
||||
if (empty($data)) {
|
||||
$data = $this->_prepare();
|
||||
}
|
||||
|
||||
unset($data['paths']);
|
||||
$data = array_filter($data, function ($v, $k) {
|
||||
return !empty($v);
|
||||
}, ARRAY_FILTER_USE_BOTH);
|
||||
|
||||
return count(Hash::flatten($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown callback
|
||||
*
|
||||
* @param \Cake\Event\Event $event Event
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(Event $event)
|
||||
{
|
||||
$this->_data = $this->_prepare();
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Log\Log;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* Log Panel - Reads log entries made this request.
|
||||
*
|
||||
*/
|
||||
class LogPanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* Initialize hook - sets up the log listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
if (Log::getConfig('debug_kit_log_panel')) {
|
||||
return;
|
||||
}
|
||||
Log::setConfig('debug_kit_log_panel', [
|
||||
'engine' => 'DebugKit.DebugKit',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the panel data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data()
|
||||
{
|
||||
return [
|
||||
'logger' => Log::engine('debug_kit_log_panel'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the summary data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary()
|
||||
{
|
||||
$logger = Log::engine('debug_kit_log_panel');
|
||||
if (!$logger) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
return (string)$logger->count();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use ArrayObject;
|
||||
use Cake\Core\App;
|
||||
use Cake\Mailer\TransportFactory;
|
||||
use DebugKit\DebugPanel;
|
||||
use DebugKit\Mailer\Transport\DebugKitTransport;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Provides debug information on the Emails sent during the request
|
||||
*/
|
||||
class MailPanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* The list of emails produced during the request
|
||||
*
|
||||
* @var ArrayObject
|
||||
*/
|
||||
protected $emailLog;
|
||||
|
||||
/**
|
||||
* Initialize hook - configures the email transport.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
$reflection = new ReflectionClass(TransportFactory::class);
|
||||
$property = $reflection->getProperty('_config');
|
||||
$property->setAccessible(true);
|
||||
$configs = $property->getValue();
|
||||
|
||||
$log = $this->emailLog = new ArrayObject();
|
||||
|
||||
foreach ($configs as $name => &$transport) {
|
||||
if (is_object($transport)) {
|
||||
$configs[$name] = new DebugKitTransport(['debugKitLog' => $log], $transport);
|
||||
continue;
|
||||
}
|
||||
|
||||
$className = App::className($transport['className'], 'Mailer/Transport', 'Transport');
|
||||
|
||||
if (!$className) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$transport['originalClassName'] = $transport['className'];
|
||||
$transport['className'] = 'DebugKit.DebugKit';
|
||||
$transport['debugKitLog'] = $log;
|
||||
}
|
||||
$property->setValue($configs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data this panel wants to store.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data()
|
||||
{
|
||||
return [
|
||||
'emails' => isset($this->emailLog) ? $this->emailLog->getArrayCopy() : [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get summary data from the queries run.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary()
|
||||
{
|
||||
if (empty($this->emailLog)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (string)count($this->emailLog);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?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 3.5.2
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Composer\Json\JsonFile;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* Packages Panel - Reads all installed packages in the project.
|
||||
*
|
||||
*/
|
||||
class PackagesPanel extends DebugPanel
|
||||
{
|
||||
/**
|
||||
* Get the panel data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data()
|
||||
{
|
||||
$packages = $devPackages = [];
|
||||
|
||||
$lockFile = new JsonFile(ROOT . DIRECTORY_SEPARATOR . 'composer.lock');
|
||||
if ($lockFile->exists()) {
|
||||
$lockContent = $lockFile->read();
|
||||
$packages = $lockContent['packages'];
|
||||
$devPackages = $lockContent['packages-dev'];
|
||||
}
|
||||
|
||||
return [
|
||||
'packages' => $packages,
|
||||
'devPackages' => $devPackages,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Core\App;
|
||||
use Cake\Core\ObjectRegistry;
|
||||
use Cake\Event\EventDispatcherTrait;
|
||||
use Cake\Event\EventManager;
|
||||
|
||||
/**
|
||||
* Registry object for panels.
|
||||
*/
|
||||
class PanelRegistry extends ObjectRegistry
|
||||
{
|
||||
use EventDispatcherTrait;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \Cake\Event\EventManager $events Event Manager that panels should bind to.
|
||||
* Typically this is the global manager.
|
||||
*/
|
||||
public function __construct(EventManager $events)
|
||||
{
|
||||
$this->setEventManager($events);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a panel class name.
|
||||
*
|
||||
* Part of the template method for Cake\Utility\ObjectRegistry::load()
|
||||
*
|
||||
* @param string $class Partial class name to resolve.
|
||||
* @return string|false Either the correct class name or false.
|
||||
*/
|
||||
protected function _resolveClassName($class)
|
||||
{
|
||||
return App::className($class, 'Panel', 'Panel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception when a component is missing.
|
||||
*
|
||||
* Part of the template method for Cake\Utility\ObjectRegistry::load()
|
||||
*
|
||||
* @param string $class The classname that is missing.
|
||||
* @param string $plugin The plugin the component is missing in.
|
||||
* @return void
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function _throwMissingClassError($class, $plugin)
|
||||
{
|
||||
throw new \RuntimeException(__d('debug_kit', "Unable to find ''{0}'' panel.", $class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the panels instance.
|
||||
*
|
||||
* Part of the template method for Cake\Utility\ObjectRegistry::load()
|
||||
*
|
||||
* @param string $class The classname to create.
|
||||
* @param string $alias The alias of the panel.
|
||||
* @param array $config An array of config to use for the panel.
|
||||
* @return \DebugKit\DebugPanel The constructed panel class.
|
||||
*/
|
||||
protected function _create($class, $alias, $config)
|
||||
{
|
||||
$instance = new $class($this, $config);
|
||||
$this->getEventManager()->on($instance);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Controller\Controller;
|
||||
use Cake\Event\Event;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* Provides debug information on the Current request params.
|
||||
*
|
||||
*/
|
||||
class RequestPanel extends DebugPanel
|
||||
{
|
||||
/**
|
||||
* Data collection callback.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The shutdown event.
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(Event $event)
|
||||
{
|
||||
/* @var \Cake\Controller\Controller $controller */
|
||||
$controller = $event->getSubject();
|
||||
$request = $controller->request;
|
||||
$this->_data = [
|
||||
'params' => $request->getAttribute("params"),
|
||||
'query' => $request->getQueryParams(),
|
||||
'data' => $request->getData(),
|
||||
'cookie' => $request->getCookieParams(),
|
||||
'get' => $_GET,
|
||||
'matchedRoute' => $request->getParam('_matchedRoute'),
|
||||
'headers' => ['response' => headers_sent($file, $line), 'file' => $file, 'line' => $line],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?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
|
||||
*
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\Routing\Router;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* A panel to get the list of connected routes for the application
|
||||
*/
|
||||
class RoutesPanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* Get summary data for the routes panel.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary()
|
||||
{
|
||||
$appClass = Configure::read('App.namespace') . '\Application';
|
||||
if (class_exists($appClass, false) && !Router::$initialized) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
$routes = array_filter(Router::routes(), function ($route) {
|
||||
return (!isset($routes->defaults['plugin'])) || $route->defaults['plugin'] !== 'DebugKit';
|
||||
});
|
||||
|
||||
return (string)count($routes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data collection callback.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The shutdown event.
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(Event $event)
|
||||
{
|
||||
$controller = $event->getSubject();
|
||||
/* @var \Cake\Http\ServerRequest $request */
|
||||
$request = $controller ? $controller->request : null;
|
||||
$this->_data = [
|
||||
'matchedRoute' => $request ? $request->getParam('_matchedRoute') : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\Http\ServerRequest as Request;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* Provides debug information on the Session contents.
|
||||
*/
|
||||
class SessionPanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* shutdown callback
|
||||
*
|
||||
* @param \Cake\Event\Event $event The event
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(Event $event)
|
||||
{
|
||||
/* @var Request $request */
|
||||
$request = $event->getSubject()->request;
|
||||
if ($request) {
|
||||
$this->_data = ['content' => $request->getSession()->read()];
|
||||
}
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use DebugKit\Database\Log\DebugLog;
|
||||
use DebugKit\DebugPanel;
|
||||
|
||||
/**
|
||||
* Provides debug information on the SQL logs and provides links to an ajax explain interface.
|
||||
*
|
||||
*/
|
||||
class SqlLogPanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* Loggers connected
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_loggers = [];
|
||||
|
||||
/**
|
||||
* Initialize hook - configures logger.
|
||||
*
|
||||
* This will unfortunately build all the connections, but they
|
||||
* won't connect until used.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
$configs = ConnectionManager::configured();
|
||||
$includeSchemaReflection = (bool)Configure::read('DebugKit.includeSchemaReflection');
|
||||
|
||||
foreach ($configs as $name) {
|
||||
$connection = ConnectionManager::get($name);
|
||||
if ($connection->configName() === 'debug_kit') {
|
||||
continue;
|
||||
}
|
||||
$logger = null;
|
||||
if ($connection->isQueryLoggingEnabled()) {
|
||||
$logger = $connection->getLogger();
|
||||
}
|
||||
|
||||
if ($logger instanceof DebugLog) {
|
||||
$logger->setIncludeSchema($includeSchemaReflection);
|
||||
$this->_loggers[] = $logger;
|
||||
continue;
|
||||
}
|
||||
$logger = new DebugLog($logger, $name, $includeSchemaReflection);
|
||||
|
||||
$connection->enableQueryLogging(true);
|
||||
|
||||
if (method_exists($connection, 'setLogger')) {
|
||||
$connection->setLogger($logger);
|
||||
} else {
|
||||
$connection->logger($logger);
|
||||
}
|
||||
|
||||
$this->_loggers[] = $logger;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data this panel wants to store.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data()
|
||||
{
|
||||
return [
|
||||
'tables' => array_map(function (Table $table) {
|
||||
return $table->getAlias();
|
||||
}, TableRegistry::getTableLocator()->genericInstances()),
|
||||
'loggers' => $this->_loggers,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get summary data from the queries run.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary()
|
||||
{
|
||||
$count = $time = 0;
|
||||
foreach ($this->_loggers as $logger) {
|
||||
$count += count($logger->queries());
|
||||
$time += $logger->totalTime();
|
||||
}
|
||||
if (!$count) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
return "$count / $time ms";
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\I18n\Number;
|
||||
use DebugKit\DebugMemory;
|
||||
use DebugKit\DebugPanel;
|
||||
use DebugKit\DebugTimer;
|
||||
|
||||
/**
|
||||
* Provides debug information on all timers used in a request.
|
||||
*/
|
||||
class TimerPanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* Return an array of events to listen to.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function implementedEvents()
|
||||
{
|
||||
$before = function ($name) {
|
||||
return function () use ($name) {
|
||||
DebugTimer::start($name, __d('debug_kit', $name));
|
||||
};
|
||||
};
|
||||
$after = function ($name) {
|
||||
return function () use ($name) {
|
||||
DebugTimer::stop($name);
|
||||
};
|
||||
};
|
||||
$both = function ($name) use ($before, $after) {
|
||||
return [
|
||||
['priority' => 0, 'callable' => $before('Event: ' . $name)],
|
||||
['priority' => 999, 'callable' => $after('Event: ' . $name)],
|
||||
];
|
||||
};
|
||||
|
||||
return [
|
||||
'Controller.initialize' => [
|
||||
['priority' => 0, 'callable' => function () {
|
||||
DebugMemory::record(__d('debug_kit', 'Controller initialization'));
|
||||
}],
|
||||
['priority' => 0, 'callable' => $before('Event: Controller.initialize')],
|
||||
['priority' => 999, 'callable' => $after('Event: Controller.initialize')],
|
||||
],
|
||||
'Controller.startup' => [
|
||||
['priority' => 0, 'callable' => $before('Event: Controller.startup')],
|
||||
['priority' => 999, 'callable' => $after('Event: Controller.startup')],
|
||||
['priority' => 999, 'callable' => function () {
|
||||
DebugMemory::record(__d('debug_kit', 'Controller action start'));
|
||||
DebugTimer::start(__d('debug_kit', 'Controller action'));
|
||||
}],
|
||||
],
|
||||
'Controller.beforeRender' => [
|
||||
['priority' => 0, 'callable' => function () {
|
||||
DebugTimer::stop(__d('debug_kit', 'Controller action'));
|
||||
}],
|
||||
['priority' => 0, 'callable' => $before('Event: Controller.beforeRender')],
|
||||
['priority' => 999, 'callable' => $after('Event: Controller.beforeRender')],
|
||||
['priority' => 999, 'callable' => function () {
|
||||
DebugMemory::record(__d('debug_kit', 'View Render start'));
|
||||
DebugTimer::start(__d('debug_kit', 'View Render start'));
|
||||
}],
|
||||
],
|
||||
'View.beforeRender' => $both('View.beforeRender'),
|
||||
'View.afterRender' => $both('View.afterRender'),
|
||||
'View.beforeLayout' => $both('View.beforeLayout'),
|
||||
'View.afterLayout' => $both('View.afterLayout'),
|
||||
'View.beforeRenderFile' => [
|
||||
['priority' => 0, 'callable' => function ($event, $filename) {
|
||||
DebugTimer::start(__d('debug_kit', 'Render {0}', $filename));
|
||||
}],
|
||||
],
|
||||
'View.afterRenderFile' => [
|
||||
['priority' => 0, 'callable' => function ($event, $filename) {
|
||||
DebugTimer::stop(__d('debug_kit', 'Render {0}', $filename));
|
||||
}],
|
||||
],
|
||||
'Controller.shutdown' => [
|
||||
['priority' => 0, 'callable' => $before('Event: Controller.shutdown')],
|
||||
['priority' => 0, 'callable' => function () {
|
||||
DebugTimer::stop(__d('debug_kit', 'View Render start'));
|
||||
DebugMemory::record(__d('debug_kit', 'Controller shutdown'));
|
||||
}],
|
||||
['priority' => 999, 'callable' => $after('Event: Controller.shutdown')],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data for the panel.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data()
|
||||
{
|
||||
return [
|
||||
'requestTime' => DebugTimer::requestTime(),
|
||||
'timers' => DebugTimer::getAll(),
|
||||
'memory' => DebugMemory::getAll(),
|
||||
'peakMemory' => DebugMemory::getPeak(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the summary for the panel.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary()
|
||||
{
|
||||
$time = Number::precision(DebugTimer::requestTime(), 2) . ' s';
|
||||
$memory = Number::toReadableSize(DebugMemory::getPeak());
|
||||
|
||||
return "$time / $memory";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Panel;
|
||||
|
||||
use Cake\Collection\Collection;
|
||||
use Cake\Datasource\EntityInterface;
|
||||
use Cake\Event\Event;
|
||||
use Cake\Form\Form;
|
||||
use Cake\ORM\Query;
|
||||
use Cake\ORM\ResultSet;
|
||||
use Cake\Utility\Hash;
|
||||
use Closure;
|
||||
use DebugKit\DebugPanel;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use PDO;
|
||||
use RuntimeException;
|
||||
use SimpleXMLElement;
|
||||
|
||||
/**
|
||||
* Provides debug information on the View variables.
|
||||
*
|
||||
*/
|
||||
class VariablesPanel extends DebugPanel
|
||||
{
|
||||
|
||||
/**
|
||||
* Extracts nested validation errors
|
||||
*
|
||||
* @param EntityInterface $entity Entity to extract
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _getErrors(EntityInterface $entity)
|
||||
{
|
||||
$errors = $entity->errors();
|
||||
|
||||
foreach ($entity->visibleProperties() as $property) {
|
||||
$v = $entity[$property];
|
||||
if ($v instanceof EntityInterface) {
|
||||
$errors[$property] = $this->_getErrors($v);
|
||||
} elseif (is_array($v)) {
|
||||
foreach ($v as $key => $varValue) {
|
||||
if ($varValue instanceof EntityInterface) {
|
||||
$errors[$property][$key] = $this->_getErrors($varValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Hash::filter($errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely retrieves debug information from an object
|
||||
* and applies a callback.
|
||||
*
|
||||
* @param callable $walker The walker to apply on the debug info array.
|
||||
* @param object $item The item whose debug info to retrieve.
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
protected function _walkDebugInfo(callable $walker, $item)
|
||||
{
|
||||
try {
|
||||
$info = $item->__debugInfo();
|
||||
} catch (\Exception $exception) {
|
||||
return __d('debug_kit', 'Could not retrieve debug info - {0}. Error: {1} in {2}, line {3}', get_class($item), $exception->getMessage(), $exception->getFile(), $exception->getLine());
|
||||
}
|
||||
|
||||
return array_map($walker, $info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown event
|
||||
*
|
||||
* @param \Cake\Event\Event $event The event
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(Event $event)
|
||||
{
|
||||
$controller = $event->getSubject();
|
||||
$errors = [];
|
||||
|
||||
$walker = function (&$item) use (&$walker) {
|
||||
if (
|
||||
$item instanceof Collection ||
|
||||
$item instanceof Query ||
|
||||
$item instanceof ResultSet
|
||||
) {
|
||||
try {
|
||||
$item = $item->toArray();
|
||||
} catch (\Cake\Database\Exception $e) {
|
||||
//Likely issue is unbuffered query; fall back to __debugInfo
|
||||
$item = $this->_walkDebugInfo($walker, $item);
|
||||
} catch (RuntimeException $e) {
|
||||
// Likely a non-select query.
|
||||
$item = $this->_walkDebugInfo($walker, $item);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$item = $this->_walkDebugInfo($walker, $item);
|
||||
}
|
||||
} elseif (
|
||||
$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->getMessage(),
|
||||
$item->getFile(),
|
||||
$item->getLine()
|
||||
);
|
||||
} elseif (is_object($item)) {
|
||||
if (method_exists($item, '__debugInfo')) {
|
||||
// Convert objects into using __debugInfo.
|
||||
$item = $this->_walkDebugInfo($walker, $item);
|
||||
} else {
|
||||
$item = $this->trySerialize($item);
|
||||
}
|
||||
} elseif (is_resource($item)) {
|
||||
$item = sprintf('[%s] %s', get_resource_type($item), $item);
|
||||
}
|
||||
|
||||
return $this->trySerialize($item);
|
||||
};
|
||||
// Copy so viewVars is not mutated.
|
||||
$vars = $controller->viewVars;
|
||||
array_walk_recursive($vars, $walker);
|
||||
|
||||
foreach ($vars as $k => $v) {
|
||||
// Get the validation errors for Entity
|
||||
if ($v instanceof EntityInterface) {
|
||||
$errors[$k] = $this->_getErrors($v);
|
||||
} elseif ($v instanceof Form) {
|
||||
$formError = $v->errors();
|
||||
if (!empty($formError)) {
|
||||
$errors[$k] = $formError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->_data = [
|
||||
'content' => $vars,
|
||||
'errors' => $errors,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to serialize an item, provide an error message if not possible
|
||||
*
|
||||
* @param mixed $item Item to check
|
||||
* @return mixed The $item if it is serializable, error message if not
|
||||
*/
|
||||
protected function trySerialize($item)
|
||||
{
|
||||
try {
|
||||
serialize($item);
|
||||
|
||||
return $item;
|
||||
} catch (\Exception $e) {
|
||||
if (is_object($item)) {
|
||||
return __d('debug_kit', 'Unserializable object - {0}. Error: {1} in {2}, line {3}', get_class($item), $e->getMessage(), $e->getFile(), $e->getLine());
|
||||
}
|
||||
|
||||
return __d('debug_kit', 'Unserializable Error: {1} in {2}, line {3}', $e->getMessage(), $e->getFile(), $e->getLine());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get summary data for the variables panel.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary()
|
||||
{
|
||||
if (!isset($this->_data['content'])) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
return (string)count($this->_data['content']);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since DebugKit 3.15.0
|
||||
* @license https://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit;
|
||||
|
||||
use Cake\Core\BasePlugin;
|
||||
|
||||
/**
|
||||
* Plugin class for CakePHP 3.6.0 plugin collection.
|
||||
*/
|
||||
class Plugin extends BasePlugin
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?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
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\Routing\Filter;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\Event\EventManager;
|
||||
use Cake\Http\Response;
|
||||
use Cake\Http\ServerRequest as Request;
|
||||
use Cake\Routing\DispatcherFilter;
|
||||
use DebugKit\ToolbarService;
|
||||
|
||||
/**
|
||||
* Toolbar injector filter.
|
||||
*
|
||||
* This class loads all the panels into the registry
|
||||
* and binds the correct events into the provided event
|
||||
* manager
|
||||
*
|
||||
* @deprecated Dispatch filters are deprecated. Long term this filter
|
||||
* will be removed and replaced with middleware.
|
||||
*/
|
||||
class DebugBarFilter extends DispatcherFilter
|
||||
{
|
||||
/**
|
||||
* @var \DebugKit\ToolbarService
|
||||
*/
|
||||
protected $service;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \Cake\Event\EventManager $events The event manager to use.
|
||||
* @param array $config The configuration data for DebugKit.
|
||||
*/
|
||||
public function __construct(EventManager $events, array $config)
|
||||
{
|
||||
parent::__construct($config);
|
||||
|
||||
$this->service = new ToolbarService($events, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event bindings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function implementedEvents()
|
||||
{
|
||||
return [
|
||||
'Dispatcher.beforeDispatch' => [
|
||||
'callable' => 'beforeDispatch',
|
||||
'priority' => 0,
|
||||
],
|
||||
'Dispatcher.afterDispatch' => [
|
||||
'callable' => 'afterDispatch',
|
||||
'priority' => 9999,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not debug kit is enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
return $this->service->isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of loaded panels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function loadedPanels()
|
||||
{
|
||||
return $this->service->registry()->loaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of loaded panels
|
||||
*
|
||||
* @param string $name The name of the panel you want to get.
|
||||
* @return \DebugKit\DebugPanel|null The panel or null.
|
||||
*/
|
||||
public function panel($name)
|
||||
{
|
||||
$registry = $this->service->registry();
|
||||
|
||||
return $registry->{$name};
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the required setup work.
|
||||
*
|
||||
* - Build panels.
|
||||
* - Connect events
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setup()
|
||||
{
|
||||
$this->service->loadPanels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the initialize method onl all the loaded panels.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The beforeDispatch event.
|
||||
* @return void
|
||||
*/
|
||||
public function beforeDispatch(Event $event)
|
||||
{
|
||||
$this->service->initializePanels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the toolbar data.
|
||||
*
|
||||
* @param \Cake\Event\Event $event The afterDispatch event.
|
||||
* @return \Psr\Http\Message\ResponseInterface|void Modified response or null
|
||||
*/
|
||||
public function afterDispatch(Event $event)
|
||||
{
|
||||
/* @var Request $request */
|
||||
$request = $event->getData('request');
|
||||
/* @var Response $response */
|
||||
$response = $event->getData('response');
|
||||
$row = $this->service->saveData($request, $response);
|
||||
if (!$row) {
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->service->injectScripts($row, $response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Shell;
|
||||
|
||||
use Cake\Console\Shell;
|
||||
use Cake\Utility\Text;
|
||||
|
||||
/**
|
||||
* Benchmark Shell Class
|
||||
*
|
||||
* Provides basic benchmarking of application requests
|
||||
* functionally similar to Apache AB
|
||||
*
|
||||
* @since DebugKit 1.0
|
||||
*/
|
||||
class BenchmarkShell extends Shell
|
||||
{
|
||||
|
||||
/**
|
||||
* Main execution of shell
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function main()
|
||||
{
|
||||
$url = $this->args[0];
|
||||
$defaults = ['t' => 100, 'n' => 10];
|
||||
$options = array_merge($defaults, $this->params);
|
||||
$times = [];
|
||||
|
||||
$this->out(Text::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(Text::insert(__d('debug_kit', 'Total Requests made: :requests'), compact('requests')));
|
||||
$this->out(Text::insert(__d('debug_kit', 'Total Time elapsed: :duration (seconds)'), compact('duration')));
|
||||
|
||||
$this->out("");
|
||||
|
||||
$this->out(Text::insert(__d('debug_kit', 'Requests/Second: :rps req/sec'), [
|
||||
'rps' => round($requests / $duration, 3),
|
||||
]));
|
||||
|
||||
$this->out(Text::insert(__d('debug_kit', 'Average request time: :average-time seconds'), [
|
||||
'average-time' => round($duration / $requests, 3),
|
||||
]));
|
||||
|
||||
$this->out(Text::insert(__d('debug_kit', 'Standard deviation of average request time: :std-dev'), [
|
||||
'std-dev' => round($this->_deviation($times, true), 3),
|
||||
]));
|
||||
|
||||
$this->out(Text::insert(__d('debug_kit', 'Longest/shortest request: :longest sec/:shortest sec'), [
|
||||
'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 bool $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 bool $sample ''
|
||||
* @return float Standard deviation
|
||||
*/
|
||||
protected function _deviation($times, $sample = true)
|
||||
{
|
||||
return sqrt($this->_variance($times, $sample));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get option parser.
|
||||
*
|
||||
* @return \Cake\Console\ConsoleOptionParser
|
||||
*/
|
||||
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', [
|
||||
'help' => __d('debug_kit', 'The URL to request.'),
|
||||
'required' => true,
|
||||
])
|
||||
->addOption('n', [
|
||||
'default' => 10,
|
||||
'help' => __d('debug_kit', 'Number of iterations to perform.'),
|
||||
])
|
||||
->addOption('t', [
|
||||
'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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?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
|
||||
*/
|
||||
namespace DebugKit\Shell;
|
||||
|
||||
use Cake\Console\Shell;
|
||||
use Cake\Filesystem\Folder;
|
||||
|
||||
/**
|
||||
* 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 \Cake\Console\ConsoleOptionParser
|
||||
*/
|
||||
public function getOptionParser()
|
||||
{
|
||||
$parser = parent::getOptionParser();
|
||||
|
||||
return $parser->addOption('path', [
|
||||
'short' => 'p',
|
||||
'help' => __d('debug_kit', 'Absolute path or relative to {0}.', 'APP'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \App\View\AppView $this
|
||||
*/
|
||||
?>
|
||||
<h1><?= __d('debug_kit', 'Debug Kit Dashboard') ?></h1>
|
||||
|
||||
<h2><?= __d('debug_kit', 'Database') ?></h2>
|
||||
<ul>
|
||||
<li><?= __d('debug_kit', 'Driver') ?>: <?= h($connection['driver']); ?></li>
|
||||
<?php if (isset($connection['rows'])): ?>
|
||||
<li><?= __d('debug_kit', 'Requests') ?>: <?= $this->Number->format($connection['rows']) ?></li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
<?php if (!empty($connection['rows'])): ?>
|
||||
<?= $this->Form->postLink(
|
||||
__d('debug_kit', 'Reset database'),
|
||||
['_method' => 'POST', 'action' => 'reset'],
|
||||
['confirm' => 'Are you sure?']
|
||||
); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<h3>Actions</h3>
|
||||
<ul>
|
||||
<li><?= $this->Html->link(__d('debug_kit', 'Mail Preview'), ['controller' => 'MailPreview']); ?></li>
|
||||
</ul>
|
||||
@@ -0,0 +1,80 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var array $metrics
|
||||
*/
|
||||
?>
|
||||
<?php if (empty($metrics)): ?>
|
||||
<p class="info"><?= __d('debug_kit', 'There were no cache operations this request.') ?></p>
|
||||
<?php else: ?>
|
||||
<?php foreach ($metrics as $name => $counters): ?>
|
||||
<section class="section-tile">
|
||||
<h3><?= __d('debug_kit', '{0} Metrics', h($name)) ?> </h3>
|
||||
<button class="btn-primary clear-cache" data-name="<?= h($name) ?>"><?= __d('debug_kit', 'Clear {0} cache', h($name)) ?></button>
|
||||
<span class="inline-message"></span>
|
||||
<table cellspacing="0" cellpadding="0" class="debug-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Metric') ?></th>
|
||||
<th><?= __d('debug_kit', 'Total') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($counters as $key => $val): ?>
|
||||
<tr>
|
||||
<td><?= h($key) ?></td>
|
||||
<td class="right-text"><?= $val ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var baseUrl = '<?= $this->Url->build([
|
||||
'plugin' => 'DebugKit',
|
||||
'controller' => 'Toolbar',
|
||||
'action' => 'clearCache'
|
||||
]); ?>';
|
||||
|
||||
function showMessage(el, text) {
|
||||
el.show().text(text).fadeOut(2000);
|
||||
}
|
||||
|
||||
$('.clear-cache').on('click', function(e) {
|
||||
var el = $(this);
|
||||
var name = el.data('name');
|
||||
var messageEl = el.parent().find('.inline-message');
|
||||
|
||||
var xhr = $.ajax({
|
||||
headers: {'X-CSRF-TOKEN': '<?= $this->request->getParam('_csrfToken') ?>'},
|
||||
url: baseUrl,
|
||||
data: {name: name},
|
||||
dataType: 'json',
|
||||
type: 'POST'
|
||||
});
|
||||
xhr.done(function(response) {
|
||||
showMessage(messageEl, name + ' ' + '<?= __d('debug_kit', 'cache cleared.') ?>');
|
||||
}).error(function(response) {
|
||||
showMessage(messageEl, name + ' ' + '<?= __d('debug_kit', 'cache could not be cleared.') ?>');
|
||||
});
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,63 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var array $paths
|
||||
* @var array $app
|
||||
* @var array $cake
|
||||
* @var array $plugins
|
||||
* @var array $vendor
|
||||
* @var array $other
|
||||
*/
|
||||
|
||||
$printer = function ($section, $data) {
|
||||
?>
|
||||
<h3><?= h(ucfirst($section)) ?> </h3>
|
||||
<ul class="list deprecation-list">
|
||||
<?php foreach ($data as $message): ?>
|
||||
<li>
|
||||
<strong><?= h($message['niceFile']) ?>:<?= h($message['line']) ?></strong>
|
||||
<br>
|
||||
<?= h($message['message']) ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php
|
||||
};
|
||||
?>
|
||||
|
||||
<?php
|
||||
if (count($app)):
|
||||
$printer('app', $app);
|
||||
endif;
|
||||
|
||||
if (count($plugins)):
|
||||
foreach ($plugins as $plugin => $pluginData):
|
||||
$printer($plugin, $pluginData);
|
||||
endforeach;
|
||||
endif;
|
||||
|
||||
if (count($cake)):
|
||||
$printer('cake', $cake);
|
||||
endif;
|
||||
|
||||
if (count($vendor)):
|
||||
foreach ($vendor as $vendorSection => $vendorData):
|
||||
$printer($vendorSection, $vendorData);
|
||||
endforeach;
|
||||
endif;
|
||||
|
||||
if (count($other)):
|
||||
$printer('other', $other);
|
||||
endif;
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
/**
|
||||
* Environment Panel Element
|
||||
*
|
||||
* Shows information about the current app environment
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
use Cake\Error\Debugger;
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var array $app
|
||||
* @var array $cake
|
||||
* @var array $php
|
||||
* @var array $hidef
|
||||
*/
|
||||
?>
|
||||
|
||||
<h2><?= __d('debug_kit', 'Application Constants') ?></h2>
|
||||
|
||||
<?php if (!empty($app)): ?>
|
||||
<table cellspacing="0" cellpadding="0" class="debug-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Constant') ?></th>
|
||||
<th><?= __d('debug_kit', 'Value') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($app as $key => $val): ?>
|
||||
<tr>
|
||||
<td><?= h($key) ?></td>
|
||||
<td><?= h(Debugger::exportVar($val)) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="warning">
|
||||
<?= __d('debug_kit', 'No application environment available.'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<h2><?= __d('debug_kit', 'CakePHP Constants') ?></h2>
|
||||
|
||||
<?php if (!empty($cake)): ?>
|
||||
<table cellspacing="0" cellpadding="0" class="debug-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Constant') ?></th>
|
||||
<th><?= __d('debug_kit', 'Value') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($cake as $key => $val): ?>
|
||||
<tr>
|
||||
<td><?= h($key) ?></td>
|
||||
<td><?= h(Debugger::exportVar($val)) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="warning">
|
||||
<?= __d('debug_kit', 'CakePHP environment unavailable.'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<h2><?= __d('debug_kit', 'INI Environment') ?></h2>
|
||||
|
||||
<?php if (!empty($ini)): ?>
|
||||
<table cellspacing="0" cellpadding="0" class="debug-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>INI Variable</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($ini as $key => $val): ?>
|
||||
<tr>
|
||||
<td><?= h($key) ?></td>
|
||||
<td><?= $this->Credentials->filter($val) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="warning">
|
||||
<?= __d('debug_kit', 'ini environment unavailable.'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<h2><?= __d('debug_kit', 'PHP Environment') ?></h2>
|
||||
|
||||
<?php if (!empty($php)): ?>
|
||||
<table cellspacing="0" cellpadding="0" class="debug-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Environment Variable') ?></th>
|
||||
<th><?= __d('debug_kit', 'Value') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($php as $key => $val): ?>
|
||||
<tr>
|
||||
<td><?= h($key) ?></td>
|
||||
<td><?= $this->Credentials->filter($val) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="warning">
|
||||
<?= __d('debug_kit', 'PHP environment unavailable.'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($hidef)): ?>
|
||||
<h2><?= __d('debug_kit', 'Hidef Environment') ?></h2>
|
||||
|
||||
<?php if (!empty($hidef)): ?>
|
||||
<table cellspacing="0" cellpadding="0" class="debug-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Constant') ?></th>
|
||||
<th><?= __d('debug_kit', 'Value') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($hidef as $key => $val): ?>
|
||||
<tr>
|
||||
<td><?= h($key) ?></td>
|
||||
<td><?= h(Debugger::exportVar($val)) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="warning">
|
||||
<?= __d('debug_kit', 'No Hidef environment available.'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
@@ -0,0 +1,140 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var \DebugKit\Model\Entity\Panel $panel
|
||||
* @var array $requests
|
||||
*/
|
||||
?>
|
||||
<div id="request-history">
|
||||
<?php if (empty($requests)): ?>
|
||||
<p class="warning"><?= __d('debug_kit', 'No previous requests logged.') ?></p>
|
||||
<?php else: ?>
|
||||
<p><?= count($requests) ?> <?= __d('debug_kit', 'previous requests available') ?></p>
|
||||
<ul class="history-list">
|
||||
<li>
|
||||
<?= $this->Html->link(
|
||||
__d('debug_kit', 'Back to current request'),
|
||||
['plugin' => 'DebugKit', 'controller' => 'Panels', 'action' => 'index', $panel->request_id],
|
||||
['class' => 'history-link', 'data-request' => $panel->request_id]
|
||||
) ?>
|
||||
</li>
|
||||
<?php foreach ($requests as $request): ?>
|
||||
<?php $url = ['plugin' => 'DebugKit', 'controller' => 'Panels', 'action' => 'index', $request->id] ?>
|
||||
<li>
|
||||
<a class="history-link" data-request="<?= $request->id ?>" href="<?= $this->Url->build($url) ?>">
|
||||
<span class="history-time"><?= h($request->requested_at) ?></span>
|
||||
<span class="history-bubble"><?= h($request->method) ?></span>
|
||||
<span class="history-bubble"><?= h($request->status_code) ?></span>
|
||||
<span class="history-bubble"><?= h($request->content_type) ?></span>
|
||||
<span class="history-url"><?= h($request->url) ?></span>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<script type="text/html" id="list-template">
|
||||
<ul class="history-list">
|
||||
<li>
|
||||
<?= $this->Html->link(
|
||||
__d('debug_kit', 'Back to current request'),
|
||||
['plugin' => 'DebugKit', 'controller' => 'Panels', 'action' => 'index', $panel->request_id],
|
||||
['class' => 'history-link', 'data-request' => $panel->request_id]
|
||||
) ?>
|
||||
</li>
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="list-item-template">
|
||||
<li>
|
||||
<?php $url = ['plugin' => 'DebugKit', 'controller' => 'Panels', 'action' => 'index'] ?>
|
||||
<a class="history-link" data-request="{id}" href="<?= $this->Url->build($url) ?>/{id}">
|
||||
<span class="history-time">{time}</span>
|
||||
<span class="history-bubble xhr">XHR</span>
|
||||
<span class="history-bubble">{method}</span>
|
||||
<span class="history-bubble">{status}</span>
|
||||
<span class="history-bubble">{type}</span>
|
||||
<span class="history-url">{url}</span>
|
||||
</a>
|
||||
</li>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var panelButtons = $('.panel');
|
||||
var thisPanel = '<?= h($panel->id) ?>';
|
||||
var toolbar = window.toolbar;
|
||||
|
||||
if (!$('#request-history > ul').length) {
|
||||
$('#request-history').html($('#list-template').html());
|
||||
}
|
||||
|
||||
var listItem = $('#list-item-template').html();
|
||||
|
||||
for (var i = 0; i < toolbar.ajaxRequests.length; i++) {
|
||||
var params = {
|
||||
id: toolbar.ajaxRequests[i].requestId,
|
||||
time: (new Date(toolbar.ajaxRequests[i].date)).toLocaleString(),
|
||||
method: toolbar.ajaxRequests[i].method,
|
||||
status: toolbar.ajaxRequests[i].status,
|
||||
url: toolbar.ajaxRequests[i].url,
|
||||
type: toolbar.ajaxRequests[i].type
|
||||
};
|
||||
var content = listItem.replace(/{([^{}]*)}/g, function(a, b) {
|
||||
var r = params[b];
|
||||
return typeof r === 'string' || typeof r === 'number' ? r : a;
|
||||
});
|
||||
$('ul.history-list li:first').after(content);
|
||||
}
|
||||
|
||||
var buttons = $('.history-link');
|
||||
// Highlight the active request.
|
||||
buttons.filter('[data-request=' + window.toolbar.currentRequest + ']').addClass('active');
|
||||
|
||||
buttons.on('click', function(e) {
|
||||
var el = $(this);
|
||||
e.preventDefault();
|
||||
buttons.removeClass('active');
|
||||
el.addClass('active');
|
||||
|
||||
window.toolbar.currentRequest = el.data('request');
|
||||
|
||||
$.getJSON(el.attr('href'), function(response) {
|
||||
if (response.panels[0].request_id == window.toolbar.originalRequest) {
|
||||
$('#panel-content-container').removeClass('history-mode');
|
||||
$('#toolbar').removeClass('history-mode');
|
||||
} else {
|
||||
$('#panel-content-container').addClass('history-mode');
|
||||
$('#toolbar').addClass('history-mode');
|
||||
}
|
||||
|
||||
for (var i = 0, len = response.panels.length; i < len; i++) {
|
||||
var panel = response.panels[i];
|
||||
// Offset by two for scroll buttons
|
||||
var button = panelButtons.eq(i + 2);
|
||||
var summary = button.find('.panel-summary');
|
||||
|
||||
// Don't overwrite the history panel.
|
||||
if (button.data('id') == thisPanel) {
|
||||
continue;
|
||||
}
|
||||
button.attr('data-id', panel.id);
|
||||
summary.text(panel.summary);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var array $paths
|
||||
* @var array $app
|
||||
* @var array $cake
|
||||
* @var array $plugins
|
||||
* @var array $vendor
|
||||
* @var array $other
|
||||
*/
|
||||
|
||||
// Backwards compat for old DebugKit data.
|
||||
if (!isset($cake) && isset($core)) {
|
||||
$cake = $core;
|
||||
}
|
||||
?>
|
||||
<h4><?= __d('debug_kit', 'Include Paths') ?></h4>
|
||||
<?= $this->Toolbar->makeNeatArray($paths) ?>
|
||||
|
||||
<h4><?= __d('debug_kit', 'Included Files') ?></h4>
|
||||
<?= $this->Toolbar->makeNeatArray(compact('app', 'cake', 'plugins', 'vendor', 'other')) ?>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var \DebugKit\Log\Engine\DebugKitLog $logger
|
||||
*/
|
||||
?>
|
||||
<?php if ($logger->noLogs()): ?>
|
||||
<p class="info"><?= __d('debug_kit', 'There were no log entries made this request') ?></p>
|
||||
<?php else: ?>
|
||||
<?php foreach ($logger->all() as $logName => $logs): ?>
|
||||
<h3><?= __d('debug_kit', '{0} Messages', h(ucfirst($logName))) ?> </h3>
|
||||
<table cellspacing="0" cellpadding="0" class="debug-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Time') ?></th>
|
||||
<th><?= __d('debug_kit', 'Message') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($logs as $log): ?>
|
||||
<tr>
|
||||
<td width="200" class="code"><?= $log[0] ?></td>
|
||||
<td><?= h($log[1]) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
@@ -0,0 +1,49 @@
|
||||
<p class="info">
|
||||
<?= __d('debug_kit',
|
||||
'Why not test your emails interactively instead? Go to the {0}',
|
||||
$this->Html->link(__d('debug_kit', 'Email previews page'), ['controller' => 'MailPreview', 'action' => 'index'], ['target' => '_blank'])) ?>
|
||||
</p>
|
||||
<?php
|
||||
if (empty($emails)) {
|
||||
echo "<p>" . __d('debug_kit', 'No emails were sent during this request') . "</p>";
|
||||
return;
|
||||
}
|
||||
$url = $this->Url->build(['controller' => 'MailPreview', 'action' => 'sent', 'panel' => $panel->id, 'id' => 0]);
|
||||
?>
|
||||
<div style="display:flex">
|
||||
<div style="width:300px;">
|
||||
<table class="debug-table">
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Subject') ?></th>
|
||||
</tr>
|
||||
<?php foreach ($emails as $k => $email) : ?>
|
||||
<tr onclick="loadSentEmail(this, <?= $k ?>)" class="<?= $k == 0 ? 'highlighted' : '' ?>">
|
||||
<td style="cursor:pointer;padding:20px 10px;line-height:20px">
|
||||
<?= "\u{2709}\u{FE0F}" ?>
|
||||
<?= !empty($email['headers']['Subject']) ?
|
||||
h($this->Text->truncate($email['headers']['Subject'])) :
|
||||
'(No Subject)'
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
<iframe seamless
|
||||
name="sent-email"
|
||||
src="<?= h($url) ?>"
|
||||
style="height:calc(100vh - 128px);flex:1;margin-left:20px;padding-left:10px;border-left:1px solid #ccc"
|
||||
>
|
||||
</iframe>
|
||||
</div>
|
||||
<script>
|
||||
function loadSentEmail(elem, index) {
|
||||
var iframe = document.getElementsByName('sent-email')[0];
|
||||
var current = iframe.contentWindow.location.href;
|
||||
newLocation = current.replace(/\/\d+$/, '/' + index);
|
||||
iframe.contentWindow.location.href = newLocation;
|
||||
|
||||
$(elem).siblings().removeClass('highlighted');
|
||||
elem.className = 'highlighted';
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,140 @@
|
||||
<?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 3.5.2
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var array $packages
|
||||
*/
|
||||
?>
|
||||
<?php if (empty($packages) && empty($devPackages)): ?>
|
||||
<div class="warning">
|
||||
<?= __d('debug_kit', '{0} not found', "'composer.lock'"); ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="check-update">
|
||||
<button class="btn-primary"><?= __d('debug_kit', 'Check for Updates') ?></button>
|
||||
<label><input type="checkbox" class="direct-dependency"><?= __d('debug_kit', 'Direct dependencies only') ?></label>
|
||||
</div>
|
||||
<div class="terminal"></div>
|
||||
<?php if (!empty($packages)): ?>
|
||||
<section class="section-tile">
|
||||
<h3><?= __d('debug_kit', 'Requirements ({0})', count($packages)) ?> </h3>
|
||||
<table cellspacing="0" cellpadding="0" class="debug-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Name') ?></th>
|
||||
<th><?= __d('debug_kit', 'Version') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($packages as $package): ?>
|
||||
<?php extract($package); ?>
|
||||
<tr>
|
||||
<td title="<?= h($description) ?>">
|
||||
<a href="https://packagist.org/packages/<?= h($name) ?>" title="<?= h($description) ?>" target="_blank" class="package-link"><?= h($name) ?></a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="package-version"><span class="panel-summary"><?= h($version) ?></span></span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($devPackages)): ?>
|
||||
<section class="section-tile">
|
||||
<h3><?= __d('debug_kit', 'Dev Requirements ({0})', count($devPackages)) ?> </h3>
|
||||
<table cellspacing="0" cellpadding="0" class="debug-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Name') ?></th>
|
||||
<th><?= __d('debug_kit', 'Version') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($devPackages as $package): ?>
|
||||
<?php extract($package); ?>
|
||||
<tr>
|
||||
<td title="<?= h($description) ?>">
|
||||
<a href="https://packagist.org/packages/<?= h($name) ?>" title="<?= h($description) ?>" target="_blank" class="package-link"><?= h($name) ?></a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="package-version"><span class="panel-summary"><?= h($version) ?></span></span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var baseUrl = '<?= $this->Url->build([
|
||||
'plugin' => 'DebugKit',
|
||||
'controller' => 'Composer',
|
||||
'action' => 'checkDependencies'
|
||||
]); ?>';
|
||||
|
||||
var terminal = $('.terminal');
|
||||
|
||||
function showMessage(el, html) {
|
||||
el.show().html(html);
|
||||
}
|
||||
|
||||
function buildLoader() {
|
||||
return '<div class="loading"><?= __d('debug_kit', 'Loading') . ' ' . $this->Html->image('DebugKit./img/cake.icon.png', ['class' => 'indicator']) ?></div>';
|
||||
}
|
||||
|
||||
function buildSuccessfulMessage(response) {
|
||||
var html = '';
|
||||
if (response.packages.bcBreaks === undefined && response.packages.semverCompatible === undefined) {
|
||||
return '<pre class="success-message">All dependencies are up to date</pre>';
|
||||
}
|
||||
if (response.packages.bcBreaks !== undefined) {
|
||||
html += '<h4 class="section-header">Update with potential BC break</h4>';
|
||||
html += '<pre>' + response.packages.bcBreaks + '</pre>';
|
||||
}
|
||||
if (response.packages.semverCompatible !== undefined) {
|
||||
html += '<h4 class="section-header">Update semver compatible</h4>';
|
||||
html += '<pre>' + response.packages.semverCompatible + '</pre>';
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
function buildErrorMessage(response) {
|
||||
return '<pre class="warning-message">' + JSON.parse(response.responseText).message + '</pre>';
|
||||
}
|
||||
|
||||
$('.check-update button').on('click', function(e) {
|
||||
showMessage(terminal, buildLoader());
|
||||
var direct = $('.direct-dependency')[0].checked;
|
||||
var xhr = $.ajax({
|
||||
headers: {'X-CSRF-TOKEN': '<?= $this->request->getParam('_csrfToken') ?>'},
|
||||
url: baseUrl,
|
||||
data: {direct: direct},
|
||||
dataType: 'json',
|
||||
type: 'POST'
|
||||
});
|
||||
xhr.done(function(response) {
|
||||
showMessage(terminal, buildSuccessfulMessage(response));
|
||||
}).error(function(response) {
|
||||
showMessage(terminal, buildErrorMessage(response));
|
||||
});
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,24 @@
|
||||
<header>
|
||||
<table>
|
||||
<tr>
|
||||
<td>View As</td>
|
||||
<td>
|
||||
<?php $partNames = array_keys($email->getParts()) ?>
|
||||
<?= $this->Form->control('part', [
|
||||
'type' => 'select',
|
||||
'label' => false,
|
||||
'value' => $this->request->getQuery('part') ?: 'html',
|
||||
'onChange' => 'formatChanged(this);',
|
||||
'options' => array_combine($partNames, $partNames),
|
||||
]);
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php foreach ($email->getHeaders() as $name => $header) :?>
|
||||
<tr>
|
||||
<td><?= h($name) ?></td>
|
||||
<td><?= h($header) ?></td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</table>
|
||||
</header>
|
||||
@@ -0,0 +1,65 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var array $headers
|
||||
* @var array $params
|
||||
* @var array $data
|
||||
* @var array $query
|
||||
* @var array $cookie
|
||||
* @var string $matchedRoute
|
||||
*/
|
||||
?>
|
||||
<?php if (!empty($headers) && $headers['response']): ?>
|
||||
<h4><?= __d('debug_kit', 'Warning') ?></h4>
|
||||
<?= '<p class="warning">' . __d('debug_kit', 'Headers already sent at file {0} and line {1}.', [$headers['file'], $headers['line']]) . '</p>' ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<h4><?= __d('debug_kit', 'Routing Params') ?></h4>
|
||||
<?= $this->Toolbar->makeNeatArray($params) ?>
|
||||
|
||||
<h4><?= __d('debug_kit', 'Post data') ?></h4>
|
||||
<?php
|
||||
if (empty($data)):
|
||||
echo '<p class="info">' . __d('debug_kit', 'No post data.') . '</p>';
|
||||
else:
|
||||
echo $this->Toolbar->makeNeatArray($data);
|
||||
endif;
|
||||
?>
|
||||
|
||||
<h4>Query string</h4>
|
||||
<?php
|
||||
if (empty($query)):
|
||||
echo '<p class="info">' . __d('debug_kit', 'No querystring data.') . '</p>';
|
||||
else:
|
||||
echo $this->Toolbar->makeNeatArray($query);
|
||||
endif;
|
||||
?>
|
||||
|
||||
<h4>Cookie</h4>
|
||||
<?php if (isset($cookie)): ?>
|
||||
<?= $this->Toolbar->makeNeatArray($cookie) ?>
|
||||
<?php else: ?>
|
||||
<p class="info"><?= __d('debug_kit', 'No Cookie data.') ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($matchedRoute)): ?>
|
||||
<h4><?= __d('debug_kit', 'Matched Route') ?></h4>
|
||||
<p><?= $this->Toolbar->makeNeatArray(['template' => $matchedRoute]) ?></p>
|
||||
<?php endif; ?>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \Cake\Routing\Route\Route[] $routes
|
||||
* @var string $matchedRoute
|
||||
*/
|
||||
use Cake\Utility\Hash;
|
||||
|
||||
$routes = Cake\Routing\Router::routes();
|
||||
?>
|
||||
<button type="button" class="btn-primary" id="toggle-debugkit-routes">
|
||||
<?= __d('debug_kit', 'Toggle debugkit internal routes') ?>
|
||||
</button>
|
||||
<table cellspacing="0" cellpadding="0" class="debug-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Route name') ?></th>
|
||||
<th class="left"><?= __d('debug_kit', 'URI template') ?></th>
|
||||
<th class="left"><?= __d('debug_kit', 'Defaults') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($routes as $route): ?>
|
||||
<?php
|
||||
$class = '';
|
||||
if ($matchedRoute === $route->template):
|
||||
$class = 'highlighted';
|
||||
elseif ($route->defaults['plugin'] === 'DebugKit'):
|
||||
$class = 'debugkit-route hidden';
|
||||
endif;
|
||||
?>
|
||||
<tr class="<?= $class ?>">
|
||||
<td><?= h(Hash::get($route->options, '_name', $route->getName())) ?></td>
|
||||
<td class="left"><?= h($route->template) ?></td>
|
||||
<td class="left"><pre><?= json_encode($route->defaults, JSON_PRETTY_PRINT) ?></pre></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#toggle-debugkit-routes').on('click', function (event) {
|
||||
event.preventDefault();
|
||||
var routes = $('.debugkit-route');
|
||||
routes.toggleClass('hidden');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var array $content
|
||||
*/
|
||||
?>
|
||||
<?= $this->Toolbar->makeNeatArray($content);
|
||||
@@ -0,0 +1,92 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var array $tables
|
||||
* @var \DebugKit\Database\Log\DebugLog[] $loggers
|
||||
*/
|
||||
$noOutput = true;
|
||||
|
||||
// Configure sqlformatter colours.
|
||||
SqlFormatter::$quote_attributes = 'style="color: #004d40;"';
|
||||
SqlFormatter::$backtick_quote_attributes = 'style="color: #26a69a;"';
|
||||
SqlFormatter::$number_attributes = 'style="color: #ec407a;"';
|
||||
SqlFormatter::$word_attributes = 'style="color: #9c27b0;"';
|
||||
SqlFormatter::$pre_attributes = 'style="color: #222; background-color: transparent;"';
|
||||
?>
|
||||
|
||||
<?php if (!empty($tables)): ?>
|
||||
<h4><?= __d('debug_kit', 'Generated Models') ?></h4>
|
||||
<p class="warning"><?= __d('debug_kit', 'The following Table objects used {0} instead of a concrete class:', '<code>Cake\ORM\Table</code>') ?></p>
|
||||
<ul class="list">
|
||||
<?php foreach ($tables as $table): ?>
|
||||
<li><?= h($table) ?></li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<hr />
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($loggers)): ?>
|
||||
<?php foreach ($loggers as $logger): ?>
|
||||
<?php
|
||||
$queries = $logger->queries();
|
||||
if (empty($queries)):
|
||||
continue;
|
||||
endif;
|
||||
|
||||
$noOutput = false;
|
||||
?>
|
||||
<div class="sql-log-panel-query-log">
|
||||
<h4><?= h($logger->name()) ?></h4>
|
||||
<h5>
|
||||
<?= __d(
|
||||
'debug_kit',
|
||||
'Total Time: {0} ms — Total Queries: {1} — Total Rows: {2}',
|
||||
$logger->totalTime(),
|
||||
count($queries),
|
||||
$logger->totalRows()
|
||||
);
|
||||
?>
|
||||
</h5>
|
||||
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Query') ?></th>
|
||||
<th><?= __d('debug_kit', 'Rows') ?></th>
|
||||
<th><?= __d('debug_kit', 'Took (ms)') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($queries as $query): ?>
|
||||
<tr>
|
||||
<td><?= SqlFormatter::format($query['query']) ?></td>
|
||||
<td><?= h($query['rows']) ?></td>
|
||||
<td><?= h($query['took']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($noOutput): ?>
|
||||
<div class="warning"><?= __d('debug_kit', 'No active database connections') ?></div>
|
||||
<?php endif ?>
|
||||
@@ -0,0 +1,101 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var float $requestTime
|
||||
* @var int $peakMemory
|
||||
* @var array $memory
|
||||
*/
|
||||
?>
|
||||
<section>
|
||||
<h3><?= __d('debug_kit', 'Memory') ?></h3>
|
||||
<div class="peak-mem-use">
|
||||
<strong><?= __d('debug_kit', 'Peak Memory Use:') ?></strong>
|
||||
<?= $this->Number->toReadableSize($peakMemory) ?>
|
||||
</div>
|
||||
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Message') ?></th>
|
||||
<th><?= __d('debug_kit', 'Memory Use') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($memory as $key => $value): ?>
|
||||
<tr>
|
||||
<td><?= h($key) ?></td>
|
||||
<td class="right-text"><?= $this->Number->toReadableSize($value) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3><?= __d('debug_kit', 'Timers') ?></h3>
|
||||
<div class="request-time">
|
||||
<strong><?= __d('debug_kit', 'Total Request Time:') ?></strong>
|
||||
<?= $this->Number->precision($requestTime * 1000, 0) ?> ms
|
||||
</div>
|
||||
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= __d('debug_kit', 'Event') ?></th>
|
||||
<th><?= __d('debug_kit', 'Time in ms') ?></th>
|
||||
<th><?= __d('debug_kit', 'Timeline') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$rows = [];
|
||||
$end = end($timers);
|
||||
$maxTime = $end['end'];
|
||||
|
||||
$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++;
|
||||
endif;
|
||||
endfor;
|
||||
$indent = str_repeat("\xC2\xA0\xC2\xA0", $indent);
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<?= h($indent . $timeInfo['message']) ?>
|
||||
</td>
|
||||
<td class="right-text"><?= $this->Number->precision($timeInfo['time'] * 1000, 2) ?></td>
|
||||
<td>
|
||||
<?= $this->SimpleGraph->bar(
|
||||
$timeInfo['time'] * 1000,
|
||||
$timeInfo['start'] * 1000,
|
||||
[
|
||||
'max' => $maxTime * 1000,
|
||||
'requestTime' => $requestTime * 1000,
|
||||
]
|
||||
) ?>
|
||||
</td>
|
||||
<?php
|
||||
$i++;
|
||||
endforeach;
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
@@ -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
|
||||
* @since DebugKit 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var string $error
|
||||
* @var bool $sort
|
||||
* @var array $content
|
||||
* @var array $errors
|
||||
*/
|
||||
|
||||
if (isset($error)):
|
||||
printf('<p class="warning">%s</p>', $error);
|
||||
endif;
|
||||
|
||||
if (!empty($content)):
|
||||
printf('<label class="toggle-checkbox"><input type="checkbox" class="neat-array-sort"%s>%s</label>', $sort ? ' checked="checked"' : '', __d('debug_kit', 'Sort variables by name'));
|
||||
$this->Toolbar->setSort($sort);
|
||||
echo $this->Toolbar->makeNeatArray($content);
|
||||
endif;
|
||||
|
||||
if (!empty($errors)):
|
||||
echo '<h4>' . __d('debug_kit', 'Validation errors') . '</h4>';
|
||||
echo $this->Toolbar->makeNeatArray($errors);
|
||||
endif;
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php $this->extend('toolbar') ?>
|
||||
|
||||
<div style="height:calc(100vh);overflow-y:scroll">
|
||||
<?php if (empty($noHeader)) : ?>
|
||||
<h2 class="panel-title">
|
||||
<?= isset($title) ? h($title) : __d('debug_kit', 'DebugKit Dashboard') ?>
|
||||
</h2>
|
||||
<?php endif ?>
|
||||
|
||||
<div class="panel-content">
|
||||
<?= $this->fetch('content'); ?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php $this->extend('toolbar') ?>
|
||||
|
||||
<div style="height:calc(100vh);overflow-y:scroll">
|
||||
<?php if (empty($noHeader)) : ?>
|
||||
<h2 class="panel-title">
|
||||
<?= isset($title) ? h($title) : __d('debug_kit', 'Mailer Previews') . " \u{1f4ee}" ?>
|
||||
</h2>
|
||||
<?php endif ?>
|
||||
|
||||
<div class="panel-content">
|
||||
<?= $this->fetch('content'); ?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
*/
|
||||
|
||||
echo $this->fetch('content');
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
*/
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title><?= isset($title) ? h($title) : "Debug Kit Toolbar" ?></title>
|
||||
<?= $this->Html->css('DebugKit./css/reset') ?>
|
||||
<?= $this->Html->css('DebugKit./css/toolbar') ?>
|
||||
</head>
|
||||
<body>
|
||||
<?= $this->fetch('content') ?>
|
||||
<div id="loader">
|
||||
<?= $this->Html->image('DebugKit./img/cake.icon.png', ['class' => 'indicator'])?>
|
||||
</div>
|
||||
</body>
|
||||
<?= $this->Html->script('DebugKit./js/jquery') ?>
|
||||
<?= $this->Html->script('DebugKit./js/toolbar-app') ?>
|
||||
<?= $this->fetch('script') ?>
|
||||
</html>
|
||||
@@ -0,0 +1,33 @@
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
iframe.messageBody {
|
||||
border: 0;
|
||||
height: calc(100vh);
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php if (!$this->request->getQuery('part')) : ?>
|
||||
<?= $this->element('preview_header'); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($part)) : ?>
|
||||
<iframe seamless name="messageBody" class="messageBody" src="?part=<?= h($part); ?>&plugin=<?= h($plugin); ?>"></iframe>
|
||||
<?php else : ?>
|
||||
<p><?= __d('debug_kit', 'You are trying to preview an email that does not have any content.') ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<script>
|
||||
function formatChanged(form) {
|
||||
var part_name = form.options[form.selectedIndex].value
|
||||
var iframe = document.getElementsByName('messageBody')[0];
|
||||
iframe.contentWindow.location.replace('?part=' + part_name + '&plugin=<?= h($plugin); ?>');
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php foreach ($mailPreviews as $plugin => $previews) : ?>
|
||||
<h3><?= $plugin ?></h3>
|
||||
<?php foreach ($previews as $preview) : ?>
|
||||
<?php $mailPreview = $preview['class'] ?>
|
||||
<h4><?= "\u{2709}\u{FE0F}" ?> <?= h($mailPreview->name()) ?></h4>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<?php foreach ($mailPreview->getEmails() as $email) : ?>
|
||||
<tr>
|
||||
<td>
|
||||
<?php
|
||||
echo $this->Html->link($email, [
|
||||
'controller' => 'MailPreview',
|
||||
'action' => 'email',
|
||||
'?' => ['plugin' => $plugin],
|
||||
$mailPreview->name(),
|
||||
$email,
|
||||
]);
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<div style="font-weight:300;margin-top:100px">
|
||||
<h3><?= __d('debug_kit', 'How to use this feature?') ?></h3>
|
||||
<p><?= __d('debug_kit', 'Testing emails can be very time consuming') ?> ⌛</p>
|
||||
<p> <?= __d('debug_kit', 'Specially when you need to click a bunch of times on an interface to trigger them.') ?></p>
|
||||
<p><?= __d('debug_kit', "Wouldn't it be better to just change the templates and refresh the browser to see the result?") ?></p>
|
||||
<p><?= __d('debug_kit', 'Just the way you work on the web interface!') ?> 🏃</p>
|
||||
|
||||
<h4><?= __d('debug_kit', 'Example') ?></h4>
|
||||
<p><?= __d('debug_kit', "{0} integrates with CakePHP’s {1} class. Here's an example of such a mailer:", 'MailPreview', 'Mailer') ?></p>
|
||||
|
||||
<pre style="background-color:#f8f8f8;font-familiy:Monaco,sans-serif;overflow:scroll;margin:10px 0;line-height:25px;">
|
||||
<?php
|
||||
$code = '
|
||||
<?php
|
||||
namespace App\Mailer;
|
||||
|
||||
use Cake\Mailer\Mailer;
|
||||
|
||||
class UserMailer extends Mailer
|
||||
{
|
||||
public function welcome($user)
|
||||
{
|
||||
return $this // ' . __d('debug_kit', 'Returning the chain is a good idea') . ' :)
|
||||
->to($user->email)
|
||||
->subject(sprintf("Welcome %s", $user->name))
|
||||
->template("welcome_mail") // ' . __d('debug_kit', 'By default template with same name as method name is used.') . '
|
||||
->layout("custom")
|
||||
->set(["user" => $user]);
|
||||
}
|
||||
}';
|
||||
highlight_string($code);
|
||||
?>
|
||||
</pre>
|
||||
<p><?= __d('debug_kit', 'Now you create a {0} class where you can pass some dummy values.', 'MailPreview') ?></p>
|
||||
|
||||
<pre style="background-color:#f8f8f8;font-familiy:Monaco,sans-serif;overflow:scroll;margin:10px 0;line-height:25px;">
|
||||
<?php
|
||||
$code = '
|
||||
<?php
|
||||
// Create the file src/Mailer/Preview/UserMailPreview.php
|
||||
namespace App\Mailer\Preview;
|
||||
|
||||
use DebugKit\Mailer\MailPreview;
|
||||
|
||||
class UserMailPreview extends MailPreview
|
||||
{
|
||||
public function welcome()
|
||||
{
|
||||
$this->loadModel("Users");
|
||||
$user = $this->Users->find()->first();
|
||||
return $this->getMailer("User")
|
||||
->welcome($user)
|
||||
->set(["activationToken" => "dummy-token"]);
|
||||
}
|
||||
}';
|
||||
highlight_string($code);
|
||||
?>
|
||||
</pre>
|
||||
|
||||
<p><?= __d('debug_kit', 'Note that the function MUST return the UserMailer object at the end.') ?></p>
|
||||
<p><?= __d('debug_kit', 'Since {0} have a fluent interface, you just need to return the result of the chain of calls.', 'Mailers') ?></p>
|
||||
<p style="margin:20px 0"><?= __d('debug_kit', "That's it, now refresh this page!") ?> 🙃</p>
|
||||
</div>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var \DebugKit\Model\Entity\Panel $panel
|
||||
*/
|
||||
?>
|
||||
<h2 class="panel-title"><?= h($panel->title) ?></h2>
|
||||
<div class="panel-content">
|
||||
<?= $this->element($panel->element) ?>
|
||||
</div>
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \DebugKit\View\AjaxView $this
|
||||
* @var \DebugKit\Model\Entity\Request $toolbar
|
||||
*/
|
||||
|
||||
use Cake\Routing\Router;
|
||||
use Cake\Core\Configure;
|
||||
|
||||
?>
|
||||
<div id="panel-content-container">
|
||||
<span id="panel-close" class="button-close">×</span>
|
||||
<div id="panel-content">
|
||||
<!-- content here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul id="toolbar" class="toolbar">
|
||||
<li class="panel-button-left panel hidden">
|
||||
<span class="panel-button">
|
||||
〈
|
||||
</span>
|
||||
</li>
|
||||
<li class="panel-button-right panel hidden">
|
||||
<span class="panel-button">
|
||||
〉
|
||||
</span>
|
||||
</li>
|
||||
<li class="toolbar-inner">
|
||||
<ul class="toolbar-inner">
|
||||
<?php foreach ($toolbar->panels as $panel): ?>
|
||||
<li class="panel hidden" data-id="<?= $panel->id ?>">
|
||||
<span class="panel-button">
|
||||
<?= h($panel->title) ?>
|
||||
</span>
|
||||
<?php if (strlen($panel->summary)): ?>
|
||||
<span class="panel-summary">
|
||||
<?= h($panel->summary) ?>
|
||||
</span>
|
||||
<?php endif ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</li>
|
||||
<li id="panel-button">
|
||||
<?= $this->Html->image('DebugKit./img/cake.icon.png', [
|
||||
'alt' => 'Debug Kit', 'title' => 'CakePHP ' . Configure::version() . ' Debug Kit'
|
||||
]) ?>
|
||||
</li>
|
||||
</ul>
|
||||
<?php $this->Html->script('DebugKit./js/debug_kit', [
|
||||
'block' => true,
|
||||
'id' => '__debug_kit_app',
|
||||
'data-id' => $toolbar->id,
|
||||
'data-url' => Router::url('/', true),
|
||||
'data-webroot' => $this->request->getAttribute("webroot"),
|
||||
]) ?>
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
<?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
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\InstanceConfigTrait;
|
||||
use Cake\Core\Plugin as CorePlugin;
|
||||
use Cake\Event\Event;
|
||||
use Cake\Event\EventManager;
|
||||
use Cake\Http\Response;
|
||||
use Cake\Http\ServerRequest;
|
||||
use Cake\Log\Log;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Routing\Router;
|
||||
use DebugKit\Panel\PanelRegistry;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Used to create the panels and inject a toolbar into
|
||||
* matching responses.
|
||||
*
|
||||
* Used by the Routing Filter and Middleware.
|
||||
*/
|
||||
class ToolbarService
|
||||
{
|
||||
use InstanceConfigTrait;
|
||||
|
||||
/**
|
||||
* The panel registry.
|
||||
*
|
||||
* @var \DebugKit\Panel\PanelRegistry
|
||||
*/
|
||||
protected $registry;
|
||||
|
||||
/**
|
||||
* Default configuration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_defaultConfig = [
|
||||
'panels' => [
|
||||
'DebugKit.Cache' => true,
|
||||
'DebugKit.Session' => true,
|
||||
'DebugKit.Request' => true,
|
||||
'DebugKit.SqlLog' => true,
|
||||
'DebugKit.Timer' => true,
|
||||
'DebugKit.Log' => true,
|
||||
'DebugKit.Variables' => true,
|
||||
'DebugKit.Environment' => true,
|
||||
'DebugKit.Include' => true,
|
||||
'DebugKit.History' => true,
|
||||
'DebugKit.Routes' => true,
|
||||
'DebugKit.Packages' => true,
|
||||
'DebugKit.Mail' => true,
|
||||
'DebugKit.Deprecations' => true,
|
||||
],
|
||||
'forceEnable' => false,
|
||||
'safeTld' => [],
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \Cake\Event\EventManager $events The event manager to use defaults to the global manager
|
||||
* @param array $config The configuration data for DebugKit.
|
||||
*/
|
||||
public function __construct(EventManager $events, array $config)
|
||||
{
|
||||
$this->setConfig($config);
|
||||
$this->registry = new PanelRegistry($events);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the PanelRegistry
|
||||
*
|
||||
* @return \DebugKit\Panel\PanelRegistry
|
||||
*/
|
||||
public function registry()
|
||||
{
|
||||
return $this->registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not debug kit is enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
$enabled = (bool)Configure::read('debug');
|
||||
|
||||
if ($enabled && !$this->isSuspiciouslyProduction()) {
|
||||
return true;
|
||||
}
|
||||
$force = $this->getConfig('forceEnable');
|
||||
if (is_callable($force)) {
|
||||
return $force();
|
||||
}
|
||||
|
||||
return $force;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this applications is being executed on a domain with a TLD
|
||||
* that is commonly associated with a production environment.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isSuspiciouslyProduction()
|
||||
{
|
||||
$host = explode('.', parse_url('http://' . env('HTTP_HOST'), PHP_URL_HOST));
|
||||
$first = current($host);
|
||||
$isIP = is_numeric(implode('', $host));
|
||||
|
||||
if (count($host) === 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($isIP && in_array($first, ['192', '10', '127'])) {
|
||||
// Accessing the app by private IP, this is safe
|
||||
return false;
|
||||
}
|
||||
|
||||
$tld = end($host);
|
||||
$safeTopLevelDomains = ['localhost', 'invalid', 'test', 'example', 'local'];
|
||||
$safeTopLevelDomains = array_merge($safeTopLevelDomains, (array)$this->getConfig('safeTld'));
|
||||
|
||||
if (!in_array($tld, $safeTopLevelDomains, true) && !$this->getConfig('forceEnable')) {
|
||||
$host = implode('.', $host);
|
||||
$safeList = implode(', ', $safeTopLevelDomains);
|
||||
Log::warning(
|
||||
"DebugKit is disabling itself as your host `{$host}` " .
|
||||
"is not in the known safe list of top-level-domains ({$safeList}). " .
|
||||
"If you would like to force DebugKit on use the `DebugKit.forceEnable` Configure option."
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of loaded panels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function loadedPanels()
|
||||
{
|
||||
return $this->registry->loaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the a loaded panel
|
||||
*
|
||||
* @param string $name The name of the panel you want to get.
|
||||
* @return \DebugKit\DebugPanel|null The panel or null.
|
||||
*/
|
||||
public function panel($name)
|
||||
{
|
||||
return $this->registry->{$name};
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all the panels being used
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function loadPanels()
|
||||
{
|
||||
foreach ($this->getConfig('panels') as $panel => $enabled) {
|
||||
list($panel, $enabled) = (is_numeric($panel)) ? [$enabled, true] : [$panel, $enabled];
|
||||
if ($enabled) {
|
||||
$this->registry->load($panel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the initialize method onl all the loaded panels.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initializePanels()
|
||||
{
|
||||
foreach ($this->registry->loaded() as $panel) {
|
||||
$this->registry->{$panel}->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the toolbar state.
|
||||
*
|
||||
* @param \Cake\Http\ServerRequest $request The request
|
||||
* @param \Psr\Http\Message\ResponseInterface $response The response
|
||||
* @return null|\DebugKit\Model\Entity\Request Saved request data.
|
||||
*/
|
||||
public function saveData(ServerRequest $request, ResponseInterface $response)
|
||||
{
|
||||
// Skip debugkit requests and requestAction()
|
||||
$path = $request->getUri()->getPath();
|
||||
if (
|
||||
strpos($path, 'debug_kit') !== false ||
|
||||
strpos($path, 'debug-kit') !== false ||
|
||||
$request->is('requested')
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
$data = [
|
||||
'url' => $request->getUri()->getPath(),
|
||||
'content_type' => $response->getHeaderLine('Content-Type'),
|
||||
'method' => $request->getMethod(),
|
||||
'status_code' => $response->getStatusCode(),
|
||||
'requested_at' => $request->getEnv('REQUEST_TIME'),
|
||||
'panels' => [],
|
||||
];
|
||||
/* @var \DebugKit\Model\Table\RequestsTable $requests */
|
||||
$requests = TableRegistry::get('DebugKit.Requests');
|
||||
$requests->gc();
|
||||
|
||||
$row = $requests->newEntity($data);
|
||||
$row->isNew(true);
|
||||
|
||||
foreach ($this->registry->loaded() as $name) {
|
||||
$panel = $this->registry->{$name};
|
||||
try {
|
||||
$content = serialize($panel->data());
|
||||
} catch (\Exception $e) {
|
||||
$content = serialize([
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
$row->panels[] = $requests->Panels->newEntity([
|
||||
'panel' => $name,
|
||||
'element' => $panel->elementName(),
|
||||
'title' => $panel->title(),
|
||||
'summary' => $panel->summary(),
|
||||
'content' => $content,
|
||||
]);
|
||||
}
|
||||
|
||||
return $requests->save($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the modified date of a file in the webroot, and returns the integer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getToolbarUrl()
|
||||
{
|
||||
$url = 'js/toolbar.js';
|
||||
$filePaths = [
|
||||
str_replace('/', DIRECTORY_SEPARATOR, WWW_ROOT . 'debug_kit/' . $url),
|
||||
str_replace('/', DIRECTORY_SEPARATOR, CorePlugin::path('DebugKit') . 'webroot/' . $url),
|
||||
];
|
||||
$url = '/debug_kit/' . $url;
|
||||
foreach ($filePaths as $filePath) {
|
||||
if (file_exists($filePath)) {
|
||||
return $url . '?' . filemtime($filePath);
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects the JS to build the toolbar.
|
||||
*
|
||||
* The toolbar will only be injected if the response's content type
|
||||
* contains HTML and there is a </body> tag.
|
||||
*
|
||||
* @param \DebugKit\Model\Entity\Request $row The request data to inject.
|
||||
* @param \Psr\Http\Message\ResponseInterface $response The response to augment.
|
||||
* @return \Psr\Http\Message\ResponseInterface The modified response
|
||||
*/
|
||||
public function injectScripts($row, ResponseInterface $response)
|
||||
{
|
||||
$response = $response->withHeader('X-DEBUGKIT-ID', $row->id);
|
||||
if (strpos($response->getHeaderLine('Content-Type'), 'html') === false) {
|
||||
return $response;
|
||||
}
|
||||
$body = $response->getBody();
|
||||
if (!$body->isSeekable() || !$body->isWritable()) {
|
||||
return $response;
|
||||
}
|
||||
$body->rewind();
|
||||
$contents = $body->getContents();
|
||||
|
||||
$pos = strrpos($contents, '</body>');
|
||||
if ($pos === false) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$url = Router::url('/', true);
|
||||
$script = sprintf(
|
||||
'<script id="__debug_kit" data-id="%s" data-url="%s" src="%s"></script>',
|
||||
$row->id,
|
||||
$url,
|
||||
Router::url($this->getToolbarUrl())
|
||||
);
|
||||
$contents = substr($contents, 0, $pos) . $script . substr($contents, $pos);
|
||||
$body->rewind();
|
||||
$body->write($contents);
|
||||
|
||||
return $response->withBody($body);
|
||||
}
|
||||
}
|
||||
+41
@@ -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
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* 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 3.2.8
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\View;
|
||||
|
||||
use Cake\View\View;
|
||||
|
||||
/**
|
||||
* A view class that is used for AJAX responses.
|
||||
*
|
||||
* Currently only switches the default layout and sets the response type
|
||||
* which just maps to text/html by default.
|
||||
*
|
||||
* @property \DebugKit\View\Helper\SimpleGraphHelper $SimpleGraph
|
||||
* @property \DebugKit\View\Helper\ToolbarHelper $Toolbar
|
||||
* @property \DebugKit\View\Helper\TidyHelper $Tidy
|
||||
*/
|
||||
class AjaxView extends View
|
||||
{
|
||||
/**
|
||||
* Initialization hook method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
$this->response = $this->response->withType('ajax');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?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 3.3.7
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\View\Helper;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Error\Debugger;
|
||||
use Cake\Filesystem\File;
|
||||
use Cake\Utility\Hash;
|
||||
use Cake\View\Helper;
|
||||
|
||||
/**
|
||||
* CredentialsHelper
|
||||
*
|
||||
* Filter sensitive data in screen, data will be displayed on mouse click
|
||||
*
|
||||
* @property \Cake\View\Helper\HtmlHelper $Html
|
||||
* @property \DebugKit\View\Helper\ToolbarHelper $Toolbar
|
||||
*/
|
||||
class CredentialsHelper extends Helper
|
||||
{
|
||||
|
||||
/**
|
||||
* Helpers property
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $helpers = ['Html', 'DebugKit.Toolbar'];
|
||||
|
||||
/**
|
||||
* Replace credentials in url's by *****
|
||||
* Example mysql://username:password@localhost/my_db -> mysql://******@localhost/my_db
|
||||
*
|
||||
* @param string $in variable to filter
|
||||
* @return string
|
||||
*/
|
||||
public function filter($in)
|
||||
{
|
||||
$regexp = '/^([^:;]+:\/\/)([^:;]+:?.*?)@(.*)$/i';
|
||||
if (!is_string($in) || empty($in)) {
|
||||
return $in;
|
||||
}
|
||||
preg_match_all($regexp, $in, $tokens);
|
||||
if (empty($tokens[0])) {
|
||||
return h($in);
|
||||
}
|
||||
$protocol = Hash::get($tokens, '1.0');
|
||||
$credentials = Hash::get($tokens, '2.0');
|
||||
$tail = Hash::get($tokens, '3.0');
|
||||
$link = $this->Html->tag('a', '******', [
|
||||
'class' => 'filtered-credentials',
|
||||
'title' => h($credentials),
|
||||
'onclick' => "this.innerHTML = this.title",
|
||||
]);
|
||||
|
||||
return h($protocol) . $link . '@' . h($tail);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?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 1.0.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\View\Helper;
|
||||
|
||||
use Cake\View\Helper;
|
||||
|
||||
/**
|
||||
* Class SimpleGraphHelper
|
||||
*
|
||||
* Allows creation and display of extremely simple graphing elements
|
||||
*
|
||||
* @since DebugKit 1.0
|
||||
*/
|
||||
class SimpleGraphHelper extends Helper
|
||||
{
|
||||
|
||||
/**
|
||||
* 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 = [
|
||||
'max' => 100,
|
||||
'width' => 350,
|
||||
'valueType' => 'value',
|
||||
];
|
||||
|
||||
/**
|
||||
* bar method
|
||||
*
|
||||
* @param float $value Value to be graphed
|
||||
* @param int $offset how much indentation
|
||||
* @param array|\Graph $options Graph options
|
||||
* @return string Html graph
|
||||
*/
|
||||
public function bar($value, $offset, $options = [])
|
||||
{
|
||||
$settings = array_merge($this->_defaultSettings, $options);
|
||||
/* @var int $max */
|
||||
/* @var int $width */
|
||||
/* @var string $valueType */
|
||||
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 sprintf(
|
||||
'<div class="graph-bar" style="%s"><div class="graph-bar-value" style="%s" title="%s"> </div></div>',
|
||||
"width: {$width}px",
|
||||
"margin-left: {$graphOffset}px; width: {$graphValue}px",
|
||||
__d('debug_kit', "Starting {0}ms into the request, taking {1}ms", $offset, $value)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
<?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 1.0.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\View\Helper;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Error\Debugger;
|
||||
use Cake\Filesystem\File;
|
||||
use Cake\View\Helper;
|
||||
|
||||
/**
|
||||
* TidyHelper class
|
||||
*
|
||||
* Passes html through tidy on the command line, and reports markup errors
|
||||
*
|
||||
* @uses AppHelper
|
||||
* @since v 1.0 (22-Jun-2009)
|
||||
*
|
||||
* @property \DebugKit\View\Helper\ToolbarHelper $Toolbar
|
||||
*/
|
||||
class TidyHelper extends Helper
|
||||
{
|
||||
|
||||
/**
|
||||
* helpers property
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $helpers = ['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 [];
|
||||
}
|
||||
$result = ['Error' => [], 'Warning' => [], 'Misc' => []];
|
||||
$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]);
|
||||
}
|
||||
// phpcs:ignore
|
||||
$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, [], '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 bool 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(['depth' => 1, 'start' => 2]) . "\n";
|
||||
//Log::write('system_calls_' . date('Y-m-d'), "\n" . $source . Debugger::exportVar(compact('cmd','out','return')));
|
||||
//Log::write('system_calls', "\n" . $source . Debugger::exportVar(compact('cmd','out','return')));
|
||||
}
|
||||
if ($return) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $_out ? $_out : true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?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 0.1
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace DebugKit\View\Helper;
|
||||
|
||||
use ArrayAccess;
|
||||
use Cake\View\Helper;
|
||||
use Closure;
|
||||
use Iterator;
|
||||
|
||||
/**
|
||||
* Provides Base methods for content specific debug toolbar helpers.
|
||||
* Acts as a facade for other toolbars helpers as well.
|
||||
*
|
||||
* @property \Cake\View\Helper\HtmlHelper $Html
|
||||
* @property \Cake\View\Helper\FormHelper $Form
|
||||
* @property \Cake\View\Helper\UrlHelper $Url
|
||||
*/
|
||||
class ToolbarHelper extends Helper
|
||||
{
|
||||
|
||||
/**
|
||||
* helpers property
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $helpers = ['Html', 'Form', 'Url'];
|
||||
|
||||
/**
|
||||
* Whether or not the top level keys should be sorted.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $sort = false;
|
||||
|
||||
/**
|
||||
* set sorting of values
|
||||
*
|
||||
* @param bool $sort Whether or not sort values by key
|
||||
* @return void
|
||||
*/
|
||||
public function setSort($sort)
|
||||
{
|
||||
$this->sort = $sort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively goes through an array and makes neat HTML out of it.
|
||||
*
|
||||
* @param mixed $values Array to make pretty.
|
||||
* @param int $openDepth Depth to add open class
|
||||
* @param int $currentDepth current depth.
|
||||
* @param bool $doubleEncode Whether or not to double encode.
|
||||
* @param \SplObjectStorage $currentAncestors Object references found down
|
||||
* the path.
|
||||
* @return string
|
||||
*/
|
||||
public function makeNeatArray($values, $openDepth = 0, $currentDepth = 0, $doubleEncode = false, \SplObjectStorage $currentAncestors = null)
|
||||
{
|
||||
if ($currentAncestors === null) {
|
||||
$ancestors = new \SplObjectStorage();
|
||||
} elseif (is_object($values)) {
|
||||
$ancestors = new \SplObjectStorage();
|
||||
$ancestors->addAll($currentAncestors);
|
||||
$ancestors->attach($values);
|
||||
} else {
|
||||
$ancestors = $currentAncestors;
|
||||
}
|
||||
$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 = [$values];
|
||||
}
|
||||
if ($values === null) {
|
||||
$values = [null];
|
||||
}
|
||||
if (is_object($values) && method_exists($values, 'toArray')) {
|
||||
$values = $values->toArray();
|
||||
}
|
||||
}
|
||||
if (empty($values)) {
|
||||
$values[] = '(empty)';
|
||||
}
|
||||
if ($this->sort && is_array($values) && $currentDepth === 0) {
|
||||
ksort($values);
|
||||
}
|
||||
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 .= '(' . (get_class($value) ?: '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 && $ancestors->contains($value)) {
|
||||
$isObject = false;
|
||||
$value = ' - recursion';
|
||||
}
|
||||
|
||||
if (
|
||||
(
|
||||
$value instanceof ArrayAccess ||
|
||||
$value instanceof Iterator ||
|
||||
is_array($value) ||
|
||||
$isObject
|
||||
) && !empty($value)
|
||||
) {
|
||||
$out .= $this->makeNeatArray($value, $openDepth, $nextDepth, $doubleEncode, $ancestors);
|
||||
} else {
|
||||
$out .= h($value, $doubleEncode);
|
||||
}
|
||||
$out .= '</li>';
|
||||
}
|
||||
$out .= '</ul>';
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user