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

tempestphp / tempest-framework / 14147890216

29 Mar 2025 05:29PM UTC coverage: 80.606% (-0.1%) from 80.716%
14147890216

Pull #1100

github

web-flow
Merge fa6d0f1d5 into 0d9328363
Pull Request #1100: refactor(router): improve static page generation console command output

27 of 55 new or added lines in 8 files covered. (49.09%)

6 existing lines in 3 files now uncovered.

10960 of 13597 relevant lines covered (80.61%)

100.01 hits per line

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

61.76
/src/Tempest/Router/src/Static/StaticGenerateCommand.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Tempest\Router\Static;
6

7
use Tempest\Console\Console;
8
use Tempest\Console\ConsoleArgument;
9
use Tempest\Console\ConsoleCommand;
10
use Tempest\Console\ExitCode;
11
use Tempest\Console\HasConsole;
12
use Tempest\Container\Container;
13
use Tempest\Core\Kernel;
14
use Tempest\EventBus\EventBus;
15
use Tempest\Http\Method;
16
use Tempest\Http\Status;
17
use Tempest\Router\DataProvider;
18
use Tempest\Router\GenericRequest;
19
use Tempest\Router\Router;
20
use Tempest\Router\Static\Exceptions\InvalidStatusCodeException;
21
use Tempest\Router\Static\Exceptions\NoTextualBodyException;
22
use Tempest\View\Exceptions\ViewCompilationError;
23
use Tempest\View\View;
24
use Tempest\View\ViewRenderer;
25
use Tempest\Vite\Exceptions\ManifestNotFoundException;
26
use Throwable;
27

28
use function Tempest\Support\path;
29
use function Tempest\uri;
30

31
final readonly class StaticGenerateCommand
32
{
33
    use HasConsole;
34

35
    public function __construct(
2✔
36
        private Console $console,
37
        private Kernel $kernel,
38
        private Container $container,
39
        private StaticPageConfig $staticPageConfig,
40
        private Router $router,
41
        private ViewRenderer $viewRenderer,
42
        private EventBus $eventBus,
43
    ) {}
2✔
44

45
    #[ConsoleCommand(name: 'static:generate', description: 'Compiles static pages')]
2✔
46
    public function __invoke(
47
        ?string $filter = null,
48
        #[ConsoleArgument(aliases: ['v'])]
49
        bool $verbose = false,
50
    ): ExitCode {
51
        $publicPath = path($this->kernel->root, 'public');
2✔
52

53
        $generated = 0;
2✔
54
        $failures = 0;
2✔
55

56
        $this->console->header('Generating static pages');
2✔
57

58
        $this->eventBus->listen(StaticPageGenerated::class, function (StaticPageGenerated $event) use (&$generated): void {
2✔
59
            $generated++;
2✔
60
            $this->keyValue("<style='fg-gray'>{$event->uri}</style>", "<style='fg-green'>{$event->path}</style>");
2✔
61
        });
2✔
62

63
        $this->eventBus->listen(StaticPageGenerationFailed::class, function (StaticPageGenerationFailed $event) use (&$failures, $verbose): void {
2✔
NEW
64
            $failures++;
×
65

66
            match (true) {
NEW
67
                $event->exception instanceof InvalidStatusCodeException => $this->keyValue(
×
NEW
68
                    "<style='fg-gray'>{$event->path}</style>",
×
NEW
69
                    "<style='fg-red'>HTTP {$event->exception->status->value}</style>",
×
NEW
70
                ),
×
NEW
71
                $event->exception instanceof NoTextualBodyException => $this->keyValue(
×
NEW
72
                    "<style='fg-gray'>{$event->path}</style>",
×
NEW
73
                    "<style='fg-red'>NO CONTENT</style>",
×
NEW
74
                ),
×
NEW
75
                $verbose === true => $this->error("Failed to generate static page: {$event->exception->getMessage()}"),
×
NEW
76
                default => $this->keyValue("<style='fg-gray'>{$event->path}</style>", "<style='fg-red'>FAILED</style>"),
×
77
            };
78
        });
2✔
79

80
        foreach ($this->staticPageConfig->staticPages as $staticPage) {
2✔
81
            /** @var DataProvider $dataProvider */
82
            $dataProvider = $this->container->get($staticPage->dataProviderClass ?? GenericDataProvider::class);
2✔
83

84
            foreach ($dataProvider->provide() as $params) {
2✔
85
                if (! is_array($params)) {
2✔
86
                    $params = [$params];
×
87
                }
88

89
                $uri = parse_url(uri($staticPage->handler, ...$params), PHP_URL_PATH);
2✔
90

91
                $fileName = $uri === '/'
2✔
92
                    ? 'index.html'
×
93
                    : ($uri . '/index.html');
2✔
94

95
                if ($filter !== null && $uri !== $filter) {
2✔
96
                    continue;
×
97
                }
98

99
                $file = path($publicPath, $fileName);
2✔
100

101
                try {
102
                    $response = $this->router->dispatch(
2✔
103
                        new GenericRequest(
2✔
104
                            method: Method::GET,
2✔
105
                            uri: $uri,
2✔
106
                        ),
2✔
107
                    );
2✔
108

109
                    if ($response->status !== Status::OK) {
2✔
NEW
110
                        throw new InvalidStatusCodeException($uri, $response->status);
×
111
                    }
112

113
                    $body = $response->body;
2✔
114

115
                    $content = ($body instanceof View)
2✔
116
                        ? $this->viewRenderer->render($body)
2✔
117
                        : $body;
×
118

119
                    if (! is_string($content)) {
2✔
NEW
120
                        throw new NoTextualBodyException($uri);
×
121
                    }
122

123
                    $directory = $file->dirname();
2✔
124

125
                    if (! $directory->isDirectory()) {
2✔
126
                        mkdir($directory->toString(), recursive: true);
2✔
127
                    }
128

129
                    file_put_contents($file->toString(), $content);
2✔
130

131
                    $this->eventBus->dispatch(new StaticPageGenerated($uri, $file->toString(), $content));
2✔
NEW
132
                } catch (Throwable $exception) {
×
UNCOV
133
                    ob_get_clean();
×
134

NEW
135
                    if ($exception instanceof ViewCompilationError && $exception->getPrevious() instanceof ManifestNotFoundException) {
×
NEW
136
                        $this->error('Run <code>vite build</code> first.');
×
NEW
137
                        return ExitCode::ERROR;
×
138
                    }
139

NEW
140
                    $this->eventBus->dispatch(new StaticPageGenerationFailed($uri, $exception));
×
141

UNCOV
142
                    continue;
×
143
                }
144
            }
145
        }
146

147
        if ($failures) {
2✔
NEW
148
            $this->keyValue('Failures', "<style='fg-red'>{$failures}</style>");
×
149
        }
150

151
        $this->keyValue('Static pages generated', "<style='fg-green'>{$generated}</style>");
2✔
152

153
        return $failures > 0
2✔
NEW
154
            ? ExitCode::ERROR
×
155
            : ExitCode::SUCCESS;
2✔
156
    }
157
}
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