Test Failed
Pull Request — master (#2834)
by Grégoire
07:06
created

DBALException   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 266
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 91.46%

Importance

Changes 0
Metric Value
wmc 29
lcom 1
cbo 0
dl 0
loc 266
ccs 75
cts 82
cp 0.9146
rs 10
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A invalidPlatformSpecified() 0 6 1
A notSupported() 0 4 1
A invalidPlatformType() 0 20 2
A invalidPlatformVersionSpecified() 0 11 1
A invalidPdoInstance() 0 7 1
A driverRequired() 0 15 2
A unknownDriver() 0 5 1
A driverExceptionDuringQuery() 0 10 2
A driverException() 0 4 1
A wrapException() 0 11 4
A formatParameters() 0 13 4
A invalidWrapperClass() 0 5 1
A invalidDriverClass() 0 5 1
A invalidTableName() 0 4 1
A noColumnsSpecifiedForTable() 0 4 1
A limitOffsetInvalid() 0 4 1
A typeExists() 0 4 1
A unknownColumnType() 0 12 2
A typeNotFound() 0 4 1
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 MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\DBAL;
21
22
use Doctrine\DBAL\Driver;
23
use Doctrine\DBAL\Driver\ExceptionConverterDriver;
24
use Doctrine\DBAL\Exception;
25
use Doctrine\DBAL\Platforms\AbstractPlatform;
26
use Doctrine\DBAL\Types\Type;
27
use Doctrine\DBAL\Types\TypeRegistry;
28
29
class DBALException extends \Exception
30
{
31
    /**
32
     * @param string $method
33
     *
34
     * @return \Doctrine\DBAL\DBALException
35
     */
36 49
    public static function notSupported($method)
37
    {
38 49
        return new self("Operation '$method' is not supported by platform.");
39
    }
40
41
    public static function invalidPlatformSpecified() : self
42
    {
43
        return new self(
44
            "Invalid 'platform' option specified, need to give an instance of ".
45
            "\Doctrine\DBAL\Platforms\AbstractPlatform.");
46
    }
47
48
    /**
49
     * @param mixed $invalidPlatform
50
     */
51 3
    public static function invalidPlatformType($invalidPlatform) : self
52
    {
53 3
        if (\is_object($invalidPlatform)) {
54 2
            return new self(
55 2
                sprintf(
56 2
                    "Option 'platform' must be a subtype of '%s', instance of '%s' given",
57 2
                    AbstractPlatform::class,
58 2
                    \get_class($invalidPlatform)
59
                )
60
            );
61
        }
62
63 1
        return new self(
64 1
            sprintf(
65 1
                "Option 'platform' must be an object and subtype of '%s'. Got '%s'",
66 1
                AbstractPlatform::class,
67 1
                \gettype($invalidPlatform)
68
            )
69
        );
70
    }
71
72
    /**
73
     * Returns a new instance for an invalid specified platform version.
74
     *
75
     * @param string $version        The invalid platform version given.
76
     * @param string $expectedFormat The expected platform version format.
77
     *
78
     * @return DBALException
79
     */
80 10
    public static function invalidPlatformVersionSpecified($version, $expectedFormat)
81
    {
82 10
        return new self(
83 10
            sprintf(
84
                'Invalid platform version "%s" specified. ' .
85 10
                'The platform version has to be specified in the format: "%s".',
86 10
                $version,
87 10
                $expectedFormat
88
            )
89
        );
90
    }
91
92
    /**
93
     * @return \Doctrine\DBAL\DBALException
94
     */
95 1
    public static function invalidPdoInstance()
96
    {
97 1
        return new self(
98
            "The 'pdo' option was used in DriverManager::getConnection() but no ".
99 1
            "instance of PDO was given."
100
        );
101
    }
102
103
    /**
104
     * @param string|null $url The URL that was provided in the connection parameters (if any).
105
     *
106
     * @return \Doctrine\DBAL\DBALException
107
     */
108 5
    public static function driverRequired($url = null)
109
    {
110 5
        if ($url) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $url of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
111 4
            return new self(
112 4
                sprintf(
113
                    "The options 'driver' or 'driverClass' are mandatory if a connection URL without scheme " .
114 4
                    "is given to DriverManager::getConnection(). Given URL: %s",
115 4
                    $url
116
                )
117
            );
118
        }
119
120 1
        return new self("The options 'driver' or 'driverClass' are mandatory if no PDO ".
121 1
            "instance is given to DriverManager::getConnection().");
122
    }
123
124
    /**
125
     * @param string $unknownDriverName
126
     * @param array  $knownDrivers
127
     *
128
     * @return \Doctrine\DBAL\DBALException
129
     */
130 1
    public static function unknownDriver($unknownDriverName, array $knownDrivers)
131
    {
132 1
        return new self("The given 'driver' ".$unknownDriverName." is unknown, ".
133 1
            "Doctrine currently supports only the following drivers: ".implode(", ", $knownDrivers));
134
    }
135
136
    /**
137
     * @param \Doctrine\DBAL\Driver     $driver
138
     * @param \Exception $driverEx
139
     * @param string     $sql
140
     * @param array      $params
141
     *
142
     * @return \Doctrine\DBAL\DBALException
143
     */
144 69
    public static function driverExceptionDuringQuery(Driver $driver, \Exception $driverEx, $sql, array $params = [])
145
    {
146 69
        $msg = "An exception occurred while executing '".$sql."'";
147 69
        if ($params) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $params of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
148 9
            $msg .= " with params " . self::formatParameters($params);
149
        }
150 69
        $msg .= ":\n\n".$driverEx->getMessage();
151
152 69
        return static::wrapException($driver, $driverEx, $msg);
0 ignored issues
show
Bug introduced by
Since wrapException() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of wrapException() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
153
    }
