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