Completed
Branch develop (85a9c8)
by Anton
05:44
created

JoinsTrait   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 313
Duplicated Lines 25.56 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 20
c 2
b 0
f 0
lcom 1
cbo 3
dl 80
loc 313
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
whereToken() 0 6 ?
A join() 0 6 1
A innerJoin() 0 6 1
A rightJoin() 0 6 1
A leftJoin() 0 6 1
A fullJoin() 0 6 1
A on() 9 9 1
A andOn() 9 9 1
A orOn() 8 8 1
A onWhere() 9 9 1
A andOnWhere() 9 9 1
A orOnWhere() 9 9 1
A onWrapper() 0 10 2
C whereWrapper() 27 27 7

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
namespace Spiral\Database\Builders\Traits;
9
10
use Spiral\Database\Entities\QueryBuilder;
11
use Spiral\Database\Exceptions\BuilderException;
12
use Spiral\Database\Injections\Expression;
13
use Spiral\Database\Injections\ExpressionInterface;
14
use Spiral\Database\Injections\FragmentInterface;
15
use Spiral\Database\Injections\Parameter;
16
use Spiral\Database\Injections\ParameterInterface;
17
18
/**
19
 * Provides ability to generate QueryCompiler JOIN tokens including ON conditions and table/column
20
 * aliases.
21
 *
22
 * Simple joins (ON userID = users.id):
23
 * $select->join('LEFT', 'info', 'userID', 'users.id');
24
 * $select->leftJoin('info', 'userID', '=', 'users.id');
25
 * $select->rightJoin('info', ['userID' => 'users.id']);
26
 *
27
 * More complex ON conditions:
28
 * $select->leftJoin('info', function($select) {
29
 *      $select->on('userID', 'users.id')->orOn('userID', 'users.masterID');
30
 * });
31
 *
32
 * To specify on conditions outside join method use "on" methods.
33
 * $select->leftJoin('info')->on('userID', '=', 'users.id');
34
 *
35
 * On methods will only support conditions based on outer table columns. You can not use parametric
36
 * values here, use "on where" conditions instead.
37
 * $select->leftJoin('info')->on('userID', '=', 'users.id')->onWhere('value', 100);
38
 *
39
 * Arguments and syntax in "on" and "onWhere" conditions is identical to "where" method defined in
40
 * AbstractWhere.
41
 * Attention, "on" and "onWhere" conditions will be applied to last registered join only!
42
 *
43
 * You can also use table aliases and use them in conditions after:
44
 * $select->join('LEFT', 'info as i')->on('i.userID', 'users.id');
45
 * $select->join('LEFT', 'info as i', function($select) {
46
 *      $select->on('i.userID', 'users.id')->orOn('i.userID', 'users.masterID');
47
 * });
48
 *
49
 * @see AbstractWhere
50
 */
