GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#93)
by joseph
17:38 queued 30s
created

Container   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 289
Duplicated Lines 0 %

Test Coverage

Coverage 82.19%

Importance

Changes 0
Metric Value
wmc 19
eloc 101
dl 0
loc 289
ccs 60
cts 73
cp 0.8219
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A autoWireServices() 0 5 2
A setUseCache() 0 5 1
A buildSymfonyContainer() 0 22 4
A autoWireConfig() 0 4 1
A autoWireCache() 0 14 2
A configVars() 0 8 1
A addConfiguration() 0 7 1
A setContainer() 0 5 1
A getServices() 0 3 1
A autoWireEntityManager() 0 8 1
A has() 0 3 1
A setupEntityValidator() 0 9 1
A get() 0 6 2
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta;
4
5
use Doctrine\Common\Cache\ArrayCache;
6
use Doctrine\Common\Cache\Cache;
7
use Doctrine\ORM\EntityManager;
8
use Doctrine\ORM\EntityManagerInterface;
9
use Doctrine\ORM\Tools\SchemaTool;
10
use Doctrine\ORM\Tools\SchemaValidator;
11
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\CodeHelper;
12
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\GenerateEmbeddableFromArchetypeCommand;
13
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\GenerateEntityCommand;
14
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\GenerateFieldCommand;
15
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\GenerateRelationsCommand;
16
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\RemoveUnusedRelationsCommand;
17
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\SetEmbeddableCommand;
18
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\SetFieldCommand;
19
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\SetRelationCommand;
20
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Embeddable\ArchetypeEmbeddableGenerator;
21
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Embeddable\EntityEmbeddableSetter;
22
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\EntityGenerator;
23
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\AbstractTestFakerDataProviderUpdater;
24
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\EntityFieldSetter;
25
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\FieldGenerator;
26
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\StandardLibraryTestGenerator;
27
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\FileCreationTransaction;
28
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\FindAndReplaceHelper;
29
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\RelationsGenerator;
30
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
31
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\PathHelper;
32
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\TypeHelper;
33
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\UnusedRelationsRemover;
34
use EdmondsCommerce\DoctrineStaticMeta\Entity\Factory\EntityFactory;
35
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\Validation\EntityValidatorInterface;
36
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\EntitySaver;
37
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\EntitySaverFactory;
38
use EdmondsCommerce\DoctrineStaticMeta\Entity\Validation\EntityValidator;
39
use EdmondsCommerce\DoctrineStaticMeta\Entity\Validation\EntityValidatorFactory;
40
use EdmondsCommerce\DoctrineStaticMeta\EntityManager\EntityManagerFactory;
41
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
42
use EdmondsCommerce\DoctrineStaticMeta\Schema\Database;
43
use EdmondsCommerce\DoctrineStaticMeta\Schema\Schema;
44
use Psr\Container\ContainerExceptionInterface;
45
use Psr\Container\ContainerInterface;
46
use Psr\Container\NotFoundExceptionInterface;
47
use Symfony\Component\DependencyInjection\ContainerBuilder;
48
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
49
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
50
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
51
use Symfony\Component\DependencyInjection\Reference;
52
use Symfony\Component\Filesystem\Filesystem;
53
use Symfony\Component\Validator\Mapping\Cache\DoctrineCache;
54
55
/**
56
 * Class Container
57
 *
58
 * @package EdmondsCommerce\DoctrineStaticMeta
59
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
60
 */
