Passed
Push — master ( b5bf25...b5ca6c )
by Aleksandar
02:13
created

QueryPartBuilder::build()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 34
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 17
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 34
ccs 18
cts 18
cp 1
crap 6
rs 9.0777
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
     * @inheritDoc
34
     */
35 7
    public function build(StructuredQuery $query, QueryBuilderState $state = null): RawQuery
36
    {
37
        /** @var MySqlQueryBuilderState $state */
38
39 7
        if ($state === null) {
40 1
            throw new \Exception('Passed state cannot be null.');
41
        }
42
43 6
        $input = $query->toArray();
44 6
        $results = $this->getInitialParts();
45
46 6
        $requiredParts = $this->getRequiredParts();
47
48 6
        foreach ($this->getPartBuilders() as $partName => $buildPart) {
49 5
            if (empty($input[$partName])) {
50
51 3
                if (in_array($partName, $requiredParts)) {
52 1
                    throw new \Exception("Part '${partName}' is required.");
53
                }
54
55 2
                continue;
56
            }
57
58 5
            $result = $this->buildPart($input[$partName], $buildPart, $state);
59
60 5
            if ($result !== null) {
61 5
                $results[] = $result;
62
            }
63
        }
64
65 5
        return RawQueryResult::create(
66 5
            implode($state->getQueryPartGlue(), $results),
67 5
            $state->getParamsBuilder()->build(),
68 5
            $query->get('config') ?? null
69
        );
70
    }
71
72
    /**
73
     * Return initial parts for the query
74
     *
75
     * @return array
76
     */
77
    protected abstract function getInitialParts(): array;
78
79
    /**
80
     * Return part builders for resolving the query parts to string.
81
     *
82
     * @return array
83
     */
84
    protected abstract function getPartBuilders(): array;
85
86
    /**
87
     * Return parts which must be set in the query in order to be built.
88
     * @return array
89
     */
90
    protected abstract function getRequiredParts(): array;
91
92
    /**
93
     * Build a specific query part.
94
     *
95
     * If the part is a structured query it will be built using a parent query builder.
96
     *
97
     * @param array|StructuredQuery $part Part to be built
98
     * @param callable $buildPart Part builder
99
     * @param MySqlQueryBuilderState $state State to be passed to the builder.
100
     * @return mixed Result of the query.
101
     */
102 5
    protected function buildPart($part, $buildPart, MySqlQueryBuilderState $state)
103
    {
104 5
        if ($part instanceof StructuredQuery) {
105 1
            return $state->getParentBuilder()->build($part, $state)->getQuery();
106
        }
107
108 4
        return $buildPart($part, $state);
109
    }
110
}