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

tempestphp / tempest-framework / 14322727335

07 Apr 2025 03:10PM UTC coverage: 81.259% (+0.4%) from 80.906%
14322727335

push

github

web-flow
fix(support): non-dev bun dependencies installation (#1124)

0 of 12 new or added lines in 1 file covered. (0.0%)

25 existing lines in 6 files now uncovered.

11434 of 14071 relevant lines covered (81.26%)

105.02 hits per line

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

89.66
/src/Tempest/View/src/Renderers/TempestViewRenderer.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Tempest\View\Renderers;
6

7
use Stringable;
8
use Tempest\Container\Container;
9
use Tempest\Support\Html\HtmlString;
10
use Tempest\View\Exceptions\ViewCompilationError;
11
use Tempest\View\Exceptions\ViewVariableIsReserved;
12
use Tempest\View\GenericView;
13
use Tempest\View\Parser\TempestViewCompiler;
14
use Tempest\View\View;
15
use Tempest\View\ViewCache;
16
use Tempest\View\ViewConfig;
17
use Tempest\View\ViewRenderer;
18
use Throwable;
19

20
use function Tempest\Support\arr;
21
use function Tempest\Support\str;
22

23
final class TempestViewRenderer implements ViewRenderer
24
{
25
    private ?View $currentView = null;
26

27
    public function __construct(
127✔
28
        private readonly TempestViewCompiler $compiler,
29
        private readonly ViewCache $viewCache,
30
        private readonly ViewConfig $viewConfig,
31
        private readonly Container $container,
32
    ) {}
127✔
33

34
    public function __get(string $name): mixed
14✔
35
    {
36
        return $this->currentView?->get($name);
14✔
37
    }
38

39
    public function __call(string $name, array $arguments): mixed
3✔
40
    {
41
        return $this->currentView?->{$name}(...$arguments);
3✔
42
    }
43

44
    public function render(string|View $view): string
122✔
45
    {
46
        $view = is_string($view) ? new GenericView($view) : $view;
122✔
47

48
        $this->validateView($view);
122✔
49

50
        $path = $this->viewCache->getCachedViewPath(
121✔
51
            path: $view->path,
121✔
52
            compiledView: fn () => $this->cleanupCompiled($this->compiler->compile($view)),
121✔
53
        );
121✔
54

55
        $view = $this->processView($view);
115✔
56

57
        return $this->renderCompiled($view, $path);
115✔
58
    }
59

60
    private function cleanupCompiled(string $compiled): string
115✔
61
    {
62
        // Remove strict type declarations
63
        $compiled = str($compiled)->replace('declare(strict_types=1);', '');
115✔
64

65
        // Cleanup and bundle imports
66
        $imports = arr();
115✔
67

68
        $compiled = $compiled->replaceRegex("/^\s*use (function )?.*;/m", function (array $matches) use (&$imports) {
115✔
69
            $imports[$matches[0]] = $matches[0];
8✔
70

71
            return '';
8✔
72
        });
115✔
73

74
        $compiled = $compiled->prepend(
115✔
75
            sprintf(
115✔
76
                '<?php
115✔
77
%s
78
?>',
115✔
79
                $imports->implode(PHP_EOL),
115✔
80
            ),
115✔
81
        );
115✔
82

83
        // Remove empty PHP blocks
84
        $compiled = $compiled->replaceRegex('/<\?php\s*\?>/', '');
115✔
85

86
        return $compiled->toString();
115✔
87
    }
88

89
    private function processView(View $view): View
115✔
90
    {
91
        foreach ($this->viewConfig->viewProcessors as $viewProcessorClass) {
115✔
92
            /** @var \Tempest\View\ViewProcessor $viewProcessor */
93
            $viewProcessor = $this->container->get($viewProcessorClass);
115✔
94

95
            $view = $viewProcessor->process($view);
115✔
96
        }
97

98
        return $view;
115✔
99
    }
100

101
    private function renderCompiled(View $_view, string $_path): string
115✔
102
    {
103
        $this->currentView = $_view;
115✔
104

105
        ob_start();
115✔
106

107
        // Extract data from view into local variables so that they can be accessed directly
108
        $_data = $_view->data;
115✔
109

110
        extract($_data, flags: EXTR_SKIP);
115✔
111

112
        try {
113
            include $_path;
115✔
114
        } catch (Throwable $throwable) {
×
115
            throw new ViewCompilationError(
×
116
                path: $_path,
×
117
                content: file_get_contents($_path),
×
118
                previous: $throwable,
×
UNCOV
119
            );
×
120
        }
121

122
        $this->currentView = null;
115✔
123

124
        return trim(ob_get_clean());
115✔
125
    }
126

127
    public function escape(null|string|HtmlString|Stringable $value): string
30✔
128
    {
129
        if ($value instanceof HtmlString) {
30✔
130
            return (string) $value;
1✔
131
        }
132

133
        return htmlentities((string) $value);
30✔
134
    }
135

136
    private function validateView(View $view): void
122✔
137
    {
138
        $data = $view->data;
122✔
139

140
        if (array_key_exists('slots', $data)) {
122✔
141
            throw new ViewVariableIsReserved('slots');
1✔
142
        }
143
    }
144
}
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