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