Overview

Namespaces

  • Evenement
  • None
  • PHP
  • Psr
    • Http
      • Message
  • Ratchet
    • Http
    • RFC6455
      • Handshake
      • Messaging
    • Server
    • Session
      • Serialize
      • Storage
        • Proxy
    • Wamp
    • WebSocket
  • React
    • EventLoop
      • Tick
      • Timer
    • Socket
    • Stream
  • Symfony
    • Component
      • HttpFoundation
        • Session
          • Attribute
          • Flash
          • Storage
            • Handler
            • Proxy
      • Routing
        • Annotation
        • Exception
        • Generator
          • Dumper
        • Loader
          • DependencyInjection
        • Matcher
          • Dumper
        • Tests
          • Annotation
          • Fixtures
            • AnnotatedClasses
            • OtherAnnotatedClasses
          • Generator
            • Dumper
          • Loader
          • Matcher
            • Dumper

Classes

  • AnnotationClassLoader
  • AnnotationDirectoryLoader
  • AnnotationFileLoader
  • ClosureLoader
  • DirectoryLoader
  • ObjectRouteLoader
  • PhpFileLoader
  • RecursiveCallbackFilterIterator
  • XmlFileLoader
  • YamlFileLoader
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: /*
  4:  * This file is part of the Symfony package.
  5:  *
  6:  * (c) Fabien Potencier <[email protected]>
  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\Routing\RouteCollection;
 15: use Symfony\Component\Routing\Route;
 16: use Symfony\Component\Config\Resource\FileResource;
 17: use Symfony\Component\Config\Loader\FileLoader;
 18: use Symfony\Component\Config\Util\XmlUtils;
 19: 
 20: /**
 21:  * XmlFileLoader loads XML routing files.
 22:  *
 23:  * @author Fabien Potencier <[email protected]>
 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('pattern') && !$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:         if ($node->hasAttribute('pattern')) {
115:             if ($node->hasAttribute('path')) {
116:                 throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path));
117:             }
118: 
119:             @trigger_error(sprintf('The "pattern" option in file "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the "path" option in the route definition instead.', $path), E_USER_DEPRECATED);
120: 
121:             $node->setAttribute('path', $node->getAttribute('pattern'));
122:             $node->removeAttribute('pattern');
123:         }
124: 
125:         $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY);
126:         $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY);
127: 
128:         list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
129: 
130:         if (isset($requirements['_method'])) {
131:             if (0 === count($methods)) {
132:                 $methods = explode('|', $requirements['_method']);
133:             }
134: 
135:             unset($requirements['_method']);
136:             @trigger_error(sprintf('The "_method" requirement of route "%s" in file "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the "methods" attribute instead.', $id, $path), E_USER_DEPRECATED);
137:         }
138: 
139:         if (isset($requirements['_scheme'])) {
140:             if (0 === count($schemes)) {
141:                 $schemes = explode('|', $requirements['_scheme']);
142:             }
143: 
144:             unset($requirements['_scheme']);
145:             @trigger_error(sprintf('The "_scheme" requirement of route "%s" in file "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the "schemes" attribute instead.', $id, $path), E_USER_DEPRECATED);
146:         }
147: 
148:         $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
149:         $collection->add($id, $route);
150:     }
151: 
152:     /**
153:      * Parses an import and adds the routes in the resource to the RouteCollection.
154:      *
155:      * @param RouteCollection $collection RouteCollection instance
156:      * @param \DOMElement     $node       Element to parse that represents a Route
157:      * @param string          $path       Full path of the XML file being processed
158:      * @param string          $file       Loaded file name
159:      *
160:      * @throws \InvalidArgumentException When the XML is invalid
161:      */
162:     protected function parseImport(RouteCollection $collection, \DOMElement $node, $path, $file)
163:     {
164:         if ('' === $resource = $node->getAttribute('resource')) {
165:             throw new \InvalidArgumentException(sprintf('The <import> element in file "%s" must have a "resource" attribute.', $path));
166:         }
167: 
168:         $type = $node->getAttribute('type');
169:         $prefix = $node->getAttribute('prefix');
170:         $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null;
171:         $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null;
172:         $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null;
173: 
174:         list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
175: 
176:         $this->setCurrentDir(dirname($path));
177: 
178:         $subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file);
179:         /* @var $subCollection RouteCollection */
180:         $subCollection->addPrefix($prefix);
181:         if (null !== $host) {
182:             $subCollection->setHost($host);
183:         }
184:         if (null !== $condition) {
185:             $subCollection->setCondition($condition);
186:         }
187:         if (null !== $schemes) {
188:             $subCollection->setSchemes($schemes);
189:         }
190:         if (null !== $methods) {
191:             $subCollection->setMethods($methods);
192:         }
193:         $subCollection->addDefaults($defaults);
194:         $subCollection->addRequirements($requirements);
195:         $subCollection->addOptions($options);
196: 
197:         $collection->addCollection($subCollection);
198:     }
199: 
200:     /**
201:      * Loads an XML file.
202:      *
203:      * @param string $file An XML file path
204:      *
205:      * @return \DOMDocument
206:      *
207:      * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors
208:      *                                   or when the XML structure is not as expected by the scheme -
209:      *                                   see validate()
210:      */
211:     protected function loadFile($file)
212:     {
213:         return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH);
214:     }
215: 
216:     /**
217:      * Parses the config elements (default, requirement, option).
218:      *
219:      * @param \DOMElement $node Element to parse that contains the configs
220:      * @param string      $path Full path of the XML file being processed
221:      *
222:      * @return array An array with the defaults as first item, requirements as second and options as third
223:      *
224:      * @throws \InvalidArgumentException When the XML is invalid
225:      */
226:     private function parseConfigs(\DOMElement $node, $path)
227:     {
228:         $defaults = array();
229:         $requirements = array();
230:         $options = array();
231:         $condition = null;
232: 
233:         foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
234:             switch ($n->localName) {
235:                 case 'default':
236:                     if ($this->isElementValueNull($n)) {
237:                         $defaults[$n->getAttribute('key')] = null;
238:                     } else {
239:                         $defaults[$n->getAttribute('key')] = trim($n->textContent);
240:                     }
241: 
242:                     break;
243:                 case 'requirement':
244:                     $requirements[$n->getAttribute('key')] = trim($n->textContent);
245:                     break;
246:                 case 'option':
247:                     $options[$n->getAttribute('key')] = trim($n->textContent);
248:                     break;
249:                 case 'condition':
250:                     $condition = trim($n->textContent);
251:                     break;
252:                 default:
253:                     throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path));
254:             }
255:         }
256: 
257:         return array($defaults, $requirements, $options, $condition);
258:     }
259: 
260:     private function isElementValueNull(\DOMElement $element)
261:     {
262:         $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance';
263: 
264:         if (!$element->hasAttributeNS($namespaceUri, 'nil')) {
265:             return false;
266:         }
267: 
268:         return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil');
269:     }
270: }
271: 
Ratchet API documentation generated by ApiGen 2.8.0