Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
Join
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
8 / 8
10
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 create
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 empty
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 parse
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 buildJoinString
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 buildCustomJoinString
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 joinString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Projom\Storage\SQL\Component;
6
7use Projom\Storage\SQL\Component\ComponentInterface;
8use Projom\Storage\SQL\Util;
9use Projom\Storage\SQL\Util\Join as SQLJoin;
10
11class Join implements ComponentInterface
12{
13    private readonly string $joined;
14
15    public function __construct(array $joins)
16    {
17        $this->parse($joins);
18    }
19
20    public static function create(array $joins): Join
21    {
22        return new Join($joins);
23    }
24
25    public function __toString(): string
26    {
27        return $this->joined;
28    }
29
30    public function empty()
31    {
32        return empty($this->joined);
33    }
34
35    private function parse(array $joins): void
36    {
37        $joinStrings = [];
38        foreach ($joins as [$currentCollectionWithField, $join, $onCollectionWithField])
39            $joinStrings[] = $this->buildJoinString($currentCollectionWithField, $join, $onCollectionWithField);
40
41        $this->joined = Util::join($joinStrings, ' ');
42    }
43
44    private function buildJoinString(
45        string $currentCollectionWithField,
46        SQLJoin $join,
47        null|string $onCollectionWithField
48    ): string {
49
50        if ($onCollectionWithField === null)
51            return $this->buildCustomJoinString($currentCollectionWithField, $join);
52
53        $currentCollectionWithField = Util::splitThenQuoteAndJoin($currentCollectionWithField, '.');
54        $onCollectionWithField = Util::splitThenQuoteAndJoin($onCollectionWithField, '.');
55
56        [$onCollection, $onCollectionField] = Util::split($onCollectionWithField, '.');
57
58        $joinString = $this->joinString($join->value, $onCollection, $currentCollectionWithField, $onCollectionWithField);
59
60        return $joinString;
61    }
62
63    /**
64     * * Format: $join->buildCustomString('UserRole.UserID = User.UserID', QueryJoin::INNER)
65     */
66    private function buildCustomJoinString(string $customString, SQLJoin $join): string
67    {
68        $stringParts = Util::split($customString, '=');
69
70        $firstParts = Util::split(array_shift($stringParts), '.');
71        $secondParts = Util::split(array_shift($stringParts), '.');
72
73        $onCollection = Util::quote($secondParts[0]);
74        $onCollectionWithValue = Util::quoteAndJoin($secondParts, '.');
75
76        $currentCollectionWithValue = Util::quoteAndJoin($firstParts, '.');
77
78        $joinString = $this->joinString($join->value, $onCollection, $currentCollectionWithValue, $onCollectionWithValue);
79
80        return $joinString;
81    }
82
83    private function joinString(
84        string $join,
85        string $onCollection,
86        string $currentCollection,
87        string $on,
88    ): string {
89
90        return "{$join} {$onCollection} ON {$currentCollection} = {$on}";
91    }
92}