Passed
Push — master ( 61ffee...578120 )
by Aleksandr
13:14
created

QueryBuilder::join()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 14
nc 1
nop 1
dl 0
loc 17
ccs 0
cts 16
cp 0
crap 2
rs 9.7998
c 1
b 0
f 0
1
<?php
2
/**
3
 * This file is part of the eav package.
4
 * @author    Aleksandr Drobotik <[email protected]>
5
 * @copyright 2023 Aleksandr Drobotik
6
 * @license   https://opensource.org/license/mit  The MIT License
7
 */
8
declare(strict_types=1);
9
10
namespace Drobotik\Eav\QueryBuilder;
11
12
use Drobotik\Eav\Database\Connection;
13
use Drobotik\Eav\Enum\_ENTITY;
14
use Drobotik\Eav\Enum\_VALUE;
15
use Drobotik\Eav\Enum\QB_CONDITION;
16
use Drobotik\Eav\Enum\QB_JOIN;
17
use Drobotik\Eav\Exception\QueryBuilderException;
18
use Doctrine\DBAL\Query\QueryBuilder as Query;
19
20
21
class QueryBuilder
22
{
23
    private Config $config;
24
    private Query $query;
25
26 1
    public function __construct()
27
    {
28 1
        $this->query = Connection::get()->createQueryBuilder();
29
    }
30
31 1
    public function getQuery(): Query
32
    {
33 1
        return $this->query;
34
    }
35
36
    public function setConfig(Config $config) : void
37
    {
38
        $this->config = $config;
39
    }
40
41
    public function getConfig() : Config
42
    {
43
        return $this->config;
44
    }
45
46 2
    public function startQuery(): void
47
    {
48 2
        $this->query->from(_ENTITY::table(), 'e');
49 2
        $this->query->addSelect('e.'._ENTITY::ID->column());
50 2
        $config = $this->getConfig();
51 2
        foreach($config->getSelected() as $selected) {
52 1
            $this->select($selected);
53
        }
54 2
        foreach ($config->getJoins() as $join) {
55 1
            $this->join($join[QB_JOIN::NAME]);
56
        }
57
    }
58
59 1
    public function endQuery(): void
60
    {
61 1
        $config = $this->getConfig();
62 1
        $query = $this->getQuery();
63 1
        $query->andwhere(sprintf('e.%s = :%s', _ENTITY::DOMAIN_ID->column(), $config->getDomainKeyParam()));
64 1
        $query->andWhere(sprintf('e.%s = :%s', _ENTITY::ATTR_SET_ID->column(), $config->getSetKeyParam()));
65
    }
66
67
68 2
    public function run() : Query
69
    {
70 2
        $this->startQuery();
71 2
        $this->applyExpressions($this->getConfig()->getExpressions(), QB_CONDITION::AND);
72 2
        $this->endQuery();
73 2
        $this->applyParams();
74 2
        return $this->getQuery();
75
    }
76
77
    /**
78
     * @throws QueryBuilderException
79
     */
80 1
    public function applyExpressions(array $expressions, ?QB_CONDITION $condition = null) : void
81
    {
82 1
        $query = $this->getQuery();
83 1
        $expr = $query->expr();
84 1
        $executed = [];
85 1
        foreach ($expressions as $expression) {
86 1
            if ($expression instanceof QB_CONDITION) {
87 1
                $condition = $expression;
88 1
            } else if ($expression instanceof Expression) {
89 1
                $executed[] = $expression->execute();
90 1
            } elseif (is_array($expression)) {
91 1
                $subOperator = $expression[0] ?? throw new QueryBuilderException('must have condition');
92 1
                $ee = array_slice($expression, 1);
93 1
                $this->applyExpressions($ee, $subOperator);
94
            }
95
        }
96
97 1
        if (count($executed) > 0) {
98 1
            if ($condition === QB_CONDITION::AND) {
99 1
                $query->andWhere($expr->and(...$executed));
100 1
            } elseif ($condition === QB_CONDITION::OR) {
101 1
                $query->orWhere($expr->or(...$executed));
102
            }
103
        }
104
    }
105
106 1
    public function applyParams(): void
107
    {
108 1
        $parameters = $this->getConfig()->getParameters();
109 1
        $this->getQuery()->setParameters($parameters);
110
    }
111
112
    public function select(string $name) : Query
113
    {
114
        return $this->getQuery()->addSelect(sprintf('%1$s.%2$s as %1$s', $name, _VALUE::VALUE->column()));
115
    }
116
117
    public function join(string $name): Query
118
    {
119
        $config = $this->getConfig();
120
        [
121
            QB_JOIN::NAME => $name,
122
            QB_JOIN::TABLE => $table,
123
            QB_JOIN::ATTR_PARAM => $paramName
124
        ] = $config->getJoin($name);
125
        return
126
            $this->getQuery()->innerJoin('e', $table, $name,
127
                sprintf('e.%s = %s.%s AND %s.%s = :%s',
128
                    _ENTITY::ID->column(),
129
                    $name,
130
                    _VALUE::ENTITY_ID->column(),
131
                    $name,
132
                    _VALUE::ATTRIBUTE_ID->column(),
133
                    $paramName
134
                )
135
            );
136
    }
137
}