Passed
Push — 2.6.0 ( ...f22176 )
by steve
18:56
created

GridRenderer   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 247
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 27
eloc 98
dl 0
loc 247
rs 10
c 0
b 0
f 0
ccs 0
cts 140
cp 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A renderRow() 0 10 3
A renderSummary() 0 37 4
A renderFile() 0 3 1
A renderPager() 0 21 4
A renderRows() 0 8 2
B renderScopes() 0 27 6
A getViewPath() 0 3 1
A renderHeaderGroups() 0 13 3
A __construct() 0 3 1
A render() 0 3 1
A doRender() 0 6 1
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: newicon
5
 * Date: 11/10/2018
6
 * Time: 14:23
7
 */
8
9
namespace neon\core\grid;
10
11
use neon\core\grid\query\YiiQuery;
12
use neon\core\helpers\Arr;
13
use neon\core\helpers\Html;
14
use yii\base\ViewContextInterface;
15
use yii\base\Widget;
16
use yii\widgets\LinkPager;
17
18
/**
19
 * Class GridRenderer
20
 * This class is responsible for grid render functions.
21
 * For crazy ambitious grids this allows you to change its rendering functions by creating your own
22
 * @package neon\core\grid
23
 */
24
class GridRenderer implements ViewContextInterface
25
{
26
	/**
27
	 * @var GridBase
28
	 */
29
	private $_grid;
30
31
	/**
32
	 * @var string
33
	 */
34
	public $viewFile = '@neon/core/grid/views/body.tpl';
35
36
	/**
37
	 * GridRenderer constructor.
38
	 * @param GridBase $grid
39
	 */
40
	public function __construct($grid)
41
	{
42
		$this->_grid = $grid;
43
	}
44
45
	/**
46
	 * Renders a view.
47
	 *
48
	 * The view to be rendered can be specified in one of the following formats:
49
	 *
50
	 * - [path alias](guide:concept-aliases) (e.g. "@app/views/site/index");
51
	 * - absolute path within application (e.g. "//site/index"): the view name starts with double slashes.
52
	 *   The actual view file will be looked for under the [[Application::viewPath|view path]] of the application.
53
	 * - absolute path within module (e.g. "/site/index"): the view name starts with a single slash.
54
	 *   The actual view file will be looked for under the [[Module::viewPath|view path]] of the currently
55
	 *   active module.
56
	 * - relative path (e.g. "index"): the actual view file will be looked for under [[viewPath]].
57
	 *
58
	 * If the view name does not contain a file extension, it will use the default one `.php`.
59
	 *
60
	 * @param string $view the view name.
61
	 * @param array $params the parameters (name-value pairs) that should be made available in the view.
62
	 * @return string the rendering result.
63
	 * @throws InvalidArgumentException if the view file does not exist.
64
	 */
65
	public function render($view, $params = [])
66
	{
67
		return neon()->view->render($view, $params, $this);
68
	}
69
70
	/**
71
	 * Renders a view file.
72
	 * @param string $file the view file to be rendered. This can be either a file path or a [path alias](guide:concept-aliases).
73
	 * @param array $params the parameters (name-value pairs) that should be made available in the view.
74
	 * @return string the rendering result.
75
	 * @throws InvalidArgumentException if the view file does not exist.
76
	 */
77
	public function renderFile($file, $params = [])
78
	{
79
		return neon()->view->renderFile($file, $params, $this);
80
	}
81
82
	/**
83
	 * Returns the directory containing the view files for this widget.
84
	 * The default implementation returns the 'views' subdirectory under the directory containing the widget class file.
85
	 * @return string the directory containing the view files for this widget.
86
	 */
87
	public function getViewPath()
88
	{
89
		return __DIR__ . DIRECTORY_SEPARATOR . 'views';
90
	}
91
92
	/**
93
	 * @return mixed
94
	 */
95
	public function doRender()
96
	{
97
		return $this->render($this->viewFile, [
98
			'debug' => (env('NEON_DEBUG') == true),
99
			'grid' => $this->_grid,
100
			'renderer' => $this
101
		]);
102
	}
103
104
	/**
105
	 * Render header groups
106
	 * @return string
107
	 */
108
	public function renderHeaderGroups()
109
	{
110
		if (empty($this->_grid->getColumnGroups())) {
111
			return '';
112
		}
113
114
		$out = '<tr>';
115
		foreach($this->_grid->getColumnGroups() as $groupLabel => $details) {
116
			$colspan = count($details['columns']);
117
			$out .= "<td colspan='$colspan'>$groupLabel</td>";
118
		}
119
		$out .= '</tr>';
120
		return $out;
121
	}
122
123
	// region Render Functions
124
	//------------------------------------------------------------------------------------------------------------------
125
126
	/**
127
	 * Renders the pager.
128
	 * @throws \Exception - if Widget instantiation fails
129
	 * @return string the rendering result
130
	 */
131
	public function renderPager()
132
	{
133
		$pagination = $this->_grid->getDataProvider()->getPagination();
134
		$filters = [];
135
		foreach($this->_grid->getFilterForm()->getFields() as $field) {
136
			if (!empty($field->getValue()))
137
				$filters[$field->getInputName()] = $field->getValue();
138
		}
139
		$queryParams = neon()->request->queryParams;
140
		// remove any pre existing grid specific filters from the url - we don't want to add them twice
141
		if (isset($queryParams[$this->_grid->gridName()]))
142
			unset($queryParams[$this->_grid->gridName()]);
143
		// gross - we need to remove any pre existing filters from the query params
144
		$pagination->params = $queryParams + $filters;
145
146
		/* @var $class LinkPager */
147
		$pager = $this->_grid->pager;
148
		$class = Arr::remove($pager, 'class', LinkPager::class);
149
		$pager['pagination'] = $pagination;
150
		$pager['view'] = neon()->view;
151
		return $class::widget($pager);
152
	}
153
154
	/**
155
	 * Render the grid rows
156
	 *
157
	 * @return string
158
	 */
159
	public function renderRows()
160
	{
161
		$models = array_values($this->_grid->getDataProvider()->getModels());
162
		$out = '';
163
		foreach($models as $index => $row) {
164
			$out .= $this->renderRow($row);
165
		}
166
		return $out;
167
	}
168
169
	/**
170
	 * Render a single grid row
171
	 *
172
	 * @param array $row - row data
173
	 * @return string
174
	 */
175
	public function renderRow($row)
176
	{
177
		$out = '<tr >';
178
		foreach ($this->_grid->getColumns() as $colKey => $columnObject) {
179
			if ($columnObject->visible) {
0 ignored issues
show
Bug introduced by
Accessing visible on the interface neon\core\grid\column\IColumn suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
180
				$out .= $columnObject->renderDataCell($row, $colKey, 0);
181
			}
182
		}
183
		$out .= '</tr>';
184
		return $out;
185
	}
186
187
	/**
188
	 * Render grid scope filters
189
	 *
190
	 * @return string
191
	 * @throws \Exception
192
	 */
193
	public function renderScopes()
194
	{
195
		$postScope = Arr::getValue($_REQUEST, [$this->_grid->id, 'scope']);
196
		if ($postScope && Arr::getValue($this->_grid->getScopes(), $postScope)) {
197
			$currentFilter = $postScope;
198
		} else {
199
			$currentFilter = key($this->_grid->getScopes());
200
		}
201
		$first = true;
202
		$filtersHTML = '';
203
		foreach($this->_grid->getScopes() as $link => $scope) {
204
205
			$count = $this->_grid->getScopeTotalCount($link);
206
			$current = '';
207
			if ($currentFilter == $link) {
208
				$current = 'active';
209
			}
210
			$filtersHTML .= '<li>';
211
			if ($first) {
212
				$first = false;
213
			} else {
214
				$filtersHTML .= ' | ';
215
			}
216
			$filtersHTML .= '<a id="'.$this->_grid->id.'-scope-'.$link
217
				.'" data-scope="'.$link.'" href="?'.$this->_grid->id.'[scope]='.$scope['key'].'" class="'.$current.'">'.$scope['name'].' <span class="count">('.$count.')</span></a></li>';
218
		}
219
		return $filtersHTML;
220
	}
221
222
	/**
223
	 * Html tag options for the summary div element
224
	 *
225
	 * @var array
226
	 */
227
	public $summaryOptions = ['class' => 'neonGrid_summary'];
228
229
	/**
230
	 * Terrible yii code: renders a summary of the fetched data - e.g. "showing 1 of 59 records"
231
	 *
232
	 * @return string
233
	 */
234
	public function renderSummary()
235
	{
236
		$count = $this->_grid->dataProvider->getCount();
237
		if ($count <= 0) {
238
			return '';
239
		}
240
		$summaryOptions = $this->summaryOptions;
241
		$tag = Arr::remove($summaryOptions, 'tag', 'div');
242
		if (($pagination = $this->_grid->dataProvider->getPagination()) !== false) {
243
			$totalCount = $this->_grid->dataProvider->getTotalCount();
244
			$begin = $pagination->getPage() * $pagination->pageSize + 1;
245
			$end = $begin + $count - 1;
246
			if ($begin > $end) {
247
				$begin = $end;
248
			}
249
			$page = $pagination->getPage() + 1;
250
			$pageCount = $pagination->pageCount;
251
			$tagMessage = ' <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.';
252
			return Html::tag($tag, \Yii::t('yii',  $tagMessage, [
253
				'begin' => $begin,
254
				'end' => $end,
255
				'count' => $count,
256
				'totalCount' => $totalCount,
257
				'page' => $page,
258
				'pageCount' => $pageCount,
259
			]), $summaryOptions);
260
		} else {
261
			$begin = $page = $pageCount = 1;
262
			$end = $totalCount = $count;
263
			return Html::tag($tag, \Yii::t('yii', 'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.', [
264
				'begin' => $begin,
265
				'end' => $end,
266
				'count' => $count,
267
				'totalCount' => $totalCount,
268
				'page' => $page,
269
				'pageCount' => $pageCount,
270
			]), $summaryOptions);
271
		}
272
	}
273
274
	//------------------------------------------------------------------------------------------------------------------
275
	//endregion
276
277
}
278