Completed
Pull Request — master (#2)
by Klochok
10:36
created

GridView   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 177
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 8

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 16
lcom 4
cbo 8
dl 0
loc 177
ccs 0
cts 64
cp 0
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Advanced Grid for Yii2.
4
 *
5
 * @link      https://github.com/hiqdev/yii2-higrid
6
 * @package   yii2-higrid
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2015-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\higrid;
12
13
use Closure;
14
use hiqdev\yii2\assets\JqueryResizableColumns\ResizableColumnsAsset;
15
use Yii;
16
use yii\data\ArrayDataProvider;
17
use yii\helpers\ArrayHelper;
18
use yii\helpers\Json;
19
use yii\web\JsExpression;
20
21
/**
22
 * Class GridView
23
 * Todo: good description.
24
 * For now see [[columns()]] docs.
25
 *
26
 * @author Andrii Vasyliev <[email protected]>
27
 * @author Dmytro Naumenko <[email protected]>
28
 */
29
class GridView extends \yii\grid\GridView
30
{
31
    /**
32
     * {@inheritdoc}
33
     */
34
    public $dataColumnClass = DataColumn::class;
35
36
    /**
37
     * {@inheritdoc}
38
     */
39
    public $detailViewClass = DetailView::class;
40
41
    public ?Closure $tableFooterRenderer = null;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected '?', expecting T_FUNCTION or T_CONST
Loading history...
42
43
    /**
44
     * @var array|boolean
45
     *  - array: options for Jquery Resizable Columns plugin initiate call
46
     *  - boolean false: resizable is disabled
47
     *
48
     * Defaults to `['store' => new JsExpression('store')]`
49
     * @see registerResizableColumns()
50
     */
51
    public $resizableColumns = [];
52
53
    public function run()
54
    {
55
        $this->registerResizableColumns();
56
        parent::run();
57
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62
    public function getId($autoGenerate = true)
63
    {
64
        if ($autoGenerate && parent::getId(false) === null) {
65
            $this->id = hash('crc32b', Json::encode($this->columns));
66
        }
67
68
        return parent::getId();
69
    }
70
71
    /**
72
     * Registers ResizableColumns plugin when [[resizableColumns]] is not false.
73
     * TODO: move somewhere.
74
     */
75
    public function registerResizableColumns()
76
    {
77
        if (!$this->resizableColumns !== false) {
78
            return;
79
        }
80
81
        $this->tableOptions['data-resizable-columns-id'] = $this->id;
82
83
        ResizableColumnsAsset::register($this->getView());
84
        $resizableColumns = Json::encode(ArrayHelper::merge([
85
            'store' => new JsExpression('store'),
86
        ], $this->resizableColumns));
87
        $this->getView()->registerJs("$('#{$this->id} table[data-resizable-columns-id]').resizableColumns($resizableColumns);");
88
    }
89
90
    /**
91
     * Runs DetailView widget based on this GridView.
92
     *
93
     * @param array $config Config that will be passed to [[detailViewClass]] initialisation.
94
     * Special element `gridOptions` will be merged to `GridView` initialisation config array.
95
     *
96
     * @throws \yii\base\InvalidConfigException
97
     *
98
     * @return mixed
99
     */
100
    public static function detailView(array $config = [])
101
    {
102
        /** @var static $grid */
103
        $grid = Yii::createObject(ArrayHelper::merge([
104
            'class' => get_called_class(),
105
            'dataProvider' => new ArrayDataProvider(['allModels' => [$config['model']]]),
106
        ], ArrayHelper::remove($config, 'gridOptions', [])));
107
        $class = $grid->detailViewClass ?: DetailView::class;
108
        $config['grid'] = $grid;
109
110
        return call_user_func([$class, 'widget'], $config);
111
    }
112
113
    /**
114
     * Returns array of columns configurations that will be used by widget to create
115
     * data columns and render them.
116
     *
117
     * Array format:
118
     *  key - column alias
119
     *  value - column configuration array
120
     *
121
     * Example:
122
     *
123
     * ```php
124
     * return [
125
     *     'login_and_avatar' => [
126
     *         'format' => 'raw',
127
     *         'value' => function ($model) {
128
     *             return Html::img($model->avatar) . $model->username;
129
     *         }
130
     *     ]
131
     * ];
132
     * ```
133
     *
134
     * Despite model does not have a `login_and_avatar` attribute, the following widget call will
135
     * use the definition above to render value:
136
     *
137
     * ```php
138
     * echo GridView::widget([
139
     *     'dataProvider' => $dataProvider,
140
     *     'columns' => ['login_and_avatar', 'status', 'actions'],
141
     * ]);
142
     * ```
143
     *
144
     * @return array
145
     */
146
    public function columns()
147
    {
148
        return [];
149
    }
150
151
    /**
152
     * Creates a [[DataColumn]] object with given config.
153
     *
154
     * @param array $config config for [[DataColumn]]
155
     * @return DataColumn the column instance
156
     */
157
    protected function createDataColumnByConfig(array $config = [])
158
    {
159
        return Yii::createObject(array_merge([
160
            'class' => $this->dataColumnClass ?: \yii\grid\DataColumn::class,
161
            'grid'  => $this,
162
        ], $config));
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168
    protected function createDataColumn($text)
169
    {
170
        $columns = $this->columns();
171
172
        if (!isset($columns[$text]) || !is_array($columns[$text])) {
173
            return parent::createDataColumn($text);
174
        }
175
176
        $config = array_merge(['attribute' => $text], $columns[$text]);
177
        return $this->createDataColumnByConfig($config);
178
    }
179
180
    /**
181
     * @var Closure use it to change default summary rendering
182
     * Method signature:
183
     *
184
     * ```php
185
     * function ($grid, $defaultSummaryCallback)
186
     * ```
187
     *
188
     * Argument `$defaultSummaryCallback` will contain a Closure that will
189
     * render default summary.
190
     * ```
191
     */
192
    public $summaryRenderer;
193
194
    /**
195
     * {@inheritdoc}
196
     */
197
    public function renderSummary()
198
    {
199
        if ($this->summaryRenderer instanceof Closure) {
200
            return call_user_func($this->summaryRenderer, $this, function () {
201
                return parent::renderSummary();
202
            });
203
        }
204
205
        return parent::renderSummary();
206
    }
207
208
    public function renderTableFooter(): string
209
    {
210
        if ($this->tableFooterRenderer instanceof Closure) {
211
            return call_user_func($this->tableFooterRenderer, $this, fn() => parent::renderTableFooter());
212
        }
213
214
        return parent::renderTableFooter();
215
    }
216
}
217