* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ namespace Chill\EventBundle\Timeline; use Chill\EventBundle\Entity\Event; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Timeline\TimelineProviderInterface; use Doctrine\ORM\EntityManager; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Role\Role; use Doctrine\ORM\Mapping\ClassMetadata; use Chill\PersonBundle\Entity\Person; use Chill\MainBundle\Entity\User; /** * Class TimelineEventProvider * * @package Chill\EventBundle\Timeline * @author Mathieu Jaumotte jaum_mathieu@collectifs.net */ class TimelineEventProvider implements TimelineProviderInterface { /** * @var EntityManager */ protected $em; /** * @var AuthorizationHelper */ protected $helper; /** * @var User */ protected $user; /** * TimelineEventProvider constructor. * * @param EntityManager $em * @param AuthorizationHelper $helper * @param TokenStorageInterface $storage */ public function __construct( EntityManager $em, AuthorizationHelper $helper, TokenStorageInterface $storage ) { $this->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 * @param array $args * @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'); $query = array( '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']) ); return $query; } /** * @param ClassMetadata $metadataEvent * @param ClassMetadata $metadataParticipation * @param ClassMetadata $metadataPerson * @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'] ; } /** * @param ClassMetadata $metadataEvent * @param ClassMetadata $metadataParticipation * @param ClassMetadata $metadataPerson * @param Person $person * @return string * @throws \Doctrine\ORM\Mapping\MappingException */ private function getWhereClause( ClassMetadata $metadataEvent, ClassMetadata $metadataParticipation, ClassMetadata $metadataPerson, Person $person ) { $role = new Role('CHILL_EVENT_SEE'); $reachableCenters = $this->helper->getReachableCenters($this->user, $role); $associationMapping = $metadataParticipation->getAssociationMapping('person'); if (count($reachableCenters) === 0) { return 'FALSE = TRUE'; } $whereClause = sprintf( '%s = %d', $associationMapping['joinColumns'][0]['name'], $person->getId()); // and $centerAndScopeLines = array(); foreach ($reachableCenters as $center) { $reachableCircleId = array_map( function (Scope $scope) { return $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; } /** * check if the context is supported * * @param string $context * @throws \LogicException if the context is not supported */ private function checkContext($context) { if ($context !== 'person') { throw new \LogicException("The context '$context' is not " . "supported. Currently only 'person' is supported"); } } /** * @param string $type * @return bool */ public function supportsType($type) { return $type === 'event'; } /** * @param array $ids * @return array|mixed[] */ public function getEntities(array $ids) { $events = $this->em->getRepository(Event::class) ->findBy(array('id' => $ids)); $result = array(); foreach ($events as $event) { $result[$event->getId()] = $event; } return $result; } /** * @param Event $entity * @param string $context * @param array $args * @return array|mixed[] */ public function getEntityTemplate($entity, $context, array $args) { $this->checkContext($context); return array( 'template' => 'ChillEventBundle:Timeline:event_person_context.html.twig', 'template_data' => array( 'event' => $entity, 'person' => $args['person'], 'user' => $this->user ) ); } }