em = $em; $this->helper = $helper; if (!$storage->getToken()->getUser() instanceof User) { throw new \RuntimeException('A user should be authenticated !'); } $this->user = $storage->getToken()->getUser(); } /** * @param string $context * * @return array|string[] * * @throws \Doctrine\ORM\Mapping\MappingException */ public function fetchQuery($context, array $args) { $this->checkContext($context); $metadataEvent = $this->em->getClassMetadata('ChillEventBundle:Event'); $metadataParticipation = $this->em->getClassMetadata('ChillEventBundle:Participation'); $metadataPerson = $this->em->getClassMetadata('ChillPersonBundle:Person'); return TimelineSingleQuery::fromArray([ 'id' => $metadataEvent->getTableName().'.'.$metadataEvent->getColumnName('id'), 'type' => 'event', 'date' => $metadataEvent->getTableName().'.'.$metadataEvent->getColumnName('date'), 'FROM' => $this->getFromClause($metadataEvent, $metadataParticipation, $metadataPerson), 'WHERE' => $this->getWhereClause($metadataEvent, $metadataParticipation, $metadataPerson, $args['person']), 'parameters' => [], ]); } /** * @return array|mixed[] */ public function getEntities(array $ids) { $events = $this->em->getRepository(Event::class) ->findBy(['id' => $ids]); $result = []; foreach ($events as $event) { $result[$event->getId()] = $event; } return $result; } /** * @param Event $entity * @param string $context * * @return array|mixed[] */ public function getEntityTemplate($entity, $context, array $args) { $this->checkContext($context); return [ 'template' => '@ChillEvent/Timeline/event_person_context.html.twig', 'template_data' => [ 'event' => $entity, 'person' => $args['person'], 'user' => $this->user, ], ]; } /** * @param string $type * * @return bool */ public function supportsType($type) { return 'event' === $type; } /** * check if the context is supported. * * @param string $context * * @throws \LogicException if the context is not supported */ private function checkContext($context) { if ('person' !== $context) { throw new \LogicException("The context '{$context}' is not supported. Currently only 'person' is supported"); } } /** * @return string * * @throws \Doctrine\ORM\Mapping\MappingException */ private function getFromClause( ClassMetadata $metadataEvent, ClassMetadata $metadataParticipation, ClassMetadata $metadataPerson, ) { $eventParticipationMapping = $metadataParticipation->getAssociationMapping('event'); $participationPersonMapping = $metadataParticipation->getAssociationMapping('person'); return $metadataEvent->getTableName() .' JOIN '.$metadataParticipation->getTableName() .' ON '.$metadataParticipation->getTableName() .'.'.$eventParticipationMapping['joinColumns'][0]['name'] .' = '.$metadataEvent->getTableName() .'.'.$eventParticipationMapping['joinColumns'][0]['referencedColumnName'] .' JOIN '.$metadataPerson->getTableName() .' ON '.$metadataPerson->getTableName() .'.'.$participationPersonMapping['joinColumns'][0]['referencedColumnName'] .' = '.$metadataParticipation->getTableName() .'.'.$participationPersonMapping['joinColumns'][0]['name']; } /** * @return string * * @throws \Doctrine\ORM\Mapping\MappingException */ private function getWhereClause( ClassMetadata $metadataEvent, ClassMetadata $metadataParticipation, ClassMetadata $metadataPerson, Person $person, ) { $role = 'CHILL_EVENT_SEE'; $reachableCenters = $this->helper->getReachableCenters($this->user, $role); $associationMapping = $metadataParticipation->getAssociationMapping('person'); if (0 === \count($reachableCenters)) { return 'FALSE = TRUE'; } $whereClause = sprintf( '%s = %d', $associationMapping['joinColumns'][0]['name'], $person->getId() ); // and $centerAndScopeLines = []; foreach ($reachableCenters as $center) { $reachableCircleId = array_map( static fn (Scope $scope) => $scope->getId(), $this->helper->getReachableCircles($this->user, $role, $person->getCenter()) ); $centerAndScopeLines[] = sprintf( '(%s = %d AND %s IN (%s))', $metadataPerson->getTableName().'.'. $metadataPerson->getAssociationMapping('center')['joinColumns'][0]['name'], $center->getId(), $metadataEvent->getTableName().'.'. $metadataEvent->getAssociationMapping('circle')['joinColumns'][0]['name'], implode(',', $reachableCircleId) ); } $whereClause .= ' AND ('.implode(' OR ', $centerAndScopeLines).')'; return $whereClause; } }