Completed
Push — master ( e6e660...2d183f )
by Pavel
02:25
created

Action::getItemParams()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 10
Ratio 100 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 10
loc 10
rs 9.4285
cc 3
eloc 5
nc 3
nop 1
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\Column;
10
11
use Nette\Utils\Html;
12
use Ublaboo\DataGrid\DataGrid;
13
use Ublaboo\DataGrid\Row;
14
15
class Action extends Column
16
{
17
18
	/**
19
	 * @var string
20
	 */
21
	protected $title;
22
23
	/**
24
	 * @var string
25
	 */
26
	protected $class;
27
28
	/**
29
	 * @var string
30
	 */
31
	protected $icon;
32
33
	/**
34
	 * @var DataGrid
35
	 */
36
	protected $grid;
37
38
	/**
39
	 * @var string
40
	 */
41
	protected $href;
42
43
	/**
44
	 * @var string
45
	 */
46
	protected $name;
47
48
	/**
49
	 * @var array
50
	 */
51
	protected $params;
52
53
	/**
54
	 * @var array
55
	 */
56
	protected $confirm;
57
58
59
	/**
60
	 * @param DataGrid $grid
61
	 * @param string   $href
62
	 * @param string   $name
63
	 * @param array    $params
64
	 */
65
	public function __construct(DataGrid $grid, $href, $name, $params)
66
	{
67
		$this->grid = $grid;
68
		$this->href = $href;
69
		$this->name = $name;
70
		$this->params = $params;
71
72
		$this->class = 'btn btn-xs btn-default';
73
	}
74
75
76
	/**
77
	 * Render row item into template
78
	 * @param  Row   $row
79
	 * @return mixed
80
	 */
81
	public function render(Row $row)
82
	{
83
		/**
84
		 * Renderer function may be used
85
		 */
86 View Code Duplication
		if ($renderer = $this->getRenderer()) {
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...
87
			if (!$renderer->getConditionCallback()) {
88
				return call_user_func_array($renderer->getCallback(), [$row->getItem()]);
89
			}
90
91
			if (call_user_func_array($this->getRenderer(), [$row->getItem()])) {
92
				return call_user_func_array($renderer->getCallback(), [$row->getItem()]);
93
			}
94
		}
95
96
		$a = Html::el('a')
97
			->href($this->grid->getPresenter()->link($this->href, $this->getItemParams($row)));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Nette\ComponentModel\IComponent as the method link() does only exist in the following implementations of said interface: Nette\Application\UI\Control, Nette\Application\UI\Multiplier, Nette\Application\UI\Presenter, Nette\Application\UI\PresenterComponent, Ublaboo\DataGrid\Compone...nator\DataGridPaginator, Ublaboo\DataGrid\DataGrid.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
98
99 View Code Duplication
		if ($this->icon) {
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...
100
			$a->add(Html::el('span')->class(DataGrid::$icon_prefix.$this->icon));
101
			
102
			if (strlen($this->name)) {
103
				$a->add('&nbsp;');
104
			}
105
		}
106
107
		$a->add($this->name);
108
109
		if ($this->title) { $a->title($this->title); }
110
		if ($this->class) { $a->class($this->class); }
111
		if ($confirm = $this->getConfirm($row)) { $a->data('confirm', $confirm); }
112
113
		return $a;
114
	}
115
116
117
	/**
118
	 * Set attribute title
119
	 * @param string $title
120
	 */
121
	public function setTitle($title)
122
	{
123
		$this->title = $title;
124
125
		return $this;
126
	}
127
128
129
	/**
130
	 * Get attribute title
131
	 * @return string
132
	 */
133
	public function getTitle()
134
	{
135
		return $this->title;
136
	}
137
138
139
	/**
140
	 * Set attribute class
141
	 * @param string $class
142
	 */
143
	public function setClass($class)
144
	{
145
		$this->class = $class;
146
147
		return $this;
148
	}
149
150
151
	/**
152
	 * Get attribute class
153
	 * @return string
154
	 */
155
	public function getClass()
156
	{
157
		return $this->class;
158
	}
159
160
161
	/**
162
	 * Set icon
163
	 * @param string $icon
164
	 */
165
	public function setIcon($icon)
166
	{
167
		$this->icon = $icon;
168
169
		return $this;
170
	}
171
172
173
	/**
174
	 * Get icon
175
	 * @return string
176
	 */
177
	public function getIcon()
178
	{
179
		return $this->icon;
180
	}
181
182
183
	/**
184
	 * Set confirm dialog
185
	 * @param string $message
186
	 * @param string $column
187
	 */
188
	public function setConfirm($message, $column = NULL)
189
	{
190
		$this->confirm = [$message, $column];
191
192
		return $this;
193
	}
194
195
196
	/**
197
	 * Get confirm dialog for particular row item
198
	 * @param Row $row
199
	 */
200
	public function getConfirm(Row $row)
201
	{
202
		if (!$this->confirm) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->confirm of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
203
			return NULL;
204
		}
205
206
		if (!$this->confirm[1]) {
207
			return $this->confirm[0];
208
		}
209
210
		return str_replace('%s', $row->getValue($this->confirm[1]), $this->confirm[0]);
211
	}
212
213
214
	/**
215
	 * Get row item params (E.g. action may be called id => $item->id, name => $item->name, ...)
216
	 * @param  Row   $row
217
	 * @return array
218
	 */
219 View Code Duplication
	protected function getItemParams(Row $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...
220
	{
221
		$return = [];
222
223
		foreach ($this->params as $param_name => $param) {
224
			$return[is_string($param_name) ? $param_name : $param] = $row->getValue($param);
225
		}
226
227
		return $return;
228
	}
229
230
}
231