Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
WidgetRegistry
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
4 / 4
9
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 addRenderer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRenderer
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 renderWidget
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Grid\Widget;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Core\Engine\Domain\Model\PermissionContext;
12use App\Core\Engine\Domain\Model\RelationGridMetadata;
13use App\Core\Engine\Domain\Model\WidgetMetadata;
14use Psr\Http\Message\ServerRequestInterface;
15
16/**
17 * Widget Registry.
18 *
19 * Central registry holding all registered WidgetRendererInterface implementations
20 * and dispatching render calls for Gridstack tiles.
21 *
22 * @package App\Core\Grid\Widget
23 */
24final class WidgetRegistry
25{
26    /**
27     * @var array<int, WidgetRendererInterface>
28     */
29    private array $renderers = [];
30
31    /**
32     * WidgetRegistry constructor.
33     *
34     * @param array<int, WidgetRendererInterface> $renderers Initial renderers.
35     */
36    public function __construct(array $renderers = [])
37    {
38        foreach ($renderers as $renderer) {
39            $this->addRenderer($renderer);
40        }
41    }
42
43    /**
44     * Registers a widget renderer.
45     *
46     * @param WidgetRendererInterface $renderer Renderer instance.
47     */
48    public function addRenderer(WidgetRendererInterface $renderer): void
49    {
50        $this->renderers[] = $renderer;
51    }
52
53    /**
54     * Finds a supporting renderer for the given widget metadata.
55     *
56     * @param WidgetMetadata $widget Widget metadata.
57     * @return WidgetRendererInterface|null Supporting renderer or null.
58     */
59    public function getRenderer(WidgetMetadata $widget): ?WidgetRendererInterface
60    {
61        foreach ($this->renderers as $renderer) {
62            if ($renderer->supports($widget)) {
63                return $renderer;
64            }
65        }
66
67        return null;
68    }
69
70    /**
71     * Renders a widget tile HTML.
72     *
73     * @param RelationGridMetadata   $relation Relation placement configuration.
74     * @param ServerRequestInterface $request  Server request.
75     * @param PermissionContext      $context  Security context.
76     * @return string Rendered HTML.
77     */
78    public function renderWidget(
79        RelationGridMetadata   $relation,
80        ServerRequestInterface $request,
81        PermissionContext      $context
82    ): string {
83        $widget = $relation->widget;
84        if ($widget === null) {
85            return '<div class="alert alert-warning m-3">Widget definition not found.</div>';
86        }
87
88        $renderer = $this->getRenderer($widget);
89        if ($renderer === null) {
90            return '<div class="alert alert-info m-3">No renderer registered for widget: '
91                . htmlspecialchars($widget->label, ENT_QUOTES, 'UTF-8') . '</div>';
92        }
93
94        return $renderer->render($relation, $request, $context);
95    }
96}