mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Add shortcut person <-> current address, and update api for
re-implements searching * add geographic function ST_CONTAINS * add a link between the current valid address and person, optimized on database side; * update PersonACLAwareRepository for re-using methods elsewhere.
This commit is contained in:
parent
50b7554aea
commit
ebb2f5d243
@ -19,6 +19,7 @@
|
||||
|
||||
namespace Chill\MainBundle\DependencyInjection;
|
||||
|
||||
use Chill\MainBundle\Doctrine\DQL\STContains;
|
||||
use Chill\MainBundle\Doctrine\DQL\StrictWordSimilarityOPS;
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\MainBundle\Form\UserJobType;
|
||||
@ -186,7 +187,8 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
|
||||
'JSONB_EXISTS_IN_ARRAY' => JsonbExistsInArray::class,
|
||||
'SIMILARITY' => Similarity::class,
|
||||
'OVERLAPSI' => OverlapsI::class,
|
||||
'STRICT_WORD_SIMILARITY_OPS' => StrictWordSimilarityOPS::class
|
||||
'STRICT_WORD_SIMILARITY_OPS' => StrictWordSimilarityOPS::class,
|
||||
'ST_CONTAINS' => STContains::class,
|
||||
],
|
||||
],
|
||||
'hydrators' => [
|
||||
|
52
src/Bundle/ChillMainBundle/Doctrine/DQL/STContains.php
Normal file
52
src/Bundle/ChillMainBundle/Doctrine/DQL/STContains.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
* Copyright (C) 2018 Champs-Libres Coopérative <info@champs-libres.coop>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
namespace Chill\MainBundle\Doctrine\DQL;
|
||||
|
||||
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
|
||||
use Doctrine\ORM\Query\Lexer;
|
||||
|
||||
/**
|
||||
* Geometry function 'ST_CONTAINS', added by postgis
|
||||
*/
|
||||
class STContains extends FunctionNode
|
||||
{
|
||||
private $firstPart;
|
||||
|
||||
private $secondPart;
|
||||
|
||||
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
|
||||
{
|
||||
return 'ST_CONTAINS('.$this->firstPart->dispatch($sqlWalker).
|
||||
', ' . $this->secondPart->dispatch($sqlWalker) .")";
|
||||
}
|
||||
|
||||
public function parse(\Doctrine\ORM\Query\Parser $parser)
|
||||
{
|
||||
$parser->match(Lexer::T_IDENTIFIER);
|
||||
$parser->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
|
||||
$this->firstPart = $parser->StringPrimary();
|
||||
|
||||
$parser->match(Lexer::T_COMMA);
|
||||
|
||||
$this->secondPart = $parser->StringPrimary();
|
||||
|
||||
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
}
|
||||
}
|
@ -419,6 +419,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
* This is computed through database and is optimized on database side.
|
||||
*
|
||||
* @var PersonCurrentAddress|null
|
||||
* @ORM\OneToOne(targetEntity=PersonCurrentAddress::class, mappedBy="person")
|
||||
*/
|
||||
private ?PersonCurrentAddress $currentPersonAddress = null;
|
||||
|
||||
|
@ -22,7 +22,8 @@ class PersonCurrentAddress
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\OneToOne(targetEntity=Person::class)
|
||||
* @ORM\OneToOne(targetEntity=Person::class, inversedBy="currentPersonAddress")
|
||||
* @ORM\JoinColumn(name="person_id", referencedColumnName="id")
|
||||
*/
|
||||
protected Person $person;
|
||||
|
||||
|
@ -60,17 +60,32 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
||||
$countryCode);
|
||||
$this->addACLClauses($qb, 'p');
|
||||
|
||||
return $this->getQueryResult($qb, $simplify, $limit, $start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to prepare and return the search query for PersonACL.
|
||||
*
|
||||
* This method replace the select clause with required parameters, depending on the
|
||||
* "simplify" parameter. It also add query limits.
|
||||
*
|
||||
* The given alias must represent the person alias.
|
||||
*
|
||||
* @return array|Person[]
|
||||
*/
|
||||
public function getQueryResult(QueryBuilder $qb, string $alias, bool $simplify, int $limit, int $start): array
|
||||
{
|
||||
if ($simplify) {
|
||||
$qb->select(
|
||||
'p.id',
|
||||
$alias.'.id',
|
||||
$qb->expr()->concat(
|
||||
'p.firstName',
|
||||
$alias.'.firstName',
|
||||
$qb->expr()->literal(' '),
|
||||
'p.lastName'
|
||||
$alias.'.lastName'
|
||||
).'AS text'
|
||||
);
|
||||
} else {
|
||||
$qb->select('p');
|
||||
$qb->select($alias);
|
||||
}
|
||||
|
||||
$qb
|
||||
@ -79,8 +94,8 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
||||
|
||||
//order by firstname, lastname
|
||||
$qb
|
||||
->orderBy('p.firstName')
|
||||
->addOrderBy('p.lastName');
|
||||
->orderBy($alias.'.firstName')
|
||||
->addOrderBy($alias.'.lastName');
|
||||
|
||||
if ($simplify) {
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_ARRAY);
|
||||
@ -104,7 +119,20 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
||||
$countryCode);
|
||||
$this->addACLClauses($qb, 'p');
|
||||
|
||||
$qb->select('COUNT(p.id)');
|
||||
return $this->getCountQueryResult($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to prepare and return the count for search query
|
||||
*
|
||||
* This method replace the select clause with required parameters, depending on the
|
||||
* "simplify" parameter.
|
||||
*
|
||||
* The given alias must represent the person alias in the query builder.
|
||||
*/
|
||||
public function getCountQueryResult(QueryBuilder $qb, $alias): int
|
||||
{
|
||||
$qb->select('COUNT('.$alias.'.id)');
|
||||
|
||||
return $qb->getQuery()->getSingleScalarResult();
|
||||
}
|
||||
@ -115,33 +143,7 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
||||
$qb = $this->createSimilarityQuery($pattern);
|
||||
$this->addACLClauses($qb, 'sp');
|
||||
|
||||
if ($simplify) {
|
||||
$qb->select(
|
||||
'sp.id',
|
||||
$qb->expr()->concat(
|
||||
'sp.firstName',
|
||||
$qb->expr()->literal(' '),
|
||||
'sp.lastName'
|
||||
).'AS text'
|
||||
);
|
||||
} else {
|
||||
$qb->select('sp');
|
||||
}
|
||||
|
||||
$qb
|
||||
->setMaxResults($maxResult)
|
||||
->setFirstResult($firstResult);
|
||||
|
||||
//order by firstname, lastname
|
||||
$qb
|
||||
->orderBy('sp.firstName')
|
||||
->addOrderBy('sp.lastName');
|
||||
|
||||
if ($simplify) {
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_ARRAY);
|
||||
} else {
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
return $this->getQueryResult($qb, 'sp', $simplify, $maxResult, $firstResult);
|
||||
}
|
||||
|
||||
public function countBySimilaritySearch(string $pattern)
|
||||
@ -149,12 +151,27 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
||||
$qb = $this->createSimilarityQuery($pattern);
|
||||
$this->addACLClauses($qb, 'sp');
|
||||
|
||||
$qb->select('COUNT(sp.id)');
|
||||
|
||||
return $qb->getQuery()->getSingleScalarResult();
|
||||
return $this->getCountQueryResult($qb, 'sp');
|
||||
}
|
||||
|
||||
private function createSearchQuery(
|
||||
/**
|
||||
* Create a search query without ACL
|
||||
*
|
||||
* The person alias is a "p"
|
||||
*
|
||||
* @param string|null $default
|
||||
* @param string|null $firstname
|
||||
* @param string|null $lastname
|
||||
* @param \DateTime|null $birthdate
|
||||
* @param \DateTime|null $birthdateBefore
|
||||
* @param \DateTime|null $birthdateAfter
|
||||
* @param string|null $gender
|
||||
* @param string|null $countryCode
|
||||
* @return QueryBuilder
|
||||
* @throws NonUniqueResultException
|
||||
* @throws ParsingException
|
||||
*/
|
||||
public function createSearchQuery(
|
||||
string $default = null,
|
||||
string $firstname = null,
|
||||
string $lastname = null,
|
||||
@ -244,7 +261,15 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
||||
$qb->setParameter('centers', $reachableCenters);
|
||||
}
|
||||
|
||||
private function createSimilarityQuery($pattern): QueryBuilder
|
||||
/**
|
||||
* Create a query for searching by similarity.
|
||||
*
|
||||
* The person alias is "sp".
|
||||
*
|
||||
* @param $pattern
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function createSimilarityQuery($pattern): QueryBuilder
|
||||
{
|
||||
$qb = $this->em->createQueryBuilder();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user