[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
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\Util\XmlUtils; 15 use Symfony\Component\DependencyInjection\Alias; 16 use Symfony\Component\DependencyInjection\Argument\BoundArgument; 17 use Symfony\Component\DependencyInjection\Argument\IteratorArgument; 18 use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; 19 use Symfony\Component\DependencyInjection\ChildDefinition; 20 use Symfony\Component\DependencyInjection\ContainerBuilder; 21 use Symfony\Component\DependencyInjection\ContainerInterface; 22 use Symfony\Component\DependencyInjection\Definition; 23 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; 24 use Symfony\Component\DependencyInjection\Exception\RuntimeException; 25 use Symfony\Component\DependencyInjection\Reference; 26 use Symfony\Component\ExpressionLanguage\Expression; 27 28 /** 29 * XmlFileLoader loads XML files service definitions. 30 * 31 * @author Fabien Potencier <fabien@symfony.com> 32 */ 33 class XmlFileLoader extends FileLoader 34 { 35 const NS = 'http://symfony.com/schema/dic/services'; 36 37 /** 38 * {@inheritdoc} 39 */ 40 public function load($resource, $type = null) 41 { 42 $path = $this->locator->locate($resource); 43 44 $xml = $this->parseFileToDOM($path); 45 46 $this->container->fileExists($path); 47 48 $defaults = $this->getServiceDefaults($xml, $path); 49 50 // anonymous services 51 $this->processAnonymousServices($xml, $path, $defaults); 52 53 // imports 54 $this->parseImports($xml, $path); 55 56 // parameters 57 $this->parseParameters($xml, $path); 58 59 // extensions 60 $this->loadFromExtensions($xml); 61 62 // services 63 try { 64 $this->parseDefinitions($xml, $path, $defaults); 65 } finally { 66 $this->instanceof = []; 67 } 68 } 69 70 /** 71 * {@inheritdoc} 72 */ 73 public function supports($resource, $type = null) 74 { 75 if (!\is_string($resource)) { 76 return false; 77 } 78 79 if (null === $type && 'xml' === pathinfo($resource, \PATHINFO_EXTENSION)) { 80 return true; 81 } 82 83 return 'xml' === $type; 84 } 85 86 /** 87 * Parses parameters. 88 * 89 * @param string $file 90 */ 91 private function parseParameters(\DOMDocument $xml, $file) 92 { 93 if ($parameters = $this->getChildren($xml->documentElement, 'parameters')) { 94 $this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter', $file)); 95 } 96 } 97 98 /** 99 * Parses imports. 100 * 101 * @param string $file 102 */ 103 private function parseImports(\DOMDocument $xml, $file) 104 { 105 $xpath = new \DOMXPath($xml); 106 $xpath->registerNamespace('container', self::NS); 107 108 if (false === $imports = $xpath->query('//container:imports/container:import')) { 109 return; 110 } 111 112 $defaultDirectory = \dirname($file); 113 foreach ($imports as $import) { 114 $this->setCurrentDir($defaultDirectory); 115 $this->import($import->getAttribute('resource'), XmlUtils::phpize($import->getAttribute('type')) ?: null, (bool) XmlUtils::phpize($import->getAttribute('ignore-errors')), $file); 116 } 117 } 118 119 /** 120 * Parses multiple definitions. 121 * 122 * @param string $file 123 */ 124 private function parseDefinitions(\DOMDocument $xml, $file, $defaults) 125 { 126 $xpath = new \DOMXPath($xml); 127 $xpath->registerNamespace('container', self::NS); 128 129 if (false === $services = $xpath->query('//container:services/container:service|//container:services/container:prototype')) { 130 return; 131 } 132 $this->setCurrentDir(\dirname($file)); 133 134 $this->instanceof = []; 135 $this->isLoadingInstanceof = true; 136 $instanceof = $xpath->query('//container:services/container:instanceof'); 137 foreach ($instanceof as $service) { 138 $this->setDefinition((string) $service->getAttribute('id'), $this->parseDefinition($service, $file, [])); 139 } 140 141 $this->isLoadingInstanceof = false; 142 foreach ($services as $service) { 143 if (null !== $definition = $this->parseDefinition($service, $file, $defaults)) { 144 if ('prototype' === $service->tagName) { 145 $this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'), (string) $service->getAttribute('exclude')); 146 } else { 147 $this->setDefinition((string) $service->getAttribute('id'), $definition); 148 } 149 } 150 } 151 } 152 153 /** 154 * Get service defaults. 155 * 156 * @return array 157 */ 158 private function getServiceDefaults(\DOMDocument $xml, $file) 159 { 160 $xpath = new \DOMXPath($xml); 161 $xpath->registerNamespace('container', self::NS); 162 163 if (null === $defaultsNode = $xpath->query('//container:services/container:defaults')->item(0)) { 164 return []; 165 } 166 $defaults = [ 167 'tags' => $this->getChildren($defaultsNode, 'tag'), 168 'bind' => array_map(function ($v) { return new BoundArgument($v); }, $this->getArgumentsAsPhp($defaultsNode, 'bind', $file)), 169 ]; 170 171 foreach ($defaults['tags'] as $tag) { 172 if ('' === $tag->getAttribute('name')) { 173 throw new InvalidArgumentException(sprintf('The tag name for tag "<defaults>" in "%s" must be a non-empty string.', $file)); 174 } 175 } 176 177 if ($defaultsNode->hasAttribute('autowire')) { 178 $defaults['autowire'] = XmlUtils::phpize($defaultsNode->getAttribute('autowire')); 179 } 180 if ($defaultsNode->hasAttribute('public')) { 181 $defaults['public'] = XmlUtils::phpize($defaultsNode->getAttribute('public')); 182 } 183 if ($defaultsNode->hasAttribute('autoconfigure')) { 184 $defaults['autoconfigure'] = XmlUtils::phpize($defaultsNode->getAttribute('autoconfigure')); 185 } 186 187 return $defaults; 188 } 189 190 /** 191 * Parses an individual Definition. 192 * 193 * @param string $file 194 * 195 * @return Definition|null 196 */ 197 private function parseDefinition(\DOMElement $service, $file, array $defaults) 198 { 199 if ($alias = $service->getAttribute('alias')) { 200 $this->validateAlias($service, $file); 201 202 $this->container->setAlias((string) $service->getAttribute('id'), $alias = new Alias($alias)); 203 if ($publicAttr = $service->getAttribute('public')) { 204 $alias->setPublic(XmlUtils::phpize($publicAttr)); 205 } elseif (isset($defaults['public'])) { 206 $alias->setPublic($defaults['public']); 207 } 208 209 return null; 210 } 211 212 if ($this->isLoadingInstanceof) { 213 $definition = new ChildDefinition(''); 214 } elseif ($parent = $service->getAttribute('parent')) { 215 if (!empty($this->instanceof)) { 216 throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "instanceof" configuration is defined as using both is not supported. Move your child definitions to a separate file.', $service->getAttribute('id'))); 217 } 218 219 foreach ($defaults as $k => $v) { 220 if ('tags' === $k) { 221 // since tags are never inherited from parents, there is no confusion 222 // thus we can safely add them as defaults to ChildDefinition 223 continue; 224 } 225 if ('bind' === $k) { 226 if ($defaults['bind']) { 227 throw new InvalidArgumentException(sprintf('Bound values on service "%s" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file.', $service->getAttribute('id'))); 228 } 229 230 continue; 231 } 232 if (!$service->hasAttribute($k)) { 233 throw new InvalidArgumentException(sprintf('Attribute "%s" on service "%s" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.', $k, $service->getAttribute('id'))); 234 } 235 } 236 237 $definition = new ChildDefinition($parent); 238 } else { 239 $definition = new Definition(); 240 241 if (isset($defaults['public'])) { 242 $definition->setPublic($defaults['public']); 243 } 244 if (isset($defaults['autowire'])) { 245 $definition->setAutowired($defaults['autowire']); 246 } 247 if (isset($defaults['autoconfigure'])) { 248 $definition->setAutoconfigured($defaults['autoconfigure']); 249 } 250 251 $definition->setChanges([]); 252 } 253 254 foreach (['class', 'public', 'shared', 'synthetic', 'lazy', 'abstract'] as $key) { 255 if ($value = $service->getAttribute($key)) { 256 $method = 'set'.$key; 257 $definition->$method(XmlUtils::phpize($value)); 258 } 259 } 260 261 if ($value = $service->getAttribute('autowire')) { 262 $definition->setAutowired(XmlUtils::phpize($value)); 263 } 264 265 if ($value = $service->getAttribute('autoconfigure')) { 266 if (!$definition instanceof ChildDefinition) { 267 $definition->setAutoconfigured(XmlUtils::phpize($value)); 268 } elseif ($value = XmlUtils::phpize($value)) { 269 throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try setting autoconfigure="false" for the service.', $service->getAttribute('id'))); 270 } 271 } 272 273 if ($files = $this->getChildren($service, 'file')) { 274 $definition->setFile($files[0]->nodeValue); 275 } 276 277 if ($deprecated = $this->getChildren($service, 'deprecated')) { 278 $definition->setDeprecated(true, $deprecated[0]->nodeValue ?: null); 279 } 280 281 $definition->setArguments($this->getArgumentsAsPhp($service, 'argument', $file, $definition instanceof ChildDefinition)); 282 $definition->setProperties($this->getArgumentsAsPhp($service, 'property', $file)); 283 284 if ($factories = $this->getChildren($service, 'factory')) { 285 $factory = $factories[0]; 286 if ($function = $factory->getAttribute('function')) { 287 $definition->setFactory($function); 288 } else { 289 if ($childService = $factory->getAttribute('service')) { 290 $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); 291 } else { 292 $class = $factory->hasAttribute('class') ? $factory->getAttribute('class') : null; 293 } 294 295 $definition->setFactory([$class, $factory->getAttribute('method')]); 296 } 297 } 298 299 if ($configurators = $this->getChildren($service, 'configurator')) { 300 $configurator = $configurators[0]; 301 if ($function = $configurator->getAttribute('function')) { 302 $definition->setConfigurator($function); 303 } else { 304 if ($childService = $configurator->getAttribute('service')) { 305 $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); 306 } else { 307 $class = $configurator->getAttribute('class'); 308 } 309 310 $definition->setConfigurator([$class, $configurator->getAttribute('method')]); 311 } 312 } 313 314 foreach ($this->getChildren($service, 'call') as $call) { 315 $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file)); 316 } 317 318 $tags = $this->getChildren($service, 'tag'); 319 320 if (!empty($defaults['tags'])) { 321 $tags = array_merge($tags, $defaults['tags']); 322 } 323 324 foreach ($tags as $tag) { 325 $parameters = []; 326 foreach ($tag->attributes as $name => $node) { 327 if ('name' === $name) { 328 continue; 329 } 330 331 if (false !== strpos($name, '-') && false === strpos($name, '_') && !\array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) { 332 $parameters[$normalizedName] = XmlUtils::phpize($node->nodeValue); 333 } 334 // keep not normalized key 335 $parameters[$name] = XmlUtils::phpize($node->nodeValue); 336 } 337 338 if ('' === $tag->getAttribute('name')) { 339 throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', (string) $service->getAttribute('id'), $file)); 340 } 341 342 $definition->addTag($tag->getAttribute('name'), $parameters); 343 } 344 345 foreach ($this->getChildren($service, 'autowiring-type') as $type) { 346 $definition->addAutowiringType($type->textContent); 347 } 348 349 $bindings = $this->getArgumentsAsPhp($service, 'bind', $file); 350 if (isset($defaults['bind'])) { 351 // deep clone, to avoid multiple process of the same instance in the passes 352 $bindings = array_merge(unserialize(serialize($defaults['bind'])), $bindings); 353 } 354 if ($bindings) { 355 $definition->setBindings($bindings); 356 } 357 358 if ($value = $service->getAttribute('decorates')) { 359 $renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null; 360 $priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0; 361 $definition->setDecoratedService($value, $renameId, $priority); 362 } 363 364 return $definition; 365 } 366 367 /** 368 * Parses a XML file to a \DOMDocument. 369 * 370 * @param string $file Path to a file 371 * 372 * @return \DOMDocument 373 * 374 * @throws InvalidArgumentException When loading of XML file returns error 375 */ 376 private function parseFileToDOM($file) 377 { 378 try { 379 $dom = XmlUtils::loadFile($file, [$this, 'validateSchema']); 380 } catch (\InvalidArgumentException $e) { 381 throw new InvalidArgumentException(sprintf('Unable to parse file "%s": ', $file).$e->getMessage(), $e->getCode(), $e); 382 } 383 384 $this->validateExtensions($dom, $file); 385 386 return $dom; 387 } 388 389 /** 390 * Processes anonymous services. 391 * 392 * @param string $file 393 * @param array $defaults 394 */ 395 private function processAnonymousServices(\DOMDocument $xml, $file, $defaults) 396 { 397 $definitions = []; 398 $count = 0; 399 $suffix = '~'.ContainerBuilder::hash($file); 400 401 $xpath = new \DOMXPath($xml); 402 $xpath->registerNamespace('container', self::NS); 403 404 // anonymous services as arguments/properties 405 if (false !== $nodes = $xpath->query('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]|//container:bind[not(@id)]|//container:factory[not(@service)]|//container:configurator[not(@service)]')) { 406 foreach ($nodes as $node) { 407 if ($services = $this->getChildren($node, 'service')) { 408 // give it a unique name 409 $id = sprintf('%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $services[0]->getAttribute('class')).$suffix); 410 $node->setAttribute('id', $id); 411 $node->setAttribute('service', $id); 412 413 $definitions[$id] = [$services[0], $file, false]; 414 $services[0]->setAttribute('id', $id); 415 416 // anonymous services are always private 417 // we could not use the constant false here, because of XML parsing 418 $services[0]->setAttribute('public', 'false'); 419 } 420 } 421 } 422 423 // anonymous services "in the wild" 424 if (false !== $nodes = $xpath->query('//container:services/container:service[not(@id)]')) { 425 foreach ($nodes as $node) { 426 @trigger_error(sprintf('Top-level anonymous services are deprecated since Symfony 3.4, the "id" attribute will be required in version 4.0 in %s at line %d.', $file, $node->getLineNo()), \E_USER_DEPRECATED); 427 428 // give it a unique name 429 $id = sprintf('%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $node->getAttribute('class')).$suffix); 430 $node->setAttribute('id', $id); 431 $definitions[$id] = [$node, $file, true]; 432 } 433 } 434 435 // resolve definitions 436 uksort($definitions, 'strnatcmp'); 437 foreach (array_reverse($definitions) as $id => list($domElement, $file, $wild)) { 438 if (null !== $definition = $this->parseDefinition($domElement, $file, $wild ? $defaults : [])) { 439 $this->setDefinition($id, $definition); 440 } 441 442 if (true === $wild) { 443 $tmpDomElement = new \DOMElement('_services', null, self::NS); 444 $domElement->parentNode->replaceChild($tmpDomElement, $domElement); 445 $tmpDomElement->setAttribute('id', $id); 446 } 447 } 448 } 449 450 /** 451 * Returns arguments as valid php types. 452 * 453 * @param string $name 454 * @param string $file 455 * 456 * @return mixed 457 */ 458 private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $isChildDefinition = false) 459 { 460 $arguments = []; 461 foreach ($this->getChildren($node, $name) as $arg) { 462 if ($arg->hasAttribute('name')) { 463 $arg->setAttribute('key', $arg->getAttribute('name')); 464 } 465 466 // this is used by ChildDefinition to overwrite a specific 467 // argument of the parent definition 468 if ($arg->hasAttribute('index')) { 469 $key = ($isChildDefinition ? 'index_' : '').$arg->getAttribute('index'); 470 } elseif (!$arg->hasAttribute('key')) { 471 // Append an empty argument, then fetch its key to overwrite it later 472 $arguments[] = null; 473 $keys = array_keys($arguments); 474 $key = array_pop($keys); 475 } else { 476 $key = $arg->getAttribute('key'); 477 } 478 479 $onInvalid = $arg->getAttribute('on-invalid'); 480 $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; 481 if ('ignore' == $onInvalid) { 482 $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; 483 } elseif ('ignore_uninitialized' == $onInvalid) { 484 $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; 485 } elseif ('null' == $onInvalid) { 486 $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; 487 } 488 489 switch ($arg->getAttribute('type')) { 490 case 'service': 491 if ('' === $arg->getAttribute('id')) { 492 throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service" has no or empty "id" attribute in "%s".', $name, $file)); 493 } 494 if ($arg->hasAttribute('strict')) { 495 @trigger_error(sprintf('The "strict" attribute used when referencing the "%s" service is deprecated since Symfony 3.3 and will be removed in 4.0.', $arg->getAttribute('id')), \E_USER_DEPRECATED); 496 } 497 498 $arguments[$key] = new Reference($arg->getAttribute('id'), $invalidBehavior); 499 break; 500 case 'expression': 501 if (!class_exists(Expression::class)) { 502 throw new \LogicException(sprintf('The type="expression" attribute cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".')); 503 } 504 505 $arguments[$key] = new Expression($arg->nodeValue); 506 break; 507 case 'collection': 508 $arguments[$key] = $this->getArgumentsAsPhp($arg, $name, $file); 509 break; 510 case 'iterator': 511 $arg = $this->getArgumentsAsPhp($arg, $name, $file); 512 try { 513 $arguments[$key] = new IteratorArgument($arg); 514 } catch (InvalidArgumentException $e) { 515 throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="iterator" only accepts collections of type="service" references in "%s".', $name, $file)); 516 } 517 break; 518 case 'tagged': 519 if (!$arg->getAttribute('tag')) { 520 throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="tagged" has no or empty "tag" attribute in "%s".', $name, $file)); 521 } 522 $arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag')); 523 break; 524 case 'string': 525 $arguments[$key] = $arg->nodeValue; 526 break; 527 case 'constant': 528 $arguments[$key] = \constant(trim($arg->nodeValue)); 529 break; 530 default: 531 $arguments[$key] = XmlUtils::phpize($arg->nodeValue); 532 } 533 } 534 535 return $arguments; 536 } 537 538 /** 539 * Get child elements by name. 540 * 541 * @param mixed $name 542 * 543 * @return \DOMElement[] 544 */ 545 private function getChildren(\DOMNode $node, $name) 546 { 547 $children = []; 548 foreach ($node->childNodes as $child) { 549 if ($child instanceof \DOMElement && $child->localName === $name && self::NS === $child->namespaceURI) { 550 $children[] = $child; 551 } 552 } 553 554 return $children; 555 } 556 557 /** 558 * Validates a documents XML schema. 559 * 560 * @return bool 561 * 562 * @throws RuntimeException When extension references a non-existent XSD file 563 */ 564 public function validateSchema(\DOMDocument $dom) 565 { 566 $schemaLocations = ['http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd')]; 567 568 if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) { 569 $items = preg_split('/\s+/', $element); 570 for ($i = 0, $nb = \count($items); $i < $nb; $i += 2) { 571 if (!$this->container->hasExtension($items[$i])) { 572 continue; 573 } 574 575 if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) { 576 $ns = $extension->getNamespace(); 577 $path = str_replace([$ns, str_replace('http://', 'https://', $ns)], str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]); 578 579 if (!is_file($path)) { 580 throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s".', \get_class($extension), $path)); 581 } 582 583 $schemaLocations[$items[$i]] = $path; 584 } 585 } 586 } 587 588 $tmpfiles = []; 589 $imports = ''; 590 foreach ($schemaLocations as $namespace => $location) { 591 $parts = explode('/', $location); 592 $locationstart = 'file:///'; 593 if (0 === stripos($location, 'phar://')) { 594 $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); 595 if ($tmpfile) { 596 copy($location, $tmpfile); 597 $tmpfiles[] = $tmpfile; 598 $parts = explode('/', str_replace('\\', '/', $tmpfile)); 599 } else { 600 array_shift($parts); 601 $locationstart = 'phar:///'; 602 } 603 } 604 $drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; 605 $location = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts)); 606 607 $imports .= sprintf(' <xsd:import namespace="%s" schemaLocation="%s" />'."\n", $namespace, $location); 608 } 609 610 $source = <<<EOF 611 <?xml version="1.0" encoding="utf-8" ?> 612 <xsd:schema xmlns="http://symfony.com/schema" 613 xmlns:xsd="http://www.w3.org/2001/XMLSchema" 614 targetNamespace="http://symfony.com/schema" 615 elementFormDefault="qualified"> 616 617 <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/> 618 $imports 619 </xsd:schema> 620 EOF 621 ; 622 623 if (\LIBXML_VERSION < 20900) { 624 $disableEntities = libxml_disable_entity_loader(false); 625 $valid = @$dom->schemaValidateSource($source); 626 libxml_disable_entity_loader($disableEntities); 627 } else { 628 $valid = @$dom->schemaValidateSource($source); 629 } 630 631 foreach ($tmpfiles as $tmpfile) { 632 @unlink($tmpfile); 633 } 634 635 return $valid; 636 } 637 638 /** 639 * Validates an alias. 640 * 641 * @param string $file 642 */ 643 private function validateAlias(\DOMElement $alias, $file) 644 { 645 foreach ($alias->attributes as $name => $node) { 646 if (!\in_array($name, ['alias', 'id', 'public'])) { 647 @trigger_error(sprintf('Using the attribute "%s" is deprecated for the service "%s" which is defined as an alias in "%s". Allowed attributes for service aliases are "alias", "id" and "public". The XmlFileLoader will raise an exception in Symfony 4.0, instead of silently ignoring unsupported attributes.', $name, $alias->getAttribute('id'), $file), \E_USER_DEPRECATED); 648 } 649 } 650 651 foreach ($alias->childNodes as $child) { 652 if ($child instanceof \DOMElement && self::NS === $child->namespaceURI) { 653 @trigger_error(sprintf('Using the element "%s" is deprecated for the service "%s" which is defined as an alias in "%s". The XmlFileLoader will raise an exception in Symfony 4.0, instead of silently ignoring unsupported elements.', $child->localName, $alias->getAttribute('id'), $file), \E_USER_DEPRECATED); 654 } 655 } 656 } 657 658 /** 659 * Validates an extension. 660 * 661 * @param string $file 662 * 663 * @throws InvalidArgumentException When no extension is found corresponding to a tag 664 */ 665 private function validateExtensions(\DOMDocument $dom, $file) 666 { 667 foreach ($dom->documentElement->childNodes as $node) { 668 if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) { 669 continue; 670 } 671 672 // can it be handled by an extension? 673 if (!$this->container->hasExtension($node->namespaceURI)) { 674 $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getNamespace(); }, $this->container->getExtensions())); 675 throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none')); 676 } 677 } 678 } 679 680 /** 681 * Loads from an extension. 682 */ 683 private function loadFromExtensions(\DOMDocument $xml) 684 { 685 foreach ($xml->documentElement->childNodes as $node) { 686 if (!$node instanceof \DOMElement || self::NS === $node->namespaceURI) { 687 continue; 688 } 689 690 $values = static::convertDomElementToArray($node); 691 if (!\is_array($values)) { 692 $values = []; 693 } 694 695 $this->container->loadFromExtension($node->namespaceURI, $values); 696 } 697 } 698 699 /** 700 * Converts a \DOMElement object to a PHP array. 701 * 702 * The following rules applies during the conversion: 703 * 704 * * Each tag is converted to a key value or an array 705 * if there is more than one "value" 706 * 707 * * The content of a tag is set under a "value" key (<foo>bar</foo>) 708 * if the tag also has some nested tags 709 * 710 * * The attributes are converted to keys (<foo foo="bar"/>) 711 * 712 * * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>) 713 * 714 * @param \DOMElement $element A \DOMElement instance 715 * 716 * @return mixed 717 */ 718 public static function convertDomElementToArray(\DOMElement $element) 719 { 720 return XmlUtils::convertDomElementToArray($element); 721 } 722 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |