diff --git a/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php index af2213bc25..59f05ff625 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php @@ -49,7 +49,7 @@ class AnonymousAuthenticationListener implements ListenerInterface $this->context->setToken(new AnonymousToken($this->key, 'anon.', array())); if (null !== $this->logger) { - $this->logger->info(sprintf('Populated SecurityContext with an anonymous Token')); + $this->logger->info('Populated SecurityContext with an anonymous Token'); } } } diff --git a/src/Symfony/Component/Security/Tests/Http/Firewall/AnonymousAuthenticationListenerTest.php b/src/Symfony/Component/Security/Tests/Http/Firewall/AnonymousAuthenticationListenerTest.php index 9e7ea90a0e..73ee8214de 100644 --- a/src/Symfony/Component/Security/Tests/Http/Firewall/AnonymousAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Tests/Http/Firewall/AnonymousAuthenticationListenerTest.php @@ -59,4 +59,21 @@ class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase $listener = new AnonymousAuthenticationListener($context, 'TheKey'); $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false)); } + + public function testHandledEventIsLogged() + { + if (!interface_exists('Psr\Log\LoggerInterface')) { + $this->markTestSkipped('The "LoggerInterface" is not available'); + } + + $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); + $logger = $this->getMock('Psr\Log\LoggerInterface'); + $logger->expects($this->once()) + ->method('info') + ->with('Populated SecurityContext with an anonymous Token') + ; + + $listener = new AnonymousAuthenticationListener($context, 'TheKey', $logger); + $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false)); + } } diff --git a/src/Symfony/Component/Security/Tests/Http/Firewall/BasicAuthenticationListenerTest.php b/src/Symfony/Component/Security/Tests/Http/Firewall/BasicAuthenticationListenerTest.php index 667869f764..58709565c3 100644 --- a/src/Symfony/Component/Security/Tests/Http/Firewall/BasicAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Tests/Http/Firewall/BasicAuthenticationListenerTest.php @@ -195,4 +195,18 @@ class BasicAuthenticationListenerTest extends \PHPUnit_Framework_TestCase $listener->handle($event); } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage $providerKey must not be empty + */ + public function testItRequiresProviderKey() + { + new BasicAuthenticationListener( + $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'), + $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), + '', + $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface') + ); + } } diff --git a/src/Symfony/Component/Security/Tests/Http/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Tests/Http/Firewall/ContextListenerTest.php index ffe6195ff4..336c3334fe 100644 --- a/src/Symfony/Component/Security/Tests/Http/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Tests/Http/Firewall/ContextListenerTest.php @@ -17,6 +17,7 @@ use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\SecurityContext; use Symfony\Component\Security\Http\Firewall\ContextListener; @@ -48,6 +49,32 @@ class ContextListenerTest extends \PHPUnit_Framework_TestCase unset($this->securityContext); } + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage $contextKey must not be empty + */ + public function testItRequiresContextKey() + { + new ContextListener( + $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'), + array(), + '' + ); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage User provider "stdClass" must implement "Symfony\Component\Security\Core\User\UserProviderInterface + */ + public function testUserProvidersNeedToImplementAnInterface() + { + new ContextListener( + $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'), + array(new \stdClass()), + 'key123' + ); + } + public function testOnKernelResponseWillAddSession() { $session = $this->runSessionOnKernelResponse( @@ -131,9 +158,7 @@ class ContextListenerTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); - $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session') - ->disableOriginalConstructor() - ->getMock(); + $session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface'); $event->expects($this->any()) ->method('getRequest') @@ -147,7 +172,7 @@ class ContextListenerTest extends \PHPUnit_Framework_TestCase $session->expects($this->any()) ->method('get') ->with('_security_key123') - ->will($this->returnValue(serialize($token))); + ->will($this->returnValue($token)); $context->expects($this->once()) ->method('setToken') ->with(null); @@ -159,11 +184,53 @@ class ContextListenerTest extends \PHPUnit_Framework_TestCase public function provideInvalidToken() { return array( - array(new \__PHP_Incomplete_Class()), - array(null), + array(serialize(new \__PHP_Incomplete_Class())), + array(serialize(null)), + array(null) ); } + public function testHandleAddsKernelResponseListener() + { + $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->disableOriginalConstructor() + ->getMock(); + + $listener = new ContextListener($context, array(), 'key123', null, $dispatcher); + + $event->expects($this->any()) + ->method('getRequestType') + ->will($this->returnValue(HttpKernelInterface::MASTER_REQUEST)); + $event->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($this->getMock('Symfony\Component\HttpFoundation\Request'))); + + $dispatcher->expects($this->once()) + ->method('addListener') + ->with(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); + + $listener->handle($event); + } + + public function testHandleRemovesTokenIfNoPreviousSessionWasFound() + { + $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); + $request->expects($this->any())->method('hasPreviousSession')->will($this->returnValue(false)); + + $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->any())->method('getRequest')->will($this->returnValue($request)); + + $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); + $context->expects($this->once())->method('setToken')->with(null); + + $listener = new ContextListener($context, array(), 'key123'); + $listener->handle($event); + } + protected function runSessionOnKernelResponse($newToken, $original = null) { $session = new Session(new MockArraySessionStorage()); @@ -189,4 +256,5 @@ class ContextListenerTest extends \PHPUnit_Framework_TestCase $listener->onKernelResponse($event); return $session; - }} + } +} diff --git a/src/Symfony/Component/Security/Tests/Http/Firewall/SwitchUserListenerTest.php b/src/Symfony/Component/Security/Tests/Http/Firewall/SwitchUserListenerTest.php new file mode 100644 index 0000000000..f8bb9f60aa --- /dev/null +++ b/src/Symfony/Component/Security/Tests/Http/Firewall/SwitchUserListenerTest.php @@ -0,0 +1,175 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Tests\Http\Firewall; + +use Symfony\Component\Security\Http\Firewall\SwitchUserListener; + +class SwitchUserListenerTest extends \PHPUnit_Framework_TestCase +{ + private $securityContext; + + private $userProvider; + + private $userChecker; + + private $accessDecisionManager; + + private $request; + + private $event; + + protected function setUp() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + if (!class_exists('Symfony\Component\HttpKernel\HttpKernel')) { + $this->markTestSkipped('The "HttpKernel" component is not available'); + } + + $this->securityContext = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); + $this->userProvider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); + $this->userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); + $this->accessDecisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'); + $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request'); + $this->request->server = $this->getMock('Symfony\Component\HttpFoundation\ServerBag'); + $this->event = $this->getEvent($this->request); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage $providerKey must not be empty + */ + public function testProviderKeyIsRequired() + { + new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, '', $this->accessDecisionManager); + } + + public function testEventIsIgnoredIfUsernameIsNotPassedWithTheRequest() + { + $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue(null)); + + $this->event->expects($this->never())->method('setResopnse'); + $this->securityContext->expects($this->never())->method('setToken'); + + $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); + $listener->handle($this->event); + } + + /** + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException + */ + public function testExitUserThrowsAuthenticationExceptionIfOriginalTokenCannotBeFound() + { + $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface'))); + + $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token)); + $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('_exit')); + + $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); + $listener->handle($this->event); + } + + public function testExitUserUpdatesToken() + { + $originalToken = $this->getToken(); + $role = $this->getMockBuilder('Symfony\Component\Security\Core\Role\SwitchUserRole') + ->disableOriginalConstructor() + ->getMock(); + $role->expects($this->any())->method('getSource')->will($this->returnValue($originalToken)); + + $this->securityContext->expects($this->any()) + ->method('getToken') + ->will($this->returnValue($this->getToken(array($role)))); + + $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('_exit')); + $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/')); + $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', ''); + + $this->securityContext->expects($this->once()) + ->method('setToken')->with($originalToken); + $this->event->expects($this->once()) + ->method('setResponse')->with($this->isInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse')); + + $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); + $listener->handle($this->event); + } + + /** + * @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException + */ + public function testSwitchUserIsDissallowed() + { + $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface'))); + + $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token)); + $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba')); + + $this->accessDecisionManager->expects($this->once()) + ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH')) + ->will($this->returnValue(false)); + + $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); + $listener->handle($this->event); + } + + public function testSwitchUser() + { + $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface'))); + $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); + $user->expects($this->any())->method('getRoles')->will($this->returnValue(array())); + + $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token)); + $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba')); + $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/')); + $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', ''); + + $this->accessDecisionManager->expects($this->once()) + ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH')) + ->will($this->returnValue(true)); + + $this->userProvider->expects($this->once()) + ->method('loadUserByUsername')->with('kuba') + ->will($this->returnValue($user)); + $this->userChecker->expects($this->once()) + ->method('checkPostAuth')->with($user); + $this->securityContext->expects($this->once()) + ->method('setToken')->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken')); + + $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); + $listener->handle($this->event); + } + + private function getEvent($request) + { + $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->disableOriginalConstructor() + ->getMock(); + + $event->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($request)); + + return $event; + } + + private function getToken(array $roles = array()) + { + $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); + $token->expects($this->any()) + ->method('getRoles') + ->will($this->returnValue($roles)); + + return $token; + } +} diff --git a/src/Symfony/Component/Security/Tests/Http/HttpUtilsTest.php b/src/Symfony/Component/Security/Tests/Http/HttpUtilsTest.php index bf078daeb9..db1aa4b94e 100644 --- a/src/Symfony/Component/Security/Tests/Http/HttpUtilsTest.php +++ b/src/Symfony/Component/Security/Tests/Http/HttpUtilsTest.php @@ -12,8 +12,10 @@ namespace Symfony\Component\Security\Tests\Http; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Security\Http\HttpUtils; +use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Security\Core\SecurityContextInterface; +use Symfony\Component\Security\Http\HttpUtils; class HttpUtilsTest extends \PHPUnit_Framework_TestCase { @@ -28,21 +30,27 @@ class HttpUtilsTest extends \PHPUnit_Framework_TestCase } } - public function testCreateRedirectResponse() + public function testCreateRedirectResponseWithPath() { $utils = new HttpUtils($this->getUrlGenerator()); - - // absolute path $response = $utils->createRedirectResponse($this->getRequest(), '/foobar'); + $this->assertTrue($response->isRedirect('http://localhost/foobar')); $this->assertEquals(302, $response->getStatusCode()); + } - // absolute URL + public function testCreateRedirectResponseWithAbsoluteUrl() + { + $utils = new HttpUtils($this->getUrlGenerator()); $response = $utils->createRedirectResponse($this->getRequest(), 'http://symfony.com/'); - $this->assertTrue($response->isRedirect('http://symfony.com/')); - // route name + $this->assertTrue($response->isRedirect('http://symfony.com/')); + } + + public function testCreateRedirectResponseWithRouteName() + { $utils = new HttpUtils($urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface')); + $urlGenerator ->expects($this->any()) ->method('generate') @@ -54,25 +62,29 @@ class HttpUtilsTest extends \PHPUnit_Framework_TestCase ->method('getContext') ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext'))) ; + $response = $utils->createRedirectResponse($this->getRequest(), 'foobar'); + $this->assertTrue($response->isRedirect('http://localhost/foo/bar')); } - public function testCreateRequest() + public function testCreateRequestWithPath() { - $utils = new HttpUtils($this->getUrlGenerator()); - - // absolute path $request = $this->getRequest(); $request->server->set('Foo', 'bar'); + + $utils = new HttpUtils($this->getUrlGenerator()); $subRequest = $utils->createRequest($request, '/foobar'); $this->assertEquals('GET', $subRequest->getMethod()); $this->assertEquals('/foobar', $subRequest->getPathInfo()); $this->assertEquals('bar', $subRequest->server->get('Foo')); + } - // route name + public function testCreateRequestWithRouteName() + { $utils = new HttpUtils($urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface')); + $urlGenerator ->expects($this->once()) ->method('generate') @@ -83,14 +95,54 @@ class HttpUtilsTest extends \PHPUnit_Framework_TestCase ->method('getContext') ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext'))) ; - $subRequest = $utils->createRequest($this->getRequest(), 'foobar'); - $this->assertEquals('/foo/bar', $subRequest->getPathInfo()); - // absolute URL + $subRequest = $utils->createRequest($this->getRequest(), 'foobar'); + + $this->assertEquals('/foo/bar', $subRequest->getPathInfo()); + } + + public function testCreateRequestWithAbsoluteUrl() + { + $utils = new HttpUtils($this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface')); $subRequest = $utils->createRequest($this->getRequest(), 'http://symfony.com/'); + $this->assertEquals('/', $subRequest->getPathInfo()); } + public function testCreateRequestPassesSessionToTheNewRequest() + { + $request = $this->getRequest(); + $request->setSession($session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface')); + + $utils = new HttpUtils($this->getUrlGenerator()); + $subRequest = $utils->createRequest($request, '/foobar'); + + $this->assertSame($session, $subRequest->getSession()); + } + + /** + * @dataProvider provideSecurityContextAttributes + */ + public function testCreateRequestPassesSecurityContextAttributesToTheNewRequest($attribute) + { + $request = $this->getRequest(); + $request->attributes->set($attribute, 'foo'); + + $utils = new HttpUtils($this->getUrlGenerator()); + $subRequest = $utils->createRequest($request, '/foobar'); + + $this->assertSame('foo', $subRequest->attributes->get($attribute)); + } + + public function provideSecurityContextAttributes() + { + return array( + array(SecurityContextInterface::AUTHENTICATION_ERROR), + array(SecurityContextInterface::ACCESS_DENIED_ERROR), + array(SecurityContextInterface::LAST_USERNAME) + ); + } + public function testCheckRequestPath() { $utils = new HttpUtils($this->getUrlGenerator()); @@ -102,26 +154,66 @@ class HttpUtilsTest extends \PHPUnit_Framework_TestCase $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo+bar'), '/foo+bar')); // Checking unicode $this->assertTrue($utils->checkRequestPath($this->getRequest(urlencode('/вход')), '/вход')); + } + public function testCheckRequestPathWithUrlMatcherAndResourceNotFound() + { $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); $urlMatcher ->expects($this->any()) ->method('match') + ->with('/') ->will($this->throwException(new ResourceNotFoundException())) ; + $utils = new HttpUtils(null, $urlMatcher); $this->assertFalse($utils->checkRequestPath($this->getRequest(), 'foobar')); + } + public function testCheckRequestPathWithUrlMatcherAndMethodNotAllowed() + { + $request = $this->getRequest(); + $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface'); + $urlMatcher + ->expects($this->any()) + ->method('matchRequest') + ->with($request) + ->will($this->throwException(new MethodNotAllowedException(array()))) + ; + + $utils = new HttpUtils(null, $urlMatcher); + $this->assertFalse($utils->checkRequestPath($request, 'foobar')); + } + + public function testCheckRequestPathWithUrlMatcherAndResourceFoundByUrl() + { $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); $urlMatcher ->expects($this->any()) ->method('match') + ->with('/foo/bar') ->will($this->returnValue(array('_route' => 'foobar'))) ; + $utils = new HttpUtils(null, $urlMatcher); $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo/bar'), 'foobar')); } + public function testCheckRequestPathWithUrlMatcherAndResourceFoundByRequest() + { + $request = $this->getRequest(); + $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface'); + $urlMatcher + ->expects($this->any()) + ->method('matchRequest') + ->with($request) + ->will($this->returnValue(array('_route' => 'foobar'))) + ; + + $utils = new HttpUtils(null, $urlMatcher); + $this->assertTrue($utils->checkRequestPath($request, 'foobar')); + } + /** * @expectedException \RuntimeException */ @@ -133,20 +225,37 @@ class HttpUtilsTest extends \PHPUnit_Framework_TestCase ->method('match') ->will($this->throwException(new \RuntimeException())) ; + $utils = new HttpUtils(null, $urlMatcher); $utils->checkRequestPath($this->getRequest(), 'foobar'); } + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Matcher must either implement UrlMatcherInterface or RequestMatcherInterface + */ + public function testUrlMatcher() + { + new HttpUtils($this->getUrlGenerator(), new \stdClass()); + } + public function testGenerateUriRemovesQueryString() { - $method = new \ReflectionMethod('Symfony\Component\Security\Http\HttpUtils', 'generateUri'); - $method->setAccessible(true); - - $utils = new HttpUtils($this->getUrlGenerator()); - $this->assertEquals('/foo/bar', $method->invoke($utils, new Request(), 'route_name')); + $utils = new HttpUtils($this->getUrlGenerator('/foo/bar')); + $this->assertEquals('/foo/bar', $utils->generateUri(new Request(), 'route_name')); $utils = new HttpUtils($this->getUrlGenerator('/foo/bar?param=value')); - $this->assertEquals('/foo/bar', $method->invoke($utils, new Request(), 'route_name')); + $this->assertEquals('/foo/bar', $utils->generateUri(new Request(), 'route_name')); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage You must provide a UrlGeneratorInterface instance to be able to use routes. + */ + public function testUrlGeneratorIsRequiredToGenerateUrl() + { + $utils = new HttpUtils(); + $utils->generateUri(new Request(), 'route_name'); } private function getUrlGenerator($generatedUrl = '/foo/bar')