Failed Conditions
Pull Request — master (#57)
by
unknown
03:45
created

Util   C

Complexity

Total Complexity 58

Size/Duplication

Total Lines 296
Duplicated Lines 6.42 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 58
lcom 1
cbo 0
dl 19
loc 296
rs 6.3005
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getExceptionInfo() 0 11 1
A ensure() 11 11 3
A ensureNot() 8 8 3
B buildException() 0 20 5
A raiseException() 0 8 2
C throwIfNotType() 0 78 35
A getExceptionAliases() 0 4 1
A setExceptionAliases() 0 4 1

How to fix   Duplicated Code    Complexity   

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:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Util often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Util, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace TraderInteractive;
4
5
use ErrorException;
6
use Exception;
7
use InvalidArgumentException;
8
use ReflectionClass;
9
use ReflectionException;
10
11
/**
12
 * Static class with various application functions.
13
 */
14
final class Util
15
{
16
    private static $exceptionAliases = ['http' => '\DominionEnterprises\HttpException'];
17
18
    /**
19
     * Returns exception info in array.
20
     *
21
     * @param Exception $e the exception to return info on
22
     *
23
     * @return array like:
24
     * <pre>
25
     * [
26
     *     'type' => 'Exception',
27
     *     'message' => 'a message',
28
     *     'code' => 0,
29
     *     'file' => '/somePath',
30
     *     'line' => 434,
31
     *     'trace' => 'a stack trace',
32
     * ]
33
     * </pre>
34
     */
35
    public static function getExceptionInfo(Exception $e) : array
36
    {
37
        return [
38
            'type' => get_class($e),
39
            'message' => $e->getMessage(),
40
            'code' => $e->getCode(),
41
            'file' => $e->getFile(),
42
            'line' => $e->getLine(),
43
            'trace' => $e->getTraceAsString(),
44
        ];
45
    }
46
47
    /**
48
     * Ensures that $valueToEnsure is equal to $valueToCheck or it throws
49
     *
50
     * Can be used like: $result = ensure(true, is_string('boo'))
51
     * Or like: $result = ensure(true, is_string('boo'), 'the message')
52
     * Or like: $result = ensure(true, is_string('boo'), 'MyException', ['the message', 2])
53
     * Or like: $result = ensure(true, is_string('boo'), new MyException('the message', 2))
54
     *
55
     * @param mixed                 $valueToEnsure the value to throw on if $valueToCheck equals it
56
     * @param mixed                 $valueToCheck  the value to check against $valueToEnsure
57
     * @param null|string|Exception $exception     null, a fully qualified exception class name, string for an Exception
58
     *                                             message, or an Exception.  The fully qualified exception class name
59
     *                                             could also be an alias in getExceptionAliases()
60
     * @param array|null            $exceptionArgs arguments to pass to a new instance of $exception. If using this
61
     *                                             parameter make sure these arguments match the constructor for an
62
     *                                             exception of type $exception.
63
     *
64
     * @return mixed returns $valueToCheck
65
     *
66
     * @throws Exception if $valueToEnsure !== $valueToCheck
67
     * @throws InvalidArgumentException if $exception was not null, a string, or an Exception
68
     */
69 View Code Duplication
    public static function ensure($valueToEnsure, $valueToCheck, $exception = null, array $exceptionArgs = null)
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...
70
    {
71
        if ($valueToEnsure !== $valueToCheck) {
72
            throw self::buildException(
73
                $exception ?: "'{$valueToEnsure}' did not equal '{$valueToCheck}'",
74
                $exceptionArgs
75
            );
76
        }
77
78
        return $valueToCheck;
79
    }
80
81
    /**
82
     * Ensures that $valueToThrowOn is not equal to $valueToCheck or it throws
83
     *
84
     * Can be used like: $curl = ensureNot(false, curl_init('boo'))
85
     * Or like: $curl = ensureNot(false, curl_init('boo'), 'bad message')
86
     * Or like: $curl = ensureNot(false, curl_init('boo'), 'MyException', ['bad message', 2])
87
     * Or like: $curl = ensureNot(false, curl_init('boo'), new MyException('bad message', 2))
88
     *
89
     * @param mixed                 $valueToThrowOn the value to throw on if $valueToCheck equals it
90
     * @param mixed                 $valueToCheck   the value to check against $valueToThrowOn
91
     * @param null|string|Exception $exception      null, a fully qualified exception class name, string for an
92
     *                                              Exception message, or an Exception.  The fully qualified exception
93
     *                                              class name could also be an alias in getExceptionAliases()
94
     * @param array|null            $exceptionArgs  arguments to pass to a new instance of $exception. If using this
95
     *                                              parameter make sure these arguments match the constructor for an
96
     *                                              exception of type $exception.
97
     *
98
     * @return mixed returns $valueToCheck
99
     *
100
     * @throws Exception if $valueToThrowOn === $valueToCheck
101
     * @throws InvalidArgumentException if $exception was not null, a string, or an Exception
102
     */
103 View Code Duplication
    public static function ensureNot($valueToThrowOn, $valueToCheck, $exception = null, array $exceptionArgs = null)
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...
104
    {
105
        if ($valueToThrowOn === $valueToCheck) {
106
            throw self::buildException($exception ?: "'{$valueToThrowOn}' equals '{$valueToCheck}'", $exceptionArgs);
107
        }
108
109
        return $valueToCheck;
110
    }
111
112
    /**
113
     * Helper method to return exception created from ensure[Not] call input.
114
     *
115
     * @param mixed      $exception     Null, a fully qualified exception class name, string for an Exception message,
116
     *                                  or an Exception.  The fully qualified exception class name could also be an
117
     *                                  alias in getExceptionAliases()
118
     * @param array|null $exceptionArgs Arguments to pass to a new instance of $exception. If using this parameter make
119
     *                                  sure these arguments match the constructor for an exception of type $exception.
120
     *
121
     * @return Exception|mixed|object
122
     * @throws ReflectionException
123
     */
124
    private static function buildException($exception, array $exceptionArgs = null)
125
    {
126
        if ($exception instanceof Exception) {
127
            return $exception;
128
        }
129
130
        if (!is_string($exception)) {
131
            throw new InvalidArgumentException('$exception was not null, a string, or an Exception');
132
        }
133
134
        if (empty($exceptionArgs)) {
135
            return new Exception($exception);
136
        }
137
138
        if (array_key_exists($exception, self::$exceptionAliases)) {
139
            $exception = self::$exceptionAliases[$exception];
140
        }
141
142
        return (new ReflectionClass($exception))->newInstanceArgs($exceptionArgs);
143
    }
144
145
    /**
146
     * Throws a new ErrorException based on the error information provided. To be
147
     * used as a callback for @see set_error_handler()
148
     *
149
     * @param int    $level   The level of the exception.
150
     * @param string $message The message the exception will give.
151
     * @param string $file    The file that the error occurred in.
152
     * @param string $line    The line that the exception occurred upon.
153
     *
154
     * @return bool false
155
     *
156
     * @throws ErrorException
157
     */
158
    public static function raiseException(int $level, string $message, string $file = null, string $line = null) : bool
159
    {
160
        if (error_reporting() === 0) {
161
            return false;
162
        }
163
164
        throw new ErrorException($message, 0, $level, $file, $line);
165
    }
166
167
    /**
168
     * Throws an exception if specified variables are not of given types.
169
     *
170
     * @param array $typesToVariables like ['string' => [$var1, $var2], 'int' => [$var1, $var2]] or
171
     *                                ['string' => $var1, 'integer' => [1, $var2]]. Supported types are the suffixes
172
     *                                of the is_* functions such as string for is_string and int for is_int
173
     * @param bool  $failOnWhitespace whether to fail strings if they are whitespace
174
     * @param bool  $allowNulls       whether to allow null values to pass through
175
     *
176
     * @return void
177
     *
178
     * @throws InvalidArgumentException if a key in $typesToVariables was not a string
179
     * @throws InvalidArgumentException if a key in $typesToVariables did not have an is_ function
180
     * @throws InvalidArgumentException if a variable is not of correct type
181
     * @throws InvalidArgumentException if a variable is whitespace and $failOnWhitespace is set
182
     */
183
    public static function throwIfNotType(
184
        array $typesToVariables,
185
        bool $failOnWhitespace = false,
186
        bool $allowNulls = false
187
    ) {
188
        foreach ($typesToVariables as $type => $variablesOrVariable) {
189
            $variables = [$variablesOrVariable];
190
            if (is_array($variablesOrVariable)) {
191
                $variables = $variablesOrVariable;
192
            }
193
194
            //cast ok since an integer won't match any of the cases.
195
            //the similar code in the cases is an optimization for those type where faster checks can be made.
196
            switch ((string)$type) {
197
                case 'bool':
198
                    foreach ($variables as $i => $variable) {
199
                        //using the continue here not negative checks to make use of short cutting optimization.
200
                        if ($variable === false || $variable === true || ($allowNulls && $variable === null)) {
201
                            continue;
202
                        }
203
204
                        throw new InvalidArgumentException("variable at position '{$i}' was not a boolean");
205
                    }
206
207
                    break;
208
                case 'null':
209
                    foreach ($variables as $i => $variable) {
210
                        if ($variable !== null) {
211
                            throw new InvalidArgumentException("variable at position '{$i}' was not null");
212
                        }
213
                    }
214
215
                    break;
216
                case 'string':
217
                    foreach ($variables as $i => $variable) {
218
                        if (is_string($variable)) {
219
                            if ($failOnWhitespace && trim($variable) === '') {
220
                                throw new InvalidArgumentException("variable at position '{$i}' was whitespace");
221
                            }
222
223
                            continue;
224
                        }
225
226
                        if ($allowNulls && $variable === null) {
227
                            continue;
228
                        }
229
230
                        throw new InvalidArgumentException("variable at position '{$i}' was not a '{$type}'");
231
                    }
232
233
                    break;
234
                case 'array':
235
                case 'callable':
236
                case 'double':
237
                case 'float':
238
                case 'int':
239
                case 'integer':
240
                case 'long':
241
                case 'numeric':
242
                case 'object':
243
                case 'real':
244
                case 'resource':
245
                case 'scalar':
246
                    $isFunction = "is_{$type}";
247
                    foreach ($variables as $i => $variable) {
248
                        if ($isFunction($variable) || ($allowNulls && $variable === null)) {
249
                            continue;
250
                        }
251
252
                        throw new InvalidArgumentException("variable at position '{$i}' was not a '{$type}'");
253
                    }
254
255
                    break;
256
                default:
257
                    throw new InvalidArgumentException('a type was not one of the is_ functions');
258
            }
259
        }
260
    }
261
262
    /**
263
     * Return the exception aliases.
264
     *
265
     * @return array array where keys are aliases and values are strings to a fully qualified exception class names.
266
     */
267
    public static function getExceptionAliases() : array
268
    {
269
        return self::$exceptionAliases;
270
    }
271
272
    /**
273
     * Set the exception aliases.
274
     *
275
     * @param array $aliases array where keys are aliases and values are strings to a fully qualified exception class
276
     *                       names.
277
     */
278
    public static function setExceptionAliases(array $aliases)
279
    {
280
        self::$exceptionAliases = $aliases;
281
    }
282
}
283