Passed
Push — master ( 9408b8...4497e7 )
by Aleksandar
02:07
created

QueryPartBuilder::buildQueryParts()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 11
c 1
b 0
f 0
nc 5
nop 2
dl 0
loc 23
ccs 12
cts 12
cp 1
crap 5
rs 9.6111
1
<?php
2
/**
3
 * Copyright 2021 Aleksandar Panic
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
namespace ArekX\PQL\Drivers\MySql\Builder\Builders;
19
20
use ArekX\PQL\Contracts\QueryBuilder;
21
use ArekX\PQL\Contracts\QueryBuilderState;
22
use ArekX\PQL\Contracts\RawQuery;
23
use ArekX\PQL\Contracts\StructuredQuery;
24
use ArekX\PQL\Drivers\MySql\Builder\MySqlQueryBuilderState;
25
use ArekX\PQL\RawQueryResult;
26
27
/**
28
 * Represents a base builder for query parts.
29
 */
30
abstract class QueryPartBuilder implements QueryBuilder
31
{
32
    /**
33
     * Build a specific query part.
34
     *
35
     * If the part is a structured query it will be built using a parent query builder.
36
     *
37
     * @param array|StructuredQuery $part Part to be built
38
     * @param callable $buildPart Part builder
39
     * @param MySqlQueryBuilderState $state State to be passed to the builder.
40
     * @return mixed Result of the query.
41
     */
42 5
    protected function buildPart($part, $buildPart, MySqlQueryBuilderState $state)
43
    {
44 5
        if ($part instanceof StructuredQuery) {
45 1
            return $state->getParentBuilder()->build($part, $state)->getQuery();
46
        }
47
48 4
        return $buildPart($part, $state);
49
    }
50
51
    /**
52
     * @inheritDoc
53
     */
54 7
    public function build(StructuredQuery $query, QueryBuilderState $state = null): RawQuery
55
    {
56
        /** @var MySqlQueryBuilderState $state */
57
58 7
        if ($state === null) {
59 1
            throw new \Exception('Passed state cannot be null.');
60
        }
61
62 6
        $input = $query->toArray();
63 6
        $results = implode($state->getQueryPartGlue(), $this->buildQueryParts($input, $state));
64
65 5
        return RawQueryResult::create(
66 5
            $results,
67 5
            $state->getParamsBuilder()->build(),
68 5
            $query->get('config') ?? null
69
        );
70
    }
71
72
    /**
73
     * Build each part from the structured query
74
     *
75
     * @param array $parts Parts from the structured query
76
     * @param MySqlQueryBuilderState $state Builder state
77
     * @return array Resulting array for each built part.
78
     * @throws \Exception
79
     */
80 6
    protected function buildQueryParts(array $parts, MySqlQueryBuilderState $state): array
81
    {
82 6
        $results = $this->getInitialParts();
83 6
        $requiredParts = $this->getRequiredParts();
84
85 6
        foreach ($this->getPartBuilders() as $partName => $buildPart) {
86 5
            if (empty($parts[$partName])) {
87
88 3
                if (in_array($partName, $requiredParts)) {
89 1
                    throw new \Exception("Part '${partName}' is required.");
90
                }
91
92 2
                continue;
93
            }
94
95 5
            $result = $this->buildPart($parts[$partName], $buildPart, $state);
96
97 5
            if ($result !== null) {
98 5
                $results[] = $result;
99
            }
100
        }
101
102 5
        return $results;
103
    }
104
105
    /**
106
     * Return initial parts for the query
107
     *
108
     * @return array
109
     */
110
    protected abstract function getInitialParts(): array;
111
112
    /**
113
     * Return parts which must be set in the query in order to be built.
114
     * @return array
115
     */
116
    protected abstract function getRequiredParts(): array;
117
118
    /**
119
     * Return part builders for resolving the query parts to string.
120
     *
121
     * @return array
122
     */
123
    protected abstract function getPartBuilders(): array;
124
}