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

tempestphp / tempest-framework / 11714560237

06 Nov 2024 06:46PM UTC coverage: 82.608% (+0.003%) from 82.605%
11714560237

push

github

web-flow
feat(container): support injecting properties using `#[Inject]` (#690)

6 of 6 new or added lines in 2 files covered. (100.0%)

95 existing lines in 9 files now uncovered.

7210 of 8728 relevant lines covered (82.61%)

49.34 hits per line

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

60.92
/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 function Tempest\env;
16
use Tempest\EventBus\EventBus;
17
use Tempest\Http\Exceptions\HttpProductionErrorHandler;
18
use Whoops\Handler\PrettyPageHandler;
19
use Whoops\Run;
20

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

25
    public bool $discoveryCache;
26

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

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

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

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

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

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

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

73
        GenericContainer::setInstance($container);
340✔
74

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

77
        return $container;
340✔
78
    }
79

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

84
        return $this;
340✔
85
    }
86

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

92
        return $this;
340✔
93
    }
94

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

99
        return $this;
340✔
100
    }
101

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

110
            $message = $error['message'] ?? '';
×
111

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

117
        return $this;
340✔
118
    }
119

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

124
        return $this;
340✔
125
    }
126

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

131
        return $this;
340✔
132
    }
133

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

138
        return $this;
340✔
139
    }
140

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

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

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

UNCOV
159
        return $this;
×
160
    }
161

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

UNCOV
166
        return $this;
×
167
    }
168

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

175
        return $this;
340✔
176
    }
177

178
    private function registerKernelErrorHandler(): self
340✔
179
    {
180
        $environment = Environment::tryFrom(env('ENVIRONMENT', 'production'));
340✔
181

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

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

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