Update role logic for organization management
This commit is contained in:
parent
252fc775bb
commit
4fc059b2a5
|
|
@ -95,14 +95,14 @@ class OrganizationController extends AbstractController
|
||||||
try {
|
try {
|
||||||
$this->entityManager->persist($organization);
|
$this->entityManager->persist($organization);
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getId(), "Organization Created");
|
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getUserIdentifier(), "Organization Created");
|
||||||
$this->loggerService->logSuperAdmin($actingUser->getId(), $actingUser->getId(), "Organization Created", $organization->getId());
|
$this->loggerService->logSuperAdmin($actingUser->getUserIdentifier(), $actingUser->getUserIdentifier(), "Organization Created", $organization->getId());
|
||||||
$this->actionService->createAction("Create Organization", $actingUser, $organization, $organization->getName());
|
$this->actionService->createAction("Create Organization", $actingUser, $organization, $organization->getName());
|
||||||
$this->addFlash('success', 'Organisation crée avec succès.');
|
$this->addFlash('success', 'Organisation crée avec succès.');
|
||||||
return $this->redirectToRoute('organization_index');
|
return $this->redirectToRoute('organization_index');
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->addFlash('danger', 'Erreur lors de la création de l\'organization');
|
$this->addFlash('danger', 'Erreur lors de la création de l\'organization');
|
||||||
$this->loggerService->logError('Error creating organization', ['acting_user_id' => $actingUser->getId(), 'error' => $e->getMessage()]);
|
$this->loggerService->logError('Error creating organization', ['acting_user_id' => $actingUser->getUserIdentifier(), 'error' => $e->getMessage()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $this->render('organization/new.html.twig', [
|
return $this->render('organization/new.html.twig', [
|
||||||
|
|
@ -125,35 +125,12 @@ class OrganizationController extends AbstractController
|
||||||
if (!$organization) {
|
if (!$organization) {
|
||||||
$this->loggerService->logEntityNotFound('Organization', [
|
$this->loggerService->logEntityNotFound('Organization', [
|
||||||
'org_id' => $id,
|
'org_id' => $id,
|
||||||
'message' => 'Organization not found for edit'], $actingUser->getId()
|
'message' => 'Organization not found for edit'], $actingUser->getUserIdentifier()
|
||||||
);
|
);
|
||||||
$this->addFlash('danger', 'Erreur, l\'organization est introuvable.');
|
$this->addFlash('danger', 'Erreur, l\'organization est introuvable.');
|
||||||
return $this->redirectToRoute('organization_index');
|
return $this->redirectToRoute('organization_index');
|
||||||
}
|
}
|
||||||
if (!$this->isGranted("ROLE_SUPER_ADMIN")) {
|
|
||||||
//check if the user is admin of the organization
|
|
||||||
$uo = $this->entityManager->getRepository(UsersOrganizations::class)->findOneBy(['users' => $actingUser, 'organization' => $organization]);
|
|
||||||
if (!$uo) {
|
|
||||||
$this->loggerService->logEntityNotFound('UO link', [
|
|
||||||
'user_id' => $actingUser->getId(),
|
|
||||||
'org_id' => $organization->getId(),
|
|
||||||
'message' => 'UO link not found for edit organization'
|
|
||||||
], $actingUser->getId());
|
|
||||||
$this->addFlash('danger', 'Erreur, accès refusé.');
|
|
||||||
return $this->redirectToRoute('organization_index');
|
|
||||||
}
|
|
||||||
$roleAdmin = $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'ADMIN']);
|
|
||||||
$uoaAdmin = $this->entityManager->getRepository(UserOrganizatonApp::class)->findOneBy(['userOrganization' => $uo, 'role' => $roleAdmin]);
|
|
||||||
if (!$uoaAdmin) {
|
|
||||||
$this->loggerService->logEntityNotFound('UOA link', [
|
|
||||||
'uo_id' => $uo->getId(),
|
|
||||||
'role_id' => $roleAdmin->getId(),
|
|
||||||
'message' => 'UOA link not found for edit organization, user is not admin of organization'
|
|
||||||
], $actingUser->getId());
|
|
||||||
$this->addFlash('danger', 'Erreur, accès refusé.');
|
|
||||||
return $this->redirectToRoute('organization_index');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$form = $this->createForm(OrganizationForm::class, $organization);
|
$form = $this->createForm(OrganizationForm::class, $organization);
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
if ($form->isSubmitted() && $form->isValid()) {
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
|
|
@ -164,16 +141,16 @@ class OrganizationController extends AbstractController
|
||||||
try {
|
try {
|
||||||
$this->entityManager->persist($organization);
|
$this->entityManager->persist($organization);
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getId(), "Organization Edited");
|
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getUserIdentifier(), "Organization Edited");
|
||||||
if ($this->isGranted("ROLE_SUPER_ADMIN")) {
|
if ($this->isGranted("ROLE_SUPER_ADMIN")) {
|
||||||
$this->loggerService->logSuperAdmin($actingUser->getId(), $actingUser->getId(), "Organization Edited", $organization->getId());
|
$this->loggerService->logSuperAdmin($actingUser->getUserIdentifier(), $actingUser->getUserIdentifier(), "Organization Edited", $organization->getId());
|
||||||
}
|
}
|
||||||
$this->actionService->createAction("Edit Organization", $actingUser, $organization, $organization->getName());
|
$this->actionService->createAction("Edit Organization", $actingUser, $organization, $organization->getName());
|
||||||
$this->addFlash('success', 'Organisation modifiée avec succès.');
|
$this->addFlash('success', 'Organisation modifiée avec succès.');
|
||||||
return $this->redirectToRoute('organization_index');
|
return $this->redirectToRoute('organization_index');
|
||||||
}catch (Exception $e) {
|
}catch (Exception $e) {
|
||||||
$this->addFlash('danger', 'Erreur lors de la modification de l\'organization');
|
$this->addFlash('danger', 'Erreur lors de la modification de l\'organization');
|
||||||
$this->loggerService->logError('Error editing organization', ['acting_user_id' => $actingUser->getId(), 'error' => $e->getMessage()]);
|
$this->loggerService->logError('Error editing organization', ['acting_user_id' => $actingUser->getUserIdentifier(), 'error' => $e->getMessage()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $this->render('organization/edit.html.twig', [
|
return $this->render('organization/edit.html.twig', [
|
||||||
|
|
@ -192,17 +169,18 @@ class OrganizationController extends AbstractController
|
||||||
$this->loggerService->logEntityNotFound('Organization', [
|
$this->loggerService->logEntityNotFound('Organization', [
|
||||||
'org_id' => $id,
|
'org_id' => $id,
|
||||||
'message' => 'Organization not found for view'
|
'message' => 'Organization not found for view'
|
||||||
], $actingUser->getId());
|
], $actingUser->getUserIdentifier());
|
||||||
$this->addFlash('danger', 'Erreur, l\'organization est introuvable.');
|
$this->addFlash('danger', 'Erreur, l\'organization est introuvable.');
|
||||||
return $this->redirectToRoute('organization_index');
|
return $this->redirectToRoute('organization_index');
|
||||||
}
|
}
|
||||||
//check if the user is admin of the organization
|
//check if the user is admin of the organization
|
||||||
if (!$this->userService->isAdminOfOrganization($organization) && !$this->isGranted("ROLE_ADMIN")) {
|
if (!$this->userService->isAdminOfOrganization($organization) && !$this->isGranted("ROLE_ADMIN")) {
|
||||||
$this->loggerService->logAccessDenied($actingUser->getId());
|
$this->loggerService->logAccessDenied($actingUser->getUserIdentifier());
|
||||||
$this->addFlash('danger', 'Erreur, accès refusé.');
|
$this->addFlash('danger', 'Erreur, accès refusé.');
|
||||||
throw new AccessDeniedHttpException('Access denied');
|
throw new AccessDeniedHttpException('Access denied');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: add project to the response
|
||||||
$allApps = $this->entityManager->getRepository(Apps::class)->findAll(); // appsAll
|
$allApps = $this->entityManager->getRepository(Apps::class)->findAll(); // appsAll
|
||||||
$orgApps = $organization->getApps()->toArray(); // apps
|
$orgApps = $organization->getApps()->toArray(); // apps
|
||||||
|
|
||||||
|
|
@ -222,14 +200,14 @@ class OrganizationController extends AbstractController
|
||||||
#[Route(path: '/delete/{id}', name: 'delete', methods: ['POST'])]
|
#[Route(path: '/delete/{id}', name: 'delete', methods: ['POST'])]
|
||||||
public function delete($id): Response
|
public function delete($id): Response
|
||||||
{
|
{
|
||||||
$this->denyAccessUnlessGranted("ROLE_ADMIN");
|
$this->denyAccessUnlessGranted("ROLE_SUPER_ADMIN");
|
||||||
$actingUser = $this->getUser();
|
$actingUser = $this->getUser();
|
||||||
$organization = $this->organizationsRepository->find($id);
|
$organization = $this->organizationsRepository->find($id);
|
||||||
if (!$organization) {
|
if (!$organization) {
|
||||||
$this->loggerService->logEntityNotFound('Organization', [
|
$this->loggerService->logEntityNotFound('Organization', [
|
||||||
'org_id' => $id,
|
'org_id' => $id,
|
||||||
'message' => 'Organization not found for delete'
|
'message' => 'Organization not found for delete'
|
||||||
], $actingUser->getId());
|
], $actingUser->getUserIdentifier());
|
||||||
$this->addFlash('danger', 'Erreur, l\'organization est introuvable.');
|
$this->addFlash('danger', 'Erreur, l\'organization est introuvable.');
|
||||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
@ -243,13 +221,13 @@ class OrganizationController extends AbstractController
|
||||||
$this->entityManager->persist($organization);
|
$this->entityManager->persist($organization);
|
||||||
$this->actionService->createAction("Delete Organization", $actingUser, $organization, $organization->getName());
|
$this->actionService->createAction("Delete Organization", $actingUser, $organization, $organization->getName());
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getId(),'Organization Deleted');
|
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getUserIdentifier(),'Organization Deleted');
|
||||||
if ($this->isGranted("ROLE_SUPER_ADMIN")) {
|
if ($this->isGranted("ROLE_SUPER_ADMIN")) {
|
||||||
$this->loggerService->logSuperAdmin($actingUser->getId(), $actingUser->getId(),'Organization Deleted', $organization->getId());
|
$this->loggerService->logSuperAdmin($actingUser->getUserIdentifier(), $actingUser->getUserIdentifier(),'Organization Deleted', $organization->getId());
|
||||||
}
|
}
|
||||||
$this->addFlash('success', 'Organisation supprimée avec succès.');
|
$this->addFlash('success', 'Organisation supprimée avec succès.');
|
||||||
}catch (\Exception $e){
|
}catch (\Exception $e){
|
||||||
$this->loggerService->logError($actingUser->getId(), ['message' => 'Error deleting organization: '.$e->getMessage()]);
|
$this->loggerService->logError($actingUser->getUserIdentifier(), ['message' => 'Error deleting organization: '.$e->getMessage()]);
|
||||||
$this->addFlash('danger', 'Erreur lors de la suppression de l\'organization.');
|
$this->addFlash('danger', 'Erreur lors de la suppression de l\'organization.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,16 +244,15 @@ class OrganizationController extends AbstractController
|
||||||
$this->loggerService->logEntityNotFound('Organization', [
|
$this->loggerService->logEntityNotFound('Organization', [
|
||||||
'org_id' => $id,
|
'org_id' => $id,
|
||||||
'message' => 'Organization not found for deactivate'
|
'message' => 'Organization not found for deactivate'
|
||||||
], $actingUser->getId());
|
], $actingUser->getUserIdentifier());
|
||||||
$this->addFlash('danger', 'Erreur, l\'organization est introuvable.');
|
$this->addFlash('danger', 'Erreur, l\'organization est introuvable.');
|
||||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
$organization->setIsActive(false);
|
$organization->setIsActive(false);
|
||||||
// $this->userOrganizationService->deactivateAllUserOrganizationLinks($actingUser, null, $organization);
|
|
||||||
$this->entityManager->persist($organization);
|
$this->entityManager->persist($organization);
|
||||||
$this->actionService->createAction("Deactivate Organization", $actingUser, $organization, $organization->getName());
|
$this->actionService->createAction("Deactivate Organization", $actingUser, $organization, $organization->getName());
|
||||||
$this->loggerService->logSuperAdmin($actingUser->getId(), $actingUser->getId(),'Organization deactivated', $organization->getId());
|
$this->loggerService->logSuperAdmin($actingUser->getUserIdentifier(), $actingUser->getUserIdentifier(),'Organization deactivated', $organization->getId());
|
||||||
$this->addFlash('success', 'Organisation désactivé avec succès.');
|
$this->addFlash('success', 'Organisation désactivé avec succès.');
|
||||||
return $this->redirectToRoute('organization_index');
|
return $this->redirectToRoute('organization_index');
|
||||||
}
|
}
|
||||||
|
|
@ -290,14 +267,14 @@ class OrganizationController extends AbstractController
|
||||||
$this->loggerService->logEntityNotFound('Organization', [
|
$this->loggerService->logEntityNotFound('Organization', [
|
||||||
'org_id' => $id,
|
'org_id' => $id,
|
||||||
'message' => 'Organization not found for activate'
|
'message' => 'Organization not found for activate'
|
||||||
], $actingUser->getId());
|
], $actingUser->getUserIdentifier());
|
||||||
$this->addFlash('danger', 'Erreur, l\'organization est introuvable.');
|
$this->addFlash('danger', 'Erreur, l\'organization est introuvable.');
|
||||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
||||||
}
|
}
|
||||||
$organization->setIsActive(true);
|
$organization->setIsActive(true);
|
||||||
$this->entityManager->persist($organization);
|
$this->entityManager->persist($organization);
|
||||||
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getId(),'Organization Activated');
|
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getUserIdentifier(),'Organization Activated');
|
||||||
$this->loggerService->logSuperAdmin($actingUser->getId(), $actingUser->getId(),'Organization Activated', $organization->getId());
|
$this->loggerService->logSuperAdmin($actingUser->getUserIdentifier(), $actingUser->getUserIdentifier(),'Organization Activated', $organization->getId());
|
||||||
$this->actionService->createAction("Activate Organization", $actingUser, $organization, $organization->getName());
|
$this->actionService->createAction("Activate Organization", $actingUser, $organization, $organization->getName());
|
||||||
$this->addFlash('success', 'Organisation activée avec succès.');
|
$this->addFlash('success', 'Organisation activée avec succès.');
|
||||||
return $this->redirectToRoute('organization_index');
|
return $this->redirectToRoute('organization_index');
|
||||||
|
|
@ -309,54 +286,21 @@ class OrganizationController extends AbstractController
|
||||||
{
|
{
|
||||||
$this->denyAccessUnlessGranted('ROLE_USER');
|
$this->denyAccessUnlessGranted('ROLE_USER');
|
||||||
|
|
||||||
|
$page = max(1, $request->query->getInt('page', 1));
|
||||||
$page = max(1, (int)$request->query->get('page', 1));
|
$size = max(1, $request->query->getInt('size', 10));
|
||||||
$size = max(1, (int)$request->query->get('size', 10));
|
|
||||||
|
|
||||||
$filters = $request->query->all('filter');
|
$filters = $request->query->all('filter');
|
||||||
|
|
||||||
|
// Fetch paginated results
|
||||||
|
$paginator = $this->organizationsRepository->findAdmissibleOrganizations(
|
||||||
|
$this->getUser(),
|
||||||
|
$this->isGranted('ROLE_ADMIN'), // Super Admin check
|
||||||
|
$page,
|
||||||
|
$size,
|
||||||
|
$filters
|
||||||
|
);
|
||||||
|
|
||||||
$qb = $this->organizationsRepository->createQueryBuilder('o')
|
$total = count($paginator);
|
||||||
->where('o.isDeleted = :del')->setParameter('del', false);
|
|
||||||
|
|
||||||
if (!empty($filters['name'])) {
|
|
||||||
$qb->andWhere('o.name LIKE :name')
|
|
||||||
->setParameter('name', '%' . $filters['name'] . '%');
|
|
||||||
}
|
|
||||||
if (!empty($filters['email'])) {
|
|
||||||
$qb->andWhere('o.email LIKE :email')
|
|
||||||
->setParameter('email', '%' . $filters['email'] . '%');
|
|
||||||
}
|
|
||||||
if (!$this->isGranted('ROLE_ADMIN')) {
|
|
||||||
$actingUser = $this->getUser();
|
|
||||||
$uo = $this->entityManager->getRepository(UsersOrganizations::class)->findBy(['users' => $actingUser]);
|
|
||||||
|
|
||||||
$allowedOrgIds = [];
|
|
||||||
foreach ($uo as $item) {
|
|
||||||
if ($this->userService->isAdminOfOrganization($item->getOrganization())) {
|
|
||||||
$allowedOrgIds[] = $item->getOrganization()->getId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If user has no organizations, ensure query returns nothing (or handle typically)
|
|
||||||
if (empty($allowedOrgIds)) {
|
|
||||||
$qb->andWhere('1 = 0'); // Force empty result
|
|
||||||
} else {
|
|
||||||
$qb->andWhere('o.id IN (:orgIds)')
|
|
||||||
->setParameter('orgIds', $allowedOrgIds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Count total
|
|
||||||
$countQb = clone $qb;
|
|
||||||
$total = (int)$countQb->select('COUNT(o.id)')->getQuery()->getSingleScalarResult();
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
$offset = ($page - 1) * $size;
|
|
||||||
$rows = $qb->setFirstResult($offset)->setMaxResults($size)->getQuery()->getResult();
|
|
||||||
|
|
||||||
// Map to array
|
|
||||||
$data = array_map(function (Organizations $org) {
|
$data = array_map(function (Organizations $org) {
|
||||||
return [
|
return [
|
||||||
'id' => $org->getId(),
|
'id' => $org->getId(),
|
||||||
|
|
@ -366,17 +310,12 @@ class OrganizationController extends AbstractController
|
||||||
'active' => $org->isActive(),
|
'active' => $org->isActive(),
|
||||||
'showUrl' => $this->generateUrl('organization_show', ['id' => $org->getId()]),
|
'showUrl' => $this->generateUrl('organization_show', ['id' => $org->getId()]),
|
||||||
];
|
];
|
||||||
}, $rows);
|
}, iterator_to_array($paginator));
|
||||||
|
|
||||||
$lastPage = (int)ceil($total / $size);
|
|
||||||
|
|
||||||
return $this->json([
|
return $this->json([
|
||||||
'data' => $data,
|
'data' => $data,
|
||||||
'last_page' => $lastPage,
|
'last_page' => (int)ceil($total / $size),
|
||||||
'total' => $total, // optional, useful for debugging
|
'total' => $total,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,11 @@
|
||||||
namespace App\Repository;
|
namespace App\Repository;
|
||||||
|
|
||||||
use App\Entity\Organizations;
|
use App\Entity\Organizations;
|
||||||
|
use App\Entity\User;
|
||||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\ORM\Tools\Pagination\Paginator;
|
||||||
use Doctrine\Persistence\ManagerRegistry;
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
use App\Entity\UsersOrganizations;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends ServiceEntityRepository<Organizations>
|
* @extends ServiceEntityRepository<Organizations>
|
||||||
|
|
@ -16,28 +19,37 @@ class OrganizationsRepository extends ServiceEntityRepository
|
||||||
parent::__construct($registry, Organizations::class);
|
parent::__construct($registry, Organizations::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
public function findAdmissibleOrganizations(User $user, bool $isSuperAdmin, int $page, int $size, array $filters = []): Paginator
|
||||||
// * @return Organizations[] Returns an array of Organizations objects
|
{
|
||||||
// */
|
$qb = $this->createQueryBuilder('o')
|
||||||
// public function findByExampleField($value): array
|
->where('o.isDeleted = :del')
|
||||||
// {
|
->setParameter('del', false);
|
||||||
// return $this->createQueryBuilder('o')
|
|
||||||
// ->andWhere('o.exampleField = :val')
|
|
||||||
// ->setParameter('val', $value)
|
|
||||||
// ->orderBy('o.id', 'ASC')
|
|
||||||
// ->setMaxResults(10)
|
|
||||||
// ->getQuery()
|
|
||||||
// ->getResult()
|
|
||||||
// ;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public function findOneBySomeField($value): ?Organizations
|
// 1. Security Logic: If not Super Admin, join UsersOrganizations to filter
|
||||||
// {
|
if (!$isSuperAdmin) {
|
||||||
// return $this->createQueryBuilder('o')
|
$qb->innerJoin(UsersOrganizations::class, 'uo', 'WITH', 'uo.organization = o')
|
||||||
// ->andWhere('o.exampleField = :val')
|
->andWhere('uo.users = :user')
|
||||||
// ->setParameter('val', $value)
|
->andWhere('uo.role = :roleAdmin')
|
||||||
// ->getQuery()
|
->andWhere('uo.isActive = true')
|
||||||
// ->getOneOrNullResult()
|
->setParameter('user', $user)
|
||||||
// ;
|
// You can pass the actual Role entity or the string name depending on your mapping
|
||||||
// }
|
->setParameter('roleAdmin', $this->_em->getRepository(\App\Entity\Roles::class)->findOneBy(['name' => 'ADMIN']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Filters
|
||||||
|
if (!empty($filters['name'])) {
|
||||||
|
$qb->andWhere('o.name LIKE :name')
|
||||||
|
->setParameter('name', '%' . $filters['name'] . '%');
|
||||||
|
}
|
||||||
|
if (!empty($filters['email'])) {
|
||||||
|
$qb->andWhere('o.email LIKE :email')
|
||||||
|
->setParameter('email', '%' . $filters['email'] . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Pagination
|
||||||
|
$qb->setFirstResult(($page - 1) * $size)
|
||||||
|
->setMaxResults($size);
|
||||||
|
|
||||||
|
return new Paginator($qb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue