[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/symfony/config/Util/ -> XmlUtils.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\Config\Util;
  13  
  14  /**
  15   * XMLUtils is a bunch of utility methods to XML operations.
  16   *
  17   * This class contains static methods only and is not meant to be instantiated.
  18   *
  19   * @author Fabien Potencier <fabien@symfony.com>
  20   * @author Martin HasoĊˆ <martin.hason@gmail.com>
  21   */
  22  class XmlUtils
  23  {
  24      /**
  25       * This class should not be instantiated.
  26       */
  27      private function __construct()
  28      {
  29      }
  30  
  31      /**
  32       * Loads an XML file.
  33       *
  34       * @param string               $file             An XML file path
  35       * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
  36       *
  37       * @return \DOMDocument
  38       *
  39       * @throws \InvalidArgumentException When loading of XML file returns error
  40       * @throws \RuntimeException         When DOM extension is missing
  41       */
  42      public static function loadFile($file, $schemaOrCallable = null)
  43      {
  44          if (!\extension_loaded('dom')) {
  45              throw new \RuntimeException('Extension DOM is required.');
  46          }
  47  
  48          $content = @file_get_contents($file);
  49          if ('' === trim($content)) {
  50              throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file));
  51          }
  52  
  53          $internalErrors = libxml_use_internal_errors(true);
  54          $disableEntities = libxml_disable_entity_loader(true);
  55          libxml_clear_errors();
  56  
  57          $dom = new \DOMDocument();
  58          $dom->validateOnParse = true;
  59          if (!$dom->loadXML($content, LIBXML_NONET | (\defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
  60              libxml_disable_entity_loader($disableEntities);
  61  
  62              throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors)));
  63          }
  64  
  65          $dom->normalizeDocument();
  66  
  67          libxml_use_internal_errors($internalErrors);
  68          libxml_disable_entity_loader($disableEntities);
  69  
  70          foreach ($dom->childNodes as $child) {
  71              if (XML_DOCUMENT_TYPE_NODE === $child->nodeType) {
  72                  throw new \InvalidArgumentException('Document types are not allowed.');
  73              }
  74          }
  75  
  76          if (null !== $schemaOrCallable) {
  77              $internalErrors = libxml_use_internal_errors(true);
  78              libxml_clear_errors();
  79  
  80              $e = null;
  81              if (\is_callable($schemaOrCallable)) {
  82                  try {
  83                      $valid = \call_user_func($schemaOrCallable, $dom, $internalErrors);
  84                  } catch (\Exception $e) {
  85                      $valid = false;
  86                  }
  87              } elseif (!\is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) {
  88                  $schemaSource = file_get_contents((string) $schemaOrCallable);
  89                  $valid = @$dom->schemaValidateSource($schemaSource);
  90              } else {
  91                  libxml_use_internal_errors($internalErrors);
  92  
  93                  throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.');
  94              }
  95  
  96              if (!$valid) {
  97                  $messages = static::getXmlErrors($internalErrors);
  98                  if (empty($messages)) {
  99                      $messages = array(sprintf('The XML file "%s" is not valid.', $file));
 100                  }
 101                  throw new \InvalidArgumentException(implode("\n", $messages), 0, $e);
 102              }
 103          }
 104  
 105          libxml_clear_errors();
 106          libxml_use_internal_errors($internalErrors);
 107  
 108          return $dom;
 109      }
 110  
 111      /**
 112       * Converts a \DOMElement object to a PHP array.
 113       *
 114       * The following rules applies during the conversion:
 115       *
 116       *  * Each tag is converted to a key value or an array
 117       *    if there is more than one "value"
 118       *
 119       *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
 120       *    if the tag also has some nested tags
 121       *
 122       *  * The attributes are converted to keys (<foo foo="bar"/>)
 123       *
 124       *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
 125       *
 126       * @param \DOMElement $element     A \DOMElement instance
 127       * @param bool        $checkPrefix Check prefix in an element or an attribute name
 128       *
 129       * @return array A PHP array
 130       */
 131      public static function convertDomElementToArray(\DOMElement $element, $checkPrefix = true)
 132      {
 133          $prefix = (string) $element->prefix;
 134          $empty = true;
 135          $config = array();
 136          foreach ($element->attributes as $name => $node) {
 137              if ($checkPrefix && !\in_array((string) $node->prefix, array('', $prefix), true)) {
 138                  continue;
 139              }
 140              $config[$name] = static::phpize($node->value);
 141              $empty = false;
 142          }
 143  
 144          $nodeValue = false;
 145          foreach ($element->childNodes as $node) {
 146              if ($node instanceof \DOMText) {
 147                  if ('' !== trim($node->nodeValue)) {
 148                      $nodeValue = trim($node->nodeValue);
 149                      $empty = false;
 150                  }
 151              } elseif ($checkPrefix && $prefix != (string) $node->prefix) {
 152                  continue;
 153              } elseif (!$node instanceof \DOMComment) {
 154                  $value = static::convertDomElementToArray($node, $checkPrefix);
 155  
 156                  $key = $node->localName;
 157                  if (isset($config[$key])) {
 158                      if (!\is_array($config[$key]) || !\is_int(key($config[$key]))) {
 159                          $config[$key] = array($config[$key]);
 160                      }
 161                      $config[$key][] = $value;
 162                  } else {
 163                      $config[$key] = $value;
 164                  }
 165  
 166                  $empty = false;
 167              }
 168          }
 169  
 170          if (false !== $nodeValue) {
 171              $value = static::phpize($nodeValue);
 172              if (\count($config)) {
 173                  $config['value'] = $value;
 174              } else {
 175                  $config = $value;
 176              }
 177          }
 178  
 179          return !$empty ? $config : null;
 180      }
 181  
 182      /**
 183       * Converts an xml value to a PHP type.
 184       *
 185       * @param mixed $value
 186       *
 187       * @return mixed
 188       */
 189      public static function phpize($value)
 190      {
 191          $value = (string) $value;
 192          $lowercaseValue = strtolower($value);
 193  
 194          switch (true) {
 195              case 'null' === $lowercaseValue:
 196                  return;
 197              case ctype_digit($value):
 198                  $raw = $value;
 199                  $cast = (int) $value;
 200  
 201                  return '0' == $value[0] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw);
 202              case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)):
 203                  $raw = $value;
 204                  $cast = (int) $value;
 205  
 206                  return '0' == $value[1] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw);
 207              case 'true' === $lowercaseValue:
 208                  return true;
 209              case 'false' === $lowercaseValue:
 210                  return false;
 211              case isset($value[1]) && '0b' == $value[0].$value[1]:
 212                  return bindec($value);
 213              case is_numeric($value):
 214                  return '0x' === $value[0].$value[1] ? hexdec($value) : (float) $value;
 215              case preg_match('/^0x[0-9a-f]++$/i', $value):
 216                  return hexdec($value);
 217              case preg_match('/^(-|\+)?[0-9]+(\.[0-9]+)?$/', $value):
 218                  return (float) $value;
 219              default:
 220                  return $value;
 221          }
 222      }
 223  
 224      protected static function getXmlErrors($internalErrors)
 225      {
 226          $errors = array();
 227          foreach (libxml_get_errors() as $error) {
 228              $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
 229                  LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
 230                  $error->code,
 231                  trim($error->message),
 232                  $error->file ?: 'n/a',
 233                  $error->line,
 234                  $error->column
 235              );
 236          }
 237  
 238          libxml_clear_errors();
 239          libxml_use_internal_errors($internalErrors);
 240  
 241          return $errors;
 242      }
 243  }


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