authorizationHelper = $authorizationHelper; $this->centerResolverDispatcher = $centerResolverDispatcher; $this->tokenStorage = $tokenStorage; $this->repository = $repository; $this->em = $em; $this->security = $security; } public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array { $user = $this->security->getUser(); $center = $this->centerResolverDispatcher->resolveCenter($period); if (0 === count($orderBy)) { $orderBy = ['date' => 'DESC']; } $scopes = $this->authorizationHelper ->getReachableCircles($user, $role, $center); return $this->em->getRepository(Activity::class) ->findByAccompanyingPeriod($period, $scopes, true, $limit, $start, $orderBy); } public function findByAccompanyingPeriodSimplified(AccompanyingPeriod $period, ?int $limit = 1000): array { $rsm = new ResultSetMappingBuilder($this->em); $sql = " SELECT a.id AS activity_id, date, CASE WHEN durationtime IS NOT NULL THEN (EXTRACT(EPOCH from durationtime) / 60)::int ELSE 0 END AS durationtimeminute, attendee_id, comment_comment, emergency, sentreceived, CASE WHEN traveltime IS NOT NULL THEN (EXTRACT(EPOCH from traveltime) / 60)::int ELSE 0 END AS traveltimeminute, t.id AS type_id, t.name as type_name, p.id AS presence_id, p.name AS presence_name, location.id AS location_id, location.address_id, location.name AS location_name, location.phonenumber1, location.phonenumber2, location.email, location.locationtype_id, locationtype.title AS locationtype_title, users.userids AS userids, thirdparties.thirdpartyids, persons.personids, actions.socialactionids, issues.socialissueids FROM activity a LEFT JOIN chill_main_location location ON a.location_id = location.id LEFT JOIN chill_main_location_type locationtype ON location.locationtype_id = locationtype.id LEFT JOIN activitytpresence p ON a.attendee_id = p.id LEFT JOIN activitytype t ON a.type_id = t.id LEFT JOIN LATERAL (SELECT jsonb_agg(user_id) userids, activity_id FROM activity_user AS au WHERE a.id = au.activity_id GROUP BY activity_id) AS users ON TRUE LEFT JOIN LATERAL (SELECT jsonb_agg(thirdparty_id) thirdpartyids, activity_id FROM activity_thirdparty AS au WHERE a.id = au.activity_id GROUP BY activity_id) AS thirdparties ON TRUE LEFT JOIN LATERAL (SELECT jsonb_agg(person_id) personids, activity_id FROM activity_person AS au WHERE a.id = au.activity_id GROUP BY activity_id) AS persons ON TRUE LEFT JOIN LATERAL (SELECT jsonb_agg(socialaction_id) socialactionids, activity_id FROM postgres.public.chill_activity_activity_chill_person_socialaction AS au WHERE a.id = au.activity_id GROUP BY activity_id) AS actions ON TRUE LEFT JOIN LATERAL (SELECT jsonb_agg(socialissue_id) socialissueids, activity_id FROM postgres.public.chill_activity_activity_chill_person_socialissue AS au WHERE a.id = au.activity_id GROUP BY activity_id) AS issues ON TRUE WHERE accompanyingperiod_id = ? ORDER BY a.date DESC, a.id DESC LIMIT ? "; $rsm ->addEntityResult(Activity::class, 'a') ->addFieldResult('a', 'activity_id', 'id') ->addFieldResult('a', 'date', 'date') ->addFieldResult('a', 'comment', 'comment') ->addFieldResult('a', 'sentreceived', 'sentReceived') ->addFieldResult('a', 'emergency', 'emergency') ->addJoinedEntityResult(Location::class, 'location', 'a', 'location') ->addFieldResult('location', 'location_id', 'id') ->addFieldResult('location', 'location_name', 'name') ->addFieldResult('location', 'phonenumber1', 'phonenumber1') ->addFieldResult('location', 'phonenumber2', 'phonenumber2') ->addFieldResult('location', 'email', 'email') ->addJoinedEntityResult(LocationType::class,'locationType', 'location', 'locationType' ) ->addFieldResult('locationType', 'locationtype_id', 'id') ->addFieldResult('locationType', 'locationtype_title', 'title') ->addJoinedEntityResult(ActivityType::class, 'activityType', 'a', 'activityType') ->addFieldResult('activityType', 'type_id', 'id') ->addFieldResult('activityType', 'type_name', 'name') ->addJoinedEntityResult(ActivityPresence::class, 'activityPresence', 'a', 'attendee') ->addFieldResult('activityPresence', 'presence_id', 'id') ->addFieldResult('activityPresence', 'presence_name', 'name') // results which cannot be mapped into entity ->addScalarResult('comment_comment', 'comment', Types::TEXT) ->addScalarResult('userids', 'userIds', Types::JSON) ->addScalarResult('thirdpartyids', 'thirdPartyIds', Types::JSON) ->addScalarResult('personids', 'personIds', Types::JSON) ->addScalarResult('socialactionids', 'socialActionIds', Types::JSON) ->addScalarResult('socialissueids', 'socialIssueIds', Types::JSON) ->addScalarResult('durationtimeminute', 'durationTimeMinute', Types::INTEGER) ->addScalarResult('traveltimeminute', 'travelTimeMinute', Types::INTEGER) ; $nq = $this->em->createNativeQuery($sql, $rsm); $nq->setParameter(0, $period->getId())->setParameter(1, $limit); return $nq->getResult(AbstractQuery::HYDRATE_ARRAY); } /** * @param array $orderBy * * @return Activity[]|array */ public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array { $user = $this->security->getUser(); $center = $this->centerResolverDispatcher->resolveCenter($person); if (0 === count($orderBy)) { $orderBy = ['date' => 'DESC']; } $reachableScopes = $this->authorizationHelper ->getReachableCircles($user, $role, $center); return $this->em->getRepository(Activity::class) ->findByPersonImplied($person, $reachableScopes, $orderBy, $limit, $start); } public function queryTimelineIndexer(string $context, array $args = []): array { $metadataActivity = $this->em->getClassMetadata(Activity::class); $from = $this->getFromClauseCenter($args); [$where, $parameters] = $this->getWhereClause($context, $args); return [ 'id' => $metadataActivity->getTableName() . '.' . $metadataActivity->getColumnName('id'), 'type' => 'activity', 'date' => $metadataActivity->getTableName() . '.' . $metadataActivity->getColumnName('date'), 'FROM' => $from, 'WHERE' => $where, 'parameters' => $parameters, ]; } private function getFromClauseCenter(array $args): string { $metadataActivity = $this->em->getClassMetadata(Activity::class); $metadataPerson = $this->em->getClassMetadata(Person::class); $associationMapping = $metadataActivity->getAssociationMapping('person'); return $metadataActivity->getTableName() . ' JOIN ' . $metadataPerson->getTableName() . ' ON ' . $metadataPerson->getTableName() . '.' . $associationMapping['joinColumns'][0]['referencedColumnName'] . ' = ' . $associationMapping['joinColumns'][0]['name']; } private function getWhereClause(string $context, array $args): array { $where = ''; $parameters = []; $metadataActivity = $this->em->getClassMetadata(Activity::class); $metadataPerson = $this->em->getClassMetadata(Person::class); $activityToPerson = $metadataActivity->getAssociationMapping('person')['joinColumns'][0]['name']; $activityToScope = $metadataActivity->getAssociationMapping('scope')['joinColumns'][0]['name']; $personToCenter = $metadataPerson->getAssociationMapping('center')['joinColumns'][0]['name']; // acls: $role = new Role(ActivityVoter::SEE); $reachableCenters = $this->authorizationHelper->getReachableCenters( $this->tokenStorage->getToken()->getUser(), $role ); if (count($reachableCenters) === 0) { // insert a dummy condition return 'FALSE = TRUE'; } if ('person' === $context) { // we start with activities having the person_id linked to person $where .= sprintf('%s = ? AND ', $activityToPerson); $parameters[] = $person->getId(); } // we add acl (reachable center and scopes) $where .= '('; // first loop for the for centers $centersI = 0; // like centers#i foreach ($reachableCenters as $center) { // we pass if not in centers if (!in_array($center, $args['centers'], true)) { continue; } // we get all the reachable scopes for this center $reachableScopes = $this->authorizationHelper->getReachableScopes($this->tokenStorage->getToken()->getUser(), $role, $center); // we get the ids for those scopes $reachablesScopesId = array_map( static function (Scope $scope) { return $scope->getId(); }, $reachableScopes ); // if not the first center if (0 < $centersI) { $where .= ') OR ('; } // condition for the center $where .= sprintf(' %s.%s = ? ', $metadataPerson->getTableName(), $personToCenter); $parameters[] = $center->getId(); // begin loop for scopes $where .= ' AND ('; $scopesI = 0; //like scope#i foreach ($reachablesScopesId as $scopeId) { if (0 < $scopesI) { $where .= ' OR '; } $where .= sprintf(' %s.%s = ? ', $metadataActivity->getTableName(), $activityToScope); $parameters[] = $scopeId; ++$scopesI; } // close loop for scopes $where .= ') '; ++$centersI; } // close loop for centers $where .= ')'; return [$where, $parameters]; } }