Skip to content

Commit

Permalink
Added more complex parameters functionnality, also in Breadcrumb title
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-synapse committed Nov 10, 2015
1 parent 33b1774 commit b251535
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 33 deletions.
89 changes: 67 additions & 22 deletions BreadcrumbTrail/Trail.php
Expand Up @@ -89,25 +89,47 @@ public function add($breadcrumb_or_title, $routeName = null, $routeParameters =
$request = $this->container->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE);

if ($request !== null) {
preg_match_all('#\{(?P<variable>\w+).?(?P<function>\w*):?(?P<parameters>(\w|,| )*)\}#', $breadcrumb_or_title, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
preg_match_all('#\{(?P<variable>\w+).?(?P<function>([\w\.])*):?(?P<parameters>(\w|,| )*)\}#', $breadcrumb_or_title, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);

foreach ($matches as $match) {
$varName = $match['variable'][0];
$functionName = $match['function'][0];
$varName = $match['variable'][0];
$functions = explode('.', $match['function'][0]);
$parameters = explode(',', $match['parameters'][0]);
$nbCalls = count($functions);

if($request->attributes->has($varName)) {
$object = $request->attributes->get($varName);

if(empty($functionName)) {
if(empty($functions)) {
$objectValue = (string) $object;
}
elseif(is_callable(array($object, $fullFunctionName = 'get'.$functionName))
|| is_callable(array($object, $fullFunctionName = 'has'.$functionName))
|| is_callable(array($object, $fullFunctionName = 'is'.$functionName))) {
$objectValue = call_user_func_array(array($object, $fullFunctionName),$parameters);
}
else {
throw new \RuntimeException(sprintf('Function "%s" not found.', $functionName));
foreach ($functions AS $f => $function) {

# While this is not the last function, call the chain
if ($f < $nbCalls - 1) {
if(is_callable(array($object, $fullFunctionName = 'get'.$function))
|| is_callable(array($object, $fullFunctionName = 'has'.$function))
|| is_callable(array($object, $fullFunctionName = 'is'.$function))) {
$object = call_user_func(array($object, $fullFunctionName));
}
else {
throw new \RuntimeException(sprintf('"%s" is not callable.', join('.', array_merge([$varName], $functions))));
}
}

# End of the chain: call the method
else {
if(is_callable(array($object, $fullFunctionName = 'get'.$function))
|| is_callable(array($object, $fullFunctionName = 'has'.$function))
|| is_callable(array($object, $fullFunctionName = 'is'.$function))) {
$objectValue = call_user_func_array(array($object, $fullFunctionName),$parameters);
}
else {
throw new \RuntimeException(sprintf('"%s" is not callable.', join('.', array_merge([$varName], $functions))));
}
}
}
}

$breadcrumb_or_title = str_replace($match[0][0], $objectValue, $breadcrumb_or_title);
Expand All @@ -119,28 +141,51 @@ public function add($breadcrumb_or_title, $routeName = null, $routeParameters =
$routeParameters[$value] = $request->get($value);
unset($routeParameters[$key]);
} else {
if (preg_match_all('#\{(?P<variable>\w+).?(?P<function>\w*):?(?P<parameters>(\w|,| )*)\}#', $value, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
if (preg_match_all('#\{(?P<variable>\w+).?(?P<function>([\w\.])*):?(?P<parameters>(\w|,| )*)\}#', $value, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {

foreach ($matches AS $match) {

$varName = $match['variable'][0];
$functionName = $match['function'][0];
$parameters = explode(',', $match['parameters'][0]);
$varName = $match['variable'][0];
$functions = explode('.', $match['function'][0]);
$parameters = explode(',', $match['parameters'][0]);
$nbCalls = count($functions);

if ($request->attributes->has($varName)) {
$object = $request->attributes->get($varName);

if (empty($functionName)) {
if (empty($functions)) {
$objectValue = (string) $object;
}
elseif (is_callable(array($object, $fullFunctionName = 'get' . $functionName))
|| is_callable(array($object, $fullFunctionName = 'has' . $functionName))
|| is_callable(array($object, $fullFunctionName = 'is' . $functionName))
) {
$objectValue = call_user_func_array(array($object, $fullFunctionName), $parameters);
}
else {
throw new \RuntimeException(sprintf('Function "%s" not found.', $functionName));
foreach ($functions AS $f => $function) {

# While this is not the last function, call the chain
if ($f < $nbCalls - 1) {
if (is_callable(array($object, $fullFunctionName = 'get' . $function))
|| is_callable(array($object, $fullFunctionName = 'has' . $function))
|| is_callable(array($object, $fullFunctionName = 'is' . $function))
) {
$object = call_user_func(array($object, $fullFunctionName));
}
else {
throw new \RuntimeException(sprintf('"%s" is not callable.', join('.', array_merge([$varName], $functions))));
}
}

# End of the chain: call the method
else {

if (is_callable(array($object, $fullFunctionName = 'get' . $function))
|| is_callable(array($object, $fullFunctionName = 'has' . $function))
|| is_callable(array($object, $fullFunctionName = 'is' . $function))
) {
$objectValue = call_user_func_array(array($object, $fullFunctionName), $parameters);
}
else {
throw new \RuntimeException(sprintf('"%s" is not callable.', join('.', array_merge([$varName], $functions))));
}
}
}
}

$routeParameter = str_replace($match[0][0], $objectValue, $value);
Expand Down
4 changes: 2 additions & 2 deletions CHANGELOG.md
@@ -1,5 +1,5 @@
#2015-11-09
- Allow complex expressions in route parameters
#2015-11-10
- Allow complex expressions in breadcrumb names and route parameters

#2014-04-18
- Rewrite documentation
Expand Down
20 changes: 11 additions & 9 deletions Resources/doc/annotation_configuration.md
Expand Up @@ -176,28 +176,30 @@ The two following expressions are equivalents :
*/
```

#### Routes with complex parameters
### Complex parameters

Assume that you have the following controller :
Assume your controllers are designed like a REST API and you have a ManyToOne relationship on Book -> Author :

```php
/**
* @Route("/object/{object}", name="my_route", requirements={"object" = "\d+"})
* @Breadcrumb("Level 1", route={"name"="my_route", "parameters"={"object"="{object.id}"}})
* @Route("/books/{book}", name="book", requirements={"book" = "\d+"}) // example: /book/53
* @Breadcrumb("{book.author.name}", route={"name"="author", "parameters"={"author"="{book.author.id}"}}) // example: /author/15
* @Breadcrumb("{book.title}", route={"name"="book", "parameters"={"book"="{book.id}"}})
*
* @param Request $request
* @param Object $object
* @param Book $book
* @return array
*/
public function indexAction(Request $request, Object $object) {
public function indexAction(Request $request, Book $book) {
return [
'id' => $object->getId(),
'name' => $object->getName(),
'id' => $book->getId(),
'title' => $book->getTitle(),
'author' => $book->getAuthor()->getName(),
];
}
```

As you can see, you can generate a route by querying {object.id} (that will translate to $object->getId()) into the route parameters.


### Position

Expand Down

0 comments on commit b251535

Please sign in to comment.