/** * Adds an operation known to be supported by instances of this class * * @param array $operations The operation known to be supported by * instances of this class. * * @return PropertyMetadata $this */ public function addOperation(OperationDefinition $operation) { if (false === $this->supportsOperation($operation->getName())) { $this->operations[] = $operation; } return $this; }
/** * Get information about a route * * @param string $routeName */ protected function getRouteMetadata($routeName) { if (isset($this->routeMetadata[$routeName])) { return $this->routeMetadata[$routeName]; } $route = $this->router->getRouteCollection()->get($routeName); if (null === $route) { // TODO Improve this throw new \Exception(sprintf('The route "%s" couldn\'t be found', $routeName)); } // TODO Check this $controller = $route->getDefault('_controller'); if (preg_match('#(.+)::([\\w]+)#', $controller, $matches)) { $class = $matches[1]; $method = $matches[2]; } elseif (preg_match('#(.+):([\\w]+)#', $controller, $matches)) { $controller = $matches[1]; $method = $matches[2]; if ($this->container->has($controller)) { $this->container->enterScope('request'); $this->container->set('request', new Request()); $class = get_class($this->container->get($controller)); $this->container->leaveScope('request'); } } if (isset($class) && isset($method)) { try { $method = new ReflectionMethod($class, $method); } catch (\ReflectionException $e) { throw new \Exception(sprintf('The controller method for the route "%s" couldn\'t be found', $routeName)); } } if (null === ($annotation = $this->getAnnotation($method, 'ML\\HydraBundle\\Mapping\\Operation'))) { throw new \Exception(sprintf('The controller method for the route "%s" is not marked as an operation', $routeName)); } $operation = new OperationDefinition($routeName); $operation->setIri($annotation->getIri()); $operation->setType($annotation->type); $operation->setRoute($route); $tmp = $this->getDocBlockText($method); $operation->setTitle($tmp['title']); $operation->setDescription($tmp['description']); $operation->setExpects($annotation->expect); $operation->setStatusCodes($annotation->status_codes); // TODO Check this $tmp = $this->getType($method); $operation->setReturns($tmp['type']); // TODO Check this! Should we use the return type instead? if ($tmp['is_array'] || null !== ($annotation = $this->getAnnotation($method, 'ML\\HydraBundle\\Mapping\\Collection'))) { $operation->setReturns('ML\\HydraBundle\\Entity\\Collection'); } // if (('array' === $operation['return']['type']) || (self::HYDRA_COLLECTION === $operation['return']['type'])) { // $operation['return']['type'] = self::HYDRA_COLLECTION; // } // method/IRI $operation->setMethod($route->getRequirement('_method')); // $operation['path'] = $route->getPath(); // $operation['variables'] = $route->compile()->getVariables(); // $operation['defaults'] = $route->getDefaults(); // unset($operation['defaults']['_controller']); // Cache the metadata since it might be needed several times $this->routeMetadata[$routeName] = $operation; return $operation; }
/** * Generate a URL for the specified operation using the passed entity/data * * @param OperationDefinition $operation The operation specifying the route * @param mixed $entity The entity to be used to fill URL variables * @param mixed $value A value to be used to fill URL variables * * @return string|null The URL or null if the URL shouldn't be exposed. */ private function generateUrl(OperationDefinition $operation, $entity, $value = null) { $route = $operation->getRoute(); $routeVariables = $route->compile()->getVariables(); $variableValues = $route->getDefaults(); unset($variableValues['_controller']); // TODO: Allow custom route variable mappings if (is_array($value)) { $variableValues += $value; // FIXXME: Check if this is really what we want in all cases } elseif (1 === count($routeVariables)) { if (is_scalar($value)) { $variableValues[reset($routeVariables)] = $value; } elseif (is_object($value) && is_callable(array($value, 'getId'))) { // TODO Make the is_callable check more robust $variableValues[reset($routeVariables)] = $value->getId(); } elseif (is_object($entity) && is_callable(array($entity, 'getId'))) { // TODO Check if this is want in all cases $variableValues[reset($routeVariables)] = $entity->getId(); } elseif (null === $value) { return null; } } else { $accessor = PropertyAccess::createPropertyAccessor(); foreach ($routeVariables as $variable) { try { $variableValues[$variable] = $accessor->getValue($value, $variable); } catch (\Exception $e) { // do nothing, no such property exists } } } return $this->router->generate($operation->getName(), $variableValues); }