mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 01:08:26 +00:00 
			
		
		
		
	FEATURE [activity][docs] generic doc for activity documents in person context
This commit is contained in:
		| @@ -0,0 +1,197 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\ActivityBundle\Repository; | ||||
|  | ||||
| use Chill\DocStoreBundle\Entity\PersonDocument; | ||||
| use Chill\DocStoreBundle\Entity\StoredObject; | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQuery; | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; | ||||
| use Chill\DocStoreBundle\GenericDoc\Providers\PersonDocumentGenericDocProvider; | ||||
| use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface; | ||||
| use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter; | ||||
| use Chill\MainBundle\Entity\Scope; | ||||
| use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface; | ||||
| use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use DateTimeImmutable; | ||||
| use Doctrine\DBAL\Types\Types; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\HttpKernel\HttpCache\Store; | ||||
|  | ||||
| class PersonActivityDocumentACLAwareRepository implements PersonDocumentACLAwareRepositoryInterface | ||||
| { | ||||
|     private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser; | ||||
|  | ||||
|     private CenterResolverManagerInterface $centerResolverManager; | ||||
|  | ||||
|     private EntityManagerInterface $em; | ||||
|  | ||||
|     public function __construct(EntityManagerInterface $em, CenterResolverManagerInterface $centerResolverManager, AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser) | ||||
|     { | ||||
|         $this->em = $em; | ||||
|         $this->centerResolverManager = $centerResolverManager; | ||||
|         $this->authorizationHelperForCurrentUser = $authorizationHelperForCurrentUser; | ||||
|     } | ||||
|  | ||||
|     public function buildQueryByPerson(Person $person): QueryBuilder | ||||
|     { | ||||
|         $qb = $this->em->getRepository(PersonDocument::class)->createQueryBuilder('d'); | ||||
|  | ||||
|         $qb | ||||
|             ->where($qb->expr()->eq('d.person', ':person')) | ||||
|             ->setParameter('person', $person); | ||||
|  | ||||
|         return $qb; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface | ||||
|     { | ||||
|         $query = $this->buildBaseFetchQueryForPerson($person, $startDate, $endDate, $content); | ||||
|  | ||||
|         return $this->addFetchQueryByPersonACL($query, $person); | ||||
|     } | ||||
|  | ||||
|     public function buildBaseFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery | ||||
|     { | ||||
|         $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class); | ||||
|  | ||||
|         $query = new FetchQuery( | ||||
|             PersonDocumentGenericDocProvider::KEY, | ||||
|             sprintf('jsonb_build_object(\'id\', stored_obj.%s)', $storedObjectMetadata->getSingleIdentifierColumnName()), | ||||
|             sprintf('stored_obj.%s', $storedObjectMetadata->getColumnName('createdAt')), | ||||
|             sprintf('%s AS stored_obj', $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName()) | ||||
|         ); | ||||
|  | ||||
|         $query->addJoinClause( | ||||
|             'JOIN public.activity_storedobject activity_doc ON activity_doc.storedobject_id = stored_obj.id' | ||||
|         ); | ||||
|  | ||||
|         $query->addJoinClause( | ||||
|             'JOIN public.activity activity ON activity.id = activity_doc.activity_id' | ||||
|         ); | ||||
|  | ||||
|         $query->addWhereClause( | ||||
|             'activity.person_id = ?', | ||||
|             [$person->getId()], | ||||
|             [Types::INTEGER] | ||||
|         ); | ||||
|  | ||||
|         if (null !== $startDate) { | ||||
|             $query->addWhereClause( | ||||
|                 sprintf('stored_obj.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')), | ||||
|                 [$startDate], | ||||
|                 [Types::DATE_IMMUTABLE] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         if (null !== $endDate) { | ||||
|             $query->addWhereClause( | ||||
|                 sprintf('stored_obj.%s < ?', $storedObjectMetadata->getColumnName('createdAt')), | ||||
|                 [$endDate], | ||||
|                 [Types::DATE_IMMUTABLE] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         if (null !== $content) { | ||||
|             $query->addWhereClause( | ||||
|                 'stored_obj.title ilike ?', | ||||
|                 ['%' . $content . '%'], | ||||
|                 [Types::STRING] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return $query; | ||||
|     } | ||||
|  | ||||
|     public function countByPerson(Person $person): int | ||||
|     { | ||||
|         $qb = $this->buildQueryByPerson($person)->select('COUNT(d)'); | ||||
|  | ||||
|         $this->addACL($qb, $person); | ||||
|  | ||||
|         return $qb->getQuery()->getSingleScalarResult(); | ||||
|     } | ||||
|  | ||||
|     public function findByPerson(Person $person, array $orderBy = [], int $limit = 20, int $offset = 0): array | ||||
|     { | ||||
|         $qb = $this->buildQueryByPerson($person)->select('d'); | ||||
|  | ||||
|         $this->addACL($qb, $person); | ||||
|  | ||||
|         foreach ($orderBy as $field => $order) { | ||||
|             $qb->addOrderBy('d.' . $field, $order); | ||||
|         } | ||||
|  | ||||
|         $qb->setFirstResult($offset)->setMaxResults($limit); | ||||
|  | ||||
|         return $qb->getQuery()->getResult(); | ||||
|     } | ||||
|  | ||||
|     private function addACL(QueryBuilder $qb, Person $person): void | ||||
|     { | ||||
|         $reachableScopes = []; | ||||
|  | ||||
|         foreach ($this->centerResolverManager->resolveCenters($person) as $center) { | ||||
|             $reachableScopes = [ | ||||
|                 ...$reachableScopes, | ||||
|                 ...$this->authorizationHelperForCurrentUser | ||||
|                     ->getReachableScopes( | ||||
|                         PersonDocumentVoter::SEE, | ||||
|                         $center | ||||
|                     ) | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         if ([] === $reachableScopes) { | ||||
|             $qb->andWhere("'FALSE' = 'TRUE'"); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $qb->andWhere($qb->expr()->in('d.scope', ':scopes')) | ||||
|             ->setParameter('scopes', $reachableScopes); | ||||
|     } | ||||
|  | ||||
|     private function addFetchQueryByPersonACL(FetchQuery $fetchQuery, Person $person): FetchQuery | ||||
|     { | ||||
|         $personDocMetadata = $this->em->getClassMetadata(PersonDocument::class); | ||||
|  | ||||
|         $reachableScopes = []; | ||||
|  | ||||
|         foreach ($this->centerResolverManager->resolveCenters($person) as $center) { | ||||
|             $reachableScopes = [ | ||||
|                 ...$reachableScopes, | ||||
|                 ...$this->authorizationHelperForCurrentUser->getReachableScopes(PersonDocumentVoter::SEE, $center) | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         if ([] === $reachableScopes) { | ||||
|             $fetchQuery->addWhereClause('FALSE = TRUE'); | ||||
|  | ||||
|             return $fetchQuery; | ||||
|         } | ||||
|  | ||||
|         $fetchQuery->addWhereClause( | ||||
|             sprintf( | ||||
|                 'person_document.%s IN (%s)', | ||||
|                 $personDocMetadata->getSingleAssociationJoinColumnName('scope'), | ||||
|                 implode(', ', array_fill(0, count($reachableScopes), '?')) | ||||
|             ), | ||||
|             array_map(static fn (Scope $s) => $s->getId(), $reachableScopes), | ||||
|             array_fill(0, count($reachableScopes), Types::INTEGER) | ||||
|         ); | ||||
|  | ||||
|         return $fetchQuery; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,57 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\ActivityBundle\Service\GenericDoc\Providers; | ||||
|  | ||||
| use Chill\ActivityBundle\Repository\PersonActivityDocumentACLAwareRepository; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; | ||||
| use Chill\DocStoreBundle\GenericDoc\GenericDocForPersonProviderInterface; | ||||
| use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use DateTimeImmutable; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
|  | ||||
| final class PersonActivityGenericDocProvider implements GenericDocForPersonProviderInterface | ||||
| { | ||||
|     public const KEY = 'person_activity_document'; | ||||
|  | ||||
|     private Security $security; | ||||
|  | ||||
|     private PersonActivityDocumentACLAwareRepository $personActivityDocumentACLAwareRepository; | ||||
|  | ||||
|     public function __construct(Security $security, PersonActivityDocumentACLAwareRepository $personActivityDocumentACLAwareRepository | ||||
| ) | ||||
|     { | ||||
|         $this->security = $security; | ||||
|         $this->personActivityDocumentACLAwareRepository = $personActivityDocumentACLAwareRepository; | ||||
|     } | ||||
|  | ||||
|     public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface | ||||
|     { | ||||
|         return $this->personActivityDocumentACLAwareRepository->buildFetchQueryForPerson( | ||||
|             $person, | ||||
|             $startDate, | ||||
|             $endDate, | ||||
|             $content | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Person $person | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isAllowedForPerson(Person $person): bool | ||||
|     { | ||||
|         return $this->security->isGranted(ActivityVoter::SEE, $person); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user