|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- <?php
-
- namespace Lc\SovBundle\Repository;
-
- use Doctrine\ORM\EntityManagerInterface;
- use Doctrine\ORM\QueryBuilder;
- use Doctrine\Persistence\ManagerRegistry;
- use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
- use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
- use EasyCorp\Bundle\EasyAdminBundle\Contracts\Orm\EntityRepositoryInterface;
- use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
- use EasyCorp\Bundle\EasyAdminBundle\Dto\FilterDataDto;
- use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
- use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory;
- use EasyCorp\Bundle\EasyAdminBundle\Factory\FormFactory;
- use EasyCorp\Bundle\EasyAdminBundle\Form\Type\ComparisonType;
- use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
- use EasyCorp\Bundle\EasyAdminBundle\Orm\EntityRepository as EaEntityRepository;
- use Knp\Component\Pager\PaginatorInterface;
- use function Symfony\Component\Translation\t;
-
- class EntityRepository
- {
-
- //protected EaEntityRepository $parent;
- protected EntityManagerInterface $entityManager;
- protected PaginatorInterface $paginator;
-
- public function __construct(
- //EaEntityRepository $entityRepository,
- EntityManagerInterface $entityManager,
- PaginatorInterface $paginator
- ) {
- //$this->parent = $entityRepository;
- $this->entityManager = $entityManager;
- $this->paginator = $paginator;
-
- }
- public function createRepositoryQuery(RepositoryQueryInterface $repositoryQuery,SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters)
- {
- // if (!empty($searchDto->getQuery())) {
- // $this->addSearchClause($repositoryQuery->getQuery(), $searchDto, $entityDto);
- // }
- //
- // if (!empty($searchDto->getAppliedFilters())) {
- // $this->addFilterClause($repositoryQuery->getQuery(), $searchDto, $entityDto, $filters, $fields);
- // }
-
- $this->addOrderClause($repositoryQuery, $searchDto, $entityDto);
- return $repositoryQuery;
- }
-
- private function addSearchClause(QueryBuilder $queryBuilder, SearchDto $searchDto, EntityDto $entityDto): void
- {
- $query = $searchDto->getQuery();
- $lowercaseQuery = mb_strtolower($query);
- $isNumericQuery = is_numeric($query);
- $isSmallIntegerQuery = ctype_digit($query) && $query >= -32768 && $query <= 32767;
- $isIntegerQuery = ctype_digit($query) && $query >= -2147483648 && $query <= 2147483647;
- $isUuidQuery = 1 === preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $query);
-
- $dqlParameters = [
- // adding '0' turns the string into a numeric value
- 'numeric_query' => is_numeric($query) ? 0 + $query : $query,
- 'uuid_query' => $query,
- 'text_query' => '%'.$lowercaseQuery.'%',
- 'words_query' => explode(' ', $lowercaseQuery),
- ];
-
- $entitiesAlreadyJoined = [];
- $configuredSearchableProperties = $searchDto->getSearchableProperties();
- $searchableProperties = empty($configuredSearchableProperties) ? $entityDto->getAllPropertyNames() : $configuredSearchableProperties;
- foreach ($searchableProperties as $propertyName) {
- if ($entityDto->isAssociation($propertyName)) {
- // support arbitrarily nested associations (e.g. foo.bar.baz.qux)
- $associatedProperties = explode('.', $propertyName);
- $numAssociatedProperties = \count($associatedProperties);
-
- if (1 === $numAssociatedProperties) {
- throw new \InvalidArgumentException(sprintf('The "%s" property included in the setSearchFields() method is not a valid search field. When using associated properties in search, you must also define the exact field used in the search (e.g. \'%s.id\', \'%s.name\', etc.)', $propertyName, $propertyName, $propertyName));
- }
-
- $originalPropertyName = $associatedProperties[0];
- $originalPropertyMetadata = $entityDto->getPropertyMetadata($originalPropertyName);
- $associatedEntityDto = $this->entityFactory->create($originalPropertyMetadata->get('targetEntity'));
-
- for ($i = 0; $i < $numAssociatedProperties - 1; ++$i) {
- $associatedEntityName = $associatedProperties[$i];
- $associatedPropertyName = $associatedProperties[$i + 1];
-
- if (!\in_array($associatedEntityName, $entitiesAlreadyJoined, true)) {
- $parentEntityName = 0 === $i ? 'entity' : $associatedProperties[$i - 1];
- $queryBuilder->leftJoin($parentEntityName.'.'.$associatedEntityName, $associatedEntityName);
- $entitiesAlreadyJoined[] = $associatedEntityName;
- }
-
- if ($i < $numAssociatedProperties - 2) {
- $propertyMetadata = $associatedEntityDto->getPropertyMetadata($associatedPropertyName);
- $targetEntity = $propertyMetadata->get('targetEntity');
- $associatedEntityDto = $this->entityFactory->create($targetEntity);
- }
- }
-
- $entityName = $associatedEntityName;
- $propertyName = $associatedPropertyName;
- $propertyDataType = $associatedEntityDto->getPropertyDataType($propertyName);
- } else {
- $entityName = 'entity';
- $propertyDataType = $entityDto->getPropertyDataType($propertyName);
- }
-
- $isSmallIntegerProperty = 'smallint' === $propertyDataType;
- $isIntegerProperty = 'integer' === $propertyDataType;
- $isNumericProperty = \in_array($propertyDataType, ['number', 'bigint', 'decimal', 'float']);
- // 'citext' is a PostgreSQL extension (https://github.com/EasyCorp/EasyAdminBundle/issues/2556)
- $isTextProperty = \in_array($propertyDataType, ['string', 'text', 'citext', 'array', 'simple_array']);
- $isGuidProperty = \in_array($propertyDataType, ['guid', 'uuid']);
-
- // this complex condition is needed to avoid issues on PostgreSQL databases
- if (
- ($isSmallIntegerProperty && $isSmallIntegerQuery) ||
- ($isIntegerProperty && $isIntegerQuery) ||
- ($isNumericProperty && $isNumericQuery)
- ) {
- $queryBuilder->orWhere(sprintf('%s.%s = :query_for_numbers', $entityName, $propertyName))
- ->setParameter('query_for_numbers', $dqlParameters['numeric_query']);
- } elseif ($isGuidProperty && $isUuidQuery) {
- $queryBuilder->orWhere(sprintf('%s.%s = :query_for_uuids', $entityName, $propertyName))
- ->setParameter('query_for_uuids', $dqlParameters['uuid_query']);
- } elseif ($isTextProperty) {
- $queryBuilder->orWhere(sprintf('LOWER(%s.%s) LIKE :query_for_text', $entityName, $propertyName))
- ->setParameter('query_for_text', $dqlParameters['text_query']);
- $queryBuilder->orWhere(sprintf('LOWER(%s.%s) IN (:query_as_words)', $entityName, $propertyName))
- ->setParameter('query_as_words', $dqlParameters['words_query']);
- }
- }
- }
-
- private function addOrderClause(RepositoryQueryInterface $repositoryQuery, SearchDto $searchDto, EntityDto $entityDto): void
- {
- foreach ($searchDto->getSort() as $sortProperty => $sortOrder) {
-
- $repositoryQuery->addOrderBy('.'.$sortProperty, $sortOrder);
-
- // $aliases = $queryBuilder->getAllAliases();
- // $sortFieldIsDoctrineAssociation = $entityDto->isAssociation($sortProperty);
- //
- // if ($sortFieldIsDoctrineAssociation) {
- // $sortFieldParts = explode('.', $sortProperty, 2);
- // // check if join has been added once before.
- // if (!\in_array($sortFieldParts[0], $aliases)) {
- // $queryBuilder->leftJoin('entity.'.$sortFieldParts[0], $sortFieldParts[0]);
- // }
- //
- // if (1 === \count($sortFieldParts)) {
- // $queryBuilder->addOrderBy('entity.'.$sortProperty, $sortOrder);
- // } else {
- // $queryBuilder->addOrderBy($sortProperty, $sortOrder);
- // }
- // } else {
- // $queryBuilder->addOrderBy('entity.'.$sortProperty, $sortOrder);
- // }
- }
- }
-
- private function addFilterClause(QueryBuilder $queryBuilder, SearchDto $searchDto, EntityDto $entityDto, FilterCollection $configuredFilters, FieldCollection $fields): void
- {
- $filtersForm = $this->formFactory->createFiltersForm($configuredFilters, $this->adminContextProvider->getContext()->getRequest());
- if (!$filtersForm->isSubmitted()) {
- return;
- }
-
- $appliedFilters = $searchDto->getAppliedFilters();
- $i = 0;
- foreach ($filtersForm as $filterForm) {
- $propertyName = $filterForm->getName();
-
- $filter = $configuredFilters->get($propertyName);
- // this filter is not defined or not applied
- if (null === $filter || !isset($appliedFilters[$propertyName])) {
- continue;
- }
-
- // if the form filter is not valid then we should not apply the filter
- if (!$filterForm->isValid()) {
- continue;
- }
-
- $submittedData = $filterForm->getData();
- if (!\is_array($submittedData)) {
- $submittedData = [
- 'comparison' => ComparisonType::EQ,
- 'value' => $submittedData,
- ];
- }
-
- $filterDataDto = FilterDataDto::new($i, $filter, current($queryBuilder->getRootAliases()), $submittedData);
- $filter->apply($queryBuilder, $filterDataDto, $fields->getByProperty($propertyName), $entityDto);
-
- ++$i;
- }
- }
-
-
-
- }
|