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

tempestphp / tempest-framework / 11924655642

19 Nov 2024 12:37PM UTC coverage: 81.705% (-0.2%) from 81.946%
11924655642

push

github

web-flow
chore(core): framework installer improvements (#752)

1 of 17 new or added lines in 2 files covered. (5.88%)

56 existing lines in 5 files now uncovered.

7869 of 9631 relevant lines covered (81.7%)

51.76 hits per line

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

60.23
/src/Tempest/Core/src/Kernel.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Tempest\Core;
6

7
use Dotenv\Dotenv;
8
use Tempest\Console\Exceptions\ConsoleErrorHandler;
9
use Tempest\Container\Container;
10
use Tempest\Container\GenericContainer;
11
use Tempest\Core\Kernel\FinishDeferredTasks;
12
use Tempest\Core\Kernel\LoadConfig;
13
use Tempest\Core\Kernel\LoadDiscoveryClasses;
14
use Tempest\Core\Kernel\LoadDiscoveryLocations;
15
use Tempest\EventBus\EventBus;
16
use Tempest\Http\Exceptions\HttpProductionErrorHandler;
17
use Whoops\Handler\PrettyPageHandler;
18
use Whoops\Run;
19

20
final class Kernel
21
{
22
    public readonly Container $container;
23

24
    public bool $discoveryCache;
25

26
    public array $discoveryClasses = [
27
        DiscoveryDiscovery::class,
28
    ];
29

30
    public function __construct(
381✔
31
        public string $root,
32
        /** @var \Tempest\Core\DiscoveryLocation[] $discoveryLocations */
33
        public array $discoveryLocations = [],
34
        ?Container $container = null,
35
    ) {
36
        $this->container = $container ?? $this->createContainer();
381✔
37

38
        $this
381✔
39
            ->loadEnv()
381✔
40
            ->registerKernelErrorHandler()
381✔
41
            ->registerShutdownFunction()
381✔
42
            ->registerKernel()
381✔
43
            ->loadComposer()
381✔
44
            ->loadDiscoveryLocations()
381✔
45
            ->loadConfig()
381✔
46
            ->loadDiscovery()
381✔
47
            ->registerErrorHandler()
381✔
48
            ->event(KernelEvent::BOOTED);
381✔
49
    }
50

UNCOV
51
    public static function boot(string $root, ?Container $container = null): self
×
52
    {
UNCOV
53
        return new self(
×
54
            root: $root,
×
55
            container: $container,
×
56
        );
×
57
    }
58

UNCOV
59
    public function shutdown(int|string $status = ''): never
×
60
    {
UNCOV
61
        $this
×
62
            ->finishDeferredTasks()
×
63
            ->event(KernelEvent::SHUTDOWN);
×
64

UNCOV
65
        exit($status);
×
66
    }
67

68
    private function createContainer(): Container
381✔
69
    {
70
        $container = new GenericContainer();
381✔
71

72
        GenericContainer::setInstance($container);
381✔
73

74
        $container->singleton(Container::class, fn () => $container);
381✔
75

76
        return $container;
381✔
77
    }
78

79
    private function loadComposer(): self
381✔
80
    {
81
        $this->container->singleton(Composer::class, new Composer($this->root));
381✔
82

83
        return $this;
381✔
84
    }
85

86
    private function loadEnv(): self
381✔
87
    {
88
        $dotenv = Dotenv::createUnsafeImmutable($this->root);
381✔
89
        $dotenv->safeLoad();
381✔
90

91
        return $this;
381✔
92
    }
93

94
    private function registerKernel(): self
381✔
95
    {
96
        $this->container->singleton(self::class, $this);
381✔
97

98
        return $this;
381✔
99
    }
100

101
    private function registerShutdownFunction(): self
381✔
102
    {
103
        // Fix for classes that don't have a proper PSR-4 namespace,
104
        // they break discovery with an unrecoverable error,
105
        // but you don't know why because PHP simply says "duplicate classname" instead of something reasonable.
106
        register_shutdown_function(function (): void {
381✔
UNCOV
107
            $error = error_get_last();
×
108

UNCOV
109
            $message = $error['message'] ?? '';
×
110

UNCOV
111
            if (str_contains($message, 'Cannot declare class')) {
×
112
                echo "Does this class have the right namespace?" . PHP_EOL;
×
113
            }
114
        });
381✔
115

116
        return $this;
381✔
117
    }
118

119
    private function loadDiscoveryLocations(): self
381✔
120
    {
121
        ($this->container->get(LoadDiscoveryLocations::class))();
381✔
122

123
        return $this;
381✔
124
    }
125

126
    private function loadDiscovery(): self
381✔
127
    {
128
        ($this->container->get(LoadDiscoveryClasses::class))();
381✔
129

130
        return $this;
381✔
131
    }
132

133
    private function loadConfig(): self
381✔
134
    {
135
        $this->container->get(LoadConfig::class)();
381✔
136

137
        return $this;
381✔
138
    }
139

140
    private function registerErrorHandler(): self
381✔
141
    {
142
        $appConfig = $this->container->get(AppConfig::class);
381✔
143

144
        if ($appConfig->environment->isTesting()) {
381✔
145
            return $this;
381✔
146
        }
147

UNCOV
148
        if (PHP_SAPI === 'cli') {
×
149
            $handler = $this->container->get(ConsoleErrorHandler::class);
×
150
            set_exception_handler($handler->handleException(...));
×
151
            set_error_handler($handler->handleError(...)); // @phpstan-ignore-line
×
152
        } elseif ($appConfig->environment->isProduction()) {
×
153
            $handler = $this->container->get(HttpProductionErrorHandler::class);
×
154
            set_exception_handler($handler->handleException(...));
×
155
            set_error_handler($handler->handleError(...)); // @phpstan-ignore-line
×
156
        }
157

UNCOV
158
        return $this;
×
159
    }
160

UNCOV
161
    private function finishDeferredTasks(): self
×
162
    {
UNCOV
163
        ($this->container->get(FinishDeferredTasks::class))();
×
164

UNCOV
165
        return $this;
×
166
    }
167

168
    private function event(object $event): self
381✔
169
    {
170
        if (interface_exists(EventBus::class)) {
381✔
171
            $this->container->get(EventBus::class)->dispatch($event);
381✔
172
        }
173

174
        return $this;
381✔
175
    }
176

177
    private function registerKernelErrorHandler(): self
381✔
178
    {
179
        $environment = Environment::fromEnv();
381✔
180

181
        if ($environment->isTesting()) {
381✔
182
            return $this;
381✔
183
        }
184

UNCOV
185
        if ($environment->isProduction()) {
×
186
            $handler = new HttpProductionErrorHandler();
×
187
            set_exception_handler($handler->handleException(...));
×
188
            set_error_handler($handler->handleError(...)); // @phpstan-ignore-line
×
189
        } elseif (PHP_SAPI !== 'cli') {
×
UNCOV
190
            $whoops = new Run();
×
191
            $whoops->pushHandler(new PrettyPageHandler());
×
192
            $whoops->register();
×
193
        }
194

UNCOV
195
        return $this;
×
196
    }
197
}
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