Completed
Push — symfony-flex ( 2a70a0 )
by Kamil
26:10 queued 12:40
created

Kernel::shutdown()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.6666
c 0
b 0
f 0
cc 3
nc 3
nop 0
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
use ProxyManager\Proxy\VirtualProxyInterface;
15
use PSS\SymfonyMockerContainer\DependencyInjection\MockerContainer;
16
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
17
use Symfony\Component\Config\Loader\LoaderInterface;
18
use Symfony\Component\Config\Resource\FileResource;
19
use Symfony\Component\DependencyInjection\ContainerBuilder;
20
use Symfony\Component\DependencyInjection\ContainerInterface;
21
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
22
use Symfony\Component\Routing\RouteCollectionBuilder;
23
24
/** @final */
25
class Kernel extends BaseKernel
26
{
27
    use MicroKernelTrait;
28
29
    private const CONFIG_EXTS = '.{php,xml,yaml,yml}';
30
31
    private const IGNORED_SERVICES_DURING_CLEANUP = [
32
        'kernel',
33
        'http_kernel',
34
        'liip_imagine.mime_type_guesser',
35
        'liip_imagine.extension_guesser',
36
    ];
37
38
    public function getCacheDir(): string
39
    {
40
        return $this->getProjectDir() . '/var/cache/' . $this->environment;
41
    }
42
43
    public function getLogDir(): string
44
    {
45
        return $this->getProjectDir() . '/var/log';
46
    }
47
48
    public function registerBundles(): iterable
49
    {
50
        $contents = require $this->getProjectDir() . '/config/bundles.php';
51
        foreach ($contents as $class => $envs) {
52
            if (isset($envs['all']) || isset($envs[$this->environment])) {
53
                yield new $class();
54
            }
55
        }
56
    }
57
58
    public function shutdown(): void
59
    {
60
        if (!$this->isTestEnvironment()) {
61
            parent::shutdown();
62
63
            return;
64
        }
65
66
        if (false === $this->booted) {
67
            return;
68
        }
69
70
        $container = $this->getContainer();
71
72
        parent::shutdown();
73
74
        $this->cleanupContainer($container);
75
    }
76
77
    protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
78
    {
79
        $container->addResource(new FileResource($this->getProjectDir() . '/config/bundles.php'));
80
        $container->setParameter('container.dumper.inline_class_loader', true);
81
        $confDir = $this->getProjectDir() . '/config';
82
83
        $loader->load($confDir . '/{packages}/*' . self::CONFIG_EXTS, 'glob');
84
        $loader->load($confDir . '/{packages}/' . $this->environment . '/**/*' . self::CONFIG_EXTS, 'glob');
85
        $loader->load($confDir . '/{services}' . self::CONFIG_EXTS, 'glob');
86
        $loader->load($confDir . '/{services}_' . $this->environment . self::CONFIG_EXTS, 'glob');
87
    }
88
89
    protected function configureRoutes(RouteCollectionBuilder $routes): void
90
    {
91
        $confDir = $this->getProjectDir() . '/config';
92
93
        $routes->import($confDir . '/{routes}/*' . self::CONFIG_EXTS, '/', 'glob');
94
        $routes->import($confDir . '/{routes}/' . $this->environment . '/**/*' . self::CONFIG_EXTS, '/', 'glob');
95
        $routes->import($confDir . '/{routes}' . self::CONFIG_EXTS, '/', 'glob');
96
    }
97
98
    protected function getContainerBaseClass(): string
99
    {
100
        if ($this->isTestEnvironment()) {
101
            return MockerContainer::class;
102
        }
103
104
        return parent::getContainerBaseClass();
105
    }
106
107
    private function isTestEnvironment(): bool
108
    {
109
        return 0 === strpos($this->getEnvironment(), 'test');
110
    }
111
112
    /**
113
     * Remove all container references from all loaded services
114
     */
115
    private function cleanupContainer(ContainerInterface $container): void
116
    {
117
        $containerReflection = new \ReflectionObject($container);
118
        $containerServicesPropertyReflection = $containerReflection->getProperty('services');
119
        $containerServicesPropertyReflection->setAccessible(true);
120
121
        $services = $containerServicesPropertyReflection->getValue($container) ?: [];
122
        foreach ($services as $serviceId => $service) {
123
            if (null === $service) {
124
                continue;
125
            }
126
127
            if (in_array($serviceId, self::IGNORED_SERVICES_DURING_CLEANUP, true)) {
128
                continue;
129
            }
130
131
            $serviceReflection = new \ReflectionObject($service);
132
133
            if ($serviceReflection->implementsInterface(VirtualProxyInterface::class)) {
134
                continue;
135
            }
136
137
            $servicePropertiesReflections = $serviceReflection->getProperties();
138
            $servicePropertiesDefaultValues = $serviceReflection->getDefaultProperties();
139
            foreach ($servicePropertiesReflections as $servicePropertyReflection) {
140
                $defaultPropertyValue = null;
141
                if (isset($servicePropertiesDefaultValues[$servicePropertyReflection->getName()])) {
142
                    $defaultPropertyValue = $servicePropertiesDefaultValues[$servicePropertyReflection->getName()];
143
                }
144
145
                $servicePropertyReflection->setAccessible(true);
146
                $servicePropertyReflection->setValue($service, $defaultPropertyValue);
147
            }
148
        }
149
150
        $containerServicesPropertyReflection->setValue($container, null);
151
    }
152
}
153