PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/symfony/config/Symfony/Component/Config/Util/XmlUtils.php

https://bitbucket.org/laborautonomo/laborautonomo-site
PHP | 222 lines | 139 code | 27 blank | 56 comment | 26 complexity | ebc3f803613b6dccfaf8686da224ffd2 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Config\Util;
  11. /**
  12. * XMLUtils is a bunch of utility methods to XML operations.
  13. *
  14. * This class contains static methods only and is not meant to be instantiated.
  15. *
  16. * @author Fabien Potencier <fabien@symfony.com>
  17. * @author Martin HasoĊˆ <martin.hason@gmail.com>
  18. */
  19. class XmlUtils
  20. {
  21. /**
  22. * This class should not be instantiated
  23. */
  24. private function __construct()
  25. {
  26. }
  27. /**
  28. * Loads an XML file.
  29. *
  30. * @param string $file An XML file path
  31. * @param string|callable $schemaOrCallable An XSD schema file path or callable
  32. *
  33. * @return \DOMDocument
  34. *
  35. * @throws \InvalidArgumentException When loading of XML file returns error
  36. */
  37. public static function loadFile($file, $schemaOrCallable = null)
  38. {
  39. $internalErrors = libxml_use_internal_errors(true);
  40. $disableEntities = libxml_disable_entity_loader(true);
  41. libxml_clear_errors();
  42. $dom = new \DOMDocument();
  43. $dom->validateOnParse = true;
  44. if (!$dom->loadXML(file_get_contents($file), LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
  45. libxml_disable_entity_loader($disableEntities);
  46. throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors)));
  47. }
  48. $dom->normalizeDocument();
  49. libxml_use_internal_errors($internalErrors);
  50. libxml_disable_entity_loader($disableEntities);
  51. foreach ($dom->childNodes as $child) {
  52. if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
  53. throw new \InvalidArgumentException('Document types are not allowed.');
  54. }
  55. }
  56. if (null !== $schemaOrCallable) {
  57. $internalErrors = libxml_use_internal_errors(true);
  58. libxml_clear_errors();
  59. $e = null;
  60. if (is_callable($schemaOrCallable)) {
  61. try {
  62. $valid = call_user_func($schemaOrCallable, $dom, $internalErrors);
  63. } catch (\Exception $e) {
  64. $valid = false;
  65. }
  66. } elseif (!is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) {
  67. $valid = @$dom->schemaValidate($schemaOrCallable);
  68. } else {
  69. libxml_use_internal_errors($internalErrors);
  70. throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.');
  71. }
  72. if (!$valid) {
  73. $messages = static::getXmlErrors($internalErrors);
  74. if (empty($messages)) {
  75. $messages = array(sprintf('The XML file "%s" is not valid.', $file));
  76. }
  77. throw new \InvalidArgumentException(implode("\n", $messages), 0, $e);
  78. }
  79. libxml_use_internal_errors($internalErrors);
  80. }
  81. return $dom;
  82. }
  83. /**
  84. * Converts a \DomElement object to a PHP array.
  85. *
  86. * The following rules applies during the conversion:
  87. *
  88. * * Each tag is converted to a key value or an array
  89. * if there is more than one "value"
  90. *
  91. * * The content of a tag is set under a "value" key (<foo>bar</foo>)
  92. * if the tag also has some nested tags
  93. *
  94. * * The attributes are converted to keys (<foo foo="bar"/>)
  95. *
  96. * * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
  97. *
  98. * @param \DomElement $element A \DomElement instance
  99. * @param Boolean $checkPrefix Check prefix in an element or an attribute name
  100. *
  101. * @return array A PHP array
  102. */
  103. public static function convertDomElementToArray(\DomElement $element, $checkPrefix = true)
  104. {
  105. $prefix = (string) $element->prefix;
  106. $empty = true;
  107. $config = array();
  108. foreach ($element->attributes as $name => $node) {
  109. if ($checkPrefix && !in_array((string) $node->prefix, array('', $prefix), true)) {
  110. continue;
  111. }
  112. $config[$name] = static::phpize($node->value);
  113. $empty = false;
  114. }
  115. $nodeValue = false;
  116. foreach ($element->childNodes as $node) {
  117. if ($node instanceof \DOMText) {
  118. if (trim($node->nodeValue)) {
  119. $nodeValue = trim($node->nodeValue);
  120. $empty = false;
  121. }
  122. } elseif ($checkPrefix && $prefix != (string) $node->prefix) {
  123. continue;
  124. } elseif (!$node instanceof \DOMComment) {
  125. $value = static::convertDomElementToArray($node, $checkPrefix);
  126. $key = $node->localName;
  127. if (isset($config[$key])) {
  128. if (!is_array($config[$key]) || !is_int(key($config[$key]))) {
  129. $config[$key] = array($config[$key]);
  130. }
  131. $config[$key][] = $value;
  132. } else {
  133. $config[$key] = $value;
  134. }
  135. $empty = false;
  136. }
  137. }
  138. if (false !== $nodeValue) {
  139. $value = static::phpize($nodeValue);
  140. if (count($config)) {
  141. $config['value'] = $value;
  142. } else {
  143. $config = $value;
  144. }
  145. }
  146. return !$empty ? $config : null;
  147. }
  148. /**
  149. * Converts an xml value to a php type.
  150. *
  151. * @param mixed $value
  152. *
  153. * @return mixed
  154. */
  155. public static function phpize($value)
  156. {
  157. $value = (string) $value;
  158. $lowercaseValue = strtolower($value);
  159. switch (true) {
  160. case 'null' === $lowercaseValue:
  161. return null;
  162. case ctype_digit($value):
  163. $raw = $value;
  164. $cast = intval($value);
  165. return '0' == $value[0] ? octdec($value) : (((string) $raw == (string) $cast) ? $cast : $raw);
  166. case 'true' === $lowercaseValue:
  167. return true;
  168. case 'false' === $lowercaseValue:
  169. return false;
  170. case is_numeric($value):
  171. return '0x' == $value[0].$value[1] ? hexdec($value) : floatval($value);
  172. case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $value):
  173. return floatval(str_replace(',', '', $value));
  174. default:
  175. return $value;
  176. }
  177. }
  178. protected static function getXmlErrors($internalErrors)
  179. {
  180. $errors = array();
  181. foreach (libxml_get_errors() as $error) {
  182. $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
  183. LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
  184. $error->code,
  185. trim($error->message),
  186. $error->file ? $error->file : 'n/a',
  187. $error->line,
  188. $error->column
  189. );
  190. }
  191. libxml_clear_errors();
  192. libxml_use_internal_errors($internalErrors);
  193. return $errors;
  194. }
  195. }