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

XmlFileLoader.php

Zuletzt modifiziert: 09.10.2024, 12:58 - Dateigröße: 14.21 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\Loader;
 013   
 014  use Symfony\Component\Config\Resource\FileResource;
 015  use Symfony\Component\Config\Util\XmlUtils;
 016  use Symfony\Component\DependencyInjection\DefinitionDecorator;
 017  use Symfony\Component\DependencyInjection\ContainerInterface;
 018  use Symfony\Component\DependencyInjection\Alias;
 019  use Symfony\Component\DependencyInjection\Definition;
 020  use Symfony\Component\DependencyInjection\Reference;
 021  use Symfony\Component\DependencyInjection\SimpleXMLElement;
 022  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 023  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 024   
 025  /**
 026   * XmlFileLoader loads XML files service definitions.
 027   *
 028   * @author Fabien Potencier <fabien@symfony.com>
 029   */
 030  class XmlFileLoader extends FileLoader
 031  {
 032      /**
 033       * Loads an XML file.
 034       *
 035       * @param mixed  $file The resource
 036       * @param string $type The resource type
 037       */
 038      public function load($file, $type = null)
 039      {
 040          $path = $this->locator->locate($file);
 041   
 042          $xml = $this->parseFile($path);
 043          $xml->registerXPathNamespace('container', 'http://symfony.com/schema/dic/services');
 044   
 045          $this->container->addResource(new FileResource($path));
 046   
 047          // anonymous services
 048          $this->processAnonymousServices($xml, $path);
 049   
 050          // imports
 051          $this->parseImports($xml, $path);
 052   
 053          // parameters
 054          $this->parseParameters($xml, $path);
 055   
 056          // extensions
 057          $this->loadFromExtensions($xml);
 058   
 059          // services
 060          $this->parseDefinitions($xml, $path);
 061      }
 062   
 063      /**
 064       * Returns true if this class supports the given resource.
 065       *
 066       * @param mixed  $resource A resource
 067       * @param string $type     The resource type
 068       *
 069       * @return bool    true if this class supports the given resource, false otherwise
 070       */
 071      public function supports($resource, $type = null)
 072      {
 073          return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION);
 074      }
 075   
 076      /**
 077       * Parses parameters
 078       *
 079       * @param SimpleXMLElement $xml
 080       * @param string           $file
 081       */
 082      private function parseParameters(SimpleXMLElement $xml, $file)
 083      {
 084          if (!$xml->parameters) {
 085              return;
 086          }
 087   
 088          $this->container->getParameterBag()->add($xml->parameters->getArgumentsAsPhp('parameter'));
 089      }
 090   
 091      /**
 092       * Parses imports
 093       *
 094       * @param SimpleXMLElement $xml
 095       * @param string           $file
 096       */
 097      private function parseImports(SimpleXMLElement $xml, $file)
 098      {
 099          if (false === $imports = $xml->xpath('//container:imports/container:import')) {
 100              return;
 101          }
 102   
 103          foreach ($imports as $import) {
 104              $this->setCurrentDir(dirname($file));
 105              $this->import((string) $import['resource'], null, (bool) $import->getAttributeAsPhp('ignore-errors'), $file);
 106          }
 107      }
 108   
 109      /**
 110       * Parses multiple definitions
 111       *
 112       * @param SimpleXMLElement $xml
 113       * @param string           $file
 114       */
 115      private function parseDefinitions(SimpleXMLElement $xml, $file)
 116      {
 117          if (false === $services = $xml->xpath('//container:services/container:service')) {
 118              return;
 119          }
 120   
 121          foreach ($services as $service) {
 122              $this->parseDefinition((string) $service['id'], $service, $file);
 123          }
 124      }
 125   
 126      /**
 127       * Parses an individual Definition
 128       *
 129       * @param string           $id
 130       * @param SimpleXMLElement $service
 131       * @param string           $file
 132       */
 133      private function parseDefinition($id, $service, $file)
 134      {
 135          if ((string) $service['alias']) {
 136              $public = true;
 137              if (isset($service['public'])) {
 138                  $public = $service->getAttributeAsPhp('public');
 139              }
 140              $this->container->setAlias($id, new Alias((string) $service['alias'], $public));
 141   
 142              return;
 143          }
 144   
 145          if (isset($service['parent'])) {
 146              $definition = new DefinitionDecorator((string) $service['parent']);
 147          } else {
 148              $definition = new Definition();
 149          }
 150   
 151          foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'lazy', 'abstract') as $key) {
 152              if (isset($service[$key])) {
 153                  $method = 'set'.str_replace('-', '', $key);
 154                  $definition->$method((string) $service->getAttributeAsPhp($key));
 155              }
 156          }
 157   
 158          if ($service->file) {
 159              $definition->setFile((string) $service->file);
 160          }
 161   
 162          $definition->setArguments($service->getArgumentsAsPhp('argument'));
 163          $definition->setProperties($service->getArgumentsAsPhp('property'));
 164   
 165          if (isset($service->configurator)) {
 166              if (isset($service->configurator['function'])) {
 167                  $definition->setConfigurator((string) $service->configurator['function']);
 168              } else {
 169                  if (isset($service->configurator['service'])) {
 170                      $class = new Reference((string) $service->configurator['service'], ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false);
 171                  } else {
 172                      $class = (string) $service->configurator['class'];
 173                  }
 174   
 175                  $definition->setConfigurator(array($class, (string) $service->configurator['method']));
 176              }
 177          }
 178   
 179          foreach ($service->call as $call) {
 180              $definition->addMethodCall((string) $call['method'], $call->getArgumentsAsPhp('argument'));
 181          }
 182   
 183          foreach ($service->tag as $tag) {
 184              $parameters = array();
 185              foreach ($tag->attributes() as $name => $value) {
 186                  if ('name' === $name) {
 187                      continue;
 188                  }
 189   
 190                  if (false !== strpos($name, '-') && false === strpos($name, '_') && !array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) {
 191                      $parameters[$normalizedName] = SimpleXMLElement::phpize($value);
 192                  }
 193                  // keep not normalized key for BC too
 194                  $parameters[$name] = SimpleXMLElement::phpize($value);
 195              }
 196   
 197              $definition->addTag((string) $tag['name'], $parameters);
 198          }
 199   
 200          $this->container->setDefinition($id, $definition);
 201      }
 202   
 203      /**
 204       * Parses a XML file.
 205       *
 206       * @param string $file Path to a file
 207       *
 208       * @return SimpleXMLElement
 209       *
 210       * @throws InvalidArgumentException When loading of XML file returns error
 211       */
 212      protected function parseFile($file)
 213      {
 214          try {
 215              $dom = XmlUtils::loadFile($file, array($this, 'validateSchema'));
 216          } catch (\InvalidArgumentException $e) {
 217              throw new InvalidArgumentException(sprintf('Unable to parse file "%s".', $file), $e->getCode(), $e);
 218          }
 219   
 220          $this->validateExtensions($dom, $file);
 221   
 222          return simplexml_import_dom($dom, 'Symfony\\Component\\DependencyInjection\\SimpleXMLElement');
 223      }
 224   
 225      /**
 226       * Processes anonymous services
 227       *
 228       * @param SimpleXMLElement $xml
 229       * @param string           $file
 230       */
 231      private function processAnonymousServices(SimpleXMLElement $xml, $file)
 232      {
 233          $definitions = array();
 234          $count = 0;
 235   
 236          // anonymous services as arguments/properties
 237          if (false !== $nodes = $xml->xpath('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]')) {
 238              foreach ($nodes as $node) {
 239                  // give it a unique name
 240                  $node['id'] = sprintf('%s_%d', md5($file), ++$count);
 241   
 242                  $definitions[(string) $node['id']] = array($node->service, $file, false);
 243                  $node->service['id'] = (string) $node['id'];
 244              }
 245          }
 246   
 247          // anonymous services "in the wild"
 248          if (false !== $nodes = $xml->xpath('//container:services/container:service[not(@id)]')) {
 249              foreach ($nodes as $node) {
 250                  // give it a unique name
 251                  $node['id'] = sprintf('%s_%d', md5($file), ++$count);
 252   
 253                  $definitions[(string) $node['id']] = array($node, $file, true);
 254                  $node->service['id'] = (string) $node['id'];
 255              }
 256          }
 257   
 258          // resolve definitions
 259          krsort($definitions);
 260          foreach ($definitions as $id => $def) {
 261              // anonymous services are always private
 262              $def[0]['public'] = false;
 263   
 264              $this->parseDefinition($id, $def[0], $def[1]);
 265   
 266              $oNode = dom_import_simplexml($def[0]);
 267              if (true === $def[2]) {
 268                  $nNode = new \DOMElement('_services');
 269                  $oNode->parentNode->replaceChild($nNode, $oNode);
 270                  $nNode->setAttribute('id', $id);
 271              } else {
 272                  $oNode->parentNode->removeChild($oNode);
 273              }
 274          }
 275      }
 276   
 277      /**
 278       * Validates a documents XML schema.
 279       *
 280       * @param \DOMDocument $dom
 281       *
 282       * @return bool
 283       *
 284       * @throws RuntimeException When extension references a non-existent XSD file
 285       */
 286      public function validateSchema(\DOMDocument $dom)
 287      {
 288          $schemaLocations = array('http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd'));
 289   
 290          if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) {
 291              $items = preg_split('/\s+/', $element);
 292              for ($i = 0, $nb = count($items); $i < $nb; $i += 2) {
 293                  if (!$this->container->hasExtension($items[$i])) {
 294                      continue;
 295                  }
 296   
 297                  if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) {
 298                      $path = str_replace($extension->getNamespace(), str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]);
 299   
 300                      if (!is_file($path)) {
 301                          throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s"', get_class($extension), $path));
 302                      }
 303   
 304                      $schemaLocations[$items[$i]] = $path;
 305                  }
 306              }
 307          }
 308   
 309          $tmpfiles = array();
 310          $imports = '';
 311          foreach ($schemaLocations as $namespace => $location) {
 312              $parts = explode('/', $location);
 313              if (0 === stripos($location, 'phar://')) {
 314                  $tmpfile = tempnam(sys_get_temp_dir(), 'sf2');
 315                  if ($tmpfile) {
 316                      copy($location, $tmpfile);
 317                      $tmpfiles[] = $tmpfile;
 318                      $parts = explode('/', str_replace('\\', '/', $tmpfile));
 319                  }
 320              }
 321              $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
 322              $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));
 323   
 324              $imports .= sprintf('  <xsd:import namespace="%s" schemaLocation="%s" />'."\n", $namespace, $location);
 325          }
 326   
 327          $source = <<<EOF
 328  <?xml version="1.0" encoding="utf-8" ?>
 329  <xsd:schema xmlns="http://symfony.com/schema"
 330      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 331      targetNamespace="http://symfony.com/schema"
 332      elementFormDefault="qualified">
 333   
 334      <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
 335  $imports
 336  </xsd:schema>
 337  EOF
 338          ;
 339   
 340          $valid = @$dom->schemaValidateSource($source);
 341   
 342          foreach ($tmpfiles as $tmpfile) {
 343              @unlink($tmpfile);
 344          }
 345   
 346          return $valid;
 347      }
 348   
 349      /**
 350       * Validates an extension.
 351       *
 352       * @param \DOMDocument $dom
 353       * @param string       $file
 354       *
 355       * @throws InvalidArgumentException When no extension is found corresponding to a tag
 356       */
 357      private function validateExtensions(\DOMDocument $dom, $file)
 358      {
 359          foreach ($dom->documentElement->childNodes as $node) {
 360              if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) {
 361                  continue;
 362              }
 363   
 364              // can it be handled by an extension?
 365              if (!$this->container->hasExtension($node->namespaceURI)) {
 366                  $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getNamespace(); }, $this->container->getExtensions()));
 367                  throw new InvalidArgumentException(sprintf(
 368                      'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s',
 369                      $node->tagName,
 370                      $file,
 371                      $node->namespaceURI,
 372                      $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'
 373                  ));
 374              }
 375          }
 376      }
 377   
 378      /**
 379       * Loads from an extension.
 380       *
 381       * @param SimpleXMLElement $xml
 382       */
 383      private function loadFromExtensions(SimpleXMLElement $xml)
 384      {
 385          foreach (dom_import_simplexml($xml)->childNodes as $node) {
 386              if (!$node instanceof \DOMElement || $node->namespaceURI === 'http://symfony.com/schema/dic/services') {
 387                  continue;
 388              }
 389   
 390              $values = static::convertDomElementToArray($node);
 391              if (!is_array($values)) {
 392                  $values = array();
 393              }
 394   
 395              $this->container->loadFromExtension($node->namespaceURI, $values);
 396          }
 397      }
 398   
 399      /**
 400       * Converts a \DomElement object to a PHP array.
 401       *
 402       * The following rules applies during the conversion:
 403       *
 404       *  * Each tag is converted to a key value or an array
 405       *    if there is more than one "value"
 406       *
 407       *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
 408       *    if the tag also has some nested tags
 409       *
 410       *  * The attributes are converted to keys (<foo foo="bar"/>)
 411       *
 412       *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
 413       *
 414       * @param \DomElement $element A \DomElement instance
 415       *
 416       * @return array A PHP array
 417       */
 418      public static function convertDomElementToArray(\DomElement $element)
 419      {
 420          return XmlUtils::convertDomElementToArray($element);
 421      }
 422  }
 423