ContainerProvider::hydrate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 2
Metric Value
dl 0
loc 8
rs 9.4285
c 3
b 0
f 2
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Jarvis\Skill\DependencyInjection;
6
7
use Jarvis\Jarvis;
8
use Jarvis\Skill\Core\CallbackResolver;
9
use Jarvis\Skill\EventBroadcaster\BroadcasterInterface;
10
use Jarvis\Skill\EventBroadcaster\ControllerEvent;
11
use Jarvis\Skill\EventBroadcaster\ExceptionEvent;
12
use Jarvis\Skill\Routing\Router;
13
use Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\HttpFoundation\Response;
15
use Symfony\Component\HttpFoundation\Session\Session;
16
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
17
18
/**
19
 * This is Jarvis internal container provider. It will inject every core
20
 * parameters and services into Jarvis.
21
 *
22
 * @author Eric Chau <[email protected]>
23
 */
24
final class ContainerProvider implements ContainerProviderInterface
25
{
26
    /**
27
     * {@inheritdoc}
28
     */
29
    public function hydrate(Jarvis $app)
30
    {
31
        $this
32
            ->mountCoreComponents($app)
33
            ->mountHttpComponents($app)
34
            ->mountCallbackResolverComponents($app)
35
        ;
36
    }
37
38
    protected function mountCoreComponents(Jarvis $app)
39
    {
40
        $app['app'] = function () use ($app): Jarvis {
41
            return $app;
42
        };
43
44
        $app['debug'] = $app['settings']['debug'] ?? Jarvis::DEFAULT_DEBUG;
45
        $app->lock('debug');
46
47
        $extra = $app['settings']['extra'] ?? [];
48
        foreach ((array) $extra as $key => $data) {
49
            $id = sprintf('%s.settings', $key);
50
            $app[$id] = $data;
51
            $app->lock($id);
52
        }
53
54
        unset($app['settings']);
55
        $app->lock('app');
56
57
        return $this;
58
    }
59
60
    protected function mountHttpComponents(Jarvis $app)
61
    {
62
        $app['request'] = function (Jarvis $app): Request {
63
            $request = Request::createFromGlobals();
64
65
            if (null === $session = $request->getSession()) {
66
                $settings = $app['session.settings'] ?? [];
67
                $storageClassname = $settings['session.storage.classname'] ?? NativeSessionStorage::class;
68
                unset($settings['session.storage.classname']);
69
                $session = new Session(new $storageClassname($settings));
70
            }
71
72
            $request->setSession($session);
73
74
            return $request;
75
        };
76
77
        $app['session'] = function (Jarvis $app): Session {
78
            return $app[Request::class]->getSession();
79
        };
80
81
        $app['router'] = function (): Router {
82
            return new Router();
83
        };
84
85
        $app->on(BroadcasterInterface::EXCEPTION_EVENT, function (ExceptionEvent $event) use ($app): void {
86
            $throwable = $event->exception();
87
            $msg = sprintf(
88
                '[%s] error in %s at line %s with message: %s',
89
                get_class($throwable),
90
                $throwable->getFile(),
91
                $throwable->getLine(),
92
                $throwable->getMessage()
93
            );
94
95
            if (!$app['debug']) {
96
                error_log($msg);
97
98
                $msg = '';
99
            }
100
101
            $event->setResponse(new Response($msg, Response::HTTP_INTERNAL_SERVER_ERROR));
102
        }, BroadcasterInterface::RECEIVER_LOW_PRIORITY);
103
104
        $app->lock(['request', 'session', 'router']);
105
106
        return $this;
107
    }
108
109
    protected function mountCallbackResolverComponents(Jarvis $app)
110
    {
111
        $app['callbackResolver'] = function (Jarvis $app): CallbackResolver {
112
            return new CallbackResolver($app);
113
        };
114
115
        $app->on(BroadcasterInterface::CONTROLLER_EVENT, function (ControllerEvent $event) use ($app): void {
116
            $event->setCallback($app[CallbackResolver::class]->toClosure($event->callback()));
117
            $event->setArguments($app[CallbackResolver::class]->resolveArgumentsForClosure(
118
                $event->callback(),
119
                $event->arguments()
120
            ));
121
        }, BroadcasterInterface::RECEIVER_LOW_PRIORITY);
122
123
        $app->lock('callbackResolver');
124
125
        return $this;
126
    }
127
}
128