diff --git a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php index b8684a0a5..ae2c448e6 100644 --- a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php +++ b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php @@ -62,7 +62,7 @@ final class ActivityACLAwareRepository $metadataActivity = $this->em->getClassMetadata(Activity::class); $from = $this->getFromClauseCenter($args); - $where = $this->getWhereClause($context, $args); + [$where, $parameters] = $this->getWhereClause($context, $args); return [ 'id' => $metadataActivity->getTableName() @@ -71,7 +71,8 @@ final class ActivityACLAwareRepository 'date' => $metadataActivity->getTableName() .'.'.$metadataActivity->getColumnName('date'), 'FROM' => $from, - 'WHERE' => $where + 'WHERE' => $where, + 'parameters' => $parameters ]; } diff --git a/src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php b/src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php index 52e1027a8..ff1d9ffb3 100644 --- a/src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php +++ b/src/Bundle/ChillActivityBundle/Timeline/TimelineActivityProvider.php @@ -29,13 +29,13 @@ use Symfony\Component\Security\Core\Role\Role; use Doctrine\ORM\Mapping\ClassMetadata; use Chill\PersonBundle\Entity\Person; use Chill\MainBundle\Entity\Scope; +use Chill\ActivityBundle\Entity\Activity; +use Chill\MainBundle\Timeline\TimelineSingleQuery; /** * Provide activity for inclusion in timeline * - * @author Julien Fastré - * @author Champs Libres - */ +*/ class TimelineActivityProvider implements TimelineProviderInterface { @@ -93,63 +93,37 @@ class TimelineActivityProvider implements TimelineProviderInterface */ public function fetchQuery($context, array $args) { - //$this->checkContext($context); - // if ('center' === $context) { - return $this->aclAwareRepository->queryTimelineIndexer($context, $args); + return TimelineSingleQuery::fromArray($this->aclAwareRepository + ->queryTimelineIndexer($context, $args)); } - $metadataActivity = $this->em->getClassMetadata('ChillActivityBundle:Activity'); - - return array( + $metadataActivity = $this->em->getClassMetadata(Activity::class); + + [$where, $parameters] = $this->getWhereClauseForPerson($args['person']); + dump($where, $parameters); + return TimelineSingleQuery::fromArray([ 'id' => $metadataActivity->getTableName() .'.'.$metadataActivity->getColumnName('id'), 'type' => 'activity', 'date' => $metadataActivity->getTableName() .'.'.$metadataActivity->getColumnName('date'), - 'FROM' => $this->getFromClause($metadataActivity, $metadataPerson), - 'WHERE' => $this->getWhereClause($metadataActivity, $metadataPerson, - $args['person']) - ); - } - - private function getFromClause(string $context) - { - switch ($context) { - case 'person': - return $this->getFromClausePerson($metadataActivity, $metadataPerson); - } - } - - private function getWhereClause(string $context, array $args) - { - switch ($context) { - case 'person': - return $this->getWhereClause($args['person']); - } - } - - /** - * - * @var $centers array|Center[] - */ - private function getWhereClauseForCenter(array $centers) - { - $clause = ""; - $role = new Role('CHILL_ACTIVITY_SEE'); - - + 'FROM' => $this->getFromClausePerson($args['person']), + 'WHERE' => $where, + 'parameters' => $parameters + ]); } private function getWhereClauseForPerson(Person $person) { + $parameters = []; $metadataActivity = $this->em->getClassMetadata('ChillActivityBundle:Activity'); + $associationMapping = $metadataActivity->getAssociationMapping('person'); $metadataPerson = $this->em->getClassMetadata('ChillPersonBundle:Person'); $role = new Role('CHILL_ACTIVITY_SEE'); $reachableCenters = $this->helper->getReachableCenters($this->user, $role); - $associationMapping = $metadataActivity->getAssociationMapping('person'); if (count($reachableCenters) === 0) { return 'FALSE = TRUE'; @@ -157,31 +131,41 @@ class TimelineActivityProvider implements TimelineProviderInterface // we start with activities having the person_id linked to person // (currently only context "person" is supported) - $whereClause = sprintf('%s = %d', - $associationMapping['joinColumns'][0]['name'], - $person->getId()); + $whereClause = sprintf(' {activity.person_id} = ? '); + $parameters[] = $person->getId(); // we add acl (reachable center and scopes) - $centerAndScopeLines = array(); + $centerAndScopeClauses = []; foreach ($reachableCenters as $center) { - $reachablesScopesId = array_map( - function(Scope $scope) { return $scope->getId(); }, - $this->helper->getReachableScopes($this->user, $role, - $person->getCenter()) - ); - - $centerAndScopeLines[] = sprintf('(%s = %d AND %s IN (%s))', - $metadataPerson->getTableName().'.'. - $metadataPerson->getAssociationMapping('center')['joinColumns'][0]['name'], - $center->getId(), - $metadataActivity->getTableName().'.'. - $metadataActivity->getAssociationMapping('scope')['joinColumns'][0]['name'], - implode(',', $reachablesScopesId)); - + $parameters[] = $center->getId(); + $scopes_ids = []; + $reachableScopes = $this->helper->getReachableScopes($this->user, $role, $person->getCenter()); + foreach ($reachableScopes as $scope) { + $scopes_ids[] = '?'; + $parameters[] = $scope->getId(); + } + $centerAndScopeClauses[] = \strtr( + '( {person.center_id} = ? AND {activity.scope_id} IN ({scopes_ids})) ', + [ + '{scopes_ids}' => \implode(", ", $scopes_ids) + ] + ); } - $whereClause .= ' AND ('.implode(' OR ', $centerAndScopeLines).')'; - - return $whereClause; + $whereClause .= ' AND ('.\implode(' OR ', $centerAndScopeClauses).' ) '; + + return [ + \strtr( + $whereClause, + [ + '{activity.person_id}' => $associationMapping['joinColumns'][0]['name'], + '{person.center_id}' => $metadataPerson->getTableName().'.'. + $metadataPerson->getAssociationMapping('center')['joinColumns'][0]['name'], + '{activity.scope_id}' => $metadataActivity->getTableName().'.'. + $metadataActivity->getAssociationMapping('scope')['joinColumns'][0]['name'], + ] + ), + $parameters + ]; } private function getFromClausePerson() @@ -199,21 +183,6 @@ class TimelineActivityProvider implements TimelineProviderInterface ; } - private function getFromClauseCenter() - { - $metadataActivity = $this->em->getClassMetadata('ChillActivityBundle:Activity'); - $metadataPerson = $this->em->getClassMetadata('ChillPersonBundle:Person'); - $associationMapping = $metadataActivity->getAssociationMapping('person'); - - return $metadataActivity->getTableName().' JOIN ' - .$metadataPerson->getTableName().' ON ' - .$metadataPerson->getTableName().'.'. - $associationMapping['joinColumns'][0]['referencedColumnName'] - .' = ' - .$associationMapping['joinColumns'][0]['name'] - ; - } - /** * * {@inheritDoc} diff --git a/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php b/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php index 2e4102af6..bd1a4cc1a 100644 --- a/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php +++ b/src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php @@ -201,10 +201,13 @@ class TimelineBuilder implements ContainerAwareInterface /** * return the SQL SELECT query as a string, * - * @return string + * @return array: first parameter is the sql string, second an array with parameters */ - private function buildSelectQuery(array $data): array + private function buildSelectQuery($data): array { + return [$data->buildSql(), $data->getParameters()]; + + // dead code $parameters = []; $sql = sprintf( diff --git a/src/Bundle/ChillMainBundle/Timeline/TimelineSingleQuery.php b/src/Bundle/ChillMainBundle/Timeline/TimelineSingleQuery.php new file mode 100644 index 000000000..cf8dc085e --- /dev/null +++ b/src/Bundle/ChillMainBundle/Timeline/TimelineSingleQuery.php @@ -0,0 +1,155 @@ +id = $id; + $this->date = $date; + $this->key = $key; + $this->from = $from; + $this->where = $where; + $this->parameters = $parameters; + } + + public static function fromArray(array $a) + { + return new TimelineSingleQuery( + $a['id'], + $a['date'], + $a['type'] ?? $a['key'], + $a['FROM'] ?? $a['from'], + $a['WHERE'] ?? $a['where'], + $a['parameters']); + } + + public function getId(): string + { + return $this->id; + } + + public function setId(string $id): self + { + $this->id = $id; + + return $this; + } + + public function getDate(): string + { + return $this->date; + } + + public function setDate(string $date): self + { + $this->date = $date; + + return $this; + } + + public function getKey(): string + { + return $this->key; + } + + public function setKey(string $key): self + { + $this->key = $key; + + return $this; + } + + public function getFrom(): string + { + return $this->from; + } + + public function setFrom(string $from): self + { + $this->from = $from; + + return $this; + } + + public function getWhere(): string + { + return $this->where; + } + + public function setWhere(string $where): self + { + $this->where = $where; + + return $this; + } + + public function getParameters(): array + { + return $this->parameters; + } + + public function setParameters(array $parameters): self + { + $this->parameters = $parameters; + + return $this; + } + + public function setDistinct(bool $distinct): self + { + $this->distinct = $distinct; + + return $this; + } + + public function isDistinct(): bool + { + return $this->distinct; + } + + public function buildSql(): string + { + $parameters = []; + + $sql = \strtr( + 'SELECT {distinct} {id} AS id, ' + . '{date} AS "date", ' + . "'{key}' AS type " + . 'FROM {from} ' + . 'WHERE {where}', + [ + '{distinct}' => $this->distinct ? 'DISTINCT' : '', + '{id}' => $this->getId(), + '{date}' => $this->getDate(), + '{key}' => $this->getKey(), + '{from}' => $this->getFrom(), + '{where}' => $this->getWhere(), + ] + ); + + return $sql; + } +}