Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
43 / 43
96.67% covered (success)
96.67%
29 / 30
86.96% covered (warning)
86.96%
20 / 23
94.12% covered (success)
94.12%
16 / 17
CRAP
0.00% covered (danger)
0.00%
0 / 1
App
100.00% covered (success)
100.00%
43 / 43
96.67% covered (success)
96.67%
29 / 30
86.96% covered (warning)
86.96%
20 / 23
100.00% covered (success)
100.00%
17 / 17
23.07
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 load
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 create
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 router
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 factory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addRoute
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 group
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 staticRoute
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMiddleware
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 errorHandler
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
3 / 3
50.00% covered (danger)
50.00%
1 / 2
100.00% covered (success)
100.00%
1 / 1
2.50
 emitter
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 middleware
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 logger
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 container
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 register
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 initializeContainer
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 run
100.00% covered (success)
100.00%
12 / 12
85.71% covered (warning)
85.71%
6 / 7
50.00% covered (danger)
50.00%
2 / 4
100.00% covered (success)
100.00%
1 / 1
4.12
1<?php
2
3declare(strict_types=1);
4
5namespace Celema\Core;
6
7use Celema\Container\Container;
8use Celema\Container\Entry;
9use Celema\Core\Emitter\Emitter;
10use Celema\Core\Emitter\Sapi;
11use Celema\Core\Error\Handler as ErrorHandler;
12use Celema\Core\Factory\Factory;
13use Celema\Core\Factory\Nyholm;
14use Celema\Router\AddsBeforeAfter;
15use Celema\Router\AddsRoutes;
16use Celema\Router\Dispatcher;
17use Celema\Router\Route;
18use Celema\Router\RouteAdder;
19use Celema\Router\Router;
20use Celema\Router\RoutingHandler;
21use Closure;
22use Override;
23use Psr\Container\ContainerInterface as PsrContainer;
24use Psr\Http\Message\ResponseInterface as Response;
25use Psr\Http\Message\ServerRequestInterface as Request;
26use Psr\Http\Server\MiddlewareInterface as Middleware;
27use Psr\Log\LoggerInterface as Logger;
28
29/** @api */
30class App implements RouteAdder
31{
32    use AddsRoutes;
33    use AddsBeforeAfter;
34
35    protected readonly Dispatcher $dispatcher;
36    protected ?ErrorHandler $errorHandler = null;
37    protected Emitter $emitter;
38
39    public function __construct(
40        protected readonly Factory $factory,
41        protected readonly Router $router,
42        protected readonly Container $container,
43    ) {
44        $this->dispatcher = new Dispatcher();
45        $this->emitter = new Sapi();
46        $this->initializeContainer();
47    }
48
49    public function load(Plugin $plugin): void
50    {
51        $plugin->load($this);
52    }
53
54    public static function create(?PsrContainer $container = null): self
55    {
56        return new self(
57            new Nyholm(),
58            new Router(),
59            new Container(container: $container),
60        );
61    }
62
63    public function router(): Router
64    {
65        return $this->router;
66    }
67
68    public function factory(): Factory
69    {
70        return $this->factory;
71    }
72
73    #[Override]
74    public function addRoute(Route $route): Route
75    {
76        return $this->router->addRoute($route);
77    }
78
79    #[Override]
80    public function group(
81        string $patternPrefix,
82        Closure $createClosure,
83        string $namePrefix = '',
84    ): void {
85        $this->router->group($patternPrefix, $createClosure, $namePrefix);
86    }
87
88    public function staticRoute(
89        string $prefix,
90        string $path,
91        string $name = '',
92    ): void {
93        $this->router->addStatic($prefix, $path, $name);
94    }
95
96    public function getMiddleware(): array
97    {
98        return $this->dispatcher->getMiddleware();
99    }
100
101    public function errorHandler(?ErrorHandler $handler = null): ?ErrorHandler
102    {
103        if ($handler !== null) {
104            $this->errorHandler = $handler;
105        }
106
107        return $this->errorHandler;
108    }
109
110    public function emitter(?Emitter $emitter = null): Emitter
111    {
112        if ($emitter !== null) {
113            $this->emitter = $emitter;
114        }
115
116        return $this->emitter;
117    }
118
119    public function middleware(Middleware ...$middleware): void
120    {
121        $this->dispatcher->middleware(...$middleware);
122    }
123
124    public function logger(Logger|callable $logger): void
125    {
126        if ($logger instanceof Logger) {
127            $this->container->add(Logger::class, $logger);
128        } else {
129            $this->container->add(Logger::class, Closure::fromCallable($logger));
130        }
131    }
132
133    public function container(): Container
134    {
135        return $this->container;
136    }
137
138    /**
139     * @param non-empty-string $key
140     * @param class-string|object $value
141     */
142    public function register(string $key, object|string $value): Entry
143    {
144        return $this->container->add($key, $value);
145    }
146
147    public function initializeContainer(): void
148    {
149        $this->container->add(Router::class, $this->router);
150        $this->container->add($this->router::class, $this->router);
151
152        $this->container->add(Factory::class, $this->factory);
153        $this->container->add($this->factory::class, $this->factory);
154    }
155
156    public function run(?Request $request = null): Response|false
157    {
158        $request ??= $this->factory->serverRequest();
159        $this->dispatcher->setBeforeHandlers($this->beforeHandlers);
160        $this->dispatcher->setAfterHandlers($this->afterHandlers);
161        $handler = new RoutingHandler(
162            $this->router,
163            $this->dispatcher,
164            $this->container,
165        );
166        $response = $this->errorHandler
167            ? $this->errorHandler->process($request, $handler)
168            : $handler->handle($request);
169
170        return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false;
171    }
172}

