Passed
Push — master ( b55be9...f6f22e )
by Christopher
01:29
created

SimpleTypeBase   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 268
Duplicated Lines 7.46 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 46
lcom 1
cbo 0
dl 20
loc 268
rs 8.3999
c 0
b 0
f 0

25 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A value() 0 10 2
A fixValue() 0 6 1
A fixWhitespace() 0 13 4
A fixFractionDigits() 0 6 2
A isBaseValid() 0 8 1
A checkMinLength() 10 10 3
A checkMaxLength() 10 10 3
A checkEnumeration() 0 7 3
A checkPattern() 0 8 3
A matchesRegexPattern() 0 5 2
isValid() 0 1 ?
A __set() 0 10 2
A __toString() 0 4 1
A setEnumoration() 0 10 3
A setLength() 0 5 1
A setMinLength() 0 5 1
A checkLength() 0 9 3
A setMaxLength() 0 5 1
A setWhiteSpaceHandle() 0 7 2
A setPattern() 0 10 3
A checkRegexValidPattern() 0 4 1
A setFractionDigits() 0 5 1
A setMinExclusive() 0 5 1
A setMaxExclusive() 0 5 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 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 integer $fractionDigits Specifies the maximum number of decimal places allowed. Must be equal to or greater than zero
8
 * @property-write integer $length Specifies the exact number of characters or list items allowed. Must be equal to or greater than zero
9
 * @property-write integer $maxExclusive Specifies the upper bounds for numeric values (the value must be less than this value)
10
 * @property-write integer $maxInclusive Specifies the upper bounds for numeric values (the value must be less than or equal to this value)
11
 * @property-write integer $maxLength Specifies the maximum number of characters or list items allowed. Must be equal to or greater than zero
12
 * @property-write integer $minExclusive Specifies the lower bounds for numeric values (the value must be greater than this value)
13
 * @property-write integer $minInclusive Specifies the lower bounds for numeric values (the value must be greater than or equal to this value)
14
 * @property-write integer $minLength Specifies the lower bounds for numeric values (the value must be greater than or equal to this value)
15
 * @property-write string $pattern Defines the exact sequence of characters that are acceptable
16
 * @property-write integer $totalDigits Specifies the exact number of digits allowed. Must be greater than zero
17
 * @property-write string $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 $whiteSpace = "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
98
        $v = $this->fixWhitespace($v, $this->whiteSpace);
99
        return $this->fixFractionDigits($v,$this->fractionDigits);
100
    }
101
102
    protected function fixWhitespace($val, $handle = "preserve")
103
    {
104
        switch ($handle) {
105
            case "preserve":
106
                return $val;
107
            case "replace":
108
                return preg_replace('/\s/', ' ', $val);
109
            case "collapse":
110
                return preg_replace('/\s+/', ' ', $val);
111
            default:
112
                throw new \InvalidArgumentException(__CLASS__ . " Called Fix whitespace with invalid handle operation");
113
        }
114
    }
115
116
    protected function fixFractionDigits($val,$fractionDigits = null){
117
        if(null ==$fractionDigits ) {
118
            return $val;
119
        }
120
        return round($val);
121
    }
122
123
    private function isBaseValid($v)
124
    {
125
        $this->checkMinLength($v);
126
        $this->checkMaxLength($v);
127
        $this->checkEnumeration($v);
128
        $this->checkPattern($v);
129
        $this->isValid($v);
130
    }
131
132 View Code Duplication
    private function checkMinLength($v)
133
    {
134
        $stringLen = strlen($v);
135
        if ($this->minLength != null) {
136
            if ($stringLen > $this->minLength) {
137
                throw new \InvalidArgumentException("the provided value for " . __CLASS__ . " is to long minLength: "
138
                    . $this->minLength);
139
            }
140
        }
141
    }
142
143 View Code Duplication
    private function checkMaxLength($v)
144
    {
145
        $stringLen = strlen($v);
146
        if ($this->maxLength != null) {
147
            if ($stringLen < $this->maxLength) {
148
                throw new \InvalidArgumentException("the provided value for " . __CLASS__ . " is to short MaxLength: "
149
                    . $this->maxLength);
150
            }
151
        }
152
    }
153
154
    private function checkEnumeration($v)
