[ Index ] |
PHP Cross Reference of phpBB-3.3.12-deutsch |
[Summary view] [Print] [Text view]
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\Routing\Loader; 13 14 use Symfony\Component\Config\Loader\FileLoader; 15 use Symfony\Component\Config\Resource\FileResource; 16 use Symfony\Component\Config\Util\XmlUtils; 17 use Symfony\Component\Routing\Route; 18 use Symfony\Component\Routing\RouteCollection; 19 20 /** 21 * XmlFileLoader loads XML routing files. 22 * 23 * @author Fabien Potencier <fabien@symfony.com> 24 * @author Tobias Schultze <http://tobion.de> 25 */ 26 class XmlFileLoader extends FileLoader 27 { 28 const NAMESPACE_URI = 'http://symfony.com/schema/routing'; 29 const SCHEME_PATH = '/schema/routing/routing-1.0.xsd'; 30 31 /** 32 * Loads an XML file. 33 * 34 * @param string $file An XML file path 35 * @param string|null $type The resource type 36 * 37 * @return RouteCollection A RouteCollection instance 38 * 39 * @throws \InvalidArgumentException when the file cannot be loaded or when the XML cannot be 40 * parsed because it does not validate against the scheme 41 */ 42 public function load($file, $type = null) 43 { 44 $path = $this->locator->locate($file); 45 46 $xml = $this->loadFile($path); 47 48 $collection = new RouteCollection(); 49 $collection->addResource(new FileResource($path)); 50 51 // process routes and imports 52 foreach ($xml->documentElement->childNodes as $node) { 53 if (!$node instanceof \DOMElement) { 54 continue; 55 } 56 57 $this->parseNode($collection, $node, $path, $file); 58 } 59 60 return $collection; 61 } 62 63 /** 64 * Parses a node from a loaded XML file. 65 * 66 * @param RouteCollection $collection Collection to associate with the node 67 * @param \DOMElement $node Element to parse 68 * @param string $path Full path of the XML file being processed 69 * @param string $file Loaded file name 70 * 71 * @throws \InvalidArgumentException When the XML is invalid 72 */ 73 protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file) 74 { 75 if (self::NAMESPACE_URI !== $node->namespaceURI) { 76 return; 77 } 78 79 switch ($node->localName) { 80 case 'route': 81 $this->parseRoute($collection, $node, $path); 82 break; 83 case 'import': 84 $this->parseImport($collection, $node, $path, $file); 85 break; 86 default: 87 throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path)); 88 } 89 } 90 91 /** 92 * {@inheritdoc} 93 */ 94 public function supports($resource, $type = null) 95 { 96 return \is_string($resource) && 'xml' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'xml' === $type); 97 } 98 99 /** 100 * Parses a route and adds it to the RouteCollection. 101 * 102 * @param RouteCollection $collection RouteCollection instance 103 * @param \DOMElement $node Element to parse that represents a Route 104 * @param string $path Full path of the XML file being processed 105 * 106 * @throws \InvalidArgumentException When the XML is invalid 107 */ 108 protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path) 109 { 110 if ('' === ($id = $node->getAttribute('id')) || !$node->hasAttribute('path')) { 111 throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "path" attribute.', $path)); 112 } 113 114 $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY); 115 $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY); 116 117 list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path); 118 119 $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition); 120 $collection->add($id, $route); 121 } 122 123 /** 124 * Parses an import and adds the routes in the resource to the RouteCollection. 125 * 126 * @param RouteCollection $collection RouteCollection instance 127 * @param \DOMElement $node Element to parse that represents a Route 128 * @param string $path Full path of the XML file being processed 129 * @param string $file Loaded file name 130 * 131 * @throws \InvalidArgumentException When the XML is invalid 132 */ 133 protected function parseImport(RouteCollection $collection, \DOMElement $node, $path, $file) 134 { 135 if ('' === $resource = $node->getAttribute('resource')) { 136 throw new \InvalidArgumentException(sprintf('The <import> element in file "%s" must have a "resource" attribute.', $path)); 137 } 138 139 $type = $node->getAttribute('type'); 140 $prefix = $node->getAttribute('prefix'); 141 $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null; 142 $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY) : null; 143 $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY) : null; 144 145 list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path); 146 147 $this->setCurrentDir(\dirname($path)); 148 149 /** @var RouteCollection[] $imported */ 150 $imported = $this->import($resource, ('' !== $type ? $type : null), false, $file) ?: []; 151 152 if (!\is_array($imported)) { 153 $imported = [$imported]; 154 } 155 156 foreach ($imported as $subCollection) { 157 /* @var $subCollection RouteCollection */ 158 $subCollection->addPrefix($prefix); 159 if (null !== $host) { 160 $subCollection->setHost($host); 161 } 162 if (null !== $condition) { 163 $subCollection->setCondition($condition); 164 } 165 if (null !== $schemes) { 166 $subCollection->setSchemes($schemes); 167 } 168 if (null !== $methods) { 169 $subCollection->setMethods($methods); 170 } 171 $subCollection->addDefaults($defaults); 172 $subCollection->addRequirements($requirements); 173 $subCollection->addOptions($options); 174 175 $collection->addCollection($subCollection); 176 } 177 } 178 179 /** 180 * Loads an XML file. 181 * 182 * @param string $file An XML file path 183 * 184 * @return \DOMDocument 185 * 186 * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors 187 * or when the XML structure is not as expected by the scheme - 188 * see validate() 189 */ 190 protected function loadFile($file) 191 { 192 return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH); 193 } 194 195 /** 196 * Parses the config elements (default, requirement, option). 197 * 198 * @param \DOMElement $node Element to parse that contains the configs 199 * @param string $path Full path of the XML file being processed 200 * 201 * @return array An array with the defaults as first item, requirements as second and options as third 202 * 203 * @throws \InvalidArgumentException When the XML is invalid 204 */ 205 private function parseConfigs(\DOMElement $node, $path) 206 { 207 $defaults = []; 208 $requirements = []; 209 $options = []; 210 $condition = null; 211 212 /** @var \DOMElement $n */ 213 foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { 214 if ($node !== $n->parentNode) { 215 continue; 216 } 217 218 switch ($n->localName) { 219 case 'default': 220 if ($this->isElementValueNull($n)) { 221 $defaults[$n->getAttribute('key')] = null; 222 } else { 223 $defaults[$n->getAttribute('key')] = $this->parseDefaultsConfig($n, $path); 224 } 225 226 break; 227 case 'requirement': 228 $requirements[$n->getAttribute('key')] = trim($n->textContent); 229 break; 230 case 'option': 231 $options[$n->getAttribute('key')] = XmlUtils::phpize(trim($n->textContent)); 232 break; 233 case 'condition': 234 $condition = trim($n->textContent); 235 break; 236 default: 237 throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path)); 238 } 239 } 240 241 if ($controller = $node->getAttribute('controller')) { 242 if (isset($defaults['_controller'])) { 243 $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName); 244 245 throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for ', $path).$name); 246 } 247 248 $defaults['_controller'] = $controller; 249 } 250 251 return [$defaults, $requirements, $options, $condition]; 252 } 253 254 /** 255 * Parses the "default" elements. 256 * 257 * @param \DOMElement $element The "default" element to parse 258 * @param string $path Full path of the XML file being processed 259 * 260 * @return array|bool|float|int|string|null The parsed value of the "default" element 261 */ 262 private function parseDefaultsConfig(\DOMElement $element, $path) 263 { 264 if ($this->isElementValueNull($element)) { 265 return null; 266 } 267 268 // Check for existing element nodes in the default element. There can 269 // only be a single element inside a default element. So this element 270 // (if one was found) can safely be returned. 271 foreach ($element->childNodes as $child) { 272 if (!$child instanceof \DOMElement) { 273 continue; 274 } 275 276 if (self::NAMESPACE_URI !== $child->namespaceURI) { 277 continue; 278 } 279 280 return $this->parseDefaultNode($child, $path); 281 } 282 283 // If the default element doesn't contain a nested "bool", "int", "float", 284 // "string", "list", or "map" element, the element contents will be treated 285 // as the string value of the associated default option. 286 return trim($element->textContent); 287 } 288 289 /** 290 * Recursively parses the value of a "default" element. 291 * 292 * @param \DOMElement $node The node value 293 * @param string $path Full path of the XML file being processed 294 * 295 * @return array|bool|float|int|string The parsed value 296 * 297 * @throws \InvalidArgumentException when the XML is invalid 298 */ 299 private function parseDefaultNode(\DOMElement $node, $path) 300 { 301 if ($this->isElementValueNull($node)) { 302 return null; 303 } 304 305 switch ($node->localName) { 306 case 'bool': 307 return 'true' === trim($node->nodeValue) || '1' === trim($node->nodeValue); 308 case 'int': 309 return (int) trim($node->nodeValue); 310 case 'float': 311 return (float) trim($node->nodeValue); 312 case 'string': 313 return trim($node->nodeValue); 314 case 'list': 315 $list = []; 316 317 foreach ($node->childNodes as $element) { 318 if (!$element instanceof \DOMElement) { 319 continue; 320 } 321 322 if (self::NAMESPACE_URI !== $element->namespaceURI) { 323 continue; 324 } 325 326 $list[] = $this->parseDefaultNode($element, $path); 327 } 328 329 return $list; 330 case 'map': 331 $map = []; 332 333 foreach ($node->childNodes as $element) { 334 if (!$element instanceof \DOMElement) { 335 continue; 336 } 337 338 if (self::NAMESPACE_URI !== $element->namespaceURI) { 339 continue; 340 } 341 342 $map[$element->getAttribute('key')] = $this->parseDefaultNode($element, $path); 343 } 344 345 return $map; 346 default: 347 throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "bool", "int", "float", "string", "list", or "map".', $node->localName, $path)); 348 } 349 } 350 351 private function isElementValueNull(\DOMElement $element) 352 { 353 $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance'; 354 355 if (!$element->hasAttributeNS($namespaceUri, 'nil')) { 356 return false; 357 } 358 359 return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil'); 360 } 361 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Jun 23 12:25:44 2024 | Cross-referenced by PHPXref 0.7.1 |