154
155
    /**
156
     * @param \Doctrine\DBAL\Driver     $driver
157
     * @param \Exception $driverEx
158
     *
159
     * @return \Doctrine\DBAL\DBALException
160
     */
161 1
    public static function driverException(Driver $driver, \Exception $driverEx)
162
    {
163 1
        return static::wrapException($driver, $driverEx, "An exception occurred in driver: " . $driverEx->getMessage());
0 ignored issues
show
Bug introduced by
Since wrapException() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of wrapException() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
164
    }
165
166
    /**
167
     * @param \Doctrine\DBAL\Driver     $driver
168
     * @param \Exception $driverEx
169
     *
170
     * @return \Doctrine\DBAL\DBALException
171
     */
172 70
    private static function wrapException(Driver $driver, \Exception $driverEx, $msg)
173
    {
174 70
        if ($driverEx instanceof Exception\DriverException) {
175 1
            return $driverEx;
176
        }
177 69
        if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof Driver\DriverException) {
178 63
            return $driver->convertException($msg, $driverEx);
179
        }
180
181 6
        return new self($msg, 0, $driverEx);
182
    }
183
184
    /**
185
     * Returns a human-readable representation of an array of parameters.
186
     * This properly handles binary data by returning a hex representation.
187
     *
188
     * @param array $params
189
     *
190
     * @return string
191
     */
192
    private static function formatParameters(array $params)
193
    {
194 9
        return '[' . implode(', ', array_map(function ($param) {
195 9
            $json = @json_encode($param);
196
197 9
            if (! is_string($json) || $json == 'null' && is_string($param)) {
198
                // JSON encoding failed, this is not a UTF-8 string.
199 1
                return '"\x' . implode('\x', str_split(bin2hex($param), 2)) . '"';
200
            }
201
202 9
            return $json;
203 9
        }, $params)) . ']';
204
    }
205
206
    /**
207
     * @param string $wrapperClass
208
     *
209
     * @return \Doctrine\DBAL\DBALException
210
     */
211 1
    public static function invalidWrapperClass($wrapperClass)
212
    {
213 1
        return new self("The given 'wrapperClass' ".$wrapperClass." has to be a ".
214 1
            "subtype of \Doctrine\DBAL\Connection.");
215
    }
216
217
    /**
218
     * @param string $driverClass
219
     *
220
     * @return \Doctrine\DBAL\DBALException
221
     */
222 1
    public static function invalidDriverClass($driverClass)
223
    {
224 1
        return new self("The given 'driverClass' ".$driverClass." has to implement the ".
225 1
            "\Doctrine\DBAL\Driver interface.");
226
    }
227
228
    /**
229
     * @param string $tableName
230
     *
231
     * @return \Doctrine\DBAL\DBALException
232
     */
233 1
    public static function invalidTableName($tableName)
234
    {
235 1
        return new self("Invalid table name specified: ".$tableName);
236
    }
237
238
    /**
239
     * @param string $tableName
240
     *
241
     * @return \Doctrine\DBAL\DBALException
242
     */
243 16
    public static function noColumnsSpecifiedForTable($tableName)
244
    {
245 16
        return new self("No columns specified for table ".$tableName);
246
    }
247
248
    /**
249
     * @return \Doctrine\DBAL\DBALException
250
     */
251
    public static function limitOffsetInvalid()
252
    {
253
        return new self("Invalid Offset in Limit Query, it has to be larger than or equal to 0.");
254
    }
255
256
    /**
257
     * @param string $name
258
     *
259
     * @return \Doctrine\DBAL\DBALException
260
     */
261
    public static function typeExists($name)
262
    {
263
        return new self('Type '.$name.' already exists.');
264
    }
265
266
    /**
267
     * @param string $name
268
     * @param bool   $legacy whether to recommend the legacy workflow
269
     *
270
     * @return \Doctrine\DBAL\DBALException
271
     */
272 1496
    public static function unknownColumnType($name, $legacy = false)
273
    {
274 1496
        $recommendedAPI = $legacy ? Type::class : TypeRegistry::class;
275 1496
        return new self('Unknown column type "'.$name.'" requested. Any Doctrine type that you use has ' .
276 1496
            'to be registered with '.$recommendedAPI.'::addType(). You can get a list of all the ' .
277 1496
            'known types with '.$recommendedAPI.'::getTypesMap(). If this error occurs during database ' .
278 1496
            'introspection then you might have forgotten to register all database types for a Doctrine Type. Use ' .
279 1496
            'AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement ' .
280 1496
            'Type#getMappedDatabaseTypes(). If the type name is empty you might ' .
281 1496
            'have a problem with the cache or forgot some mapping information.'
282
        );
283
    }
284
285
    /**
286
     * @param string $name
287
     *
288
     * @return \Doctrine\DBAL\DBALException
289
     */
290 16
    public static function typeNotFound($name)
291
    {
292 16
        return new self('Type to be overwritten '.$name.' does not exist.');
293
    }
294
}
295