index($this->nominatedUser(), $this->permissionsRequest()); self::assertSame( [Role::MANAGER => 'Manager:in', Role::GROUPS_ADMIN => 'Preisrechner Admin'], $controller->parameters['approvableRoles'], ); self::assertSame([], $controller->parameters['selfRefusedRoles']); } public function testWhatCannotBeSelfApprovedIsNotOffered(): void { $user = (new User('admin@example.org'))->setRoles([Role::ADMIN, Role::pending(Role::ADMIN), Role::pending(Role::MANAGER)]); $controller = new TestableShowController(currentUser: $user); $controller->index($user, $this->permissionsRequest()); // ROLE_ADMIN needs a second administrator, so no button leads into an access denied page. self::assertSame([Role::MANAGER => 'Manager:in'], $controller->parameters['approvableRoles']); self::assertSame([Role::ADMIN => 'Administration'], $controller->parameters['selfRefusedRoles']); } public function testTheReturnUrlOfTheListIsForwardedUntouched(): void { $controller = new TestableShowController(); $controller->index($this->nominatedUser(), $this->permissionsRequest()); // Calling return_url() in the template instead would hand the approval this very modal // and redirect the browser onto a bare modal fragment afterwards. self::assertSame('%2Fadmin%2Fuser%3Fpage%3D2', $controller->parameters['returnUrl']); } public function testWithoutAReturnUrlTheListIsUsed(): void { $controller = new TestableShowController(); $controller->index($this->nominatedUser(), Request::create('/admin/user/7/permissions')); self::assertSame(rawurlencode('/app_admin_user'), $controller->parameters['returnUrl']); } private function nominatedUser(): User { return (new User('teamer@example.org')) ->setRoles([Role::TEAMER, Role::pending(Role::MANAGER), Role::pending(Role::GROUPS_ADMIN)]); } /** * The list links the modal with r=return_url(), which rawurlencodes the URI, and path() * encodes that again as a query value — so what arrives here is encoded exactly once. */ private function permissionsRequest(): Request { return Request::create('/admin/user/7/permissions?r='.rawurlencode(rawurlencode('/admin/user?page=2'))); } } final class TestableShowController extends ShowController { /** @var array */ public array $parameters = []; public function __construct(private readonly ?UserInterface $currentUser = null) { } protected function getUser(): ?UserInterface { return $this->currentUser; } /** * @param array $parameters */ protected function render(string $view, array $parameters = [], ?Response $response = null): Response { $this->parameters = $parameters; return new Response(); } /** * @param array $parameters */ protected function generateUrl(string $route, array $parameters = [], int $referenceType = 1): string { return '/'.$route; } }