*/ public function getUserOrganizations(User $user, int $organizationsId = null): array { $userOrganizations = $this->entityManager ->getRepository(UsersOrganizations::class) ->findAllDistinctOrganizationsByUserId($user->getId()); $organizations = []; foreach ($userOrganizations as $uo) { $orgId = $uo->getOrganization()->getId(); // If $organizationsId is provided, skip other organizations if ($organizationsId !== null && $orgId !== $organizationsId) { continue; } // Initialize the organization entry if it doesn't exist $organizations[$orgId] = $organizations[$orgId] ?? $this->createEmptyOrganizationBucket($uo); $organizations[$orgId]['uoId'] = $uo->getId(); // Aggregate roles & apps $this->addRole($organizations[$orgId]['roles'], $uo->getRole()); $this->addApps($organizations[$orgId]['apps'], $uo->getApps()); } $this->normalizeAppsIndexes($organizations); return array_values($organizations); } /** * Build the initial array structure for a fresh organization entry. * * @param UsersOrganizations $link * @return array{organization:object, roles:Roles[], apps:array} */ private function createEmptyOrganizationBucket(UsersOrganizations $link): array { return [ 'organization' => $link->getOrganization(), 'roles' => [], 'apps' => [], ]; } /** * Add a Role entity to the roles array only if it is not already present (by ID). * * @param Roles[] &$roles * @param Roles|null $role */ private function addRole(array &$roles, ?Roles $role): void { if ($role === null) { return; } foreach ($roles as $existingRole) { if ($existingRole->getId() === $role->getId()) { return; // Already present } } $roles[] = $role; } /** * Merge one or many apps into the apps map, keeping only one entry per id. * * @param array &$apps * @param iterable $appsToAdd Collection returned by $userOrganizations->getApps() */ private function addApps(array &$apps, iterable $appsToAdd): void { foreach ($appsToAdd as $app) { $apps[$app->getId()] = $apps[$app->getId()] ?? $app; } } /** * Convert apps from associative maps (keyed by id) to plain indexed arrays, * so the final output is clean JSON-able. * * @param array &$organizations */ private function normalizeAppsIndexes(array &$organizations): void { foreach ($organizations as &$org) { $org['apps'] = array_values($org['apps']); } } /** * Set user organizations with roles, ensuring USER role is always present * * @param User $user * @param Organizations $organization * @param array $selectedRoles Array of role IDs to set for the user in the organization */ public function setUserOrganizations(User $user, Organizations $organization, array $selectedRoles): void { $repo = $this->entityManager->getRepository(UsersOrganizations::class); $roleRepo = $this->entityManager->getRepository(Roles::class); // Get the USER role entity $userRole = $roleRepo->findOneBy(['name' => 'USER']); if (!$userRole) { throw new \RuntimeException('USER role not found'); } // If USER role is not selected, deactivate all roles and return if (!in_array($userRole->getId(), $selectedRoles)) { $this->deactivateAllUserRoles($user, $organization); return; } // 1. Get all current UsersOrganizations for this user/org $currentUserOrgs = $repo->findBy([ 'users' => $user, 'organization' => $organization ]); // 2. Build a map: roleId => UsersOrganizations entity $currentRolesMap = []; foreach ($currentUserOrgs as $uo) { $currentRolesMap[$uo->getRole()->getId()] = $uo; } // 3. Check if we need to ensure USER role exists $hasNonUserRole = false; foreach ($selectedRoles as $roleId) { if ($roleId !== $userRole->getId()) { $hasNonUserRole = true; break; } } // 4. If we have non-USER roles, ensure USER role is present if ($hasNonUserRole && !in_array($userRole->getId(), $selectedRoles)) { $selectedRoles[] = $userRole->getId(); } // 5. Add new roles that are selected but not present foreach ($selectedRoles as $roleId) { if (!isset($currentRolesMap[$roleId])) { $roleEntity = $roleRepo->find($roleId); if ($roleEntity) { $newUserOrganization = new UsersOrganizations(); $newUserOrganization->setUsers($user); $newUserOrganization->setRole($roleEntity); $newUserOrganization->setOrganization($organization); $newUserOrganization->setIsActive(true); // Ensure new roles are active $this->entityManager->persist($newUserOrganization); } } else { // If role exists but was inactive, reactivate it $currentRolesMap[$roleId]->setIsActive(true); $this->entityManager->persist($currentRolesMap[$roleId]); } // Remove from map so we know which ones to deactivate later unset($currentRolesMap[$roleId]); } // 6. Remove roles that are present but not selected (deactivate them) foreach ($currentRolesMap as $uo) { $uo->setIsActive(false); $this->entityManager->persist($uo); } $this->entityManager->flush(); } public function setUserOrganizationsApps(User $user, Organizations $organization, array $selectedApps) { $apps = []; $userOrganizations = $this->entityManager ->getRepository(UsersOrganizations::class) ->findAllDistinctOrganizationsByUserId($user->getId()); foreach ($userOrganizations as $uo) { $this->addApps($apps, $uo->getApps()); } $roleUser = $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'USER']); $uoEntity = $this->entityManager ->getRepository(UsersOrganizations::class) ->findOneBy(['users' => $user, 'organization' => $organization, 'role' => $roleUser]); // dd($uoEntity->getApps()->toArray()); // 1. Remove apps that are no longer selected foreach ($uoEntity->getApps()->toArray() as $existingApp) { if (!in_array($existingApp->getId(), $selectedApps)) { $uoEntity->removeApp($existingApp); } } // 2. Add newly selected apps foreach ($selectedApps as $appId) { $appEntity = $this->entityManager->getRepository(Apps::class)->find($appId); if ($appEntity && !$uoEntity->getApps()->contains($appEntity)) { $uoEntity->addApp($appEntity); } } $this->entityManager->persist($uoEntity); $this->entityManager->flush(); } /** * Deactivate all roles if role USER is deactivated * @param User $user * @param Organizations $organization * @return void */ public function deactivateAllUserRoles(User $user, Organizations $organization): void { $repo = $this->entityManager->getRepository(UsersOrganizations::class); $userOrganizations = $repo->findBy([ 'users' => $user, 'organization' => $organization ]); foreach ($userOrganizations as $uo) { $uo->setIsActive(false); $this->entityManager->persist($uo); } $this->entityManager->flush(); } }