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

IlyasDeckers / ody-core / 13575371463

27 Feb 2025 08:34PM UTC coverage: 28.921% (+0.6%) from 28.348%
13575371463

push

github

IlyasDeckers
Refactoring/cleaning up/getting rid of redundant helper functions

0 of 68 new or added lines in 8 files covered. (0.0%)

9 existing lines in 5 files now uncovered.

544 of 1881 relevant lines covered (28.92%)

8.7 hits per line

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

64.13
/src/Kernel.php
1
<?php
2
declare(strict_types=1);
3
namespace Ody\Core;
4

5
use DI\Container;
6
use Invoker\CallableResolver as InvokerCallableResolver;
7
use Invoker\Invoker;
8
use Invoker\ParameterResolver\AssociativeArrayResolver;
9
use Invoker\ParameterResolver\Container\TypeHintContainerResolver;
10
use Invoker\ParameterResolver\DefaultValueResolver;
11
use Invoker\ParameterResolver\ResolverChain;
12
use Ody\Core\DI\ControllerInvoker;
13
use Ody\Core\Facades\Facade;
14
use Ody\Core\Factory\KernelFactory;
15
use Ody\Core\Factory\ServerRequestCreatorFactory;
16
use Ody\Core\Interfaces\CallableResolverInterface;
17
use Ody\Core\Interfaces\MiddlewareDispatcherInterface;
18
use Ody\Core\Interfaces\RouteCollectorInterface;
19
use Ody\Core\Interfaces\RouteResolverInterface;
20
use Ody\Core\Middleware\BodyParsingMiddleware;
21
use Ody\Core\Middleware\ErrorMiddleware;
22
use Ody\Core\Middleware\RoutingMiddleware;
23
use Ody\Core\Routing\RouteCollectorProxy;
24
use Ody\Core\Routing\RouteResolver;
25
use Ody\Core\Routing\RouteRunner;
26
use Psr\Container\ContainerInterface;
27
use Psr\Http\Message\ResponseFactoryInterface;
28
use Psr\Http\Message\ResponseInterface;
29
use Psr\Http\Message\ServerRequestInterface;
30
use Psr\Http\Server\MiddlewareInterface;
31
use Psr\Http\Server\RequestHandlerInterface;
32
use Psr\Log\LoggerInterface;
33

34
/**
35
 * @api
36
 * @template TContainerInterface of (ContainerInterface|null)
37
 * @template-extends RouteCollectorProxy<TContainerInterface>
38
 */
39
class Kernel extends RouteCollectorProxy implements RequestHandlerInterface
40
{
41
    /**
42
     * Current version
43
     *
44
     * @var string
45
     */
46
    public const VERSION = '0.0.1';
47

48
    protected RouteResolverInterface $routeResolver;
49

50
    protected MiddlewareDispatcherInterface $middlewareDispatcher;
51

52
    /**
53
     * @param ResponseFactoryInterface $responseFactory
54
     * @param ContainerInterface|null $container
55
     * @param CallableResolverInterface|null $callableResolver
56
     * @param RouteCollectorInterface|null $routeCollector
57
     * @param RouteResolverInterface|null $routeResolver
58
     * @param MiddlewareDispatcherInterface|null $middlewareDispatcher
59
     */
60
    public function __construct(
99✔
61
        ResponseFactoryInterface $responseFactory,
62
        ?ContainerInterface $container = null,
63
        ?CallableResolverInterface $callableResolver = null,
64
        ?RouteCollectorInterface $routeCollector = null,
65
        ?RouteResolverInterface $routeResolver = null,
66
        ?MiddlewareDispatcherInterface $middlewareDispatcher = null
67
    ) {
68
        parent::__construct(
99✔
69
            $responseFactory,
99✔
70
            $callableResolver ?? new CallableResolver($container),
99✔
71
            $container,
99✔
72
            $routeCollector
99✔
73
        );
99✔
74

75
        $this->routeResolver = $routeResolver ?? new RouteResolver($this->routeCollector);
99✔
76
        $routeRunner = new RouteRunner($this->routeResolver, $this->routeCollector->getRouteParser(), $this);
99✔
77

78
        if (!$middlewareDispatcher) {
99✔
79
            $middlewareDispatcher = new MiddlewareDispatcher($routeRunner, $this->callableResolver, $container);
98✔
80
        } else {
81
            $middlewareDispatcher->seedMiddlewareStack($routeRunner);
1✔
82
        }
83

84
        $this->middlewareDispatcher = $middlewareDispatcher;
99✔
85
    }
86

87
    public static function init(): Kernel
×
88
    {
89
        Env::load(base_path());
×
90
        $debug = (bool) config('app.debug');
×
UNCOV
91
        $container = new Container([
×
92
            'di.service' => [...config('server.services', [])],
×
93
        ]);
×
94
        $app = self::create($container);
×
95
        $app->addBodyParsingMiddleware();
×
96
        $app->addRoutingMiddleware();
×
97
        $app->addErrorMiddleware($debug, $debug, $debug);
×
98
        Facade::setFacadeApplication($app);
×
99

100
        /**
101
         * Register routes
102
         */
103
        require base_path('App/routes.php');
×
104

105
        /**
106
         * Register DB
107
         */
108
        if (class_exists('Ody\DB\Eloquent')) {
×
NEW
109
            $dbConfig = config('database.environments')[config('app.environment', 'local')];
×
110
            \Ody\DB\Eloquent::boot($dbConfig);
×
111
        }
112

113
        return $app;
×
114
    }
115

116
    /** Bridge DI */
117
    public static function create(?ContainerInterface $container = null): Kernel
×
118
    {
119
        $container = $container ?: new Container;
×
120

121
        $callableResolver = new InvokerCallableResolver($container);
×
122

123
        $container->set(CallableResolverInterface::class, new \Ody\Core\DI\CallableResolver($callableResolver));
×
124
        $app = KernelFactory::createFromContainer($container);
×
125

126
        $container->set(Kernel::class, $app);
×
127

128
        $controllerInvoker = static::createControllerInvoker($container);
×
129
        $app->getRouteCollector()->setDefaultInvocationStrategy($controllerInvoker);
×
130

131
        return $app;
×
132
    }
133

134
    /** Bridge DI */
135
    private static function createControllerInvoker(ContainerInterface $container): ControllerInvoker
×
136
    {
137
        $resolvers = [
×
138
            // Inject parameters by name first
139
            new AssociativeArrayResolver,
×
140
            // Then inject services by type-hints for those that weren't resolved
141
            new TypeHintContainerResolver($container),
×
142
            // Then fall back on parameters default values for optional route parameters
143
            new DefaultValueResolver,
×
144
        ];
×
145

146
        $invoker = new Invoker(new ResolverChain($resolvers), $container);
×
147

148
        return new ControllerInvoker($invoker);
×
149
    }
150

151
    /**
152
     * @return RouteResolverInterface
153
     */
154
    public function getRouteResolver(): RouteResolverInterface
1✔
155
    {
156
        return $this->routeResolver;
1✔
157
    }
158

159
    /**
160
     * @return MiddlewareDispatcherInterface
161
     */
162
    public function getMiddlewareDispatcher(): MiddlewareDispatcherInterface
1✔
163
    {
164
        return $this->middlewareDispatcher;
1✔
165
    }
166

167
    /**
168
     * @param MiddlewareInterface|string|callable $middleware
169
     * @return Kernel<TContainerInterface>
170
     */
171
    public function add($middleware): self
6✔
172
    {
173
        $this->middlewareDispatcher->add($middleware);
6✔
174
        return $this;
5✔
175
    }
176

177
    /**
178
     * @param MiddlewareInterface $middleware
179
     * @return Kernel<TContainerInterface>
180
     */
181
    public function addMiddleware(MiddlewareInterface $middleware): self
1✔
182
    {
183
        $this->middlewareDispatcher->addMiddleware($middleware);
1✔
184
        return $this;
1✔
185
    }
186

187
    /**
188
     * Add the built-in routing middleware to the app middleware stack
189
     *
190
     * This method can be used to control middleware order and is not required for default routing operation.
191
     *
192
     * @return RoutingMiddleware
193
     */
194
    public function addRoutingMiddleware(): RoutingMiddleware
1✔
195
    {
196
        $routingMiddleware = new RoutingMiddleware(
1✔
197
            $this->getRouteResolver(),
1✔
198
            $this->getRouteCollector()->getRouteParser()
1✔
199
        );
1✔
200
        $this->add($routingMiddleware);
1✔
201
        return $routingMiddleware;
1✔
202
    }
203

204
    /**
205
     * Add the built-in error middleware to the app middleware stack
206
     *
207
     * @param bool                 $displayErrorDetails
208
     * @param bool                 $logErrors
209
     * @param bool                 $logErrorDetails
210
     * @param LoggerInterface|null $logger
211
     *
212
     * @return ErrorMiddleware
213
     */
214
    public function addErrorMiddleware(
1✔
215
        bool $displayErrorDetails,
216
        bool $logErrors,
217
        bool $logErrorDetails,
218
        ?LoggerInterface $logger = null
219
    ): ErrorMiddleware {
220
        $errorMiddleware = new ErrorMiddleware(
1✔
221
            $this->getCallableResolver(),
1✔
222
            $this->getResponseFactory(),
1✔
223
            $displayErrorDetails,
1✔
224
            $logErrors,
1✔
225
            $logErrorDetails,
1✔
226
            $logger
1✔
227
        );
1✔
228
        $this->add($errorMiddleware);
1✔
229
        return $errorMiddleware;
1✔
230
    }
231

232
    /**
233
     * Add the body parsing middleware to the app middleware stack
234
     *
235
     * @param callable[] $bodyParsers
236
     *
237
     * @return BodyParsingMiddleware
238
     */
239
    public function addBodyParsingMiddleware(array $bodyParsers = []): BodyParsingMiddleware
1✔
240
    {
241
        $bodyParsingMiddleware = new BodyParsingMiddleware($bodyParsers);
1✔
242
        $this->add($bodyParsingMiddleware);
1✔
243
        return $bodyParsingMiddleware;
1✔
244
    }
245

246
    /**
247
     * Run application
248
     *
249
     * This method traverses the application middleware stack and then sends the
250
     * resultant Response object to the HTTP client.
251
     *
252
     * @param ServerRequestInterface|null $request
253
     * @return void
254
     */
255
    public function run(?ServerRequestInterface $request = null): void
2✔
256
    {
257
        if (!$request) {
2✔
258
            $serverRequestCreator = ServerRequestCreatorFactory::create();
1✔
259
            $request = $serverRequestCreator->createServerRequestFromGlobals();
1✔
260
        }
261

262
        $response = $this->handle($request);
2✔
263
        $responseEmitter = new ResponseEmitter();
2✔
264
        $responseEmitter->emit($response);
2✔
265
    }
266

267
    /**
268
     * Handle a request
269
     *
270
     * This method traverses the application middleware stack and then returns the
271
     * resultant Response object.
272
     *
273
     * @param ServerRequestInterface $request
274
     * @return ResponseInterface
275
     */
276
    public function handle(ServerRequestInterface $request): ResponseInterface
45✔
277
    {
278
        $response = $this->middlewareDispatcher->handle($request);
45✔
279

280
        /**
281
         * This is to be in compliance with RFC 2616, Section 9.
282
         * If the incoming request method is HEAD, we need to ensure that the response body
283
         * is empty as the request may fall back on a GET route handler due to FastRoute's
284
         * routing logic which could potentially append content to the response body
285
         * https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4
286
         */
287
        $method = strtoupper($request->getMethod());
42✔
288
        if ($method === 'HEAD') {
42✔
289
            $emptyBody = $this->responseFactory->createResponse()->getBody();
1✔
290
            return $response->withBody($emptyBody);
1✔
291
        }
292

293
        return $response;
41✔
294
    }
295
}
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