Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

Container.php

Zuletzt modifiziert: 09.10.2024, 12:54 - Dateigröße: 19.54 KiB


001  <?php
002   
003  /*
004   * This file is part of the Symfony package.
005   *
006   * (c) Fabien Potencier <fabien@symfony.com>
007   *
008   * For the full copyright and license information, please view the LICENSE
009   * file that was distributed with this source code.
010   */
011   
012  namespace Symfony\Component\DependencyInjection;
013   
014  use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
015  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
016  use Symfony\Component\DependencyInjection\Exception\LogicException;
017  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
018  use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
019  use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
020  use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
021  use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
022  use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
023   
024  /**
025   * Container is a dependency injection container.
026   *
027   * It gives access to object instances (services).
028   *
029   * Services and parameters are simple key/pair stores.
030   *
031   * Parameter and service keys are case insensitive.
032   *
033   * A service id can contain lowercased letters, digits, underscores, and dots.
034   * Underscores are used to separate words, and dots to group services
035   * under namespaces:
036   *
037   * <ul>
038   *   <li>request</li>
039   *   <li>mysql_session_storage</li>
040   *   <li>symfony.mysql_session_storage</li>
041   * </ul>
042   *
043   * A service can also be defined by creating a method named
044   * getXXXService(), where XXX is the camelized version of the id:
045   *
046   * <ul>
047   *   <li>request -> getRequestService()</li>
048   *   <li>mysql_session_storage -> getMysqlSessionStorageService()</li>
049   *   <li>symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()</li>
050   * </ul>
051   *
052   * The container can have three possible behaviors when a service does not exist:
053   *
054   *  * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default)
055   *  * NULL_ON_INVALID_REFERENCE:      Returns null
056   *  * IGNORE_ON_INVALID_REFERENCE:    Ignores the wrapping command asking for the reference
057   *                                    (for instance, ignore a setter if the service does not exist)
058   *
059   * @author Fabien Potencier <fabien@symfony.com>
060   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
061   */
062  class Container implements IntrospectableContainerInterface, ResettableContainerInterface
063  {
064      /**
065       * @var ParameterBagInterface
066       */
067      protected $parameterBag;
068   
069      protected $services = array();
070      protected $methodMap = array();
071      protected $aliases = array();
072      protected $scopes = array();
073      protected $scopeChildren = array();
074      protected $scopedServices = array();
075      protected $scopeStacks = array();
076      protected $loading = array();
077   
078      private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_');
079   
080      /**
081       * @param ParameterBagInterface $parameterBag A ParameterBagInterface instance
082       */
083      public function __construct(ParameterBagInterface $parameterBag = null)
084      {
085          $this->parameterBag = $parameterBag ?: new ParameterBag();
086      }
087   
088      /**
089       * Compiles the container.
090       *
091       * This method does two things:
092       *
093       *  * Parameter values are resolved;
094       *  * The parameter bag is frozen.
095       */
096      public function compile()
097      {
098          $this->parameterBag->resolve();
099   
100          $this->parameterBag = new FrozenParameterBag($this->parameterBag->all());
101      }
102   
103      /**
104       * Returns true if the container parameter bag are frozen.
105       *
106       * @return bool true if the container parameter bag are frozen, false otherwise
107       */
108      public function isFrozen()
109      {
110          return $this->parameterBag instanceof FrozenParameterBag;
111      }
112   
113      /**
114       * Gets the service container parameter bag.
115       *
116       * @return ParameterBagInterface A ParameterBagInterface instance
117       */
118      public function getParameterBag()
119      {
120          return $this->parameterBag;
121      }
122   
123      /**
124       * Gets a parameter.
125       *
126       * @param string $name The parameter name
127       *
128       * @return mixed The parameter value
129       *
130       * @throws InvalidArgumentException if the parameter is not defined
131       */
132      public function getParameter($name)
133      {
134          return $this->parameterBag->get($name);
135      }
136   
137      /**
138       * Checks if a parameter exists.
139       *
140       * @param string $name The parameter name
141       *
142       * @return bool The presence of parameter in container
143       */
144      public function hasParameter($name)
145      {
146          return $this->parameterBag->has($name);
147      }
148   
149      /**
150       * Sets a parameter.
151       *
152       * @param string $name  The parameter name
153       * @param mixed  $value The parameter value
154       */
155      public function setParameter($name, $value)
156      {
157          $this->parameterBag->set($name, $value);
158      }
159   
160      /**
161       * Sets a service.
162       *
163       * Setting a service to null resets the service: has() returns false and get()
164       * behaves in the same way as if the service was never created.
165       *
166       * Note: The $scope parameter is deprecated since version 2.8 and will be removed in 3.0.
167       *
168       * @param string $id      The service identifier
169       * @param object $service The service instance
170       * @param string $scope   The scope of the service
171       *
172       * @throws RuntimeException         When trying to set a service in an inactive scope
173       * @throws InvalidArgumentException When trying to set a service in the prototype scope
174       */
175      public function set($id, $service, $scope = self::SCOPE_CONTAINER)
176      {
177          if (!in_array($scope, array('container', 'request')) || ('request' === $scope && 'request' !== $id)) {
178              @trigger_error('The concept of container scopes is deprecated since version 2.8 and will be removed in 3.0. Omit the third parameter.', E_USER_DEPRECATED);
179          }
180   
181          if (self::SCOPE_PROTOTYPE === $scope) {
182              throw new InvalidArgumentException(sprintf('You cannot set service "%s" of scope "prototype".', $id));
183          }
184   
185          $id = strtolower($id);
186   
187          if ('service_container' === $id) {
188              // BC: 'service_container' is no longer a self-reference but always
189              // $this, so ignore this call.
190              // @todo Throw InvalidArgumentException in next major release.
191              return;
192          }
193          if (self::SCOPE_CONTAINER !== $scope) {
194              if (!isset($this->scopedServices[$scope])) {
195                  throw new RuntimeException(sprintf('You cannot set service "%s" of inactive scope.', $id));
196              }
197   
198              $this->scopedServices[$scope][$id] = $service;
199          }
200   
201          if (isset($this->aliases[$id])) {
202              unset($this->aliases[$id]);
203          }
204   
205          $this->services[$id] = $service;
206   
207          if (method_exists($this, $method = 'synchronize'.strtr($id, $this->underscoreMap).'Service')) {
208              $this->$method();
209          }
210   
211          if (null === $service) {
212              if (self::SCOPE_CONTAINER !== $scope) {
213                  unset($this->scopedServices[$scope][$id]);
214              }
215   
216              unset($this->services[$id]);
217          }
218      }
219   
220      /**
221       * Returns true if the given service is defined.
222       *
223       * @param string $id The service identifier
224       *
225       * @return bool true if the service is defined, false otherwise
226       */
227      public function has($id)
228      {
229          for ($i = 2;;) {
230              if ('service_container' === $id
231                  || isset($this->aliases[$id])
232                  || isset($this->services[$id])
233                  || array_key_exists($id, $this->services)
234              ) {
235                  return true;
236              }
237              if (--$i && $id !== $lcId = strtolower($id)) {
238                  $id = $lcId;
239              } else {
240                  return method_exists($this, 'get'.strtr($id, $this->underscoreMap).'Service');
241              }
242          }
243      }
244   
245      /**
246       * Gets a service.
247       *
248       * If a service is defined both through a set() method and
249       * with a get{$id}Service() method, the former has always precedence.
250       *
251       * @param string $id              The service identifier
252       * @param int    $invalidBehavior The behavior when the service does not exist
253       *
254       * @return object The associated service
255       *
256       * @throws ServiceCircularReferenceException When a circular reference is detected
257       * @throws ServiceNotFoundException          When the service is not defined
258       * @throws \Exception                        if an exception has been thrown when the service has been resolved
259       *
260       * @see Reference
261       */
262      public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE)
263      {
264          // Attempt to retrieve the service by checking first aliases then
265          // available services. Service IDs are case insensitive, however since
266          // this method can be called thousands of times during a request, avoid
267          // calling strtolower() unless necessary.
268          for ($i = 2;;) {
269              if ('service_container' === $id) {
270                  return $this;
271              }
272              if (isset($this->aliases[$id])) {
273                  $id = $this->aliases[$id];
274              }
275              // Re-use shared service instance if it exists.
276              if (isset($this->services[$id]) || array_key_exists($id, $this->services)) {
277                  return $this->services[$id];
278              }
279   
280              if (isset($this->loading[$id])) {
281                  throw new ServiceCircularReferenceException($id, array_keys($this->loading));
282              }
283   
284              if (isset($this->methodMap[$id])) {
285                  $method = $this->methodMap[$id];
286              } elseif (--$i && $id !== $lcId = strtolower($id)) {
287                  $id = $lcId;
288                  continue;
289              } elseif (method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) {
290                  // $method is set to the right value, proceed
291              } else {
292                  if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
293                      if (!$id) {
294                          throw new ServiceNotFoundException($id);
295                      }
296   
297                      $alternatives = array();
298                      foreach ($this->getServiceIds() as $knownId) {
299                          $lev = levenshtein($id, $knownId);
300                          if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) {
301                              $alternatives[] = $knownId;
302                          }
303                      }
304   
305                      throw new ServiceNotFoundException($id, null, null, $alternatives);
306                  }
307   
308                  return;
309              }
310   
311              $this->loading[$id] = true;
312   
313              try {
314                  $service = $this->$method();
315              } catch (\Exception $e) {
316                  unset($this->loading[$id]);
317                  unset($this->services[$id]);
318   
319                  if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
320                      return;
321                  }
322   
323                  throw $e;
324              } catch (\Throwable $e) {
325                  unset($this->loading[$id]);
326                  unset($this->services[$id]);
327   
328                  throw $e;
329              }
330   
331              unset($this->loading[$id]);
332   
333              return $service;
334          }
335      }
336   
337      /**
338       * Returns true if the given service has actually been initialized.
339       *
340       * @param string $id The service identifier
341       *
342       * @return bool true if service has already been initialized, false otherwise
343       */
344      public function initialized($id)
345      {
346          $id = strtolower($id);
347   
348          if ('service_container' === $id) {
349              // BC: 'service_container' was a synthetic service previously.
350              // @todo Change to false in next major release.
351              return true;
352          }
353   
354          if (isset($this->aliases[$id])) {
355              $id = $this->aliases[$id];
356          }
357   
358          return isset($this->services[$id]) || array_key_exists($id, $this->services);
359      }
360   
361      /**
362       * {@inheritdoc}
363       */
364      public function reset()
365      {
366          if (!empty($this->scopedServices)) {
367              throw new LogicException('Resetting the container is not allowed when a scope is active.');
368          }
369   
370          $this->services = array();
371      }
372   
373      /**
374       * Gets all service ids.
375       *
376       * @return array An array of all defined service ids
377       */
378      public function getServiceIds()
379      {
380          $ids = array();
381          foreach (get_class_methods($this) as $method) {
382              if (preg_match('/^get(.+)Service$/', $method, $match)) {
383                  $ids[] = self::underscore($match[1]);
384              }
385          }
386          $ids[] = 'service_container';
387   
388          return array_unique(array_merge($ids, array_keys($this->services)));
389      }
390   
391      /**
392       * This is called when you enter a scope.
393       *
394       * @param string $name
395       *
396       * @throws RuntimeException         When the parent scope is inactive
397       * @throws InvalidArgumentException When the scope does not exist
398       *
399       * @deprecated since version 2.8, to be removed in 3.0.
400       */
401      public function enterScope($name)
402      {
403          if ('request' !== $name) {
404              @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
405          }
406   
407          if (!isset($this->scopes[$name])) {
408              throw new InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name));
409          }
410   
411          if (self::SCOPE_CONTAINER !== $this->scopes[$name] && !isset($this->scopedServices[$this->scopes[$name]])) {
412              throw new RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name]));
413          }
414   
415          // check if a scope of this name is already active, if so we need to
416          // remove all services of this scope, and those of any of its child
417          // scopes from the global services map
418          if (isset($this->scopedServices[$name])) {
419              $services = array($this->services, $name => $this->scopedServices[$name]);
420              unset($this->scopedServices[$name]);
421   
422              foreach ($this->scopeChildren[$name] as $child) {
423                  if (isset($this->scopedServices[$child])) {
424                      $services[$child] = $this->scopedServices[$child];
425                      unset($this->scopedServices[$child]);
426                  }
427              }
428   
429              // update global map
430              $this->services = call_user_func_array('array_diff_key', $services);
431              array_shift($services);
432   
433              // add stack entry for this scope so we can restore the removed services later
434              if (!isset($this->scopeStacks[$name])) {
435                  $this->scopeStacks[$name] = new \SplStack();
436              }
437              $this->scopeStacks[$name]->push($services);
438          }
439   
440          $this->scopedServices[$name] = array();
441      }
442   
443      /**
444       * This is called to leave the current scope, and move back to the parent
445       * scope.
446       *
447       * @param string $name The name of the scope to leave
448       *
449       * @throws InvalidArgumentException if the scope is not active
450       *
451       * @deprecated since version 2.8, to be removed in 3.0.
452       */
453      public function leaveScope($name)
454      {
455          if ('request' !== $name) {
456              @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
457          }
458   
459          if (!isset($this->scopedServices[$name])) {
460              throw new InvalidArgumentException(sprintf('The scope "%s" is not active.', $name));
461          }
462   
463          // remove all services of this scope, or any of its child scopes from
464          // the global service map
465          $services = array($this->services, $this->scopedServices[$name]);
466          unset($this->scopedServices[$name]);
467   
468          foreach ($this->scopeChildren[$name] as $child) {
469              if (isset($this->scopedServices[$child])) {
470                  $services[] = $this->scopedServices[$child];
471                  unset($this->scopedServices[$child]);
472              }
473          }
474   
475          // update global map
476          $this->services = call_user_func_array('array_diff_key', $services);
477   
478          // check if we need to restore services of a previous scope of this type
479          if (isset($this->scopeStacks[$name]) && count($this->scopeStacks[$name]) > 0) {
480              $services = $this->scopeStacks[$name]->pop();
481              $this->scopedServices += $services;
482   
483              if ($this->scopeStacks[$name]->isEmpty()) {
484                  unset($this->scopeStacks[$name]);
485              }
486   
487              foreach ($services as $array) {
488                  foreach ($array as $id => $service) {
489                      $this->set($id, $service, $name);
490                  }
491              }
492          }
493      }
494   
495      /**
496       * Adds a scope to the container.
497       *
498       * @param ScopeInterface $scope
499       *
500       * @throws InvalidArgumentException
501       *
502       * @deprecated since version 2.8, to be removed in 3.0.
503       */
504      public function addScope(ScopeInterface $scope)
505      {
506          $name = $scope->getName();
507          $parentScope = $scope->getParentName();
508   
509          if ('request' !== $name) {
510              @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
511          }
512          if (self::SCOPE_CONTAINER === $name || self::SCOPE_PROTOTYPE === $name) {
513              throw new InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name));
514          }
515          if (isset($this->scopes[$name])) {
516              throw new InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name));
517          }
518          if (self::SCOPE_CONTAINER !== $parentScope && !isset($this->scopes[$parentScope])) {
519              throw new InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope));
520          }
521   
522          $this->scopes[$name] = $parentScope;
523          $this->scopeChildren[$name] = array();
524   
525          // normalize the child relations
526          while ($parentScope !== self::SCOPE_CONTAINER) {
527              $this->scopeChildren[$parentScope][] = $name;
528              $parentScope = $this->scopes[$parentScope];
529          }
530      }
531   
532      /**
533       * Returns whether this container has a certain scope.
534       *
535       * @param string $name The name of the scope
536       *
537       * @return bool
538       *
539       * @deprecated since version 2.8, to be removed in 3.0.
540       */
541      public function hasScope($name)
542      {
543          if ('request' !== $name) {
544              @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
545          }
546   
547          return isset($this->scopes[$name]);
548      }
549   
550      /**
551       * Returns whether this scope is currently active.
552       *
553       * This does not actually check if the passed scope actually exists.
554       *
555       * @param string $name
556       *
557       * @return bool
558       *
559       * @deprecated since version 2.8, to be removed in 3.0.
560       */
561      public function isScopeActive($name)
562      {
563          @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
564   
565          return isset($this->scopedServices[$name]);
566      }
567   
568      /**
569       * Camelizes a string.
570       *
571       * @param string $id A string to camelize
572       *
573       * @return string The camelized string
574       */
575      public static function camelize($id)
576      {
577          return strtr(ucwords(strtr($id, array('_' => ' ', '.' => '_ ', '\\' => '_ '))), array(' ' => ''));
578      }
579   
580      /**
581       * A string to underscore.
582       *
583       * @param string $id The string to underscore
584       *
585       * @return string The underscored string
586       */
587      public static function underscore($id)
588      {
589          return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), str_replace('_', '.', $id)));
590      }
591   
592      private function __clone()
593      {
594      }
595  }
596