From df292cbf7d0b0d8185bffcf6cff090b9d3b79d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Tue, 1 Aug 2023 14:56:42 +0200 Subject: [PATCH] [Workflow] Add a profiler --- .../FrameworkExtension.php | 5 ++ .../Resources/config/workflow_debug.php | 27 ++++++++ .../views/Collector/workflow.html.twig | 62 +++++++++++++++++++ .../Resources/views/Icon/workflow.svg | 1 + src/Symfony/Component/Workflow/CHANGELOG.md | 1 + .../DataCollector/WorkflowDataCollector.php | 60 ++++++++++++++++++ 6 files changed, 156 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow_debug.php create mode 100644 src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/workflow.html.twig create mode 100644 src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/workflow.svg create mode 100644 src/Symfony/Component/Workflow/DataCollector/WorkflowDataCollector.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index b1ae9e6d31aef..2610d4311f74f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -280,6 +280,7 @@ public function load(array $configs, ContainerBuilder $container) $this->readConfigEnabled('translator', $container, $config['translator']); $this->readConfigEnabled('property_access', $container, $config['property_access']); $this->readConfigEnabled('profiler', $container, $config['profiler']); + $this->readConfigEnabled('workflows', $container, $config['workflows']); // A translator must always be registered (as support is included by // default in the Form and Validator component). If disabled, an identity @@ -876,6 +877,10 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ $loader->load('mailer_debug.php'); } + if ($this->isInitializedConfigEnabled('workflows')) { + $loader->load('workflow_debug.php'); + } + if ($this->isInitializedConfigEnabled('http_client')) { $loader->load('http_client_debug.php'); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow_debug.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow_debug.php new file mode 100644 index 0000000000000..c37373e0f605a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow_debug.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\Workflow\DataCollector\WorkflowDataCollector; + +return static function (ContainerConfigurator $container) { + $container->services() + ->set('data_collector.workflow', WorkflowDataCollector::class) + ->tag('data_collector', [ + 'template' => '@WebProfiler/Collector/workflow.html.twig', + 'id' => 'workflow', + ]) + ->args([ + tagged_iterator('workflow', 'name'), + ]) + ; +}; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/workflow.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/workflow.html.twig new file mode 100644 index 0000000000000..5fba10fbb48ac --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/workflow.html.twig @@ -0,0 +1,62 @@ +{% extends '@WebProfiler/Profiler/layout.html.twig' %} + +{% block menu %} + + + {{ source('@WebProfiler/Icon/workflow.svg') }} + + Workflow + +{% endblock %} + +{% block panel %} +

Workflow

+ + {% if collector.workflows|length == 0 %} +
+

There are no workflows configured.

+
+ {% else %} + + +

Definitions

+
+ {% for name, data in collector.workflows %} +
+

{{ name }}

+
+
+                            {{ data.dump|raw }}
+                        
+
+
+ {% endfor %} +
+ {% endif %} +{% endblock %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/workflow.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/workflow.svg new file mode 100644 index 0000000000000..c6b9886f94f34 --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/workflow.svg @@ -0,0 +1 @@ + diff --git a/src/Symfony/Component/Workflow/CHANGELOG.md b/src/Symfony/Component/Workflow/CHANGELOG.md index 1fc1373198bbd..e1656d6118e78 100644 --- a/src/Symfony/Component/Workflow/CHANGELOG.md +++ b/src/Symfony/Component/Workflow/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * Add `with-metadata` option to the `workflow:dump` command to include places, transitions and workflow's metadata into dumped graph * Add support for storing marking in a property + * Add a profiler 6.2 --- diff --git a/src/Symfony/Component/Workflow/DataCollector/WorkflowDataCollector.php b/src/Symfony/Component/Workflow/DataCollector/WorkflowDataCollector.php new file mode 100644 index 0000000000000..a708b268289a3 --- /dev/null +++ b/src/Symfony/Component/Workflow/DataCollector/WorkflowDataCollector.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Workflow\DataCollector; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\DataCollector; +use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; +use Symfony\Component\Workflow\Dumper\MermaidDumper; +use Symfony\Component\Workflow\StateMachine; + +/** + * @author Grégoire Pineau + */ +final class WorkflowDataCollector extends DataCollector implements LateDataCollectorInterface +{ + public function __construct( + private readonly iterable $workflows, + ) { + } + + public function collect(Request $request, Response $response, \Throwable $exception = null): void + { + } + + public function lateCollect(): void + { + foreach ($this->workflows as $workflow) { + $type = $workflow instanceof StateMachine ? MermaidDumper::TRANSITION_TYPE_STATEMACHINE : MermaidDumper::TRANSITION_TYPE_WORKFLOW; + $dumper = new MermaidDumper($type); + $this->data['workflows'][$workflow->getName()] = [ + 'dump' => $dumper->dump($workflow->getDefinition()), + ]; + } + } + + public function getName(): string + { + return 'workflow'; + } + + public function reset(): void + { + $this->data = []; + } + + public function getWorkflows(): array + { + return $this->data['workflows'] ?? []; + } +}