Completed
Push — master ( d10bcc...5ab9f6 )
by Hong
02:33
created

JoinTrait::realJoin()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.2
c 0
b 0
f 0
cc 4
eloc 15
nc 4
nop 5
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Query
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Query\Traits\Clause;
16
17
use Phossa2\Query\Interfaces\ExpressionInterface;
18
use Phossa2\Query\Interfaces\Clause\JoinInterface;
19
20
/**
21
 * JoinTrait
22
 *
23
 * Implementation of JoinInterface
24
 *
25
 * @package Phossa2\Query
26
 * @author  Hong Zhang <[email protected]>
27
 * @see     JoinInterface
28
 * @version 2.0.0
29
 * @since   2.0.0 added
30
 */
31
trait JoinTrait
32
{
33
    /**
34
     * {@inheritDoc}
35
     */
36
    public function join($secondTable, $onClause = '', $firstTable = '')
37
    {
38
        return $this->realJoin('INNER JOIN', $secondTable, $onClause, $firstTable);
39
    }
40
41
    /**
42
     * {@inheritDoc}
43
     */
44
    public function leftJoin($secondTable, $onClause = '', $firstTable = '')
45
    {
46
        return $this->realJoin('LEFT JOIN', $secondTable, $onClause, $firstTable);
47
    }
48
49
    /**
50
     * {@inheritDoc}
51
     */
52
    public function joinRaw(/*# string */ $joinType, /*# string */ $rawString)
53
    {
54
        return $this->realJoin($joinType, $rawString, '', '', true);
55
    }
56
57
    /**
58
     * The real join
59
     *
60
     * @param  string $joinType
61
     * @param  string|string[]|SelectStatementInterface $secondTable
62
     * @param  string|string[]|ExpressionInterface $onClause
63
     * @param  string $firstTable
64
     * @param  bool $rawMode
65
     * @return $this
66
     * @access protected
67
     */
68
    protected function realJoin(
69
        /*# string */ $joinType,
70
        $secondTable,
71
        $onClause = '',
72
        $firstTable = '',
73
        /*# bool */ $rawMode = false
74
    ) {
75
        $alias = 0; // no alias
76
        if ($rawMode || '' === $onClause) { // raw mode
77
            $rawMode = true;
78
        }
79
        if (!$rawMode) { // fix table/alias/on
80
            $onClause = $this->fixOnClause($onClause);
81
            list($secondTable, $alias) = $this->fixJoinTable($secondTable);
82
        }
83
        $clause = &$this->getClause('JOIN');
84
        $clause[] = [$rawMode, $joinType, $secondTable, $alias, $onClause, $firstTable];
85
        return $this;
86
    }
87
88
    /**
89
     * Fix join table
90
     *
91
     * @param  string|string[]|SelectStatementInterface $table
92
     * @return array [table, alias]
93
     * @access protected
94
     */
95
    protected function fixJoinTable($table)
96
    {
97
        if (is_object($table)) {
98
            return [$table, uniqid()]; // need an alias
99
        } elseif (is_string($table)) {
100
            return [$table, 0]; // alias set 0
101
        } else {
102
            return $table; // array
103
        }
104
    }
105
106
    /**
107
     * Fix 'ON' clause
108
     *
109
     * @param  mixed $onClause
110
     * @return array|ExpressionInterface
111
     * @access protected
112
     */
113
    protected function fixOnClause($onClause)
114
    {
115
        if (is_string($onClause)) {
116
            return [$onClause, '=', $onClause];
117
        } elseif (is_array($onClause) && !isset($onClause[2])) {
118
            return [$onClause[0], '=', $onClause[1]];
119
        } else {
120
            return $onClause;
121
        }
122
    }
123
124
    /**
125
     * Build join
126
     *
127
     * @param  string $prefix
128
     * @param  array $settings
129
     * @return string
130
     * @access protected
131
     */
132
    protected function buildJoin(
133
        /*# string */ $prefix,
134
        array $settings
135
    )/*# : string */ {
136
        $string = '';
137
        $clause = &$this->getClause('JOIN');
138
        foreach ($clause as $cls) {
139
            $result = [];
140
            $prefix = $cls[1]; // join type
141
            if ($cls[0]) { // raw mode
142
                $result[] = $cls[2];
143
            } else {
144
                $result[] = $this->buildJoinTable($cls, $settings);
145
                $result[] = $this->buildJoinOn($cls, $settings);
146
            }
147
            $string .= $this->joinClause($prefix, '', $result, $settings);
148
        }
149
        return $string;
150
    }
151
152
    /**
153
     * Build TABLE part
154
     *
155
     * @param  array $cls
156
     * @param  array $settings
157
     * @return string
158
     * @access protected
159
     */
160
    protected function buildJoinTable(array $cls, array $settings)/*# : string */
161
    {
162
        $table = $cls[2];
163
        $alias = $cls[3];
164
        return $this->quoteItem($table, $settings) . $this->quoteAlias($alias, $settings);
165
    }
166
167
    /**
168
     * Build ON part
169
     *
170
     * @param  array $cls
171
     * @param  array $settings
172
     * @return string
173
     * @access protected
174
     */
175
    protected function buildJoinOn(array $cls, array $settings)/*# : string */
176
    {
177
        $on = $cls[4];
178
        $res = ['ON'];
179
180
        if (is_object($on)) {
181
            $res[] = $on->getStatement($settings);
182
        } else {
183
            // first
184
            $res[] = $this->quote($this->getFirstTableAlias($cls) . $on[0], $settings);
185
            // operator
186
            $res[] = $on[1];
187
            // second
188
            $res[] = $this->quote($this->getSecondTableAlias($cls) . $on[2], $settings);
189
        }
190
        return join(' ', $res);
191
    }
192
193
    /**
194
     * Get first table alias
195
     *
196
     * @param  array $cls
197
     * @return string
198
     * @access protected
199
     */
200
    protected function getFirstTableAlias(array $cls)/*# : string */
201
    {
202
        // first table specified
203
        if (!empty($cls[5])) {
204
            return $cls[5] . '.';
205
        } else {
206
            $tables = &$this->getClause('FROM');
207
            reset($tables);
208
            $alias = key($tables);
209
            return (is_int($alias) ? $tables[$alias][0] : $alias) . '.';
210
        }
211
    }
212
213
    /**
214
     * Get second table alias
215
     *
216
     * @param  array $cls
217
     * @return string
218
     * @access protected
219
     */
220
    protected function getSecondTableAlias(array $cls)/*# : string */
221
    {
222
        $alias = $cls[3];
223
        if (!is_string($alias)) {
224
            $alias = $cls[2];
225
        }
226
        return $alias . '.';
227
    }
228
229
    abstract protected function quote(/*# string */ $str, array $settings)/*# : string */;
230
    abstract protected function isRaw($str, /*# bool */ $rawMode)/*# : bool */;
231
    abstract protected function &getClause(/*# string */ $clauseName)/*# : array */;
232
    abstract protected function flatSettings(array $settings)/*# : array */;
233
    abstract protected function quoteItem(
234
        $item,
235
        array $settings,
236
        /*# bool */ $rawMode = false
237
    )/*# : string */;
238
    abstract protected function quoteAlias($alias, array $settings)/*# : string */;
239
    abstract protected function joinClause(
240
        /*# : string */ $prefix,
241
        /*# : string */ $seperator,
242
        array $clause,
243
        array $settings
244
    )/*# : string */;
245
}
246