[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/symfony/dependency-injection/Loader/ -> YamlFileLoader.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\DependencyInjection\Loader;
  13  
  14  use Symfony\Component\Config\Resource\FileResource;
  15  use Symfony\Component\DependencyInjection\Alias;
  16  use Symfony\Component\DependencyInjection\ContainerInterface;
  17  use Symfony\Component\DependencyInjection\Definition;
  18  use Symfony\Component\DependencyInjection\DefinitionDecorator;
  19  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
  20  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
  21  use Symfony\Component\DependencyInjection\Reference;
  22  use Symfony\Component\ExpressionLanguage\Expression;
  23  use Symfony\Component\Yaml\Exception\ParseException;
  24  use Symfony\Component\Yaml\Parser as YamlParser;
  25  
  26  /**
  27   * YamlFileLoader loads YAML files service definitions.
  28   *
  29   * The YAML format does not support anonymous services (cf. the XML loader).
  30   *
  31   * @author Fabien Potencier <fabien@symfony.com>
  32   */
  33  class YamlFileLoader extends FileLoader
  34  {
  35      private $yamlParser;
  36  
  37      /**
  38       * {@inheritdoc}
  39       */
  40      public function load($resource, $type = null)
  41      {
  42          $path = $this->locator->locate($resource);
  43  
  44          $content = $this->loadFile($path);
  45  
  46          $this->container->addResource(new FileResource($path));
  47  
  48          // empty file
  49          if (null === $content) {
  50              return;
  51          }
  52  
  53          // imports
  54          $this->parseImports($content, $path);
  55  
  56          // parameters
  57          if (isset($content['parameters'])) {
  58              if (!\is_array($content['parameters'])) {
  59                  throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $resource));
  60              }
  61  
  62              foreach ($content['parameters'] as $key => $value) {
  63                  $this->container->setParameter($key, $this->resolveServices($value));
  64              }
  65          }
  66  
  67          // extensions
  68          $this->loadFromExtensions($content);
  69  
  70          // services
  71          $this->parseDefinitions($content, $resource);
  72      }
  73  
  74      /**
  75       * {@inheritdoc}
  76       */
  77      public function supports($resource, $type = null)
  78      {
  79          return \is_string($resource) && \in_array(pathinfo($resource, PATHINFO_EXTENSION), array('yml', 'yaml'), true);
  80      }
  81  
  82      /**
  83       * Parses all imports.
  84       *
  85       * @param array  $content
  86       * @param string $file
  87       */
  88      private function parseImports(array $content, $file)
  89      {
  90          if (!isset($content['imports'])) {
  91              return;
  92          }
  93  
  94          if (!\is_array($content['imports'])) {
  95              throw new InvalidArgumentException(sprintf('The "imports" key should contain an array in %s. Check your YAML syntax.', $file));
  96          }
  97  
  98          $defaultDirectory = \dirname($file);
  99          foreach ($content['imports'] as $import) {
 100              if (!\is_array($import)) {
 101                  throw new InvalidArgumentException(sprintf('The values in the "imports" key should be arrays in %s. Check your YAML syntax.', $file));
 102              }
 103  
 104              $this->setCurrentDir($defaultDirectory);
 105              $this->import($import['resource'], null, isset($import['ignore_errors']) ? (bool) $import['ignore_errors'] : false, $file);
 106          }
 107      }
 108  
 109      /**
 110       * Parses definitions.
 111       *
 112       * @param array  $content
 113       * @param string $file
 114       */
 115      private function parseDefinitions(array $content, $file)
 116      {
 117          if (!isset($content['services'])) {
 118              return;
 119          }
 120  
 121          if (!\is_array($content['services'])) {
 122              throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file));
 123          }
 124  
 125          foreach ($content['services'] as $id => $service) {
 126              $this->parseDefinition($id, $service, $file);
 127          }
 128      }
 129  
 130      /**
 131       * Parses a definition.
 132       *
 133       * @param string       $id
 134       * @param array|string $service
 135       * @param string       $file
 136       *
 137       * @throws InvalidArgumentException When tags are invalid
 138       */
 139      private function parseDefinition($id, $service, $file)
 140      {
 141          if (\is_string($service) && 0 === strpos($service, '@')) {
 142              $this->container->setAlias($id, substr($service, 1));
 143  
 144              return;
 145          }
 146  
 147          if (!\is_array($service)) {
 148              throw new InvalidArgumentException(sprintf('A service definition must be an array or a string starting with "@" but %s found for service "%s" in %s. Check your YAML syntax.', \gettype($service), $id, $file));
 149          }
 150  
 151          if (isset($service['alias'])) {
 152              $public = !array_key_exists('public', $service) || (bool) $service['public'];
 153              $this->container->setAlias($id, new Alias($service['alias'], $public));
 154  
 155              return;
 156          }
 157  
 158          if (isset($service['parent'])) {
 159              $definition = new DefinitionDecorator($service['parent']);
 160          } else {
 161              $definition = new Definition();
 162          }
 163  
 164          if (isset($service['class'])) {
 165              $definition->setClass($service['class']);
 166          }
 167  
 168          if (isset($service['shared'])) {
 169              $definition->setShared($service['shared']);
 170          }
 171  
 172          if (isset($service['scope'])) {
 173              if ('request' !== $id) {
 174                  @trigger_error(sprintf('The "scope" key of service "%s" in file "%s" is deprecated since Symfony 2.8 and will be removed in 3.0.', $id, $file), E_USER_DEPRECATED);
 175              }
 176              $definition->setScope($service['scope'], false);
 177          }
 178  
 179          if (isset($service['synthetic'])) {
 180              $definition->setSynthetic($service['synthetic']);
 181          }
 182  
 183          if (isset($service['synchronized'])) {
 184              @trigger_error(sprintf('The "synchronized" key of service "%s" in file "%s" is deprecated since Symfony 2.7 and will be removed in 3.0.', $id, $file), E_USER_DEPRECATED);
 185              $definition->setSynchronized($service['synchronized'], 'request' !== $id);
 186          }
 187  
 188          if (isset($service['lazy'])) {
 189              $definition->setLazy($service['lazy']);
 190          }
 191  
 192          if (isset($service['public'])) {
 193              $definition->setPublic($service['public']);
 194          }
 195  
 196          if (isset($service['abstract'])) {
 197              $definition->setAbstract($service['abstract']);
 198          }
 199  
 200          if (array_key_exists('deprecated', $service)) {
 201              $definition->setDeprecated(true, $service['deprecated']);
 202          }
 203  
 204          if (isset($service['factory'])) {
 205              if (\is_string($service['factory'])) {
 206                  if (false !== strpos($service['factory'], ':') && false === strpos($service['factory'], '::')) {
 207                      $parts = explode(':', $service['factory']);
 208                      $definition->setFactory(array($this->resolveServices('@'.$parts[0]), $parts[1]));
 209                  } else {
 210                      $definition->setFactory($service['factory']);
 211                  }
 212              } else {
 213                  $definition->setFactory(array($this->resolveServices($service['factory'][0]), $service['factory'][1]));
 214              }
 215          }
 216  
 217          if (isset($service['factory_class'])) {
 218              @trigger_error(sprintf('The "factory_class" key of service "%s" in file "%s" is deprecated since Symfony 2.6 and will be removed in 3.0. Use "factory" instead.', $id, $file), E_USER_DEPRECATED);
 219              $definition->setFactoryClass($service['factory_class']);
 220          }
 221  
 222          if (isset($service['factory_method'])) {
 223              @trigger_error(sprintf('The "factory_method" key of service "%s" in file "%s" is deprecated since Symfony 2.6 and will be removed in 3.0. Use "factory" instead.', $id, $file), E_USER_DEPRECATED);
 224              $definition->setFactoryMethod($service['factory_method']);
 225          }
 226  
 227          if (isset($service['factory_service'])) {
 228              @trigger_error(sprintf('The "factory_service" key of service "%s" in file "%s" is deprecated since Symfony 2.6 and will be removed in 3.0. Use "factory" instead.', $id, $file), E_USER_DEPRECATED);
 229              $definition->setFactoryService($service['factory_service']);
 230          }
 231  
 232          if (isset($service['file'])) {
 233              $definition->setFile($service['file']);
 234          }
 235  
 236          if (isset($service['arguments'])) {
 237              $definition->setArguments($this->resolveServices($service['arguments']));
 238          }
 239  
 240          if (isset($service['properties'])) {
 241              $definition->setProperties($this->resolveServices($service['properties']));
 242          }
 243  
 244          if (isset($service['configurator'])) {
 245              if (\is_string($service['configurator'])) {
 246                  $definition->setConfigurator($service['configurator']);
 247              } else {
 248                  $definition->setConfigurator(array($this->resolveServices($service['configurator'][0]), $service['configurator'][1]));
 249              }
 250          }
 251  
 252          if (isset($service['calls'])) {
 253              if (!\is_array($service['calls'])) {
 254                  throw new InvalidArgumentException(sprintf('Parameter "calls" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
 255              }
 256  
 257              foreach ($service['calls'] as $call) {
 258                  if (isset($call['method'])) {
 259                      $method = $call['method'];
 260                      $args = isset($call['arguments']) ? $this->resolveServices($call['arguments']) : array();
 261                  } else {
 262                      $method = $call[0];
 263                      $args = isset($call[1]) ? $this->resolveServices($call[1]) : array();
 264                  }
 265  
 266                  $definition->addMethodCall($method, $args);
 267              }
 268          }
 269  
 270          if (isset($service['tags'])) {
 271              if (!\is_array($service['tags'])) {
 272                  throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
 273              }
 274  
 275              foreach ($service['tags'] as $tag) {
 276                  if (!\is_array($tag)) {
 277                      throw new InvalidArgumentException(sprintf('A "tags" entry must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
 278                  }
 279  
 280                  if (!isset($tag['name'])) {
 281                      throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file));
 282                  }
 283  
 284                  if (!\is_string($tag['name']) || '' === $tag['name']) {
 285                      throw new InvalidArgumentException(sprintf('The tag name for service "%s" in %s must be a non-empty string.', $id, $file));
 286                  }
 287  
 288                  $name = $tag['name'];
 289                  unset($tag['name']);
 290  
 291                  foreach ($tag as $attribute => $value) {
 292                      if (!is_scalar($value) && null !== $value) {
 293                          throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in %s. Check your YAML syntax.', $id, $name, $attribute, $file));
 294                      }
 295                  }
 296  
 297                  $definition->addTag($name, $tag);
 298              }
 299          }
 300  
 301          if (isset($service['decorates'])) {
 302              if ('' !== $service['decorates'] && '@' === $service['decorates'][0]) {
 303                  throw new InvalidArgumentException(sprintf('The value of the "decorates" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $id, $service['decorates'], substr($service['decorates'], 1)));
 304              }
 305  
 306              $renameId = isset($service['decoration_inner_name']) ? $service['decoration_inner_name'] : null;
 307              $priority = isset($service['decoration_priority']) ? $service['decoration_priority'] : 0;
 308              $definition->setDecoratedService($service['decorates'], $renameId, $priority);
 309          }
 310  
 311          if (isset($service['autowire'])) {
 312              $definition->setAutowired($service['autowire']);
 313          }
 314  
 315          if (isset($service['autowiring_types'])) {
 316              if (\is_string($service['autowiring_types'])) {
 317                  $definition->addAutowiringType($service['autowiring_types']);
 318              } else {
 319                  if (!\is_array($service['autowiring_types'])) {
 320                      throw new InvalidArgumentException(sprintf('Parameter "autowiring_types" must be a string or an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
 321                  }
 322  
 323                  foreach ($service['autowiring_types'] as $autowiringType) {
 324                      if (!\is_string($autowiringType)) {
 325                          throw new InvalidArgumentException(sprintf('A "autowiring_types" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file));
 326                      }
 327  
 328                      $definition->addAutowiringType($autowiringType);
 329                  }
 330              }
 331          }
 332  
 333          $this->container->setDefinition($id, $definition);
 334      }
 335  
 336      /**
 337       * Loads a YAML file.
 338       *
 339       * @param string $file
 340       *
 341       * @return array The file content
 342       *
 343       * @throws InvalidArgumentException when the given file is not a local file or when it does not exist
 344       */
 345      protected function loadFile($file)
 346      {
 347          if (!class_exists('Symfony\Component\Yaml\Parser')) {
 348              throw new RuntimeException('Unable to load YAML config files as the Symfony Yaml Component is not installed.');
 349          }
 350  
 351          if (!stream_is_local($file)) {
 352              throw new InvalidArgumentException(sprintf('This is not a local file "%s".', $file));
 353          }
 354  
 355          if (!file_exists($file)) {
 356              throw new InvalidArgumentException(sprintf('The file "%s" does not exist.', $file));
 357          }
 358  
 359          if (null === $this->yamlParser) {
 360              $this->yamlParser = new YamlParser();
 361          }
 362  
 363          try {
 364              $configuration = $this->yamlParser->parse(file_get_contents($file));
 365          } catch (ParseException $e) {
 366              throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $file), 0, $e);
 367          }
 368  
 369          return $this->validate($configuration, $file);
 370      }
 371  
 372      /**
 373       * Validates a YAML file.
 374       *
 375       * @param mixed  $content
 376       * @param string $file
 377       *
 378       * @return array
 379       *
 380       * @throws InvalidArgumentException When service file is not valid
 381       */
 382      private function validate($content, $file)
 383      {
 384          if (null === $content) {
 385              return $content;
 386          }
 387  
 388          if (!\is_array($content)) {
 389              throw new InvalidArgumentException(sprintf('The service file "%s" is not valid. It should contain an array. Check your YAML syntax.', $file));
 390          }
 391  
 392          foreach ($content as $namespace => $data) {
 393              if (\in_array($namespace, array('imports', 'parameters', 'services'))) {
 394                  continue;
 395              }
 396  
 397              if (!$this->container->hasExtension($namespace)) {
 398                  $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getAlias(); }, $this->container->getExtensions()));
 399                  throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $namespace, $file, $namespace, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'));
 400              }
 401          }
 402  
 403          return $content;
 404      }
 405  
 406      /**
 407       * Resolves services.
 408       *
 409       * @param string|array $value
 410       *
 411       * @return array|string|Reference
 412       */
 413      private function resolveServices($value)
 414      {
 415          if (\is_array($value)) {
 416              $value = array_map(array($this, 'resolveServices'), $value);
 417          } elseif (\is_string($value) && 0 === strpos($value, '@=')) {
 418              return new Expression(substr($value, 2));
 419          } elseif (\is_string($value) && 0 === strpos($value, '@')) {
 420              if (0 === strpos($value, '@@')) {
 421                  $value = substr($value, 1);
 422                  $invalidBehavior = null;
 423              } elseif (0 === strpos($value, '@?')) {
 424                  $value = substr($value, 2);
 425                  $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
 426              } else {
 427                  $value = substr($value, 1);
 428                  $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
 429              }
 430  
 431              if ('=' === substr($value, -1)) {
 432                  $value = substr($value, 0, -1);
 433                  $strict = false;
 434              } else {
 435                  $strict = true;
 436              }
 437  
 438              if (null !== $invalidBehavior) {
 439                  $value = new Reference($value, $invalidBehavior, $strict);
 440              }
 441          }
 442  
 443          return $value;
 444      }
 445  
 446      /**
 447       * Loads from Extensions.
 448       */
 449      private function loadFromExtensions(array $content)
 450      {
 451          foreach ($content as $namespace => $values) {
 452              if (\in_array($namespace, array('imports', 'parameters', 'services'))) {
 453                  continue;
 454              }
 455  
 456              if (!\is_array($values) && null !== $values) {
 457                  $values = array();
 458              }
 459  
 460              $this->container->loadFromExtension($namespace, $values);
 461          }
 462      }
 463  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1