From 33b177405ab057527a09c3a03e631a4e6f70aa64 Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Mon, 9 Nov 2015 11:41:18 +0100 Subject: [PATCH 1/3] Added complex parameters functionnality --- BreadcrumbTrail/Trail.php | 36 +++++++++++++++++++++-- CHANGELOG.md | 3 ++ Resources/doc/annotation_configuration.md | 23 +++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/BreadcrumbTrail/Trail.php b/BreadcrumbTrail/Trail.php index 23d96e6..dde7fdb 100644 --- a/BreadcrumbTrail/Trail.php +++ b/BreadcrumbTrail/Trail.php @@ -102,8 +102,8 @@ public function add($breadcrumb_or_title, $routeName = null, $routeParameters = $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))) { + || is_callable(array($object, $fullFunctionName = 'has'.$functionName)) + || is_callable(array($object, $fullFunctionName = 'is'.$functionName))) { $objectValue = call_user_func_array(array($object, $fullFunctionName),$parameters); } else { @@ -119,7 +119,37 @@ public function add($breadcrumb_or_title, $routeName = null, $routeParameters = $routeParameters[$value] = $request->get($value); unset($routeParameters[$key]); } else { - if (preg_match('#^\{(?P\w+)\}$#', $value, $matches)) { + if (preg_match_all('#\{(?P\w+).?(?P\w*):?(?P(\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]); + + if ($request->attributes->has($varName)) { + $object = $request->attributes->get($varName); + + if (empty($functionName)) { + $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)); + } + + $routeParameter = str_replace($match[0][0], $objectValue, $value); + $routeParameters[$key] = $routeParameter; + } + + + } + } elseif (preg_match('#^\{(?P\w+)\}$#', $value, $matches)) { $routeParameters[$key] = $request->get($matches['parameter']); } } diff --git a/CHANGELOG.md b/CHANGELOG.md index f5905ba..3310aec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +#2015-11-09 + - Allow complex expressions in route parameters + #2014-04-18 - Rewrite documentation diff --git a/Resources/doc/annotation_configuration.md b/Resources/doc/annotation_configuration.md index 07c7ec9..dd7fe4c 100644 --- a/Resources/doc/annotation_configuration.md +++ b/Resources/doc/annotation_configuration.md @@ -176,6 +176,29 @@ The two following expressions are equivalents : */ ``` +#### Routes with complex parameters + +Assume that you have the following controller : + +```php +/** + * @Route("/object/{object}", name="my_route", requirements={"object" = "\d+"}) + * @Breadcrumb("Level 1", route={"name"="my_route", "parameters"={"object"="{object.id}"}}) + * + * @param Request $request + * @param Object $object + * @return array + */ +public function indexAction(Request $request, Object $object) { + return [ + 'id' => $object->getId(), + 'name' => $object->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 ```php From b2515355d235bfce96becf4aa97de977e05ee026 Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Tue, 10 Nov 2015 13:16:34 +0100 Subject: [PATCH 2/3] Added more complex parameters functionnality, also in Breadcrumb title --- BreadcrumbTrail/Trail.php | 89 +++++++++++++++++------ CHANGELOG.md | 4 +- Resources/doc/annotation_configuration.md | 20 ++--- 3 files changed, 80 insertions(+), 33 deletions(-) diff --git a/BreadcrumbTrail/Trail.php b/BreadcrumbTrail/Trail.php index dde7fdb..9c593c2 100644 --- a/BreadcrumbTrail/Trail.php +++ b/BreadcrumbTrail/Trail.php @@ -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\w+).?(?P\w*):?(?P(\w|,| )*)\}#', $breadcrumb_or_title, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); + preg_match_all('#\{(?P\w+).?(?P([\w\.])*):?(?P(\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); @@ -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\w+).?(?P\w*):?(?P(\w|,| )*)\}#', $value, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) { + if (preg_match_all('#\{(?P\w+).?(?P([\w\.])*):?(?P(\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); diff --git a/CHANGELOG.md b/CHANGELOG.md index 3310aec..4527a96 100644 --- a/CHANGELOG.md +++ b/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 diff --git a/Resources/doc/annotation_configuration.md b/Resources/doc/annotation_configuration.md index dd7fe4c..8fb2e21 100644 --- a/Resources/doc/annotation_configuration.md +++ b/Resources/doc/annotation_configuration.md @@ -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 From 6d1044c0de2e33e0c79e9fc6ae4098ff9032c23f Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Tue, 10 Nov 2015 14:29:06 +0100 Subject: [PATCH 3/3] Bugfix on empty results given by preg_match_all --- BreadcrumbTrail/Trail.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BreadcrumbTrail/Trail.php b/BreadcrumbTrail/Trail.php index 9c593c2..890f264 100644 --- a/BreadcrumbTrail/Trail.php +++ b/BreadcrumbTrail/Trail.php @@ -93,8 +93,8 @@ public function add($breadcrumb_or_title, $routeName = null, $routeParameters = foreach ($matches as $match) { $varName = $match['variable'][0]; - $functions = explode('.', $match['function'][0]); - $parameters = explode(',', $match['parameters'][0]); + $functions = $match['function'][0] ? explode('.', $match['function'][0]) : array(); + $parameters = $match['parameters'][0] ? explode(',', $match['parameters'][0]) : array(); $nbCalls = count($functions); if($request->attributes->has($varName)) { @@ -146,8 +146,8 @@ public function add($breadcrumb_or_title, $routeName = null, $routeParameters = foreach ($matches AS $match) { $varName = $match['variable'][0]; - $functions = explode('.', $match['function'][0]); - $parameters = explode(',', $match['parameters'][0]); + $functions = $match['function'][0] ? explode('.', $match['function'][0]) : array(); + $parameters = $match['parameters'][0] ? explode(',', $match['parameters'][0]) : array(); $nbCalls = count($functions); if ($request->attributes->has($varName)) {