Passed
Push — master ( eabf33...342b63 )
by Michiel
05:53
created

DefaultPDOQuerySplitter::nextQuery()   D

Complexity

Conditions 19
Paths 32

Size

Total Lines 84
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 43
CRAP Score 19.0042

Importance

Changes 0
Metric Value
cc 19
eloc 44
c 0
b 0
f 0
nc 32
nop 0
dl 0
loc 84
ccs 43
cts 44
cp 0.9773
crap 19.0042
rs 4.5166

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
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 *
19
 * @package phing.tasks.ext.pdo
20
 */
21
22
use Phing\Io\Reader;
23
use Phing\Util\StringHelper;
24
25
/**
26
 * Splits SQL source into queries using simple regular expressions
27
 *
28
 * Extracted from PDOSQLExecTask::runStatements()
29
 *
30
 * @author  Hans Lellelid <[email protected]>
31
 * @author  Alexey Borzov <[email protected]>
32
 * @package phing.tasks.ext.pdo
33
 */
34
class DefaultPDOQuerySplitter extends PDOQuerySplitter
35
{
36
    /**
37
     * Delimiter type, one of PDOSQLExecTask::DELIM_ROW or PDOSQLExecTask::DELIM_NORMAL
38
     *
39
     * @var string
40
     */
41
    private $delimiterType;
42
43
    /**
44
     * Leftover SQL from previous line
45
     *
46
     * @var string
47
     */
48
    private $sqlBacklog = '';
49
50
    /**
51
     * Constructor, sets the parent task, reader with SQL source and delimiter type
52
     *
53
     * @param PDOSQLExecTask $parent
54
     * @param Reader $reader
55
     * @param string $delimiterType
56
     */
57 2
    public function __construct(PDOSQLExecTask $parent, Reader $reader, $delimiterType = PDOSQLExecTask::DELIM_NORMAL)
58
    {
59 2
        parent::__construct($parent, $reader);
60 2
        $this->delimiterType = $delimiterType;
61 2
    }
62
63
    /**
64
     * Returns next query from SQL source, null if no more queries left
65
     *
66
     * In case of "row" delimiter type this searches for strings containing only
67
     * delimiters. In case of "normal" delimiter type, this uses simple regular
68
     * expression logic to search for delimiters.
69
     *
70
     * @return string|null
71
     */
72 2
    public function nextQuery()
73
    {
74 2
        $sql = "";
75 2
        $hasQuery = false;
76
77 2
        while (($line = $this->sqlReader->readLine()) !== null) {
78 2
            $delimiter = $this->parent->getDelimiter();
79 2
            $project = $this->parent->getOwningTarget()->getProject();
80 2
            $line = $project->replaceProperties(trim($line));
81
82
            if (
83 2
                ($line != $delimiter)
84 2
                && (StringHelper::startsWith("//", $line)
85 2
                    || StringHelper::startsWith("--", $line)
86 2
                    || StringHelper::startsWith("#", $line))
87
            ) {
88 2
                continue;
89
            }
90
91
            if (
92 2
                strlen($line) > 4
93 2
                && strtoupper(substr($line, 0, 4)) == "REM "
94
            ) {
95
                continue;
96
            }
97
98
            // MySQL supports defining new delimiters
99 2
            if (preg_match('/DELIMITER [\'"]?([^\'" $]+)[\'"]?/i', $line, $matches)) {
100 1
                $this->parent->setDelimiter($matches[1]);
101 1
                continue;
102
            }
103
104 2
            if ($this->sqlBacklog !== "") {
105 1
                $sql = $this->sqlBacklog;
106 1
                $this->sqlBacklog = "";
107
            }
108
109 2
            $sql .= " " . $line . "\n";
110
111
            // SQL defines "--" as a comment to EOL
112
            // and in Oracle it may contain a hint
113
            // so we cannot just remove it, instead we must end it
114 2
            if (strpos($line, "--") !== false) {
115 2
                $sql .= "\n";
116
            }
117
118
            // DELIM_ROW doesn't need this (as far as i can tell)
119 2
            if ($this->delimiterType == PDOSQLExecTask::DELIM_NORMAL) {
120 1
                $reg = "#((?:\"(?:\\\\.|[^\"])*\"?)+|'(?:\\\\.|[^'])*'?|" . preg_quote($delimiter) . ")#";
121
122 1
                $sqlParts = preg_split($reg, $sql, 0, PREG_SPLIT_DELIM_CAPTURE);
123 1
                $this->sqlBacklog = "";
124 1
                foreach ($sqlParts as $sqlPart) {
125
                    // we always want to append, even if it's a delim (which will be stripped off later)
126 1
                    $this->sqlBacklog .= $sqlPart;
127
128
                    // we found a single (not enclosed by ' or ") delimiter, so we can use all stuff before the delim as the actual query
129 1
                    if ($sqlPart === $delimiter) {
130 1
                        $sql = $this->sqlBacklog;
131 1
                        $this->sqlBacklog = "";
132 1
                        $hasQuery = true;
133
                    }
134
                }
135
            }
136
137 2
            if ($hasQuery || ($this->delimiterType == PDOSQLExecTask::DELIM_ROW && $line == $delimiter)) {
138
                // this assumes there is always a delimter on the end of the SQL statement.
139 2
                $sql = StringHelper::substring(
140 2
                    $sql,
141 2
                    0,
142 2
                    strlen($sql) - strlen($delimiter)
143 2
                    - ($this->delimiterType == PDOSQLExecTask::DELIM_ROW ? 2 : 1)
144
                );
145
146 2
                return $sql;
147
            }
148
        }
149
150
        // Catch any statements not followed by ;
151 2
        if ($sql !== "") {
152 2
            return $sql;
153
        }
154
155 2
        return null;
156
    }
157
}
158