• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CPS-IT / handlebars / 16768687229

06 Aug 2025 05:50AM UTC coverage: 91.407%. Remained the same
16768687229

push

github

web-flow
Merge pull request #454 from CPS-IT/renovate/major-github-artifact-actions

851 of 931 relevant lines covered (91.41%)

5.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.73
/Classes/Renderer/Template/Path/ContentObjectPathProvider.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the TYPO3 CMS extension "handlebars".
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17

18
namespace Fr\Typo3Handlebars\Renderer\Template\Path;
19

20
use TYPO3\CMS\Core;
21

22
/**
23
 * ContentObjectPathProvider
24
 *
25
 * @author Elias Häußler <e.haeussler@familie-redlich.de>
26
 * @license GPL-2.0-or-later
27
 *
28
 * @phpstan-type RootPathStackItem array{
29
 *     current: array<int, string>,
30
 *     merged: array<int, string>|null,
31
 * }
32
 */
33
final class ContentObjectPathProvider implements PathProvider, Core\SingletonInterface
34
{
35
    /**
36
     * @var list<array{
37
     *     partialRootPaths: RootPathStackItem,
38
     *     templateRootPaths: RootPathStackItem,
39
     * }>
40
     */
41
    private array $stack = [];
42

43
    private ?int $currentItem = null;
44

45
    /**
46
     * @param array<string, mixed> $configuration
47
     */
48
    public function push(array $configuration): void
4✔
49
    {
50
        $partialRootPaths = [];
4✔
51
        $templateRootPaths = [];
4✔
52

53
        if (is_array($configuration['templateRootPaths'] ?? null)) {
4✔
54
            $templateRootPaths = $configuration['templateRootPaths'];
4✔
55
        }
56
        if (is_array($configuration['partialRootPaths'] ?? null)) {
4✔
57
            $partialRootPaths = $configuration['partialRootPaths'];
4✔
58
        }
59

60
        // A single root path receives highest priority
61
        if (is_string($configuration['templateRootPath'] ?? null)) {
4✔
62
            $templateRootPaths[PHP_INT_MAX] = $configuration['templateRootPath'];
4✔
63
        }
64
        if (is_string($configuration['partialRootPath'] ?? null)) {
4✔
65
            $partialRootPaths[PHP_INT_MAX] = $configuration['partialRootPath'];
4✔
66
        }
67

68
        \ksort($templateRootPaths);
4✔
69
        \ksort($partialRootPaths);
4✔
70

71
        $this->stack[] = [
4✔
72
            'partialRootPaths' => [
4✔
73
                'current' => $partialRootPaths,
4✔
74
                'merged' => null,
4✔
75
            ],
4✔
76
            'templateRootPaths' => [
4✔
77
                'current' => $templateRootPaths,
4✔
78
                'merged' => null,
4✔
79
            ],
4✔
80
        ];
4✔
81

82
        if ($this->currentItem === null) {
4✔
83
            $this->currentItem = 0;
4✔
84
        } else {
85
            $this->currentItem++;
3✔
86
        }
87
    }
88

89
    public function pop(): void
2✔
90
    {
91
        if ($this->stack === []) {
2✔
92
            return;
1✔
93
        }
94

95
        array_pop($this->stack);
1✔
96

97
        if ($this->stack === []) {
1✔
98
            $this->currentItem = null;
1✔
99
        } else {
100
            $this->currentItem--;
1✔
101
        }
102
    }
103

104
    public function isEmpty(): bool
3✔
105
    {
106
        return $this->currentItem === null;
3✔
107
    }
108

109
    public function getPartialRootPaths(): array
3✔
110
    {
111
        return $this->getMergedRootPathsFromStack('partialRootPaths');
3✔
112
    }
113

114
    public function getTemplateRootPaths(): array
3✔
115
    {
116
        return $this->getMergedRootPathsFromStack('templateRootPaths');
3✔
117
    }
118

119
    public function isCacheable(): bool
×
120
    {
121
        // Caching is done internally, based on the current stack
122
        return false;
×
123
    }
124

125
    /**
126
     * @param 'partialRootPaths'|'templateRootPaths' $type
127
     * @return array<int, string>
128
     */
129
    private function getMergedRootPathsFromStack(string $type): array
5✔
130
    {
131
        if ($this->currentItem === null) {
5✔
132
            return [];
2✔
133
        }
134

135
        // Merge and cache root paths
136
        if ($this->stack[$this->currentItem][$type]['merged'] === null) {
3✔
137
            $this->stack[$this->currentItem][$type]['merged'] = $this->stack[0][$type]['current'];
3✔
138

139
            for ($i = 1; $i <= $this->currentItem; $i++) {
3✔
140
                Core\Utility\ArrayUtility::mergeRecursiveWithOverrule(
2✔
141
                    $this->stack[$this->currentItem][$type]['merged'],
2✔
142
                    $this->stack[$i][$type]['current'],
2✔
143
                );
2✔
144
            }
145

146
            \ksort($this->stack[$this->currentItem][$type]['merged']);
3✔
147
        }
148

149
        return $this->stack[$this->currentItem][$type]['merged'];
3✔
150
    }
151

152
    public static function getPriority(): int
×
153
    {
154
        return 100;
×
155
    }
156
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc