mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-13 13:54:23 +00:00
extend search api to users
This commit is contained in:
parent
6b4e27a531
commit
54c4524b27
@ -22,7 +22,9 @@
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Controller;
|
namespace Chill\MainBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Search\SearchApiNoQueryException;
|
||||||
use Chill\MainBundle\Serializer\Model\Collection;
|
use Chill\MainBundle\Serializer\Model\Collection;
|
||||||
|
use GuzzleHttp\Psr7\Response;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Chill\MainBundle\Search\UnknowSearchDomainException;
|
use Chill\MainBundle\Search\UnknowSearchDomainException;
|
||||||
@ -33,6 +35,7 @@ use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
|||||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Chill\MainBundle\Search\SearchProvider;
|
use Chill\MainBundle\Search\SearchProvider;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||||
use Chill\MainBundle\Search\SearchApi;
|
use Chill\MainBundle\Search\SearchApi;
|
||||||
@ -159,9 +162,13 @@ class SearchController extends AbstractController
|
|||||||
." one type");
|
." one type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
$collection = $this->searchApi->getResults($query, $types, []);
|
$collection = $this->searchApi->getResults($query, $types, []);
|
||||||
|
} catch (SearchApiNoQueryException $e) {
|
||||||
|
throw new BadRequestHttpException($e->getMessage(), $e);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->json($collection);
|
return $this->json($collection, \Symfony\Component\HttpFoundation\Response::HTTP_OK, [], [ "groups" => ["read"]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function advancedSearchListAction(Request $request)
|
public function advancedSearchListAction(Request $request)
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Search\Entity;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Repository\UserRepository;
|
||||||
|
use Chill\MainBundle\Search\SearchApiInterface;
|
||||||
|
use Chill\MainBundle\Search\SearchApiQuery;
|
||||||
|
|
||||||
|
class SearchUserApiProvider implements SearchApiInterface
|
||||||
|
{
|
||||||
|
private UserRepository $userRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param UserRepository $userRepository
|
||||||
|
*/
|
||||||
|
public function __construct(UserRepository $userRepository)
|
||||||
|
{
|
||||||
|
$this->userRepository = $userRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideQuery(string $pattern, array $parameters): SearchApiQuery
|
||||||
|
{
|
||||||
|
$query = new SearchApiQuery();
|
||||||
|
$query
|
||||||
|
->setSelectKey("user")
|
||||||
|
->setSelectJsonbMetadata("jsonb_build_object('id', u.id)")
|
||||||
|
->setSelectPertinence("GREATEST(SIMILARITY(LOWER(UNACCENT(?)), u.usernamecanonical),
|
||||||
|
SIMILARITY(LOWER(UNACCENT(?)), u.emailcanonical))", [ $pattern, $pattern ])
|
||||||
|
->setFromClause("users AS u")
|
||||||
|
->setWhereClause("SIMILARITY(LOWER(UNACCENT(?)), u.usernamecanonical) > 0.15
|
||||||
|
OR
|
||||||
|
SIMILARITY(LOWER(UNACCENT(?)), u.emailcanonical) > 0.15
|
||||||
|
", [ $pattern, $pattern ]);
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsTypes(string $pattern, array $types, array $parameters): bool
|
||||||
|
{
|
||||||
|
return \in_array('user', $types);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepare(array $metadatas): void
|
||||||
|
{
|
||||||
|
$ids = \array_map(fn($m) => $m['id'], $metadatas);
|
||||||
|
|
||||||
|
$this->userRepository->findBy([ 'id' => $ids ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsResult(string $key, array $metadatas): bool
|
||||||
|
{
|
||||||
|
return $key === 'user';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getResult(string $key, array $metadata, float $pertinence)
|
||||||
|
{
|
||||||
|
return $this->userRepository->find($metadata['id']);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Search;
|
namespace Chill\MainBundle\Search;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Search\Entity\SearchUserApiProvider;
|
||||||
use Chill\MainBundle\Serializer\Model\Collection;
|
use Chill\MainBundle\Serializer\Model\Collection;
|
||||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||||
use Chill\PersonBundle\Search\SearchPersonApiProvider;
|
use Chill\PersonBundle\Search\SearchPersonApiProvider;
|
||||||
@ -25,12 +26,14 @@ class SearchApi
|
|||||||
EntityManagerInterface $em,
|
EntityManagerInterface $em,
|
||||||
SearchPersonApiProvider $searchPerson,
|
SearchPersonApiProvider $searchPerson,
|
||||||
ThirdPartyApiSearch $thirdPartyApiSearch,
|
ThirdPartyApiSearch $thirdPartyApiSearch,
|
||||||
|
SearchUserApiProvider $searchUser,
|
||||||
PaginatorFactory $paginator
|
PaginatorFactory $paginator
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
$this->em = $em;
|
$this->em = $em;
|
||||||
$this->providers[] = $searchPerson;
|
$this->providers[] = $searchPerson;
|
||||||
$this->providers[] = $thirdPartyApiSearch;
|
$this->providers[] = $thirdPartyApiSearch;
|
||||||
|
$this->providers[] = $searchUser;
|
||||||
$this->paginator = $paginator;
|
$this->paginator = $paginator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +44,10 @@ class SearchApi
|
|||||||
{
|
{
|
||||||
$queries = $this->findQueries($pattern, $types, $parameters);
|
$queries = $this->findQueries($pattern, $types, $parameters);
|
||||||
|
|
||||||
|
if (0 === count($queries)) {
|
||||||
|
throw new SearchApiNoQueryException($pattern, $types, $parameters);
|
||||||
|
}
|
||||||
|
|
||||||
$total = $this->countItems($queries, $types, $parameters);
|
$total = $this->countItems($queries, $types, $parameters);
|
||||||
$paginator = $this->paginator->create($total);
|
$paginator = $this->paginator->create($total);
|
||||||
|
|
||||||
@ -49,9 +56,7 @@ class SearchApi
|
|||||||
$this->prepareProviders($rawResults);
|
$this->prepareProviders($rawResults);
|
||||||
$results = $this->buildResults($rawResults);
|
$results = $this->buildResults($rawResults);
|
||||||
|
|
||||||
$collection = new Collection($results, $paginator);
|
return new Collection($results, $paginator);
|
||||||
|
|
||||||
return $collection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function findQueries($pattern, array $types, array $parameters): array
|
private function findQueries($pattern, array $types, array $parameters): array
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Search;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class SearchApiNoQueryException extends \RuntimeException
|
||||||
|
{
|
||||||
|
private string $pattern;
|
||||||
|
private array $types;
|
||||||
|
private array $parameters;
|
||||||
|
|
||||||
|
public function __construct(string $pattern = "", array $types = [], array $parameters = [], $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$typesStr = \implode(", ", $types);
|
||||||
|
$message = "No query for this search: pattern : {$pattern}, types: {$typesStr}";
|
||||||
|
$this->pattern = $pattern;
|
||||||
|
$this->types = $types;
|
||||||
|
$this->parameters = $parameters;
|
||||||
|
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
@ -127,8 +127,6 @@ paths:
|
|||||||
- person
|
- person
|
||||||
- thirdparty
|
- thirdparty
|
||||||
description: >
|
description: >
|
||||||
**Warning**: This is currently a stub (not really implemented
|
|
||||||
|
|
||||||
The search is performed across multiple entities. The entities must be listed into
|
The search is performed across multiple entities. The entities must be listed into
|
||||||
`type` parameters.
|
`type` parameters.
|
||||||
|
|
||||||
@ -152,6 +150,7 @@ paths:
|
|||||||
enum:
|
enum:
|
||||||
- person
|
- person
|
||||||
- thirdparty
|
- thirdparty
|
||||||
|
- user
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: "OK"
|
description: "OK"
|
||||||
|
@ -7,3 +7,8 @@ services:
|
|||||||
Chill\MainBundle\Search\SearchApi:
|
Chill\MainBundle\Search\SearchApi:
|
||||||
autowire: true
|
autowire: true
|
||||||
autoconfigure: true
|
autoconfigure: true
|
||||||
|
|
||||||
|
Chill\MainBundle\Search\Entity\:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
resource: '../../Search/Entity'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user