Passed
Push — master ( 415210...f32ea8 )
by Christopher
02:16
created

SimpleTypeBase   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 281
Duplicated Lines 4.27 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 55
lcom 1
cbo 0
dl 12
loc 281
rs 6.8
c 0
b 0
f 0

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A value() 0 10 2
A fixValue() 0 4 1
A fixWhitespace() 0 13 4
C isBaseValid() 6 32 11
A matchesRegexPattern() 0 5 2
isValid() 0 1 ?
C __set() 0 42 13
A setEnumoration() 0 10 3
A setMaxLength() 0 5 1
A checkLength() 0 9 3
A setMinLength() 0 5 1
A setWhiteSpaceHandle() 0 7 2
A setPattern() 0 10 3
A checkPattern() 0 4 1
A setFractionDigits() 0 5 1
A setMinExclusive() 0 5 1
A setMaxExclusive() 0 5 1
A __toString() 0 4 1
A checkMinLength() 6 10 3

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 SimpleTypeBase 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 SimpleTypeBase, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace AlgoWeb\xsdTypes;
3
4
/**
5
 * Base Class representing xsd anySimpleTypes
6
 * @property-write array $enumeration Defines a list of acceptable values
7
 * @property-write array $fractionDigits Specifies the maximum number of decimal places allowed. Must be equal to or greater than zero
8
 * @property-write array $length Specifies the exact number of characters or list items allowed. Must be equal to or greater than zero
9
 * @property-write array $maxExclusive Specifies the upper bounds for numeric values (the value must be less than this value)
10
 * @property-write array $maxInclusive Specifies the upper bounds for numeric values (the value must be less than or equal to this value)
11
 * @property-write array $maxLength Specifies the maximum number of characters or list items allowed. Must be equal to or greater than zero
12
 * @property-write array $minExclusive Specifies the lower bounds for numeric values (the value must be greater than this value)
13
 * @property-write array $minInclusive Specifies the lower bounds for numeric values (the value must be greater than or equal to this value)
14
 * @property-write array $minLength Specifies the lower bounds for numeric values (the value must be greater than or equal to this value)
15
 * @property-write array $pattern Defines the exact sequence of characters that are acceptable
16
 * @property-write array $totalDigits Specifies the exact number of digits allowed. Must be greater than zero
17
 * @property-write array whiteSpace Specifies how white space (line feeds, tabs, spaces, and carriage returns) is handled
18
 */
