Completed
Push — master ( 655b5a...34bcd6 )
by Pavel
02:21
created

Row   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 317
Duplicated Lines 19.56 %

Coupling/Cohesion

Components 2
Dependencies 5

Test Coverage

Coverage 40.21%

Importance

Changes 6
Bugs 0 Features 1
Metric Value
wmc 44
c 6
b 0
f 1
lcom 2
cbo 5
dl 62
loc 317
ccs 39
cts 97
cp 0.4021
rs 8.3396

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 2
A getId() 0 4 1
A getControl() 0 4 1
A getControlClass() 0 8 2
C getValue() 0 28 7
C getActiveRowProperty() 18 24 7
B getLeanMapperEntityProperty() 22 22 4
B getNextrasEntityProperty() 22 22 4
B getDoctrineEntityProperty() 0 23 5
A getItem() 0 4 1
A hasGroupAction() 0 6 2
A hasAction() 0 6 2
A hasInlineEdit() 0 6 2
A applyColumnCallback() 0 10 2
A formatDibiRowKey() 0 8 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 Row 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 Row, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * @copyright   Copyright (c) 2015 ublaboo <[email protected]>
5
 * @author      Pavel Janda <[email protected]>
6
 * @package     Ublaboo
7
 */
8
9
namespace Ublaboo\DataGrid;
10
11
use Nette;
12
use LeanMapper;
13
use Nextras;
14
use DibiRow;
15
use Ublaboo\DataGrid\Utils\PropertyAccessHelper;
16
use Nette\Utils\Html;
17
use Ublaboo\DataGrid\Exception\DataGridException;
18
use Nette\Database\Table\ActiveRow;
19
20
class Row extends Nette\Object
21 1
{
22
23 1
	/**
24
	 * @var DataGrid
25
	 */
26
	protected $datagrid;
27
28
	/**
29
	 * @var mixed
30
	 */
31
	protected $item;
32
33
	/**
34
	 * @var string
35
	 */
36
	protected $primary_key;
37
38
	/**
39
	 * @var mixed
40
	 */
41
	protected $id;
42
43
	/**
44
	 * @var Html
45
	 */
46
	protected $control;
47
48
49
	/**
50
	 * @param DataGrid $datagrid
51
	 * @param mixed    $item
52
	 * @param string   $primary_key
53
	 */
54
	public function __construct(DataGrid $datagrid, $item, $primary_key)
55
	{
56 1
		$this->control = Html::el('tr');
57 1
		$this->datagrid = $datagrid;
58 1
		$this->item = $item;
59 1
		$this->primary_key = $primary_key;
60 1
		$this->id = $this->getValue($primary_key);
61
62 1
		if ($datagrid->hasColumnsSummary()) {
63
			$datagrid->getColumnsSummary()->add($this);
64
		}
65 1
	}
66
67
68
	/**
69
	 * Get id value of item
70
	 * @return mixed
71
	 */
72
	public function getId()
73
	{
74 1
		return $this->id;
75
	}
76
77
78
	/**
79
	 * Get item value of key
80
	 * @param  mixed $key
81
	 * @return mixed
82
	 */
83
	public function getValue($key)
84
	{
85 1
		if ($this->item instanceof LeanMapper\Entity) {
86 1
			return $this->getLeanMapperEntityProperty($this->item, $key);
87
88 1
		} else if ($this->item instanceof Nextras\Orm\Entity\Entity) {
89
			return $this->getNextrasEntityProperty($this->item, $key);
90
91 1
		} else if ($this->item instanceof DibiRow) {
0 ignored issues
show
Bug introduced by
The class DibiRow does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
92
			return $this->item->{$this->formatDibiRowKey($key)};
93
94 1
		} else if ($this->item instanceof ActiveRow) {
95
			return $this->getActiveRowProperty($this->item, $key);
96
97 1
		} else if ($this->item instanceof Nette\Database\Row) {
98
			return $this->item->{$key};
99
100 1
		} else if (is_array($this->item)) {
101 1
			return $this->item[$key];
102
103
		} else {
104
			/**
105
			 * Doctrine entity
106
			 */
107 1
			return $this->getDoctrineEntityProperty($this->item, $key);
108
109
		}
110
	}
111
112
113
	/**
114
	 * @return Html
115
	 */
116
	public function getControl()
117
	{
118 1
		return $this->control;
119
	}
120
121
122
	/**
123
	 * @return string
124
	 */
125
	public function getControlClass()
126
	{
127 1
		if (!$class = $this->control->class) {
128
			return '';
129
		}
130
131 1
		return implode(' ', array_keys($class));
132
	}
133
134
135
	/**
136
	 * @param  ActiveRow $item
137
	 * @param  string    $key
138
	 * @return mixed|NULL
139
	 */
140
	public function getActiveRowProperty(ActiveRow $item, $key)
0 ignored issues
show
Unused Code introduced by
The parameter $item 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...
141
	{
142 View Code Duplication
		if (preg_match("/^:([a-zA-Z0-9_$]+)\.([a-zA-Z0-9_$]+)(:([a-zA-Z0-9_$]+))?$/", $key, $matches)) {
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...
143
			$relatedTable = $matches[1];
144
			$relatedColumn = $matches[2];
145
			$throughColumn = isset($matches[4]) ? $matches[4] : NULL;
146
147
			$relatedRow = $this->item->related($relatedTable, $throughColumn)->fetch();
148
149
			return $relatedRow ? $relatedRow->{$relatedColumn} : NULL;
150
		}
151
152 1 View Code Duplication
		if (preg_match("/^([a-zA-Z0-9_$]+)\.([a-zA-Z0-9_$]+)(:([a-zA-Z0-9_$]+))?$/", $key, $matches)) {
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...
153
			$referencedTable = $matches[1];
154
			$referencedColumn = $matches[2];
155
			$throughColumn = isset($matches[4]) ? $matches[4] : NULL;
156
157
			$referencedRow = $this->item->ref($referencedTable, $throughColumn);
158
159
			return $referencedRow ? $referencedRow->{$referencedColumn} : NULL;
160
		}
161
162
		return $this->item->{$key};
163
	}
164
165
166
	/**
167
	 * LeanMapper: Access object properties to get a item value
168
	 * @param  LeanMapper\Entity $item
169
	 * @param  mixed             $key
170
	 * @return mixed
171
	 */
172 View Code Duplication
	public function getLeanMapperEntityProperty(LeanMapper\Entity $item, $key)
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...
173
	{
174 1
		$properties = explode('.', $key);
175 1
		$value = $item;
176
177 1
		while ($property = array_shift($properties)) {
178 1
			if (!isset($value->{$property})) {
179
				if ($this->datagrid->strict_entity_property) {
180
					throw new DataGridException(sprintf(
181
						'Target Property [%s] is not an object or is empty, trying to get [%s]',
182
						$value, str_replace('.', '->', $key)
183
					));
184
				}
185
186
				return NULL;
187
			}
188
189 1
			$value = $value->{$property};
190 1
		}
191
192 1
		return $value;
193
	}
194
195
196
	/**
197
	 * Nextras: Access object properties to get a item value
198
	 * @param  Nextras\Orm\Entity\Entity $item
199
	 * @param  string                    $key
200
	 * @return mixed
201
	 */
202 View Code Duplication
	public function getNextrasEntityProperty(Nextras\Orm\Entity\Entity $item, $key)
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...
203
	{
204
		$properties = explode('.', $key);
205
		$value = $item;
206
207
		while ($property = array_shift($properties)) {
208
			if (!isset($value->{$property})) {
209 1
				if ($this->datagrid->strict_entity_property) {
210
					throw new DataGridException(sprintf(
211
						'Target Property [%s] is not an object or is empty, trying to get [%s]',
212
						$value, str_replace('.', '->', $key)
213
					));
214
				}
215
216
				return NULL;
217
			}
218
219
			$value = $value->{$property};
220
		}
221
222
		return $value;
223
	}
224
225
226
	/**
227
	 * Doctrine: Access object properties to get a item value
228
	 * @param  mixed $item
229
	 * @param  mixed $key
230
	 * @return mixed
231
	 */
232
	public function getDoctrineEntityProperty($item, $key)
233
	{
234 1
		$properties = explode('.', $key);
235 1
		$value = $item;
236 1
		$accessor = PropertyAccessHelper::getAccessor();
237
238 1
		while ($property = array_shift($properties)) {
239 1
			if (!is_object($value) && !$value) {
240
				if ($this->datagrid->strict_entity_property) {
241
					throw new DataGridException(sprintf(
242
						'Target Property [%s] is not an object or is empty, trying to get [%s]',
243
						$value, str_replace('.', '->', $key)
244
					));
245
				}
246
247
				return NULL;
248
			}
249
250 1
			$value = $accessor->getValue($value, $property);
251 1
		}
252
253 1
		return $value;
254
	}
255
256
257
	/**
258
	 * Get original item
259
	 * @return mixed
260
	 */
261
	public function getItem()
262
	{
263
		return $this->item;
264
	}
265
266
267
	/**
268
	 * Has particular row group actions allowed?
269
	 * @return bool
270
	 */
271
	public function hasGroupAction()
272
	{
273
		$condition = $this->datagrid->getRowCondition('group_action');
274
275
		return $condition ? $condition($this->item) : TRUE;
276
	}
277
278
279
	/**
280
	 * Has particular row a action allowed?
281
	 * @param  mixed  $key
282
	 * @return bool
283
	 */
284
	public function hasAction($key)
285
	{
286
		$condition = $this->datagrid->getRowCondition('action', $key);
287
288
		return $condition ? $condition($this->item) : TRUE;
289
	}
290
291
292
	/**
293
	 * Has particular row inlie edit allowed?
294
	 * @return bool
295
	 */
296
	public function hasInlineEdit()
297
	{
298
		$condition = $this->datagrid->getRowCondition('inline_edit');
299
300
		return $condition ? $condition($this->item) : TRUE;
301
	}
302
303
304
	/**
305
	 * @param  string        $key
306
	 * @param  Column\Column $column
307
	 * @return void
308
	 */
309
	public function applyColumnCallback($key, Column\Column $column)
310
	{
311
		$callback = $this->datagrid->getColumnCallback($key);
312
313
		if ($callback !== NULL) {
314
			call_user_func($callback, $column, $this->getItem());
315
		}
316
317
		return $column;
318
	}
319
320
321
	/**
322
	 * Key may contain ".", get rid of it (+ the table alias)
323
	 * 
324
	 * @param  string $key
325
	 * @return string
326
	 */
327
	private function formatDibiRowKey($key)
328
	{
329
		if ($offset = strpos($key, '.')) {
330
			return substr($key, $offset + 1);
331
		}
332
333
		return $key;
334
	}
335
336
}
337