Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

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

XmlUtils.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 9.64 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\Config\Util;
013   
014  use Symfony\Component\Config\Util\Exception\InvalidXmlException;
015  use Symfony\Component\Config\Util\Exception\XmlParsingException;
016   
017  /**
018   * XMLUtils is a bunch of utility methods to XML operations.
019   *
020   * This class contains static methods only and is not meant to be instantiated.
021   *
022   * @author Fabien Potencier <fabien@symfony.com>
023   * @author Martin Hasoň <martin.hason@gmail.com>
024   * @author Ole Rößner <ole@roessner.it>
025   */
026  class XmlUtils
027  {
028      /**
029       * This class should not be instantiated.
030       */
031      private function __construct()
032      {
033      }
034   
035      /**
036       * Parses an XML string.
037       *
038       * @param string               $content          An XML string
039       * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
040       *
041       * @return \DOMDocument
042       *
043       * @throws XmlParsingException When parsing of XML file returns error
044       * @throws InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself
045       * @throws \RuntimeException   When DOM extension is missing
046       */
047      public static function parse($content, $schemaOrCallable = null)
048      {
049          if (!\extension_loaded('dom')) {
050              throw new \RuntimeException('Extension DOM is required.');
051          }
052   
053          $internalErrors = libxml_use_internal_errors(true);
054          if (\LIBXML_VERSION < 20900) {
055              $disableEntities = libxml_disable_entity_loader(true);
056          }
057          libxml_clear_errors();
058   
059          $dom = new \DOMDocument();
060          $dom->validateOnParse = true;
061          if (!$dom->loadXML($content, \LIBXML_NONET | (\defined('LIBXML_COMPACT') ? \LIBXML_COMPACT : 0))) {
062              if (\LIBXML_VERSION < 20900) {
063                  libxml_disable_entity_loader($disableEntities);
064              }
065   
066              throw new XmlParsingException(implode("\n", static::getXmlErrors($internalErrors)));
067          }
068   
069          $dom->normalizeDocument();
070   
071          libxml_use_internal_errors($internalErrors);
072          if (\LIBXML_VERSION < 20900) {
073              libxml_disable_entity_loader($disableEntities);
074          }
075   
076          foreach ($dom->childNodes as $child) {
077              if (\XML_DOCUMENT_TYPE_NODE === $child->nodeType) {
078                  throw new XmlParsingException('Document types are not allowed.');
079              }
080          }
081   
082          if (null !== $schemaOrCallable) {
083              $internalErrors = libxml_use_internal_errors(true);
084              libxml_clear_errors();
085   
086              $e = null;
087              if (\is_callable($schemaOrCallable)) {
088                  try {
089                      $valid = \call_user_func($schemaOrCallable, $dom, $internalErrors);
090                  } catch (\Exception $e) {
091                      $valid = false;
092                  }
093              } elseif (!\is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) {
094                  $schemaSource = file_get_contents((string) $schemaOrCallable);
095                  $valid = @$dom->schemaValidateSource($schemaSource);
096              } else {
097                  libxml_use_internal_errors($internalErrors);
098   
099                  throw new XmlParsingException('The schemaOrCallable argument has to be a valid path to XSD file or callable.');
100              }
101   
102              if (!$valid) {
103                  $messages = static::getXmlErrors($internalErrors);
104                  if (empty($messages)) {
105                      throw new InvalidXmlException('The XML is not valid.', 0, $e);
106                  }
107                  throw new XmlParsingException(implode("\n", $messages), 0, $e);
108              }
109          }
110   
111          libxml_clear_errors();
112          libxml_use_internal_errors($internalErrors);
113   
114          return $dom;
115      }
116   
117      /**
118       * Loads an XML file.
119       *
120       * @param string               $file             An XML file path
121       * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
122       *
123       * @return \DOMDocument
124       *
125       * @throws \InvalidArgumentException When loading of XML file returns error
126       * @throws XmlParsingException       When XML parsing returns any errors
127       * @throws \RuntimeException         When DOM extension is missing
128       */
129      public static function loadFile($file, $schemaOrCallable = null)
130      {
131          if (!is_file($file)) {
132              throw new \InvalidArgumentException(sprintf('Resource "%s" is not a file.', $file));
133          }
134   
135          if (!is_readable($file)) {
136              throw new \InvalidArgumentException(sprintf('File "%s" is not readable.', $file));
137          }
138   
139          $content = @file_get_contents($file);
140   
141          if ('' === trim($content)) {
142              throw new \InvalidArgumentException(sprintf('File "%s" does not contain valid XML, it is empty.', $file));
143          }
144   
145          try {
146              return static::parse($content, $schemaOrCallable);
147          } catch (InvalidXmlException $e) {
148              throw new XmlParsingException(sprintf('The XML file "%s" is not valid.', $file), 0, $e->getPrevious());
149          }
150      }
151   
152      /**
153       * Converts a \DOMElement object to a PHP array.
154       *
155       * The following rules applies during the conversion:
156       *
157       *  * Each tag is converted to a key value or an array
158       *    if there is more than one "value"
159       *
160       *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
161       *    if the tag also has some nested tags
162       *
163       *  * The attributes are converted to keys (<foo foo="bar"/>)
164       *
165       *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
166       *
167       * @param \DOMElement $element     A \DOMElement instance
168       * @param bool        $checkPrefix Check prefix in an element or an attribute name
169       *
170       * @return mixed
171       */
172      public static function convertDomElementToArray(\DOMElement $element, $checkPrefix = true)
173      {
174          $prefix = (string) $element->prefix;
175          $empty = true;
176          $config = [];
177          foreach ($element->attributes as $name => $node) {
178              if ($checkPrefix && !\in_array((string) $node->prefix, ['', $prefix], true)) {
179                  continue;
180              }
181              $config[$name] = static::phpize($node->value);
182              $empty = false;
183          }
184   
185          $nodeValue = false;
186          foreach ($element->childNodes as $node) {
187              if ($node instanceof \DOMText) {
188                  if ('' !== trim($node->nodeValue)) {
189                      $nodeValue = trim($node->nodeValue);
190                      $empty = false;
191                  }
192              } elseif ($checkPrefix && $prefix != (string) $node->prefix) {
193                  continue;
194              } elseif (!$node instanceof \DOMComment) {
195                  $value = static::convertDomElementToArray($node, $checkPrefix);
196   
197                  $key = $node->localName;
198                  if (isset($config[$key])) {
199                      if (!\is_array($config[$key]) || !\is_int(key($config[$key]))) {
200                          $config[$key] = [$config[$key]];
201                      }
202                      $config[$key][] = $value;
203                  } else {
204                      $config[$key] = $value;
205                  }
206   
207                  $empty = false;
208              }
209          }
210   
211          if (false !== $nodeValue) {
212              $value = static::phpize($nodeValue);
213              if (\count($config)) {
214                  $config['value'] = $value;
215              } else {
216                  $config = $value;
217              }
218          }
219   
220          return !$empty ? $config : null;
221      }
222   
223      /**
224       * Converts an xml value to a PHP type.
225       *
226       * @param mixed $value
227       *
228       * @return mixed
229       */
230      public static function phpize($value)
231      {
232          $value = (string) $value;
233          $lowercaseValue = strtolower($value);
234   
235          switch (true) {
236              case 'null' === $lowercaseValue:
237                  return null;
238              case ctype_digit($value):
239                  $raw = $value;
240                  $cast = (int) $value;
241   
242                  return '0' == $value[0] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw);
243              case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)):
244                  $raw = $value;
245                  $cast = (int) $value;
246   
247                  return '0' == $value[1] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw);
248              case 'true' === $lowercaseValue:
249                  return true;
250              case 'false' === $lowercaseValue:
251                  return false;
252              case isset($value[1]) && '0b' == $value[0].$value[1] && preg_match('/^0b[01]*$/', $value):
253                  return bindec($value);
254              case is_numeric($value):
255                  return '0x' === $value[0].$value[1] ? hexdec($value) : (float) $value;
256              case preg_match('/^0x[0-9a-f]++$/i', $value):
257                  return hexdec($value);
258              case preg_match('/^[+-]?[0-9]+(\.[0-9]+)?$/', $value):
259                  return (float) $value;
260              default:
261                  return $value;
262          }
263      }
264   
265      protected static function getXmlErrors($internalErrors)
266      {
267          $errors = [];
268          foreach (libxml_get_errors() as $error) {
269              $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
270                  \LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
271                  $error->code,
272                  trim($error->message),
273                  $error->file ?: 'n/a',
274                  $error->line,
275                  $error->column
276              );
277          }
278   
279          libxml_clear_errors();
280          libxml_use_internal_errors($internalErrors);
281   
282          return $errors;
283      }
284  }
285