Branches

Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once. Please also be aware that some branches may be implicit rather than explicit, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

App->__construct
40        protected readonly Factory $factory,
41        protected readonly Router $router,
42        protected readonly Container $container,
43    ) {
44        $this->dispatcher = new Dispatcher();
45        $this->emitter = new Sapi();
46        $this->initializeContainer();
47    }
App->addRoute
74    public function addRoute(Route $route): Route
75    {
76        return $this->router->addRoute($route);
77    }
App->container
135        return $this->container;
136    }
App->create
54    public static function create(?PsrContainer $container = null): self
55    {
56        return new self(
57            new Nyholm(),
58            new Router(),
59            new Container(container: $container),
60        );
61    }
App->emitter
110    public function emitter(?Emitter $emitter = null): Emitter
111    {
112        if ($emitter !== null) {
113            $this->emitter = $emitter;
114        }
115
116        return $this->emitter;
116        return $this->emitter;
117    }
App->errorHandler
101    public function errorHandler(?ErrorHandler $handler = null): ?ErrorHandler
102    {
103        if ($handler !== null) {
104            $this->errorHandler = $handler;
105        }
106
107        return $this->errorHandler;
107        return $this->errorHandler;
108    }
App->factory
70        return $this->factory;
71    }
App->getMiddleware
98        return $this->dispatcher->getMiddleware();
99    }
App->group
81        string $patternPrefix,
82        Closure $createClosure,
83        string $namePrefix = '',
84    ): void {
85        $this->router->group($patternPrefix, $createClosure, $namePrefix);
86    }
App->initializeContainer
149        $this->container->add(Router::class, $this->router);
150        $this->container->add($this->router::class, $this->router);
151
152        $this->container->add(Factory::class, $this->factory);
153        $this->container->add($this->factory::class, $this->factory);
154    }
App->load
49    public function load(Plugin $plugin): void
50    {
51        $plugin->load($this);
52    }
App->logger
124    public function logger(Logger|callable $logger): void
125    {
126        if ($logger instanceof Logger) {
126        if ($logger instanceof Logger) {
127            $this->container->add(Logger::class, $logger);
129            $this->container->add(Logger::class, Closure::fromCallable($logger));
130        }
131    }
131    }
App->middleware
119    public function middleware(Middleware ...$middleware): void
120    {
121        $this->dispatcher->middleware(...$middleware);
122    }
App->register
142    public function register(string $key, object|string $value): Entry
143    {
144        return $this->container->add($key, $value);
145    }
App->router
65        return $this->router;
66    }
App->run
156    public function run(?Request $request = null): Response|false
157    {
158        $request ??= $this->factory->serverRequest();
159        $this->dispatcher->setBeforeHandlers($this->beforeHandlers);
160        $this->dispatcher->setAfterHandlers($this->afterHandlers);
161        $handler = new RoutingHandler(
162            $this->router,
163            $this->dispatcher,
164            $this->container,
165        );
166        $response = $this->errorHandler
167            ? $this->errorHandler->process($request, $handler)
166        $response = $this->errorHandler
167            ? $this->errorHandler->process($request, $handler)
168            : $handler->handle($request);
166        $response = $this->errorHandler
167            ? $this->errorHandler->process($request, $handler)
168            : $handler->handle($request);
169
170        return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false;
170        return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false;
170        return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false;
170        return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false;
171    }
App->staticRoute
89        string $prefix,
90        string $path,
91        string $name = '',
92    ): void {
93        $this->router->addStatic($prefix, $path, $name);
94    }