Completed
Push — 1.3-kernel-container-loader ( d8fd3a )
by Kamil
12:46
created

Kernel::getContainerLoader()   A

Complexity

Conditions 1
Paths 1

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 1
nc 1
nop 1
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\DelegatingLoader;
18
use Symfony\Component\Config\Loader\LoaderInterface;
19
use Symfony\Component\Config\Loader\LoaderResolver;
20
use Symfony\Component\Config\Resource\FileResource;
21
use Symfony\Component\DependencyInjection\ContainerBuilder;
22
use Symfony\Component\DependencyInjection\ContainerInterface;
23
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
24
use Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
25
use Symfony\Component\DependencyInjection\Loader\GlobFileLoader;
26
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
27
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
28
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
29
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
30
use Symfony\Component\HttpKernel\Config\FileLocator;
31
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
32
use Symfony\Component\Routing\RouteCollectionBuilder;
33
use Webmozart\Assert\Assert;
34
35
/** @final */
36
class Kernel extends BaseKernel
37
{
38
    use MicroKernelTrait;
39
40
    private const CONFIG_EXTS = '.{php,xml,yaml,yml}';
41
42
    private const IGNORED_SERVICES_DURING_CLEANUP = [
43
        'kernel',
44
        'http_kernel',
45
        'liip_imagine.mime_type_guesser',
46
        'liip_imagine.extension_guesser',
47
    ];
48
49
    public function getCacheDir(): string
50
    {
51
        return $this->getProjectDir() . '/var/cache/' . $this->environment;
52
    }
53
54
    public function getLogDir(): string
55
    {
56
        return $this->getProjectDir() . '/var/log';
57
    }
58
59
    public function registerBundles(): iterable
60
    {
61
        $contents = require $this->getProjectDir() . '/config/bundles.php';
62
        foreach ($contents as $class => $envs) {
63
            if (isset($envs['all']) || isset($envs[$this->environment])) {
64
                yield new $class();
65
            }
66
        }
67
    }
68
69
    public function shutdown(): void
70
    {
71
        if (!$this->isTestEnvironment()) {
72
            parent::shutdown();
73
74
            return;
75
        }
76
77
        if (false === $this->booted) {
78
            return;
79
        }
80
81
        $container = $this->getContainer();
82
83
        parent::shutdown();
84
85
        $this->cleanupContainer($container);
86
    }
87
88
    protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
89
    {
90
        $container->addResource(new FileResource($this->getProjectDir() . '/config/bundles.php'));
91
        $container->setParameter('container.dumper.inline_class_loader', true);
92
        $confDir = $this->getProjectDir() . '/config';
93
94
        $loader->load($confDir . '/{packages}/*' . self::CONFIG_EXTS, 'glob');
95
        $loader->load($confDir . '/{packages}/' . $this->environment . '/**/*' . self::CONFIG_EXTS, 'glob');
96
        $loader->load($confDir . '/{services}' . self::CONFIG_EXTS, 'glob');
97
        $loader->load($confDir . '/{services}_' . $this->environment . self::CONFIG_EXTS, 'glob');
98
    }
99
100
    protected function configureRoutes(RouteCollectionBuilder $routes): void
101
    {
102
        $confDir = $this->getProjectDir() . '/config';
103
104
        $routes->import($confDir . '/{routes}/*' . self::CONFIG_EXTS, '/', 'glob');
105
        $routes->import($confDir . '/{routes}/' . $this->environment . '/**/*' . self::CONFIG_EXTS, '/', 'glob');
106
        $routes->import($confDir . '/{routes}' . self::CONFIG_EXTS, '/', 'glob');
107
    }
108
109
    protected function getContainerBaseClass(): string
110
    {
111
        if ($this->isTestEnvironment()) {
112
            return MockerContainer::class;
113
        }
114
115
        return parent::getContainerBaseClass();
116
    }
117
118
    protected function getContainerLoader(ContainerInterface $container): LoaderInterface
119
    {
120
        /** @var ContainerBuilder $container */
121
        Assert::isInstanceOf($container, ContainerBuilder::class);
122
123
        $locator = new FileLocator($this, $this->getRootDir() . '/Resources');
124
        $resolver = new LoaderResolver(array(
125
            new XmlFileLoader($container, $locator),
126
            new YamlFileLoader($container, $locator),
127
            new IniFileLoader($container, $locator),
128
            new PhpFileLoader($container, $locator),
129
            new GlobFileLoader($container, $locator),
130
            new DirectoryLoader($container, $locator),
131
            new ClosureLoader($container),
132
        ));
133
134
        return new DelegatingLoader($resolver);
135
    }
136
137
    private function isTestEnvironment(): bool
138
    {
139
        return 0 === strpos($this->getEnvironment(), 'test');
140
    }
141
142
    /**
143
     * Remove all container references from all loaded services
144
     */
145
    private function cleanupContainer(ContainerInterface $container): void
146
    {
147
        $containerReflection = new \ReflectionObject($container);
148
        $containerServicesPropertyReflection = $containerReflection->getProperty('services');
149
        $containerServicesPropertyReflection->setAccessible(true);
150
151
        $services = $containerServicesPropertyReflection->getValue($container) ?: [];
152
        foreach ($services as $serviceId => $service) {
153
            if (null === $service) {
154
                continue;
155
            }
156
157
            if (in_array($serviceId, self::IGNORED_SERVICES_DURING_CLEANUP, true)) {
158
                continue;
159
            }
160
161
            $serviceReflection = new \ReflectionObject($service);
162
163
            if ($serviceReflection->implementsInterface(VirtualProxyInterface::class)) {
164
                continue;
165
            }
166
167
            $servicePropertiesReflections = $serviceReflection->getProperties();
168
            $servicePropertiesDefaultValues = $serviceReflection->getDefaultProperties();
169
            foreach ($servicePropertiesReflections as $servicePropertyReflection) {
170
                $defaultPropertyValue = null;
171
                if (isset($servicePropertiesDefaultValues[$servicePropertyReflection->getName()])) {
172
                    $defaultPropertyValue = $servicePropertiesDefaultValues[$servicePropertyReflection->getName()];
173
                }
174
175
                $servicePropertyReflection->setAccessible(true);
176
                $servicePropertyReflection->setValue($service, $defaultPropertyValue);
177
            }
178
        }
179
180
        $containerServicesPropertyReflection->setValue($container, null);
181
    }
182
}
183