Passed
Push — main ( b92cd4...d72029 )
by Thomas
03:18
created

App::renderer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Conia\Chuck;
6
7
use Closure;
8
use Conia\Chuck\Exception\RuntimeException;
9
use Conia\Chuck\MiddlewareInterface;
10
use Conia\Chuck\Registry;
11
use Conia\Chuck\RegistryEntry;
12
use Conia\Chuck\Renderer\JsonRenderer;
13
use Conia\Chuck\Renderer\Renderer;
14
use Conia\Chuck\Renderer\TextRenderer;
15
use Conia\Chuck\ResponseFactory;
16
use Conia\Chuck\Routing\AddsRoutes;
17
use Conia\Chuck\Routing\Group;
18
use Conia\Chuck\Routing\Route;
19
use Conia\Chuck\Routing\Router;
20
use Psr\Container\ContainerInterface;
21
use Psr\Http\Message\ResponseFactoryInterface;
22
use Psr\Http\Message\ServerRequestInterface;
23
use Psr\Http\Message\StreamFactoryInterface;
24
use Throwable;
25
26
/** @psalm-consistent-constructor */
27
class App
28
{
29
    use AddsRoutes;
30
31 23
    public function __construct(
32
        protected Config $config,
33
        protected Router $router,
34
        protected Registry $registry,
35
    ) {
36 23
        $this->initializeRegistry();
37
    }
38
39 21
    public static function create(?Config $config = null, ?ContainerInterface $container = null): static
40
    {
41 21
        if (!$config) {
42 17
            $config = new Config('chuck', debug: false);
43
        }
44
45 21
        $registry = new Registry($container);
46 21
        $router = new Router();
47
48 21
        $errorHandler = new ErrorHandler($config, $registry);
0 ignored issues
show
Bug introduced by
The type Conia\Chuck\ErrorHandler was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
49 21
        $errorHandler->setup();
50
51 21
        return new static($config, $router, $registry);
52
    }
53
54 13
    public function router(): Router
55
    {
56 13
        return $this->router;
57
    }
58
59 2
    public function config(): Config
60
    {
61 2
        return $this->config;
62
    }
63
64 3
    public function registry(): Registry
65
    {
66 3
        return $this->registry;
67
    }
68
69 14
    public function addRoute(Route $route): void
70
    {
71 14
        $this->router->addRoute($route);
72
    }
73
74 1
    public function addGroup(Group $group): void
75
    {
76 1
        $this->router->addGroup($group);
77
    }
78
79 1
    public function group(
80
        string $patternPrefix,
81
        Closure $createClosure,
82
        ?string $namePrefix = null,
83
    ): Group {
84 1
        $group = new Group($patternPrefix, $createClosure, $namePrefix);
85 1
        $this->router->addGroup($group);
86
87 1
        return $group;
88
    }
89
90 1
    public function staticRoute(
91
        string $prefix,
92
        string $path,
93
        ?string $name = null,
94
    ): void {
95 1
        $this->router->addStatic($prefix, $path, $name);
96
    }
97
98
    /**
99
     * @param MiddlewareInterface|callable(
100
     *     Request,
101
     *     callable
102
     * ):\Conia\Chuck\Response $middleware
103
     *
104
     * TODO: Why can't we import the custom psalm type MiddlewareCallable from MiddlewareInterface
105
     */
106 5
    public function middleware(MiddlewareInterface|callable ...$middleware): void
107
    {
108 5
        $this->router->middleware(...$middleware);
109
    }
110
111
    /**
112
     * @psalm-param non-empty-string $name
113
     * @psalm-param non-empty-string $class
114
     */
115 1
    public function renderer(string $name, string $class): RegistryEntry
116
    {
117 1
        return $this->registry->tag(Renderer::class)->add($name, $class)->asIs();
118
    }
119
120
    /**
121
     * @psalm-param non-empty-string $key
122
     * @psalm-param class-string|object $value
123
     */
124 1
    public function register(string $key, object|string $value): RegistryEntry
125
    {
126 1
        return $this->registry->add($key, $value);
127
    }
128
129 5
    public function run(): Response
130
    {
131 5
        $serverRequest = $this->registry->get(ServerRequestInterface::class);
132 5
        assert($serverRequest instanceof ServerRequestInterface);
133 5
        $request = new Request($serverRequest);
134 5
        $this->registry->add(Request::class, $request);
135
136 5
        $response = $this->router->dispatch($request, $this->registry);
137
138 5
        (new Emitter())->emit($response->psr7());
139
140 5
        return $response;
141
    }
142
143 23
    protected function initializeRegistry(): void
144
    {
145 23
        $registry = $this->registry;
146
147 23
        $registry->add(Config::class, $this->config);
148 23
        $registry->add($this->config::class, $this->config);
149 23
        $registry->add(Router::class, $this->router);
150 23
        $registry->add($this->router::class, $this->router);
151 23
        $registry->add(App::class, $this);
152
153 23
        $registry->add(ResponseFactoryInterface::class, \Nyholm\Psr7\Factory\Psr17Factory::class);
154 23
        $registry->add(StreamFactoryInterface::class, \Nyholm\Psr7\Factory\Psr17Factory::class);
155 23
        $registry->add(ResponseFactory::class, new ResponseFactory($this->registry));
156 23
        $registry->add(ServerRequestInterface::class, function (): ServerRequestInterface {
157
            try {
158 5
                $psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory();
159 5
                $creator = new \Nyholm\Psr7Server\ServerRequestCreator(
160 5
                    $psr17Factory, // ServerRequestFactory
161 5
                    $psr17Factory, // UriFactory
162 5
                    $psr17Factory, // UploadedFileFactory
163 5
                    $psr17Factory  // StreamFactory
164 5
                );
165
166 5
                return $creator->fromGlobals();
167
                // @codeCoverageIgnoreStart
168
            } catch (Throwable) {
169
                throw new RuntimeException('Install nyholm/psr7-server');
170
                // @codeCoverageIgnoreEnd
171
            }
172 23
        });
173
174 23
        $registry->tag(Renderer::class)->add('text', TextRenderer::class)->asIs();
175 23
        $registry->tag(Renderer::class)->add('json', JsonRenderer::class)->asIs();
176
    }
177
}
178