Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

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