Passed
Pull Request — master (#8)
by Alex
17:31
created

AbstractComposite::createNewQueryBuilder()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 10
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arp\DoctrineQueryFilter\Filter;
6
7
use Arp\DoctrineQueryFilter\Enum\WhereType;
8
use Arp\DoctrineQueryFilter\Exception\QueryFilterManagerException;
9
use Arp\DoctrineQueryFilter\Filter\Exception\FilterException;
10
use Arp\DoctrineQueryFilter\Metadata\MetadataInterface;
11
use Arp\DoctrineQueryFilter\QueryBuilderInterface;
12
use Doctrine\ORM\Query\Expr\Composite;
13
14
/**
15
 * @author  Alex Patterson <[email protected]>
16
 * @package Arp\DoctrineQueryFilter\Filter
17
 */
18
abstract class AbstractComposite extends AbstractFilter
19
{
20
    /**
21
     * @param QueryBuilderInterface $queryBuilder
22
     *
23
     * @return Composite
24
     */
25
    abstract protected function createComposite(QueryBuilderInterface $queryBuilder): Composite;
26
27
    /**
28
     * @param QueryBuilderInterface $queryBuilder
29
     * @param MetadataInterface     $metadata
30
     * @param array<mixed>          $criteria
31
     *
32
     * @throws FilterException
33
     */
34
    public function filter(QueryBuilderInterface $queryBuilder, MetadataInterface $metadata, array $criteria): void
35
    {
36
        if (empty($criteria['conditions'])) {
37
            return;
38
        }
39
        $qb = $this->createNewQueryBuilder($queryBuilder);
40
        $this->applyConditions($qb, $metadata, $criteria['conditions']);
41
42
        $parts = $qb->getQueryParts();
43
        if (
44
            !isset($parts['where'])
45
            || (!$parts['where'] instanceof Composite)
46
            || (!method_exists($parts['where'], 'getParts'))
47
        ) {
48
            return;
49
        }
50
51
        $compositeExpr = $this->createComposite($queryBuilder);
52
        $compositeExpr->addMultiple($parts['where']->getParts());
53
54
        if (!isset($criteria['where']) || WhereType::AND === $criteria['where']) {
55
            $queryBuilder->andWhere($compositeExpr);
56
        } else {
57
            $queryBuilder->orWhere($compositeExpr);
58
        }
59
60
        $queryBuilder->mergeParameters($qb);
61
    }
62
63
    protected function createNewQueryBuilder(QueryBuilderInterface $queryBuilder): QueryBuilderInterface
64
    {
65
        $qb = $queryBuilder->createQueryBuilder();
66
67
        $alias = $queryBuilder->getRootAlias();
68
        if (!empty($alias)) {
69
            $qb->setRootAlias($alias);
70
        }
71
72
        return $qb;
73
    }
74
75
    /**
76
     * @param QueryBuilderInterface        $qb
77
     * @param MetadataInterface            $metadata
78
     * @param iterable<mixed>|array<mixed> $conditions
79
     *
80
     * @throws FilterException
81
     */
82
    private function applyConditions(QueryBuilderInterface $qb, MetadataInterface $metadata, $conditions): void
83
    {
84
        try {
85
            $this->queryFilterManager->filter($qb, $metadata->getName(), ['filters' => $conditions]);
86
        } catch (QueryFilterManagerException $e) {
87
            throw new FilterException(
88
                sprintf('Failed to construct query filter \'%s\' conditions: %s', static::class, $e->getMessage()),
89
                $e->getCode(),
90
                $e
91
            );
92
        }
93
    }
94
}
95