61
class Container implements ContainerInterface
62
{
63
    /**
64
     * This is the list of services managed by this container
65
     *
66
     * This list is used to also generate a PHPStorm meta data file which assists with dynamic type hinting when using
67
     * the container as a service locator
68
     *
69
     * @see ./../../.phpstorm.meta.php/container.meta.php
70
     */
71
    public const SERVICES = [
72
        AbstractTestFakerDataProviderUpdater::class,
73
        ArchetypeEmbeddableGenerator::class,
74
        CodeHelper::class,
75
        Config::class,
76
        Database::class,
77
        DoctrineCache::class,
78
        EntityEmbeddableSetter::class,
79
        EntityFactory::class,
80
        EntityFieldSetter::class,
81
        EntityGenerator::class,
82
        EntityManagerInterface::class,
83
        EntityManagerFactory::class,
84
        EntitySaver::class,
85
        EntitySaverFactory::class,
86
        EntityValidator::class,
87
        EntityValidatorFactory::class,
88
        FieldGenerator::class,
89
        FileCreationTransaction::class,
90
        Filesystem::class,
91
        FindAndReplaceHelper::class,
92
        GenerateEmbeddableFromArchetypeCommand::class,
93
        GenerateEntityCommand::class,
94
        GenerateFieldCommand::class,
95
        GenerateRelationsCommand::class,
96
        NamespaceHelper::class,
97
        PathHelper::class,
98
        RelationsGenerator::class,
99
        RelationsGenerator::class,
100
        RemoveUnusedRelationsCommand::class,
101
        Schema::class,
102
        Schema::class,
103
        SchemaTool::class,
104
        SchemaValidator::class,
105
        SetEmbeddableCommand::class,
106
        SetFieldCommand::class,
107
        SetRelationCommand::class,
108
        StandardLibraryTestGenerator::class,
109
        TypeHelper::class,
110
        UnusedRelationsRemover::class,
111
    ];
112
113
    /**
114
     * The directory that container cache files will be stored
115
     */
116
    public const CACHE_PATH = __DIR__ . '/../cache/';
117
118
    public const SYMFONY_CACHE_PATH = self::CACHE_PATH . '/container.symfony.php';
119
120
    /**
121
     * @var bool
122
     */
123
    private $useCache = false;
124
125
    /**
126
     * @var ContainerInterface
127
     */
128
    private $container;
129
130
    /**
131
     * @param bool $useCache
132
     *
133
     * @return Container
134
     */
135
    public function setUseCache(bool $useCache): Container
136
    {
137
        $this->useCache = $useCache;
138
139
        return $this;
140
    }
141
142
    /**
143
     * @param array $server - normally you would pass in $_SERVER
144
     *
145
     * @throws DoctrineStaticMetaException
146
     */
147 146
    public function buildSymfonyContainer(array $server): void
148
    {
149 146
        if (true === $this->useCache && file_exists(self::SYMFONY_CACHE_PATH)) {
150
            /** @noinspection PhpIncludeInspection */
151
            require self::SYMFONY_CACHE_PATH;
152
            $this->setContainer(new \ProjectServiceContainer());
153
154
            return;
155
        }
156
157
        try {
158 146
            $container = new ContainerBuilder();
159 146
            $this->addConfiguration($container, $server);
160 146
            $container->compile();
161 146
            $this->setContainer($container);
162 146
            $dumper = new PhpDumper($container);
163 146
            file_put_contents(self::SYMFONY_CACHE_PATH, $dumper->dump());
164
        } catch (ServiceNotFoundException | InvalidArgumentException $e) {
165
            throw new DoctrineStaticMetaException(
166
                'Exception building the container: ' . $e->getMessage(),
167
                $e->getCode(),
168
                $e
169
            );
170
        }
171 146
    }
172
173
    /**
174
     * Set a container instance
175
     *
176
     * @param ContainerInterface $container
177
     *
178
     * @return $this
179
     */
180 146
    public function setContainer(ContainerInterface $container): self
181
    {
182 146
        $this->container = $container;
183
184 146
        return $this;
185
    }
186
187
    /**
188
     * Build all the definitions, alias and other configuration for this container. Each of these steps need to be
189
     * carried out to allow the everything to work, however you may wish to change individual bits. Therefore this
190
     * method has been made final, but the individual methods can be overwritten if you extend off the class
191
     *
192
     * @param ContainerBuilder $container
193
     * @param array            $server
194
     *
195
     * @throws \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
196
     * @throws \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
197
     */
198 146
    final public function addConfiguration(ContainerBuilder $container, array $server): void
199
    {
200 146
        $this->autoWireServices($container);
201 146
        $this->autoWireCache($container, $server);
202 146
        $this->autoWireConfig($container, $server);
203 146
        $this->autoWireEntityManager($container);
204 146
        $this->setupEntityValidator($container);
205 146
    }
206
207
    /**
208
     * This takes every class from the getServices method, auto wires them and marks them as public. You may wish to
209
     * override this if you want to mark certain classes as private
210
     *
211
     * @param ContainerBuilder $container
212
     */
213 146
    public function autoWireServices(ContainerBuilder $container): void
214
    {
215 146
        $services = $this->getServices();
216 146
        foreach ($services as $class) {
217 146
            $container->autowire($class, $class)->setPublic(true);
218
        }
219 146
    }
220
221
    /**
222
     * This is a simple wrapper around the class constants. You can use this to add, remove, or replace individual
223
     * services that will be auto wired
224
     *
225
     * @return array
226
     */
227 146
    public function getServices(): array
228
    {
229 146
        return self::SERVICES;
230
    }
231
232
    /**
233
     * This is used to auto wire the doctrine cache. If we are in dev mode then this will always use the Array Cache,
234
     * if not then the cache will be set to what is in the $server array. Override this method if you wish to use
235
     * different logic to handle caching
236
     *
237
     * @param ContainerBuilder $container
238
     * @param array            $server
239
     */
240 146
    public function autoWireCache(ContainerBuilder $container, array $server): void
241
    {
242 146
        $cacheDriver = $server[Config::PARAM_DOCTRINE_CACHE_DRIVER] ?? Config::DEFAULT_DOCTRINE_CACHE_DRIVER;
243 146
        $container->autowire($cacheDriver);
244
        /**
245
         * Which Cache Driver is used for the Cache Inteface?
246
         *
247
         * If Dev mode, we always use the Array Cache
248
         *
249
         * Otherwise, we use the Configured Cache driver (which defaults to Array Cache)
250
         */
251 146
        $cache = ($server[Config::PARAM_DEVMODE] ?? false) ? ArrayCache::class : $cacheDriver;
252 146
        $container->setAlias(Cache::class, $cache);
253 146
        $container->getDefinition(DoctrineCache::class)->addArgument(new Reference($cacheDriver));
254 146
    }
255
256
    /**
257
     * This is used to auto wire the config interface. It sets the $server param as a constructor argument and then
258
     * sets the concrete class as the implementation for the Interface. Override this if you wish to use different
259
     * logic for where the config comes from
260
     *
261
     * @param ContainerBuilder $container
262
     * @param array            $server
263
     */
264 146
    public function autoWireConfig(ContainerBuilder $container, array $server): void
265
    {
266 146
        $container->getDefinition(Config::class)->setArgument('$server', $this->configVars($server));
267 146
        $container->setAlias(ConfigInterface::class, Config::class);
268 146
    }
269
270
    /**
271
     * Take the $server array, normally a copy of $_SERVER, and pull out just the bits required by config
272
     *
273
     * @param array $server
274
     *
275
     * @return array
276
     */
277 146
    protected function configVars(array $server): array
278
    {
279 146
        $return = array_intersect_key(
280 146
            $server,
281 146
            array_flip(ConfigInterface::PARAMS)
282
        );
283
284 146
        return $return;
285
    }
286
287
    /**
288
     * This is used to auto wire the entity manager. It first adds the DSM factory as the factory for the class, and
289
     * sets the Entity Manager as the implementation of the interface. Overrider this if you want to use your own
290
     * factory to create and configure the entity manager
291
     *
292
     * @param ContainerBuilder $container
293
     */
294 146
    public function autoWireEntityManager(ContainerBuilder $container): void
295
    {
296 146
        $container->getDefinition(EntityManagerInterface::class)
297 146
                  ->addArgument(new Reference(Config::class))
298 146
                  ->setFactory(
299
                      [
300 146
                          new Reference(EntityManagerFactory::class),
301 146
                          'getEntityManager',
302
                      ]
303
                  );
304
    }
305
306 146
    /**
307 146
     * This is used to auto wire and set the factory for the entity validator. Override this if you wish to use you own
308
     * validator
309
     *
310
     * @param ContainerBuilder $container
311
     */
312
    public function setupEntityValidator(ContainerBuilder $container): void
313
    {
314
        $container->setAlias(EntityValidatorInterface::class, EntityValidator::class);
315 146
        $container->getDefinition(EntityValidator::class)
316
                  ->addArgument(new Reference(Cache::class))
317 146
                  ->setFactory(
318 146
                      [
319 146
                          new Reference(EntityValidatorFactory::class),
320 146
                          'getEntityValidator',
321
                      ]
322 146
                  );
323 146
    }
324
325
    /**
326 146
     * @param string $id
327
     *
328
     * @return mixed
329
     * @SuppressWarnings(PHPMD.ShortVariable)
330
     * @throws DoctrineStaticMetaException
331
     */
332
    public function get($id)
333
    {
334
        try {
335 142
            return $this->container->get($id);
336
        } catch (ContainerExceptionInterface | NotFoundExceptionInterface $e) {
337
            throw new DoctrineStaticMetaException('Exception getting service ' . $id, $e->getCode(), $e);
0 ignored issues
show
Bug introduced by
The method getCode() does not exist on Psr\Container\ContainerExceptionInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Psr\Container\NotFoundExceptionInterface or Symfony\Component\Depend...tion\ExceptionInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

337
            throw new DoctrineStaticMetaException('Exception getting service ' . $id, $e->/** @scrutinizer ignore-call */ getCode(), $e);
Loading history...
338 142
        }
339
    }
340
341
    /**
342
     * @param string $id
343
     * @SuppressWarnings(PHPMD.ShortVariable)
344
     *
345
     * @return bool|void
346
     */
347
    public function has($id)
348
    {
349
        return $this->container->has($id);
350
    }
351
}
352