From 4836b25adce6fcb6155c8a8db6844fa28236f190 Mon Sep 17 00:00:00 2001 From: Bartek Wajda Date: Mon, 19 Jun 2023 11:12:16 +0200 Subject: [PATCH] IBX-5663: Paginated role assignments to improve performance in the Roles module (#2102) * IBX-5663: Paginated role assignments to improve performance in the Roles module * IBX-5663: Updated list action API method to `loadRoles` * IBX-5663: Removed temporary `dump` * IBX-5663: Applied review remarks --- .../Controller/RoleAssignmentController.php | 40 +++++++------- src/bundle/Controller/RoleController.php | 21 ++------ .../themes/admin/user/role/index.html.twig | 5 +- .../RoleAssignmentsSearchAdapter.php | 52 +++++++++++++++++++ 4 files changed, 81 insertions(+), 37 deletions(-) create mode 100644 src/lib/Pagination/Pagerfanta/RoleAssignmentsSearchAdapter.php diff --git a/src/bundle/Controller/RoleAssignmentController.php b/src/bundle/Controller/RoleAssignmentController.php index e247549f51..910cfe7abd 100644 --- a/src/bundle/Controller/RoleAssignmentController.php +++ b/src/bundle/Controller/RoleAssignmentController.php @@ -22,7 +22,7 @@ use EzSystems\EzPlatformAdminUi\Form\Factory\FormFactory; use EzSystems\EzPlatformAdminUi\Form\SubmitHandler; use EzSystems\EzPlatformAdminUi\Notification\TranslatableNotificationHandlerInterface; -use Pagerfanta\Adapter\ArrayAdapter; +use Ibexa\AdminUi\Pagination\Pagerfanta\RoleAssignmentsSearchAdapter; use Pagerfanta\Pagerfanta; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; @@ -60,31 +60,33 @@ public function __construct( } /** - * @param \eZ\Publish\API\Repository\Values\User\Role $role - * @param string $routeName - * @param int $assignmentPage - * - * @return \Symfony\Component\HttpFoundation\Response + * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException */ - public function listAction(Role $role, string $routeName, int $assignmentPage = 1): Response - { + public function listAction( + Role $role, + string $routeName, + int $assignmentsCount, + int $assignmentPage = 1 + ): Response { + $pagerfanta = new Pagerfanta( + new RoleAssignmentsSearchAdapter( + $this->roleService, + $role, + $assignmentsCount + ) + ); + $pagerfanta->setMaxPerPage($this->configResolver->getParameter('pagination.role_assignment_limit')); + $pagerfanta->setCurrentPage($assignmentPage); + // If user has no permission to content/read than he should see empty table. try { - $assignments = $this->roleService->getRoleAssignments($role); + /** @var \eZ\Publish\API\Repository\Values\User\RoleAssignment[] $assignments */ + $assignments = $pagerfanta->getCurrentPageResults(); } catch (UnauthorizedException $e) { $assignments = []; } - $pagerfanta = new Pagerfanta( - new ArrayAdapter($assignments) - ); - - $pagerfanta->setMaxPerPage($this->configResolver->getParameter('pagination.role_assignment_limit')); - $pagerfanta->setCurrentPage(min($assignmentPage, $pagerfanta->getNbPages())); - - /** @var \eZ\Publish\API\Repository\Values\User\RoleAssignment[] $assignments */ - $assignments = $pagerfanta->getCurrentPageResults(); - $deleteRoleAssignmentsForm = $this->formFactory->deleteRoleAssignments( new RoleAssignmentsDeleteData($role, $this->getRoleAssignmentsNumbers($assignments)) ); diff --git a/src/bundle/Controller/RoleController.php b/src/bundle/Controller/RoleController.php index 822f32054c..d0dba99a58 100644 --- a/src/bundle/Controller/RoleController.php +++ b/src/bundle/Controller/RoleController.php @@ -77,13 +77,6 @@ public function __construct( $this->configResolver = $configResolver; } - /** - * @param \Symfony\Component\HttpFoundation\Request $request - * - * @return \Symfony\Component\HttpFoundation\Response - * - * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException - */ public function listAction(Request $request): Response { $page = $request->query->get('page') ?? 1; @@ -117,12 +110,8 @@ public function listAction(Request $request): Response } /** - * @param \Symfony\Component\HttpFoundation\Request $request - * @param \eZ\Publish\API\Repository\Values\User\Role $role - * @param int $policyPage - * @param int $assignmentPage - * - * @return \Symfony\Component\HttpFoundation\Response + * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException */ public function viewAction(Request $request, Role $role, int $policyPage = 1, int $assignmentPage = 1): Response { @@ -132,14 +121,14 @@ public function viewAction(Request $request, Role $role, int $policyPage = 1, in // If user has no permission to content/read than he should see empty table. try { - $assignments = $this->roleService->getRoleAssignments($role); + $assignmentsCount = $this->roleService->countRoleAssignments($role); } catch (UnauthorizedException $e) { - $assignments = []; + $assignmentsCount = 0; } return $this->render('@ezdesign/user/role/index.html.twig', [ 'role' => $role, - 'assignments' => $assignments, + 'assignments_count' => $assignmentsCount, 'delete_form' => $deleteForm->createView(), 'route_name' => $request->get('_route'), 'policy_page' => $policyPage, diff --git a/src/bundle/Resources/views/themes/admin/user/role/index.html.twig b/src/bundle/Resources/views/themes/admin/user/role/index.html.twig index d738b04957..d47a1df298 100644 --- a/src/bundle/Resources/views/themes/admin/user/role/index.html.twig +++ b/src/bundle/Resources/views/themes/admin/user/role/index.html.twig @@ -32,7 +32,7 @@ @@ -51,7 +51,8 @@ {{ render(controller('EzSystems\\EzPlatformAdminUiBundle\\Controller\\RoleAssignmentController::listAction', { roleId: role.id, assignmentPage: assignment_page, - routeName: route_name + routeName: route_name, + assignmentsCount: assignments_count })) }} diff --git a/src/lib/Pagination/Pagerfanta/RoleAssignmentsSearchAdapter.php b/src/lib/Pagination/Pagerfanta/RoleAssignmentsSearchAdapter.php new file mode 100644 index 0000000000..0dddf9d23a --- /dev/null +++ b/src/lib/Pagination/Pagerfanta/RoleAssignmentsSearchAdapter.php @@ -0,0 +1,52 @@ +roleService = $roleService; + $this->role = $role; + $this->assignmentsCount = $assignmentsCount; + } + + /** + * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException + * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException + */ + public function getNbResults(): int + { + return $this->assignmentsCount ?: $this->roleService->countRoleAssignments($this->role); + } + + /** + * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException + * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException + */ + public function getSlice($offset, $length): iterable + { + return $this->roleService->loadRoleAssignments($this->role, $offset, $length); + } +}