155
    {
156
        if (is_array($this->enumeration) && !in_array($v, $this->enumeration)) {
157
            throw new \InvalidArgumentException("the provided value for " . __CLASS__ . " is not " .
158
                implode(" || ", $this->enumeration));
159
        }
160
    }
161
162
    private function checkPattern($v)
163
    {
164
        if ($this->pattern != null) {
165
            if (!$this->matchesRegexPattern($this->pattern, $v)) {
166
                throw new \InvalidArgumentException("assigned value that dose not match pattern " . __CLASS__);
167
            }
168
        }
169
    }
170
171
    /**
172
     * Checks a pattern against a string
173
     * @param string $pattern the regex pattern
174
     * @param string $string the string to check
175
     * @return bool true if string matches pattern
176
     */
177
    private function matchesRegexPattern($pattern, $string)
178
    {
179
        $matches = null;
180
        return (1 == preg_match($pattern, $string, $matches) && $string == $matches[0]);
181
    }
182
183
    abstract protected function isValid($v);
184
185
    public function __set($name, $value)
186
    {
187
        if (!in_array($name, ["enumeration", "totalDigits", "length", "maxLength", "minLength", "whiteSpace",
188
            "pattern", "fractionDigits", "minInclusive", "minExclusive", "maxExclusive"])
189
        ) {
190
            throw new \InvalidArgumentException("Invalid parameters (facets) assignment for: " . __CLASS__);
191
        }
192
        $setFunctionName = "set" . ucfirst($name);
193
        $this->$setFunctionName($value);
194
    }
195
196
    /**
197
     * Gets a string value
198
     *
199
     * @return string
200
     */
201
    public function __toString()
202
    {
203
        return strval($this->__value);
204
    }
205
206
    private function setEnumoration($value)
207
    {
208
        if (!is_array($value)) {
209
            throw new \InvalidArgumentException("enumoration values MUST be an array " . __CLASS__);
210
        }
211
        if (0 == count($value)) {
212
            throw new \InvalidArgumentException("enumoration values MUST have at least one value " . __CLASS__);
213
        }
214
        $this->enumeration = $value;
215
    }
216
217
    private function setLength($value)
218
    {
219
        $this->setMinLength($value);
220
        $this->setMaxLength($value);
221
    }
222
223
    private function setMinLength($value)
224
    {
225
        $this->checkLength($value);
226
        $this->minLength = $value;
227
    }
228
229
    private function checkLength($value, $min = 0)
230
    {
231
        if (((int)$value) != $value) {
232
            throw new \InvalidArgumentException("length values MUST be castable to int " . __CLASS__);
233
        }
234
        if ($min >= $value) {
235
            throw new \InvalidArgumentException("length values MUST be greater then 0 " . __CLASS__);
236
        }
237
    }
238
239
    private function setMaxLength($value)
240
    {
241
        $this->checkLength($value);
242
        $this->maxLength = $value;
243
    }
244
245
    private function setWhiteSpaceHandle($value)
246
    {
247
        if (!in_array($value, ["preserve", "replace", "collapse"])) {
248
            throw new \InvalidArgumentException("Invalid white space handleing method " . __CLASS__);
249
        }
250
        $this->whiteSpace = $value;
251
    }
252
253
    private function setPattern($value)
254
    {
255
        if (!$this->checkRegexValidPattern($value)) {
256
            $value = "/" . $value . "/";
257
            if (!$this->checkRegexValidPattern($value)) {
258
                throw new \InvalidArgumentException("Invalid regex Pattern provided: " . __CLASS__);
259
            }
260
        }
261
        $this->pattern = $value;
262
    }
263
264
    private function checkRegexValidPattern($pattern)
265
    {
266
        return (@preg_match($pattern, null) === false);
267
    }
268
269
    private function setFractionDigits($value)
270
    {
271
        $this->checkLength($value);
272
        $this->fractionDigits = $value;
273
    }
274
275
    private function setMinExclusive($value)
276
    {
277
        $this->checkLength($value, -1);
278
        $this->minExclusive = $value;
279
    }
280
281
    private function setMaxExclusive($value)
282
    {
283
        $this->checkLength($value);
284
        $this->maxExclusive = $value;
285
    }
286
}
287