Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dump debug panel #12506

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
- Added the `editable` and `savable` asset query params. ([#12266](https://github.com/craftcms/cms/pull/12266))
- Added the `savable` entry query param. ([#12266](https://github.com/craftcms/cms/pull/12266))
- The `editable` entry query param can now be set to `false` to only show entries that _can’t_ be viewed by the current user. ([#12266](https://github.com/craftcms/cms/pull/12266))
- Added the `{% dump %}` tag, which dumps variables into a new “Dumps” Debug Toolbar panel. ([#12506](https://github.com/craftcms/cms/pull/12506))
- The `dump()` Twig function now utilizes `Craft::dump()`, and no longer requires Dev Mode to be active. ([#12486](https://github.com/craftcms/cms/pull/12486), [#12479](https://github.com/craftcms/cms/discussions/12479))
- The `{% dd %}` Twig tag can now output the entire `context` array, if no variable is passed to it. ([#12486](https://github.com/craftcms/cms/pull/12486))
- `Craft::dump()`, `Craft::dd()`, the `dump()` Twig function, and the `{% dd %}` Twig tag now use Symfony’s VarDumper. ([#12479](https://github.com/craftcms/cms/discussions/12479))
Expand All @@ -35,6 +36,7 @@
- Added `craft\console\ControllerTrait::init()`.
- Added `craft\console\ControllerTrait::options()`.
- Added `craft\console\ControllerTrait::runAction()`.
- Added `craft\debug\DumpPanel`.
- Added `craft\elements\conditions\assets\ViewableConditionRule`. ([#12266](https://github.com/craftcms/cms/pull/12266))
- Added `craft\elements\conditions\entries\ViewableConditionRule`. ([#12266](https://github.com/craftcms/cms/pull/12266))
- Added `craft\elemens\Entry::EVENT_DEFINE_PARENT_SELECTION_CRITERIA`. ([#12475](https://github.com/craftcms/cms/discussions/12475))
Expand Down
80 changes: 80 additions & 0 deletions src/debug/DumpPanel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php
/**
* @link https://craftcms.com/
* @copyright Copyright (c) Pixel & Tonic, Inc.
* @license https://craftcms.github.io/license/
*/

namespace craft\debug;

use Craft;
use yii\debug\Module as DebugModule;
use yii\debug\Panel;
use yii\web\NotFoundHttpException;

/**
* Debugger panel that collects and displays dumped variables.
*
* @author Pixel & Tonic, Inc. <[email protected]>
* @since 4.4.0
*/
class DumpPanel extends Panel
{
/**
* Displays a variable, if the Dump panel is active
*
* @param mixed $var The variable to be dumped.
* @param string $file The source file or template name
* @param int $line The line number
*/
public static function dump(mixed $var, string $file, int $line): void
{
$debugModule = Craft::$app->getModule('debug');
if (
$debugModule instanceof DebugModule &&
isset($debugModule->panels['dump']) &&
$debugModule->panels['dump'] instanceof DumpPanel
) {
ob_start();
Craft::dump($var);
$debugModule->panels['dump']->data[] = [$file, $line, ob_get_clean()];
}
}

/**
* @inheritdoc
*/
public function getName(): string
{
return 'Dumps';
}

/**
* @inheritdoc
*/
public function getSummary(): string
{
return Craft::$app->getView()->render('@app/views/debug/dump/summary', [
'panel' => $this,
]);
}

/**
* @inheritdoc
* @throws NotFoundHttpException if a `trace` parameter is in the query string, but its value isn’t a valid deprecation warning’s ID
*/
public function getDetail(): string
{
return Craft::$app->getView()->render('@app/views/debug/dump/detail', [
'panel' => $this,
]);
}

/**
* @inheritdoc
*/
public function save()
{
return $this->data ?? [];
}
}
18 changes: 18 additions & 0 deletions src/views/debug/dump/detail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php


/** @var craft\debug\DumpPanel $panel */
?>
<h1>Variable Dumps</h1>
<?php

?>

<?php if (empty($panel->data)): ?>
<p>No variables were dumped on this request.</p>
<?php else: ?>
<?php foreach ($panel->data as [$file, $line, $dump]): ?>
<h3><code><?= $file ?>:<?= $line ?></code></h3>
<?= $dump ?>
<?php endforeach; ?>
<?php endif; ?>
10 changes: 10 additions & 0 deletions src/views/debug/dump/summary.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
/** @var craft\debug\DumpPanel $panel */
$count = count($panel->data);
?>
<div class="yii-debug-toolbar__block">
<a href="<?= $panel->getUrl() ?>">
Dumps <span
class="yii-debug-toolbar__label"><?= $count ?></span>
</a>
</div>
2 changes: 2 additions & 0 deletions src/web/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use craft\db\Query;
use craft\db\Table;
use craft\debug\DeprecatedPanel;
use craft\debug\DumpPanel;
use craft\debug\Module as DebugModule;
use craft\debug\RequestPanel;
use craft\debug\UserPanel;
Expand Down Expand Up @@ -450,6 +451,7 @@ protected function debugBootstrap(): void
],
'request' => RequestPanel::class,
'log' => LogPanel::class,
'dump' => DumpPanel::class,
'deprecated' => DeprecatedPanel::class,
'profiling' => ProfilingPanel::class,
'db' => DbPanel::class,
Expand Down
2 changes: 2 additions & 0 deletions src/web/twig/Extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
use craft\web\twig\tokenparsers\CacheTokenParser;
use craft\web\twig\tokenparsers\DdTokenParser;
use craft\web\twig\tokenparsers\DeprecatedTokenParser;
use craft\web\twig\tokenparsers\DumpTokenParser;
use craft\web\twig\tokenparsers\ExitTokenParser;
use craft\web\twig\tokenparsers\HeaderTokenParser;
use craft\web\twig\tokenparsers\HookTokenParser;
Expand Down Expand Up @@ -132,6 +133,7 @@ public function getTokenParsers(): array
new CacheTokenParser(),
new DeprecatedTokenParser(),
new DdTokenParser(),
new DumpTokenParser(),
new ExitTokenParser(),
new HeaderTokenParser(),
new HookTokenParser(),
Expand Down
41 changes: 41 additions & 0 deletions src/web/twig/nodes/DumpNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
/**
* @link https://craftcms.com/
* @copyright Copyright (c) Pixel & Tonic, Inc.
* @license https://craftcms.github.io/license/
*/

namespace craft\web\twig\nodes;

use craft\debug\DumpPanel;
use craft\helpers\Template;
use Twig\Compiler;
use Twig\Node\Node;

/**
* Class DumpNode
*
* @author Pixel & Tonic, Inc. <[email protected]>
* @since 4.4.0
*/
class DumpNode extends Node
{
/**
* @inheritdoc
*/
public function compile(Compiler $compiler): void
{
$compiler
->addDebugInfo($this)
->write(sprintf('%s::dump(', DumpPanel::class));

if ($this->hasNode('var')) {
$compiler->subcompile($this->getNode('var'));
} else {
$compiler->raw(sprintf('%s::contextWithoutTemplate($context)', Template::class));
}

$compiler
->raw(sprintf(", '%s', %s);\n", $this->getTemplateName(), $this->getTemplateLine()));
}
}
49 changes: 49 additions & 0 deletions src/web/twig/tokenparsers/DumpTokenParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/**
* @link https://craftcms.com/
* @copyright Copyright (c) Pixel & Tonic, Inc.
* @license https://craftcms.github.io/license/
*/

namespace craft\web\twig\tokenparsers;

use craft\web\twig\nodes\DumpNode;
use Twig\Token;
use Twig\TokenParser\AbstractTokenParser;

/**
* Class DumpTokenParser
*
* @author Pixel & Tonic, Inc. <[email protected]>
* @since 4.4.0
*/
class DumpTokenParser extends AbstractTokenParser
{
/**
* @inheritdoc
*/
public function parse(Token $token): DumpNode
{
$lineno = $token->getLine();
$parser = $this->parser;
$stream = $parser->getStream();

$nodes = [];

if (!$stream->test(Token::BLOCK_END_TYPE)) {
$nodes['var'] = $parser->getExpressionParser()->parseExpression();
}

$stream->expect(Token::BLOCK_END_TYPE);

return new DumpNode($nodes, [], $lineno, $this->getTag());
}

/**
* @inheritdoc
*/
public function getTag(): string
{
return 'dump';
}
}