19
abstract class SimpleTypeBase
20
{
21
    /**
22
     * @Exclude
23
     * @var array Defines a list of acceptable values
24
     */
25
    private $enumeration = array();
26
    /**
27
     * @Exclude
28
     * @var integer Specifies the maximum number of characters or list items allowed. Must be equal to or greater than zero
29
     */
30
    private $maxLength = null;
31
    /**
32
     * @Exclude
33
     * @var integer Specifies the minimum number of characters or list items allowed. Must be equal to or greater than zero
34
     */
35
    private $minLength = null;
36
    /**
37
     * @Exclude
38
     * @var string Specifies how white space (line feeds, tabs, spaces, and carriage returns) is handled
39
     */
40
    private $whiteSpaceHandle = "preserve";
41
    /**
42
     * @Exclude
43
     * @var string Defines the exact sequence of characters that are acceptable
44
     */
45
    private $pattern = null;
46
    /**
47
     * @Exclude
48
     * @var string Specifies the maximum number of decimal places allowed. Must be equal to or greater than zero
49
     */
50
    private $fractionDigits = null;
51
    /**
52
     * @Exclude
53
     * @var integer Specifies the lower bounds for numeric values (the value must be greater than this value)
54
     */
55
    private $minExclusive = null;
56
    /**
57
     * @Exclude
58
     * @var integer Specifies the upper bounds for numeric values (the value must be less than this value)
59
     */
60
    private $maxExclusive = null;
61
62
    /**
63
     * @property mixed $__value
64
     */
65
    private $__value = null;
66
67
    /**
68
     * Construct
69
     *
70
     * @param mixed $value
71
     */
72
    public function __construct($value)
73
    {
74
        $this->value($value);
75
    }
76
77
    /**
78
     * Gets or sets the inner value
79
     *
80
     * @param mixed ...$value
81
     * @return mixed
82
     * @throws \Exception
83
     */
84
    public function value(...$value)
85
    {
86
        if (0 >= count($value)) {
87
            return $this->__value;
88
        }
89
        $v = $this->fixValue($value[0]);
90
        $this->isBaseValid($v);
91
        $this->__value = $v;
92
        return $v;
93
    }
94
95
    protected function fixValue($v)
96
    {
97
        return $this->fixWhitespace($v, $this->whiteSpaceHandle);
98
    }
99
100
    protected function fixWhitespace($val, $handle = "preserve")
101
    {
102
        switch ($handle) {
103
            case "preserve":
104
                return $val;
105
            case "replace":
106
                return preg_replace('/\s/', ' ', $val);
107
            case "collapse":
108
                return preg_replace('/\s+/', ' ', $val);
109
            default:
110
                throw new \InvalidArgumentException(__CLASS__ . " Called Fix whitespace with invalid handle operation");
111
        }
112
    }
113
114
    private function isBaseValid($v)
115
    {
116
        $stringLen = strlen($v);
117 View Code Duplication
        if ($this->minLength != null) {
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...
118
            if ($stringLen > $this->minLength) {
119
                throw new \InvalidArgumentException("the provided value for " . __CLASS__ . " is to long minLength: "
120
                    . $this->minLength);
121
            }
122
        }
123
        if ($this->maxLength != null) {
124
            if ($stringLen < $this->maxLength) {
125
                throw new \InvalidArgumentException("the provided value for " . __CLASS__ . " is to short MaxLength: "
126
                    . $this->maxLength);
127
            }
128
        }
129
        if ($this->length != null) {
130
            if ($stringLen != $this->length) {
131
                throw new \InvalidArgumentException("the provided value for " . __CLASS__ . " is not "
132
                    . $this->length);
133
            }
134
        }
135
        if (is_array($this->enumeration) && !in_array($v, $this->enumeration)) {
136
            throw new \InvalidArgumentException("the provided value for " . __CLASS__ . " is not " .
137
                implode(" || ", $this->enumeration));
138
        }
139
        if ($this->pattern != null) {
140
            if (!$this->matchesRegexPattern($this->pattern, $v)) {
141
                throw new \InvalidArgumentException("assigned value that dose not match pattern " . __CLASS__);
142
            }
143
        }
144
        $this->isValid($v);
145
    }
146
147
    /**
148
     * Checks a pattern against a string
149
     * @param string $pattern the regex pattern
150
     * @param string $string the string to check
151
     * @return bool true if string matches pattern
152
     */
153
    private function matchesRegexPattern($pattern, $string)
154
    {
155
        $matches = null;
156
        return (1 == preg_match($pattern, $string, $matches) && $string == $matches[0]);
157
    }
158
159
    abstract protected function isValid($v);
160
161
    public function __set($name, $value)
162
    {
163
        switch ($name) {
164
            case "enumeration":
165
                $this->setEnumoration($value);
166
                return;
167
            case "totalDigits":
168
            case "length":
169
                $this->setMaxLength($value);
170
                $this->setMinLength($value);
171
                return;
172
            case "maxLength":
173
                $this->setMaxLength($value);
174
                return;
175
            case "minLength":
176
                $this->setMinLength($value);
177
                return;
178
            case "whiteSpaceHandle":
179
                $this->setWhiteSpaceHandle($value);
180
                return;
181
            case "pattern":
182
                $this->setPattern($value);
183
                return;
184
            case "fractionDigits":
185
                $this->setFractionDigits($value);
186
                return;
187
            case "minInclusive":
188
                $value--;
189
            // bump down by one to become MinExclusive
190
            case "minExclusive":
191
                $this->setMinExclusive($value);
192
                return;
193
            case "maxInclusive":
194
                $value++;
195
            // bump up by one to become MaxExclusive
196
            case "maxExclusive":
197
                $this->setMaxExclusive($value);
198
                return;
199
            default:
200
                throw new \InvalidArgumentException("Invalid parameters (facets) assignment for anyURI: " . __CLASS__);
201
        }
202
    }
203
204
    private function setEnumoration($value)
205
    {
206
        if (!is_array($value)) {
207
            throw new \InvalidArgumentException("enumoration values MUST be an array " . __CLASS__);
208
        }
209
        if (0 == count($value)) {
210
            throw new \InvalidArgumentException("enumoration values MUST have at least one value " . __CLASS__);
211
        }
212
        $this->enumeration = $value;
213
    }
214
215
    private function setMaxLength($value)
216
    {
217
        $this->checkLength($value);
218
        $this->maxLength = $value;
219
    }
220
221
    private function checkLength($value, $min = 0)
222
    {
223
        if (((int)$value) != $value) {
224
            throw new \InvalidArgumentException("length values MUST be castable to int " . __CLASS__);
225
        }
226
        if ($min >= $value) {
227
            throw new \InvalidArgumentException("length values MUST be greater then 0 " . __CLASS__);
228
        }
229
    }
230
231
    private function setMinLength($value)
232
    {
233
        $this->checkLength($value);
234
        $this->minLength = $value;
235
    }
236
237
    private function setWhiteSpaceHandle($value)
238
    {
239
        if (!in_array($value, ["preserve", "replace", "collapse"])) {
240
            throw new \InvalidArgumentException("Invalid white space handleing method " . __CLASS__);
241
        }
242
        $this->whiteSpaceHandle = $value;
243
    }
244
245
    private function setPattern($value)
246
    {
247
        if (!$this->checkPattern($value)) {
248
            $value = "/" . $value . "/";
249
            if (!$this->checkPattern($value)) {
250
                throw new \InvalidArgumentException("Invalid regex Pattern provided: " . __CLASS__);
251
            }
252
        }
253
        $this->pattern = $value;
254
    }
255
256
    private function checkPattern($pattern)
257
    {
258
        return (@preg_match($pattern, null) === false);
259
    }
260
261
    private function setFractionDigits($value)
262
    {
263
        $this->checkLength($value);
264
        $this->fractionDigits = $value;
265
    }
266
267
    private function setMinExclusive($value)
268
    {
269
        $this->checkLength($value, -1);
270
        $this->minExclusive = $value;
271
    }
272
273
    private function setMaxExclusive($value)
274
    {
275
        $this->checkLength($value);
276
        $this->maxExclusive = $value;
277
    }
278
279
    /**
280
     * Gets a string value
281
     *
282
     * @return mixed
283
     */
284
    public function __toString()
285
    {
286
        return strval($this->__value);
287
    }
288
289
    private function checkMinLength($v)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
290
    {
291
        $stringLen = strlen($v);
292 View Code Duplication
        if ($this->minLength != null) {
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...
293
            if ($stringLen > $this->minLength) {
294
                throw new \InvalidArgumentException("the provided value for " . __CLASS__ . " is to long minLength: "
295
                    . $this->minLength);
296
            }
297
        }
298
    }
299
}
300