51
trait JoinsTrait
52
{
53
    /**
54
     * Name/id of last join, every ON and ON WHERE call will be associated with this join.
55
     *
56
     * @var string
57
     */
58
    private $activeJoin = null;
59
60
    /**
61
     * Set of join tokens with on and on where conditions associated, must be supported by
62
     * QueryCompilers.
63
     *
64
     * @var array
65
     */
66
    protected $joinTokens = [];
67
68
    /**
69
     * Parameters collected while generating ON WHERE tokens, must be in a same order as parameters
70
     * in resulted query. Parameters declared in ON methods will be converted into expressions and
71
     * will not be aggregated.
72
     *
73
     * @see AbstractWhere
74
     * @var array
75
     */
76
    protected $onParameters = [];
77
78
    /**
79
     * Register new JOIN with specified type with set of on conditions (linking one table to
80
     * another, no parametric on conditions allowed here).
81
     *
82
     * @param string $type  Join type. Allowed values, LEFT, RIGHT, INNER and etc.
83
     * @param string $table Joined table name (without prefix), may include AS statement.
84
     * @param mixed  $on    Simplified on definition linking table names (no parameters allowed) or
85
     *                      closure.
86
     * @return $this
87
     * @throws BuilderException
88
     */
89
    public function join($type, $table, $on = null)
0 ignored issues
show
Unused Code introduced by
The parameter $on is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
90
    {
91
        $this->joinTokens[$this->activeJoin = $table] = ['type' => strtoupper($type), 'on' => []];
92
93
        return call_user_func_array([$this, 'on'], array_slice(func_get_args(), 2));
94
    }
95
96
    /**
97
     * Register new INNER JOIN with set of on conditions (linking one table to another, no
98
     * parametric on conditions allowed here).
99
     *
100
     * @link http://www.w3schools.com/sql/sql_join_inner.asp
101
     * @see  join()
102
     * @param string $table Joined table name (without prefix), may include AS statement.
103
     * @param mixed  $on    Simplified on definition linking table names (no parameters allowed) or
104
     *                      closure.
105
     * @return $this
106
     * @throws BuilderException
107
     */
108
    public function innerJoin($table, $on = null)
0 ignored issues
show
Unused Code introduced by
The parameter $on is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
109
    {
110
        $this->joinTokens[$this->activeJoin = $table] = ['type' => 'INNER', 'on' => []];
111
112
        return call_user_func_array([$this, 'on'], array_slice(func_get_args(), 1));
113
    }
114
115
    /**
116
     * Register new RIGHT JOIN with set of on conditions (linking one table to another, no
117
     * parametric on conditions allowed here).
118
     *
119
     * @link http://www.w3schools.com/sql/sql_join_right.asp
120
     * @see  join()
121
     * @param string $table Joined table name (without prefix), may include AS statement.
122
     * @param mixed  $on    Simplified on definition linking table names (no parameters allowed) or
123
     *                      closure.
124
     * @return $this
125
     * @throws BuilderException
126
     */
127
    public function rightJoin($table, $on = null)
0 ignored issues
show
Unused Code introduced by
The parameter $on is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
128
    {
129
        $this->joinTokens[$this->activeJoin = $table] = ['type' => 'RIGHT', 'on' => []];
130
131
        return call_user_func_array([$this, 'on'], array_slice(func_get_args(), 1));
132
    }
133
134
    /**
135
     * Register new LEFT JOIN with set of on conditions (linking one table to another, no parametric
136
     * on conditions allowed here).
137
     *
138
     * @link http://www.w3schools.com/sql/sql_join_left.asp
139
     * @see  join()
140
     * @param string $table Joined table name (without prefix), may include AS statement.
141
     * @param mixed  $on    Simplified on definition linking table names (no parameters allowed) or
142
     *                      closure.
143
     * @return $this
144
     * @throws BuilderException
145
     */
146
    public function leftJoin($table, $on = null)
0 ignored issues
show
Unused Code introduced by
The parameter $on is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
147
    {
148
        $this->joinTokens[$this->activeJoin = $table] = ['type' => 'LEFT', 'on' => []];
149
150
        return call_user_func_array([$this, 'on'], array_slice(func_get_args(), 1));
151
    }
152
153
    /**
154
     * Register new FULL JOIN with set of on conditions (linking one table to another, no parametric
155
     * on conditions allowed here).
156
     *
157
     * @link http://www.w3schools.com/sql/sql_join_full.asp
158
     * @see  join()
159
     * @param string $table Joined table name (without prefix), may include AS statement.
160
     * @param mixed  $on    Simplified on definition linking table names (no parameters allowed) or
161
     *                      closure.
162
     * @return $this
163
     * @throws BuilderException
164
     */
165
    public function fullJoin($table, $on = null)
0 ignored issues
show
Unused Code introduced by
The parameter $on is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
166
    {
167
        $this->joinTokens[$this->activeJoin = $table] = ['type' => 'FULL', 'on' => []];
168
169
        return call_user_func_array([$this, 'on'], array_slice(func_get_args(), 1));
170
    }
171
172
    /**
173
     * Simple ON condition with various set of arguments. Can only be used to link column values
174
     * together, no parametric values allowed.
175
     *
176
     * @param mixed $joined   Joined column name or expression.
177
     * @param mixed $operator Foreign column name, if operator specified.
178
     * @param mixed $outer    Foreign column name.
179
     * @return $this
180
     * @throws BuilderException
181
     */
182 View Code Duplication
    public function on($joined = null, $operator = null, $outer = null)
0 ignored issues
show
Unused Code introduced by
The parameter $joined is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $outer is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
183
    {
184
        $this->whereToken(
185
            'AND', func_get_args(), $this->joinTokens[$this->activeJoin]['on'],
186
            $this->onWrapper()
187
        );
188
189
        return $this;
190
    }
191
192
    /**
193
     * Simple AND ON condition with various set of arguments. Can only be used to link column values
194
     * together, no parametric values allowed.
195
     *
196
     * @param mixed $joined   Joined column name or expression.
197
     * @param mixed $operator Foreign column name, if operator specified.
198
     * @param mixed $outer    Foreign column name.
199
     * @return $this
200
     * @throws BuilderException
201
     */
202 View Code Duplication
    public function andOn($joined = null, $operator = null, $outer = null)
0 ignored issues
show
Unused Code introduced by
The parameter $joined is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $outer is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
203
    {
204
        $this->whereToken(
205
            'AND', func_get_args(), $this->joinTokens[$this->activeJoin]['on'],
206
            $this->onWrapper()
207
        );
208
209
        return $this;
210
    }
211
212
    /**
213
     * Simple OR ON condition with various set of arguments. Can only be used to link column values
214
     * together, no parametric values allowed.
215
     *
216
     * @param mixed $joined   Joined column name or expression.
217
     * @param mixed $operator Foreign column name, if operator specified.
218
     * @param mixed $outer    Foreign column name.
219
     * @return $this
220
     * @throws BuilderException
221
     */
222 View Code Duplication
    public function orOn($joined = null, $operator = null, $outer = null)
0 ignored issues
show
Unused Code introduced by
The parameter $joined is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $outer is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
223
    {
224
        $this->whereToken(
225
            'AND', func_get_args(), $this->joinTokens[$this->activeJoin]['on'], $this->onWrapper()
226
        );
227
228
        return $this;
229
    }
230
231
    /**
232
     * Simple ON WHERE condition with various set of arguments. You can use parametric values in
233
     * such methods.
234
     *
235
     * @see AbstractWhere
236
     * @param string|mixed $joined   Joined column or expression.
237
     * @param mixed        $variousA Operator or value.
238
     * @param mixed        $variousB Value, if operator specified.
239
     * @param mixed        $variousC Required only in between statements.
240
     * @return $this
241
     * @throws BuilderException
242
     */
243 View Code Duplication
    public function onWhere($joined, $variousA = null, $variousB = null, $variousC = null)
0 ignored issues
show
Unused Code introduced by
The parameter $joined is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $variousA is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $variousB is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $variousC is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
244
    {
245
        $this->whereToken(
246
            'AND', func_get_args(), $this->joinTokens[$this->activeJoin]['on'],
247
            $this->whereWrapper()
248
        );
249
250
        return $this;
251
    }
252
253
    /**
254
     * Simple AND ON WHERE condition with various set of arguments. You can use parametric values in
255
     * such methods.
256
     *
257
     * @see AbstractWhere
258
     * @param string|mixed $joined   Joined column or expression.
259
     * @param mixed        $variousA Operator or value.
260
     * @param mixed        $variousB Value, if operator specified.
261
     * @param mixed        $variousC Required only in between statements.
262
     * @return $this
263
     * @throws BuilderException
264
     */
265 View Code Duplication
    public function andOnWhere($joined, $variousA = null, $variousB = null, $variousC = null)
0 ignored issues
show
Unused Code introduced by
The parameter $joined is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $variousA is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $variousB is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $variousC is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
266
    {
267
        $this->whereToken(
268
            'AND', func_get_args(), $this->joinTokens[$this->activeJoin]['on'],
269
            $this->whereWrapper()
270
        );
271
272
        return $this;
273
    }
274
275
    /**
276
     * Simple OR ON WHERE condition with various set of arguments. You can use parametric values in
277
     * such methods.
278
     *
279
     * @see AbstractWhere
280
     * @param string|mixed $joined   Joined column or expression.
281
     * @param mixed        $variousA Operator or value.
282
     * @param mixed        $variousB Value, if operator specified.
283
     * @param mixed        $variousC Required only in between statements.
284
     * @return $this
285
     * @throws BuilderException
286
     */
287 View Code Duplication
    public function orOnWhere($joined, $variousA = null, $variousB = null, $variousC = null)
0 ignored issues
show
Unused Code introduced by
The parameter $joined is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $variousA is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $variousB is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $variousC is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
288
    {
289
        $this->whereToken(
290
            'AND', func_get_args(), $this->joinTokens[$this->activeJoin]['on'],
291
            $this->whereWrapper()
292
        );
293
294
        return $this;
295
    }
296
297
    /**
298
     * Convert various amount of where function arguments into valid where token.
299
     *
300
     * @see AbstractWhere
301
     * @param string        $joiner     Boolean joiner (AND | OR).
302
     * @param array         $parameters Set of parameters collected from where functions.
303
     * @param array         $tokens     Array to aggregate compiled tokens. Reference.
304
     * @param \Closure|null $wrapper    Callback or closure used to wrap/collect every potential
305
     *                                  parameter.
306
     * @throws BuilderException
307
     */
308
    abstract protected function whereToken(
309
        $joiner,
310
        array $parameters,
311
        &$tokens = [],
312
        callable $wrapper
313
    );
314
315
    /**
316
     * Convert parameters used in JOIN ON statements into sql expressions.
317
     *
318
     * @return \Closure
319
     */
320
    private function onWrapper()
321
    {
322
        return function ($parameter) {
323
            if ($parameter instanceof FragmentInterface) {
324
                return $parameter;
325
            }
326
327
            return new Expression($parameter);
328
        };
329
    }
330
331
    /**
332
     * Applied to every potential parameter while ON WHERE tokens generation.
333
     *
334
     * @return \Closure
335
     */
336 View Code Duplication
    private function whereWrapper()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
337
    {
338
        return function ($parameter) {
339
            if ($parameter instanceof FragmentInterface) {
340
                //We are only not creating bindings for plan fragments
341
                if (!$parameter instanceof ParameterInterface && !$parameter instanceof QueryBuilder) {
342
                    return $parameter;
343
                }
344
345
                return $parameter;
346
            }
347
348
            if (is_array($parameter)) {
349
                throw new BuilderException("Arrays must be wrapped with Parameter instance.");
350
            }
351
352
            //Wrapping all values with ParameterInterface
353
            if (!$parameter instanceof ParameterInterface && !$parameter instanceof ExpressionInterface) {
354
                $parameter = new Parameter($parameter, Parameter::DETECT_TYPE);
355
            };
356
357
            //Let's store to sent to driver when needed
358
            $this->onParameters[] = $parameter;
359
360
            return $parameter;
361
        };
362
    }
363
}