Completed
Push — master ( 0777f1...91ab9a )
by Kevin
03:18
created

Attribute   B

Complexity

Total Complexity 42

Size/Duplication

Total Lines 227
Duplicated Lines 21.59 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 93.2%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 42
c 1
b 0
f 0
lcom 1
cbo 2
dl 49
loc 227
ccs 96
cts 103
cp 0.932
rs 8.295

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getName() 0 4 1
A getType() 0 4 1
B setType() 0 18 9
A getValue() 0 4 1
A getIsStandard() 0 4 1
A setIsStandard() 0 6 1
C clean() 37 71 14
A cleanAttributeBoolean() 0 9 2
C cleanAttributeInteger() 12 28 8
A cleanAttributeUri() 0 6 1
A __toString() 0 10 2

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

1
<?php
2
3
namespace Groundskeeper\Tokens;
4
5
use Groundskeeper\Configuration;
6
use Psr\Log\LoggerInterface;
7
8
class Attribute
9
{
10
    const BOOL      = 'ci_boo'; // boolean
11
    const CI_ENUM   = 'ci_enu'; // case-insensitive enumeration
12
    const CI_SSENUM = 'ci_sse'; // case-insensitive space-separated enumeration
13
    const INT       = 'ci_int'; // integer
14
    const JS        = 'cs_jsc'; // javascript
15
    const CI_STRING = 'ci_str'; // case-insensitive string
16
    const CS_STRING = 'cs_str'; // case-sensitive string
17
    const URI       = 'cs_uri'; // uri
18
19
    /** @var string */
20
    private $name;
21
22
    /** @var string */
23
    private $type;
24
25
    /** @var null|mixed */
26
    private $value;
27
28
    /** @var bool */
29
    private $isStandard;
30
31
    /**
32
     * Constructor
33
     */
34 57
    public function __construct($name, $value)
35
    {
36 57
        $this->name = $name;
37 57
        $this->type = null;
38 57
        $this->value = $value;
39 57
        $this->isStandard = false;
40 57
    }
41
42
    /**
43
     * Getter for 'name'.
44
     */
45 50
    public function getName()
46
    {
47 50
        return $this->name;
48
    }
49
50
    /**
51
     * Getter for 'type'.
52
     */
53
    public function getType()
54
    {
55
        return $this->type;
56
    }
57
58
    /**
59
     * Chainable setter for 'type'.
60
     */
61 49
    public function setType($type)
62
    {
63 49
        $typeEnum = mb_substr($type, 0, 6);
64 49
        if ($typeEnum !== self::BOOL &&
65 49
            $typeEnum !== self::CI_ENUM &&
66 49
            $typeEnum !== self::CI_SSENUM &&
67 49
            $typeEnum !== self::INT &&
68 49
            $typeEnum !== self::JS &&
69 49
            $typeEnum !== self::CI_STRING &&
70 49
            $typeEnum !== self::CS_STRING &&
71 49
            $typeEnum !== self::URI) {
72
            throw new \InvalidArgumentException('Invalid attribute type: ' . $typeEnum);
73
        }
74
75 49
        $this->type = $type;
76
77 49
        return $this;
78
    }
79
80
    /**
81
     * Getter for 'value'.
82
     */
83 4
    public function getValue()
84
    {
85 4
        return $this->value;
86
    }
87
88
    /**
89
     * Getter for 'isStandard'.
90
     */
91
    public function getIsStandard()
92
    {
93
        return $this->isStandard;
94
    }
95
96
    /**
97
     * Chainable setter for 'isStandard'.
98
     */
99 49
    public function setIsStandard($isStandard)
100
    {
101 49
        $this->isStandard = (bool) $isStandard;
102
103 49
        return $this;
104
    }
105
106 49
    public function clean(Configuration $configuration, Element $element, LoggerInterface $logger)
107
    {
108 49
        if ($configuration->get('clean-strategy') == Configuration::CLEAN_STRATEGY_NONE) {
109
            return true;
110
        }
111
112
        // Remove non-standard attributes.
113 49
        if ($configuration->get('clean-strategy') != Configuration::CLEAN_STRATEGY_LENIENT && $this->isStandard === false) {
114 8
            $logger->debug('Removing non-standard attribute "' . $this->name . '" from ' . $element);
115
116 8
            return false;
117
        }
118
119
        // Validate attribute value.
120 49
        list($caseSensitivity, $attributeType) = explode('_', $this->type);
121
122
        // Standard is case-insensitive attribute values should be lower case.
123 49
        if ($caseSensitivity == 'ci' && $this->value !== true) {
124 13
            $newValue = strtolower($this->value);
125 13 View Code Duplication
            if ($newValue !== $this->value) {
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...
126 2
                $logger->debug('Within ' . $element . ', the value for the attribute "' . $this->name . '" is case-insensitive.  The value has been converted to lower case.');
127 2
                $this->value = $newValue;
128 2
            }
129 13
        }
130
131
        // Validate value types.
132
        switch ($attributeType) {
133 49 View Code Duplication
        case 'boo': // boolean
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...
134 1
            $cleanResult = $this->cleanAttributeBoolean(
135 1
                $configuration,
136 1
                $element,
137
                $logger
138 1
            );
139 1
            if ($configuration->get('clean-strategy') != Configuration::CLEAN_STRATEGY_LENIENT) {
140 1
                return $cleanResult;
141
            }
142
143 1
            break;
144
145 48
        case 'enu': // enumeration
146
            /// @todo
147
            break;
148
149 48 View Code Duplication
        case 'int': // integer
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...
150 4
            $cleanResult = $this->cleanAttributeInteger(
151 4
                $configuration,
152 4
                $element,
153
                $logger
154 4
            );
155 4
            if ($configuration->get('clean-strategy') != Configuration::CLEAN_STRATEGY_LENIENT) {
156 4
                return $cleanResult;
157
            }
158
159 4
            break;
160
161 44 View Code Duplication
        case 'uri': // URI
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...
162 14
            $cleanResult = $this->cleanAttributeUri(
163 14
                $configuration,
164 14
                $element,
165
                $logger
166 14
            );
167 14
            if ($configuration->get('clean-strategy') != Configuration::CLEAN_STRATEGY_LENIENT) {
168 14
                return $cleanResult;
169
            }
170
171 14
            break;
172
        }
173
174
175 49
        return true;
176
    }
177
178 1
    private function cleanAttributeBoolean(Configuration $configuration, Element $element, LoggerInterface $logger)
0 ignored issues
show
Unused Code introduced by
The parameter $configuration is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
179
    {
180 1
        if ($this->value !== true) {
181 1
            $logger->debug('Within ' . $element . ', the attribute "' . $this->name . '" is a boolean attribute.  The value has been removed.');
182 1
            $this->value = true;
183 1
        }
184
185 1
        return true;
186
    }
187
188 4
    private function cleanAttributeInteger(Configuration $configuration, Element $element, LoggerInterface $logger)
189
    {
190 4
        if ($this->value === true ||
191 4
            $this->value == '') {
192 1 View Code Duplication
            if ($configuration->get('clean-strategy') !== Configuration::CLEAN_STRATEGY_LENIENT) {
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...
193 1
                $logger->debug('Within ' . $element . ', the value for the attribute "' . $this->name . '" is required to be an positive, non-zero integer.  The value is invalid, therefore the attribute has been removed.');
194 1
            }
195
196 1
            return false;
197
        }
198
199 4
        if (!is_int($this->value)) {
200 4
            $origonalValue = (string) $this->value;
201 4
            $this->value = (int) $this->value;
202 4 View Code Duplication
            if ($origonalValue != ((string) $this->value)) {
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...
203 2
                $logger->debug('Within ' . $element . ', the value for the attribute "' . $this->name . '" is required to be an positive, non-zero integer.  The value has been converted to an integer.');
204 2
            }
205 4
        }
206
207 4 View Code Duplication
        if ($this->value <= 0 &&
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...
208 4
        $configuration->get('clean-strategy') !== Configuration::CLEAN_STRATEGY_LENIENT) {
209 1
            $logger->debug('Within ' . $element . ', the value for the attribute "' . $this->value . '" is required to be an positive, non-zero integer.  The value is invalid, therefore the attribute has been removed.');
210
211 1
            return false;
212
        }
213
214 4
        return true;
215
    }
216
217 14
    private function cleanAttributeUri(Configuration $configuration, Element $element, LoggerInterface $logger)
0 ignored issues
show
Unused Code introduced by
The parameter $configuration is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $element is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $logger is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
218
    {
219
        /// @todo
220
221 14
        return true;
222
    }
223
224 51
    public function __toString()
225
    {
226 51
        $output = $this->name;
227 51
        if ($this->value === true) {
228 3
            return $output;
229
        }
230
231
        /// @todo Escape double quotes in value.
232 51
        return $output . '="' . $this->value . '"';
233
    }
234
}
235