AbstractAction   B
last analyzed

Complexity

Total Complexity 42

Size/Duplication

Total Lines 336
Duplicated Lines 19.64 %

Coupling/Cohesion

Components 2
Dependencies 2

Importance

Changes 0
Metric Value
wmc 42
lcom 2
cbo 2
dl 66
loc 336
rs 8.295
c 0
b 0
f 0

23 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setLink() 0 4 1
A getLink() 0 4 1
A getLinkReplaced() 10 19 4
A getColumnValuePlaceholder() 0 6 1
A getLinkColumnPlaceholders() 0 4 1
A getRowIdPlaceholder() 0 4 1
A setAttribute() 0 4 1
A getAttribute() 0 8 2
A removeAttribute() 0 6 2
A getAttributes() 0 4 1
A getAttributesString() 12 12 3
A setTitle() 0 4 1
A getTitle() 0 4 1
A addClass() 0 10 2
A setShowOnValueOperator() 8 8 3
A getShowOnValueOperator() 0 4 1
A addShowOnValue() 0 8 1
A getShowOnValues() 0 4 1
A hasShowOnValues() 0 8 2
D isDisplayed() 36 36 10
getHtmlType() 0 1 ?
A toHtml() 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 AbstractAction 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 AbstractAction, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace ZfcDatagrid\Column\Action;
4
5
use ZfcDatagrid\Column;
6
use ZfcDatagrid\Column\AbstractColumn;
7
use ZfcDatagrid\Filter;
8
9
abstract class AbstractAction
10
{
11
    const ROW_ID_PLACEHOLDER = ':rowId:';
12
13
    /**
14
     * @var \ZfcDatagrid\Column\AbstractColumn[]
15
     */
16
    protected $linkColumnPlaceholders = [];
17
18
    /**
19
     * @var array
20
     */
21
    protected $htmlAttributes = [];
22
23
    /**
24
     * @var string
25
     */
26
    protected $showOnValueOperator = 'OR';
27
28
    /**
29
     * @var array
30
     */
31
    protected $showOnValues = [];
32
33
    public function __construct()
34
    {
35
        $this->setLink('#');
36
    }
37
38
    /**
39
     * Set the link.
40
     *
41
     * @param string $href
42
     */
43
    public function setLink($href)
44
    {
45
        $this->setAttribute('href', $href);
46
    }
47
48
    /**
49
     * @return string
50
     */
51
    public function getLink()
52
    {
53
        return $this->getAttribute('href');
54
    }
55
56
    /**
57
     * This is needed public for rowClickAction...
58
     *
59
     * @param array $row
60
     *
61
     * @return string
62
     */
63
    public function getLinkReplaced(array $row)
64
    {
65
        $link = $this->getLink();
66
67
        // Replace placeholders
68 View Code Duplication
        if (strpos($this->getLink(), self::ROW_ID_PLACEHOLDER) !== false) {
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...
69
            $id = '';
70
            if (isset($row['idConcated'])) {
71
                $id = $row['idConcated'];
72
            }
73
            $link = str_replace(self::ROW_ID_PLACEHOLDER, $id, $link);
74
        }
75
76 View Code Duplication
        foreach ($this->getLinkColumnPlaceholders() as $col) {
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...
77
            $link = str_replace(':'.$col->getUniqueId().':', $row[$col->getUniqueId()], $link);
78
        }
79
80
        return $link;
81
    }
82
83
    /**
84
     * Get the column row value placeholder
85
     * $action->setLink('/myLink/something/id/'.$action->getRowIdPlaceholder().'/something/'.$action->getColumnRowPlaceholder($myCol));.
86
     *
87
     * @param AbstractColumn $col
88
     *
89
     * @return string
90
     */
91
    public function getColumnValuePlaceholder(AbstractColumn $col)
92
    {
93
        $this->linkColumnPlaceholders[] = $col;
94
95
        return ':'.$col->getUniqueId().':';
96
    }
97
98
    /**
99
     * @return \ZfcDatagrid\Column\AbstractColumn[]
100
     */
101
    public function getLinkColumnPlaceholders()
102
    {
103
        return $this->linkColumnPlaceholders;
104
    }
105
106
    /**
107
     * Returns the rowId placeholder
108
     * Can be used e.g.
109
     * $action->setLink('/myLink/something/id/'.$action->getRowIdPlaceholder());.
110
     *
111
     * @return string
112
     */
113
    public function getRowIdPlaceholder()
114
    {
115
        return self::ROW_ID_PLACEHOLDER;
116
    }
117
118
    /**
119
     * Set a HTML attributes.
120
     *
121
     * @param string $name
122
     * @param string $value
123
     */
124
    public function setAttribute($name, $value)
125
    {
126
        $this->htmlAttributes[$name] = (string) $value;
127
    }
128
129
    /**
130
     * Get a HTML attribute.
131
     *
132
     * @param string $name
133
     *
134
     * @return string
135
     */
136
    public function getAttribute($name)
137
    {
138
        if (isset($this->htmlAttributes[$name])) {
139
            return $this->htmlAttributes[$name];
140
        }
141
142
        return '';
143
    }
144
145
    /**
146
     * Removes an HTML attribute.
147
     *
148
     * @param string $name
149
     */
150
    public function removeAttribute($name)
151
    {
152
        if (isset($this->htmlAttributes[$name])) {
153
            unset($this->htmlAttributes[$name]);
154
        }
155
    }
156
157
    /**
158
     * Get all HTML attributes.
159
     *
160
     * @return array
161
     */
162
    public function getAttributes()
163
    {
164
        return $this->htmlAttributes;
165
    }
166
167
    /**
168
     * Get the string version of the attributes.
169
     *
170
     * @param array $row
171
     *
172
     * @return string
173
     */
174 View Code Duplication
    protected function getAttributesString(array $row)
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...
175
    {
176
        $attributes = [];
177
        foreach ($this->getAttributes() as $attrKey => $attrValue) {
178
            if ('href' === $attrKey) {
179
                $attrValue = $this->getLinkReplaced($row);
180
            }
181
            $attributes[] = $attrKey.'="'.$attrValue.'"';
182
        }
183
184
        return implode(' ', $attributes);
185
    }
186
187
    /**
188
     * Set the title attribute.
189
     *
190
     * @param string $name
191
     */
192
    public function setTitle($name)
193
    {
194
        $this->setAttribute('title', $name);
195
    }
196
197
    /**
198
     * Get the title attribute.
199
     *
200
     * @return string
201
     */
202
    public function getTitle()
203
    {
204
        return $this->getAttribute('title');
205
    }
206
207
    /**
208
     * Add a css class.
209
     *
210
     * @param string $className
211
     */
212
    public function addClass($className)
213
    {
214
        $attr = $this->getAttribute('class');
215
        if ($attr != '') {
216
            $attr .= ' ';
217
        }
218
        $attr .= (string) $className;
219
220
        $this->setAttribute('class', $attr);
221
    }
222
223
    /**
224
     * Display the values with AND or OR (if multiple showOnValues are defined).
225
     *
226
     * @param string $operator
227
     */
228 View Code Duplication
    public function setShowOnValueOperator($operator = 'OR')
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...
229
    {
230
        if ($operator != 'AND' && $operator != 'OR') {
231
            throw new \InvalidArgumentException('not allowed operator: "'.$operator.'" (AND / OR is allowed)');
232
        }
233
234
        $this->showOnValueOperator = (string) $operator;
235
    }
236
237
    /**
238
     * Get the show on value operator, e.g.
239
     * OR, AND.
240
     *
241
     * @return string
242
     */
243
    public function getShowOnValueOperator()
244
    {
245
        return $this->showOnValueOperator;
246
    }
247
248
    /**
249
     * Show this action only on the values defined.
250
     *
251
     * @param Column\AbstractColumn $col
252
     * @param string                $value
253
     * @param string                $comparison
254
     */
255
    public function addShowOnValue(Column\AbstractColumn $col, $value = null, $comparison = Filter::EQUAL)
256
    {
257
        $this->showOnValues[] = [
258
            'column' => $col,
259
            'value' => $value,
260
            'comparison' => $comparison,
261
        ];
262
    }
263
264
    /**
265
     * @return array
266
     */
267
    public function getShowOnValues()
268
    {
269
        return $this->showOnValues;
270
    }
271
272
    /**
273
     * @return bool
274
     */
275
    public function hasShowOnValues()
276
    {
277
        if (count($this->showOnValues) > 0) {
278
            return true;
279
        }
280
281
        return false;
282
    }
283
284
    /**
285
     * Display this action on this row?
286
     *
287
     * @param array $row
288
     *
289
     * @return bool
290
     */
291 View Code Duplication
    public function isDisplayed(array $row)
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...
292
    {
293
        if ($this->hasShowOnValues() === false) {
294
            return true;
295
        }
296
297
        $isDisplayed = false;
298
        foreach ($this->getShowOnValues() as $rule) {
299
            $value = '';
300
            if (isset($row[$rule['column']->getUniqueId()])) {
301
                $value = $row[$rule['column']->getUniqueId()];
302
            }
303
304
            if ($rule['value'] instanceof AbstractColumn) {
305
                if (isset($row[$rule['value']->getUniqueId()])) {
306
                    $ruleValue = $row[$rule['value']->getUniqueId()];
307
                } else {
308
                    $ruleValue = '';
309
                }
310
            } else {
311
                $ruleValue = $rule['value'];
312
            }
313
314
            $isDisplayedMatch = Filter::isApply($value, $ruleValue, $rule['comparison']);
315
            if ($this->getShowOnValueOperator() == 'OR' && true === $isDisplayedMatch) {
316
                // For OR one match is enough
317
                return true;
318
            } elseif ($this->getShowOnValueOperator() == 'AND' && false === $isDisplayedMatch) {
319
                return false;
320
            } else {
321
                $isDisplayed = $isDisplayedMatch;
322
            }
323
        }
324
325
        return $isDisplayed;
326
    }
327
328
    /**
329
     * Get the HTML from the type.
330
     *
331
     * @return string
332
     */
333
    abstract protected function getHtmlType();
334
335
    /**
336
     * @param array $row
337
     *
338
     * @return string
339
     */
340
    public function toHtml(array $row)
341
    {
342
        return '<a '.$this->getAttributesString($row).'>'.$this->getHtmlType().'</a>';
343
    }
344
}
345