/** * @param \DOMElement $mappingNode * @param string $path * * @return ClassMetadata */ protected function parseMappingNode(\DOMElement $mappingNode, $path) { $className = $this->readAttribute($mappingNode, 'class', sprintf('in "%s"', $path)); if (!class_exists($className)) { throw new \InvalidArgumentException(sprintf('Configuration found for unknown class "%s" in "%s".', $className, $path)); } $classMetadata = new ClassMetadata($className); try { $classMetadata->setExtendedClass($this->readAttribute($mappingNode, 'extend', sprintf('for "%s" in "%s"', $className, $path))); } catch (\InvalidArgumentException $e) { // the extend and uri-schema attributes may be omitted } $uriSchemaNodes = $mappingNode->getElementsByTagNameNS(self::NAMESPACE_URI, 'definition'); // support the old attribute name until 2.0 $uriSchemaIndex = 0; foreach ($uriSchemaNodes as $uriSchemaNode) { $uriSchemaName = $uriSchemaNode->hasAttribute('name') ? $uriSchemaNode->getAttribute('name') : $uriSchemaIndex; $classMetadata->setAutoRouteDefinition($uriSchemaName, $this->parseDefinitionNode($uriSchemaNode, $classMetadata, $path)); ++$uriSchemaIndex; } $conflictResolverNodes = $mappingNode->getElementsByTagNameNS(self::NAMESPACE_URI, 'conflict-resolver'); $resolversLength = $conflictResolverNodes->length; if (1 < $resolversLength) { throw new \InvalidArgumentException(sprintf('There can only be one conflict resolver per mapping, %d given for "%s" in ""%s', $resolversLength, $className, $path)); } elseif (1 === $resolversLength) { $this->parseConflictResolverNode($conflictResolverNodes->item(0), $classMetadata, $path); } $defunctRouteHandlerNodes = $mappingNode->getElementsByTagNameNS(self::NAMESPACE_URI, 'defunct-route-handler'); $defunctRouteHandlerLength = $defunctRouteHandlerNodes->length; if (1 < $defunctRouteHandlerLength) { throw new \InvalidArgumentException(sprintf('There can only be one defunct route handler per mapping, %d given for "%s" in ""%s', $defunctRouteHandlerLength, $className, $path)); } elseif (1 === $defunctRouteHandlerLength) { $this->parseDefunctRouteHandlerNode($defunctRouteHandlerNodes->item(0), $classMetadata, $path); } $tokenProviders = $mappingNode->getElementsByTagNameNS(self::NAMESPACE_URI, 'token-provider'); // token providers can be omitted if the schema is constructed of // global token providers only if (0 !== count($tokenProviders)) { foreach ($tokenProviders as $tokenNode) { $this->parseTokenProviderNode($tokenNode, $classMetadata, $path); } } return $classMetadata; }
/** * @param string $className * @param array $mappingNode * @param string $path */ protected function parseMappingNode($className, $mappingNode, $path) { if (!class_exists($className)) { throw new \InvalidArgumentException(sprintf('Configuration found for unknown class "%s" in "%s".', $className, $path)); } $classMetadata = new ClassMetadata($className); $this->validateNode($mappingNode, array('uri_schema', 'definitions', 'conflict_resolver', 'defunct_route_handler', 'extend', 'token_providers'), sprintf('routing auto class metadata (%s)', $className)); if (!isset($mappingNode['definitions'])) { throw new \InvalidArgumentException(sprintf('Mapping node for "%s" must define a list of auto route definitions under the `definitions` key.', $className)); } foreach ($mappingNode as $key => $value) { switch ($key) { case 'definitions': foreach ($this->getAutoRouteDefinitions($value) as $definitionName => $definition) { $classMetadata->setAutoRouteDefinition($definitionName, $definition); } break; case 'conflict_resolver': $classMetadata->setConflictResolver($this->parseServiceConfig($mappingNode['conflict_resolver'], $className, $path)); break; case 'defunct_route_handler': $classMetadata->setDefunctRouteHandler($this->parseServiceConfig($mappingNode['defunct_route_handler'], $className, $path)); break; case 'extend': $classMetadata->setExtendedClass($mappingNode['extend']); break; case 'token_providers': foreach ($mappingNode['token_providers'] as $tokenName => $provider) { $classMetadata->addTokenProvider($tokenName, $this->parseServiceConfig($provider, $className, $path)); } break; default: throw new \InvalidArgumentException(sprintf('Unknown mapping key "%s"', $key)); } } return $classMetadata; }
/** * @expectedException \Symfony\Cmf\Component\RoutingAuto\Mapping\Exception\CircularReferenceException * @expectedExceptionMessage "Symfony\Cmf\Component\RoutingAuto\Tests\Resources\Fixtures\ChildClass" */ public function testsFailsWithPhpCircularReference() { $childMetadata = new ClassMetadata('Symfony\\Cmf\\Component\\RoutingAuto\\Tests\\Resources\\Fixtures\\ChildClass'); $childMetadata->setAutoRouteDefinition('one', new AutoRouteDefinition('{title}')); $parentMetadata = new ClassMetadata('Symfony\\Cmf\\Component\\RoutingAuto\\Tests\\Resources\\Fixtures\\ParentClass'); $parentMetadata->setExtendedClass('Symfony\\Cmf\\Component\\RoutingAuto\\Tests\\Resources\\Fixtures\\ChildClass'); $parentMetadata->addTokenProvider('title', $this->createTokenProvider('provider1')); $this->factory->addMetadatas(array($childMetadata, $parentMetadata)); $this->factory->getMetadataForClass('Symfony\\Cmf\\Component\\RoutingAuto\\Tests\\Resources\\Fixtures\\ChildClass'); }