‪TYPO3CMS  10.4
FailsafeContainer.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Container\ContainerInterface;
21 
25 class ‪FailsafeContainer implements ContainerInterface
26 {
30  private ‪$entries = [];
31 
35  private ‪$factories = [];
36 
45  public function ‪__construct(iterable $providers = [], array ‪$entries = [])
46  {
47  $this->entries = ‪$entries;
48 
49  ‪$factories = [];
50  foreach ($providers as $provider) {
52  ‪$factories = $provider->getFactories() + ‪$factories;
53  foreach ($provider->getExtensions() as $id => $extension) {
54  // Decorate a previously defined extension or if that is not available,
55  // create a lazy lookup to a factory from the list of vanilla factories.
56  // Lazy because we currently can not know whether a factory will only
57  // become available due to a subsequent provider.
58  $innerFactory = $this->factories[$id] ?? function (ContainerInterface $c) use (&‪$factories, $id) {
59  return isset(‪$factories[$id]) ? ‪$factories[$id]($c) : null;
60  };
61 
62  $this->factories[$id] = function (ContainerInterface $container) use ($extension, $innerFactory) {
63  $previous = $innerFactory($container);
64  return $extension($container, $previous);
65  };
66  }
67  }
68 
69  // Add factories to the list of factories for services that were not extended.
70  // (i.e those that have not been specified in getExtensions)
71  $this->factories += ‪$factories;
72  }
73 
78  public function ‪has($id)
79  {
80  return array_key_exists($id, $this->entries) || array_key_exists($id, $this->factories);
81  }
82 
87  private function ‪create(string $id)
88  {
89  $factory = $this->factories[$id] ?? null;
90 
91  if ((bool)$factory) {
92  // Remove factory as it is no longer required.
93  // Set factory to false to be able to detect
94  // cyclic dependency loops.
95  $this->factories[$id] = false;
96 
97  return $this->entries[$id] = $factory($this);
98  }
99  if (array_key_exists($id, $this->entries)) {
100  // This condition is triggered in the unlikely case that the entry is null
101  // Note: That is because the coalesce operator used in get() can not handle that
102  return $this->entries[$id];
103  }
104  if ($factory === null) {
105  throw new ‪NotFoundException('Container entry "' . $id . '" is not available.', 1519978105);
106  }
107  // if ($factory === false)
108  throw new ‪ContainerException('Container entry "' . $id . '" is part of a cyclic dependency chain.', 1520175002);
109  }
110 
115  public function get($id)
116  {
117  return $this->entries[$id] ?? $this->‪create($id);
118  }
119 }
‪TYPO3\CMS\Core\DependencyInjection\FailsafeContainer\has
‪bool has($id)
Definition: FailsafeContainer.php:76
‪TYPO3\CMS\Core\DependencyInjection\ContainerException
Definition: ContainerException.php:27
‪TYPO3\CMS\Core\DependencyInjection\FailsafeContainer\$entries
‪array $entries
Definition: FailsafeContainer.php:29
‪TYPO3\CMS\Core\DependencyInjection\FailsafeContainer\create
‪mixed create(string $id)
Definition: FailsafeContainer.php:85
‪TYPO3\CMS\Core\DependencyInjection\FailsafeContainer
Definition: FailsafeContainer.php:26
‪TYPO3\CMS\Core\DependencyInjection
Definition: AutowireInjectMethodsPass.php:18
‪TYPO3\CMS\Core\DependencyInjection\FailsafeContainer\$factories
‪array $factories
Definition: FailsafeContainer.php:33
‪TYPO3\CMS\Core\DependencyInjection\FailsafeContainer\__construct
‪__construct(iterable $providers=[], array $entries=[])
Definition: FailsafeContainer.php:43
‪TYPO3\CMS\Core\DependencyInjection\NotFoundException
Definition: NotFoundException.php:27