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