Completed
Push — 1.1 ( 6ab797...def185 )
by David
03:11
created

StatementFactory::toObject()   C

Complexity

Conditions 10
Paths 193

Size

Total Lines 68
Code Lines 45

Duplication

Lines 20
Ratio 29.41 %

Importance

Changes 6
Bugs 1 Features 0
Metric Value
c 6
b 1
f 0
dl 20
loc 68
rs 5.7143
cc 10
eloc 45
nc 193
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * expression-types.php.
5
 *
6
 *
7
 * Copyright (c) 2010-2013, Justin Swanhart
8
 * with contributions by André Rothe <[email protected], [email protected]>
9
 * and David Négrier <[email protected]>
10
 *
11
 * All rights reserved.
12
 *
13
 * Redistribution and use in source and binary forms, with or without modification,
14
 * are permitted provided that the following conditions are met:
15
 *
16
 *   * Redistributions of source code must retain the above copyright notice,
17
 *     this list of conditions and the following disclaimer.
18
 *   * Redistributions in binary form must reproduce the above copyright notice,
19
 *     this list of conditions and the following disclaimer in the documentation
20
 *     and/or other materials provided with the distribution.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31
 * DAMAGE.
32
 */
33
34
namespace SQLParser\Query;
35
36
use SQLParser\Node\NodeFactory;
37
use SQLParser\Node\Operator;
38
39
/**
40
 * This class has the ability to create instances implementing NodeInterface based on a descriptive array.
41
 *
42
 * @author David Négrier <[email protected]>
43
 */
44
class StatementFactory
45
{
46
    public static function toObject(array $desc)
47
    {
48
        if (isset($desc['SELECT'])) {
49
            $select = new Select();
50
51
            $columns = array_map(function ($item) {
52
                return NodeFactory::toObject($item);
53
            }, $desc['SELECT']);
54
            $columns = NodeFactory::simplify($columns);
55
            $select->setColumns($columns);
0 ignored issues
show
Documentation introduced by
$columns is of type array|object, but the function expects a array<integer,object<SQL...er\Node\NodeInterface>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
56
57
            if (isset($desc['OPTIONS'])) {
58
                $options = $desc['OPTIONS'];
59
                $key = array_search('DISTINCT', $options);
60
                if ($key !== false) {
61
                    $select->setDistinct(true);
62
                    unset($options[$key]);
63
                } else {
64
                    $select->setDistinct(false);
65
                }
66
                $select->setOptions($options);
67
            }
68
69
            if (isset($desc['FROM'])) {
70
                $from = self::mapArrayToNodeObjectList($desc['FROM']);
71
                $select->setFrom($from);
72
            }
73
74 View Code Duplication
            if (isset($desc['WHERE'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
75
                $where = self::mapArrayToNodeObjectList($desc['WHERE']);
76
                $where = NodeFactory::simplify($where);
77
                $select->setWhere($where);
0 ignored issues
show
Documentation introduced by
$where is of type array|object, but the function expects a array<integer,object<SQL...ser\Node\NodeInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
78
            }
79
80 View Code Duplication
            if (isset($desc['GROUP'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
81
                $group = self::mapArrayToNodeObjectList($desc['GROUP']);
82
                $group = NodeFactory::simplify($group);
83
                $select->setGroup($group);
0 ignored issues
show
Documentation introduced by
$group is of type array|object, but the function expects a array<integer,object<SQL...ser\Node\NodeInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
84
            }
85
86 View Code Duplication
            if (isset($desc['HAVING'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
87
                $having = self::mapArrayToNodeObjectList($desc['HAVING']);
88
                $having = NodeFactory::simplify($having);
89
                $select->setHaving($having);
0 ignored issues
show
Documentation introduced by
$having is of type array|object, but the function expects a array<integer,object<SQL...ser\Node\NodeInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
90
            }
91
92 View Code Duplication
            if (isset($desc['ORDER'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
93
                $order = self::mapArrayToNodeObjectList($desc['ORDER']);
94
                $order = NodeFactory::simplify($order);
95
                $select->setOrder($order);
0 ignored issues
show
Documentation introduced by
$order is of type array|object, but the function expects a array<integer,object<SQL...ser\Node\NodeInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
96
            }
97
98
            if (isset($desc['LIMIT'])) {
99
                $descLimit = self::checkLimitDesc($desc['LIMIT']);
100
101
                $limit = NodeFactory::toObject($descLimit['limit']);
102
                //$limit = NodeFactory::simplify($limit);
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
103
                $select->setLimit($limit);
104
105
                $offset = NodeFactory::toObject($descLimit['offset']);
106
                //$offset = NodeFactory::simplify($offset);
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
107
                $select->setOffset($offset);
108
            }
109
            return $select;
110
        } else {
111
            throw new \BadMethodCallException('Unknown query');
112
        }
113
    }
114
115
    /**
116
     * @param array $descLimit
117
     * @return array
118
     * @throws \Exception
119
     */
120
    private static function checkLimitDesc(array $descLimit) {
121
        if(count($descLimit) > 2) {
122
            throw new \Exception('The limit returned by the SQLParser contains more than 2 items, something might went wrong.');
123
        }
124
        return ['offset' => $descLimit[0], 'limit' => $descLimit[1]];
125
    }
126
127
    /**
128
     * @param array $items An array of objects represented as SQLParser arrays.
129
     */
130
    private static function mapArrayToNodeObjectList(array $items) {
131
        $list = [];
132
133
        $nextAndPartOfBetween = false;
134
135
        // Special case, let's replace the AND of a between with a ANDBETWEEN object.
136
        foreach ($items as $item) {
137
            $obj = NodeFactory::toObject($item);
138
            if ($obj instanceof Operator) {
139
                if ($obj->getValue() == 'BETWEEN') {
140
                    $nextAndPartOfBetween = true;
141
                } elseif ($nextAndPartOfBetween && $obj->getValue() == 'AND') {
142
                    $nextAndPartOfBetween = false;
143
                    $obj->setValue('AND_FROM_BETWEEN');
144
                }
145
            }
146
            $list[] = $obj;
147
        }
148
        return $list;
149
    }
150
}
151