xref: /plugin/combo/ComboStrap/IdManager.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1*04fd306cSNickeau<?php
2*04fd306cSNickeau
3*04fd306cSNickeaunamespace ComboStrap;
4*04fd306cSNickeau
5*04fd306cSNickeau/**
6*04fd306cSNickeau * A manager to return an unique id for a node
7*04fd306cSNickeau *
8*04fd306cSNickeau * Example: if you create multiple {@link PageExplorerTag}
9*04fd306cSNickeau * you may have several tag for the same page/namespace
10*04fd306cSNickeau * but the node id should be unique as it's used for the collapsing
11*04fd306cSNickeau */
12*04fd306cSNickeauclass IdManager
13*04fd306cSNickeau{
14*04fd306cSNickeau
15*04fd306cSNickeau
16*04fd306cSNickeau    const CANONICAL = "id-manager";
17*04fd306cSNickeau
18*04fd306cSNickeau    /**
19*04fd306cSNickeau     * @var array
20*04fd306cSNickeau     */
21*04fd306cSNickeau    private array $lastIdByScope = [];
22*04fd306cSNickeau    private ExecutionContext $executionContext;
23*04fd306cSNickeau
24*04fd306cSNickeau    /**
25*04fd306cSNickeau     * @param ExecutionContext $executionContext
26*04fd306cSNickeau     */
27*04fd306cSNickeau    public function __construct(ExecutionContext $executionContext)
28*04fd306cSNickeau    {
29*04fd306cSNickeau        $this->executionContext = $executionContext;
30*04fd306cSNickeau    }
31*04fd306cSNickeau
32*04fd306cSNickeau    /**
33*04fd306cSNickeau     * @return IdManager
34*04fd306cSNickeau     * @deprecated use {@link ExecutionContext::getIdManager()} instead
35*04fd306cSNickeau     * via {@link ExecutionContext::getExecutingMarkupHandler()}
36*04fd306cSNickeau     */
37*04fd306cSNickeau    static function getOrCreate(): IdManager
38*04fd306cSNickeau    {
39*04fd306cSNickeau
40*04fd306cSNickeau        return ExecutionContext::getActualOrCreateFromEnv()->getIdManager();
41*04fd306cSNickeau
42*04fd306cSNickeau
43*04fd306cSNickeau    }
44*04fd306cSNickeau
45*04fd306cSNickeau
46*04fd306cSNickeau    public function generateNewHtmlIdForComponent(string $componentId, Path $executingPath = null): string
47*04fd306cSNickeau    {
48*04fd306cSNickeau
49*04fd306cSNickeau        if ($executingPath === null) {
50*04fd306cSNickeau
51*04fd306cSNickeau            try {
52*04fd306cSNickeau                $executingPath = $this->executionContext
53*04fd306cSNickeau                    ->getExecutingMarkupHandler()
54*04fd306cSNickeau                    ->getExecutingPathOrNull();
55*04fd306cSNickeau            } catch (ExceptionNotFound $e) {
56*04fd306cSNickeau                // ok, dynamic, markup string run ?
57*04fd306cSNickeau            }
58*04fd306cSNickeau
59*04fd306cSNickeau        }
60*04fd306cSNickeau
61*04fd306cSNickeau        $idScope = $componentId;
62*04fd306cSNickeau        if ($executingPath !== null) {
63*04fd306cSNickeau            try {
64*04fd306cSNickeau                $slotName = $executingPath->getLastNameWithoutExtension();
65*04fd306cSNickeau                $idScope = "$idScope-$slotName";
66*04fd306cSNickeau            } catch (ExceptionNotFound $e) {
67*04fd306cSNickeau                // no name (ie root)
68*04fd306cSNickeau            }
69*04fd306cSNickeau        }
70*04fd306cSNickeau        $lastId = self::generateAndGetNewSequenceValueForScope($idScope);
71*04fd306cSNickeau
72*04fd306cSNickeau        return Html::toHtmlId("$idScope-$lastId");
73*04fd306cSNickeau    }
74*04fd306cSNickeau
75*04fd306cSNickeau    private function generateAndGetNewSequenceValueForScope(string $scope)
76*04fd306cSNickeau    {
77*04fd306cSNickeau
78*04fd306cSNickeau        $lastId = $this->lastIdByScope[$scope];
79*04fd306cSNickeau        if ($lastId === null) {
80*04fd306cSNickeau            $lastId = 1;
81*04fd306cSNickeau        } else {
82*04fd306cSNickeau            $lastId = $lastId + 1;
83*04fd306cSNickeau        }
84*04fd306cSNickeau        $this->lastIdByScope[$scope] = $lastId;
85*04fd306cSNickeau        return $lastId;
86*04fd306cSNickeau
87*04fd306cSNickeau    }
88*04fd306cSNickeau
89*04fd306cSNickeau}
90