Completed
Push — master ( 5dba8f...8924a6 )
by Klochok
04:46
created

IndexPage::beginSearchForm()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 4
cp 0
crap 2
rs 10
1
<?php
2
/**
3
 * HiPanel core package.
4
 *
5
 * @link      https://hipanel.com/
6
 * @package   hipanel-core
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2014-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hipanel\widgets;
12
13
use hipanel\models\IndexPageUiOptions;
14
use Yii;
15
use yii\base\InvalidParamException;
16
use yii\base\Model;
17
use yii\base\Widget;
18
use yii\bootstrap\ButtonDropdown;
19
use yii\data\DataProviderInterface;
20
use yii\helpers\Html;
21
use yii\helpers\Inflector;
22
use yii\helpers\Json;
23
use yii\helpers\Url;
24
use yii\web\View;
25
26
class IndexPage extends Widget
27
{
28
    /**
29
     * @var string
30
     */
31
    protected $_layout;
32
33
    /**
34
     * @var Model the search model
35
     */
36
    public $model;
37
38
    /**
39
     * @var IndexPageUiOptions
40
     */
41
    private $uiModel;
42
43
    /**
44
     * @var object original view context.
45
     * It is used to render sub-views with the same context, as IndexPage
46
     */
47
    public $originalContext;
48
49
    /**
50
     * @var DataProviderInterface
51
     */
52
    public $dataProvider;
53
54
    /**
55
     * @var array Hash of document blocks, that can be rendered later in the widget's views
56
     * Blocks can be set explicitly on widget initialisation, or by calling [[beginContent]] and
57
     * [[endContent]]
58
     *
59
     * @see beginContent
60
     * @see endContent
61
     */
62
    public $contents = [];
63
64
    /**
65
     * @var string the name of current content block, that is under the render
66
     * @see beginContent
67
     * @see endContent
68
     */
69
    protected $_current = null;
70
71
    /**
72
     * @var array
73
     */
74
    public $searchFormData = [];
75
76
    /**
77
     * @var array
78
     */
79
    public $searchFormOptions = [];
80
81
    /**
82
     * @var string the name of view file that contains search fields for the index page. Defaults to `_search`
83
     * @see renderSearchForm()
84
     */
85
    public $searchView = '_search';
86
87
    /** {@inheritdoc} */
88
    public function init()
89
    {
90
        parent::init();
91
        $searchFormId = Json::htmlEncode("#{$this->getBulkFormId()}");
92
        $this->originalContext = Yii::$app->view->context;
93
        $view = $this->getView();
94
        // Fix a very narrow select2 input in the search tables
95
        $view->registerCss('#content-pjax .select2-dropdown--below { min-width: 170px!important; }');
96
        $view->registerJs(<<<"JS"
97
        // Checkbox
98
        var checkboxes = $('table input[type="checkbox"]');
99
        var bulkcontainer = $('.box-bulk-actions fieldset');
100
        checkboxes.on('ifChecked ifUnchecked', function(event) {
101
            if (event.type == 'ifChecked' && $('input.icheck').filter(':checked').length > 0) {
102
                bulkcontainer.prop('disabled', false);
103
            } else if ($('input.icheck').filter(':checked').length == 0) {
104
                bulkcontainer.prop('disabled', true);
105
            }
106
        });
107
        // On/Off Actions TODO: reduce scope
108
        $(document).on('click', '.box-bulk-actions a', function (event) {
109
            var link = $(this);
110
            var action = link.data('action');
111
            var form = $($searchFormId);
112
            if (action) {
113
                form.attr({'action': action, method: 'POST'}).submit();
114
            }
115
        });
116
        // Do not open select2 when clear
117
        var el = $('div[role=grid] :input[data-combo-field]');
118
        el.on('select2:unselecting', function(e) {
119
            el.data('unselecting', true);
120
        }).on('select2:open', function(e) { // note the open event is important
121
            if (el.data('unselecting')) {
122
                el.removeData('unselecting'); // you need to unset this before close
123
                el.select2('close');
124
            }
125
        });
126
JS
127
        );
128
    }
129
130
    public function getUiModel()
131
    {
132
        if ($this->uiModel === null) {
133
            $this->uiModel = $this->originalContext->indexPageUiOptionsModel;
134
        }
135
136
        return $this->uiModel;
137
    }
138
139
    /**
140
     * Begins output buffer capture to save data in [[contents]] with the $name key.
141
     * Must not be called nested. See [[endContent]] for capture terminating.
142
     * @param string $name
143
     */
144
    public function beginContent($name)
145
    {
146
        if ($this->_current) {
147
            throw new InvalidParamException('Output buffer capture is already running for ' . $this->_current);
148
        }
149
        $this->_current = $name;
150
        ob_start();
151
        ob_implicit_flush(false);
152
    }
153
154
    /**
155
     * Terminates output buffer capture started by [[beginContent()]].
156
     * @see beginContent
157
     */
158
    public function endContent()
159
    {
160
        if (!$this->_current) {
161
            throw new InvalidParamException('Outout buffer capture is not running. Call beginContent() first');
162
        }
163
        $this->contents[$this->_current] = ob_get_contents();
164
        ob_end_clean();
165
        $this->_current = null;
166
    }
167
168
    /**
169
     * Returns content saved in [[content]] by $name.
170
     * @param string $name
171
     * @return string
172
     */
173
    public function renderContent($name)
174
    {
175
        return $this->contents[$name];
176
    }
177
178
    public function run()
179
    {
180
        $layout = $this->getLayout();
181
        if ($layout === 'horizontal') {
182
            $this->horizontalClientScriptInit();
183
        }
184
185
        return $this->render($layout);
186
    }
187
188
    private function horizontalClientScriptInit()
189
    {
190
        $view = $this->getView();
191
        $view->registerCss('
192
            .affix {
193
                top: 5px;
194
            }
195
            .affix-bottom {
196
                position: fixed!important;
197
            }
198
            @media (min-width: 768px) {
199
                .affix {
200
                    position: fixed;
201
                }
202
            }
203
            @media (max-width: 768px) {
204
                .affix {
205
                    position: static;
206
                }
207
            }
208
            .advanced-search[min-width~="150px"] form > div {
209
                width: 100%;
210
            }
211
            #scrollspy * {
212
              /* Свойства изменение которых необходимо отслеживать */
213
              transition-property: all;
214
215
              /* Устанавливаем "незаметную для глаза" длительность перехода */
216
              transition-duration: 1ms;
217
            }
218
        ');
219
        $view->registerJs("
220
            function affixInit() {
221
                $('#scrollspy').affix({
222
                    offset: {
223
                        top: ($('header.main-header').outerHeight(true) + $('section.content-header').outerHeight(true)) + 15,
224
                        bottom: ($('footer').outerHeight(true)) + 15
225
                    }
226
                });
227
            }
228
            $(document).on('pjax:end', function() {
229
                $('.advanced-search form > div').css({'width': '100%'});
230
                
231
                // Fix left search block position
232
                $(window).trigger('scroll');
233
            });
234
            if ($(window).height() > $('#scrollspy').outerHeight(true) && $(window).width() > 991) {
235
                if ( $('#scrollspy').outerHeight(true) < $('.horizontal-view .col-md-9 > .box').outerHeight(true) ) {
236
                    var fixAffixWidth = function() {
237
                        $('#scrollspy').each(function() {
238
                            $(this).width( $(this).parent().width() );
239
                        });
240
                    }
241
                    fixAffixWidth();
242
                    $(window).resize(fixAffixWidth);
243
                    affixInit();
244
                    $('a.sidebar-toggle').click(function() {
245
                        setTimeout(function(){
246
                            fixAffixWidth();
247
                        }, 500);
248
                    });
249
                }
250
            }
251
        ", View::POS_LOAD);
252
    }
253
254
    public function detectLayout()
255
    {
256
        return $this->getUiModel()->orientation;
257
    }
258
259
    /**
260
     * @param array $data
261
     * @void
262
     */
263
    public function setSearchFormData($data = [])
264
    {
265
        $this->searchFormData = $data;
266
    }
267
268
    /**
269
     * @param array $options
270
     * @void
271
     */
272
    public function setSearchFormOptions($options = [])
273
    {
274
        $this->searchFormOptions = $options;
275
    }
276
277
    public function renderSearchForm($advancedSearchOptions = [])
278
    {
279
        $advancedSearchOptions = array_merge($advancedSearchOptions, $this->searchFormOptions);
280
        ob_start();
281
        ob_implicit_flush(false);
282
        try {
283
            $search = $this->beginSearchForm($advancedSearchOptions);
284
            foreach (['per_page', 'representation'] as $key) {
285
                echo Html::hiddenInput($key, Yii::$app->request->get($key));
286
            }
287
            echo Yii::$app->view->render($this->searchView, array_merge(compact('search'), $this->searchFormData), $this->originalContext);
288
            $search->end();
289
        } catch (\Exception $e) {
290
            ob_end_clean();
291
            throw $e;
292
        }
293
294
        return ob_get_clean();
295
    }
296
297
    public function beginSearchForm($options = [])
298
    {
299
        return AdvancedSearch::begin(array_merge(['model' => $this->model], $options));
300
    }
301
302
    public function renderSearchButton()
303
    {
304
        return AdvancedSearch::renderButton() . "\n";
305
    }
306
307
    public function renderLayoutSwitcher()
308
    {
309
        return IndexLayoutSwitcher::widget(['uiModel' => $this->getUiModel()]);
310
    }
311
312
    public function renderPerPage()
313
    {
314
        $items = [];
315
        foreach ([25, 50, 100, 200, 500] as $pageSize) {
316
            $items[] = ['label' => $pageSize, 'url' => Url::current(['per_page' => $pageSize])];
317
        }
318
        return ButtonDropdown::widget([
319
            'label' => Yii::t('hipanel', 'Per page') . ': ' . $this->getUiModel()->per_page,
320
            'options' => ['class' => 'btn-default btn-sm'],
321
            'dropdown' => [
322
                'items' => $items,
323
            ],
324
        ]);
325
    }
326
327
    /**
328
     * Renders button to choose representation.
329
     * Returns empty string when nothing to choose (less then 2 representations available).
330
     * @param array $grid class
331
     * @param mixed $current selected representation
0 ignored issues
show
Bug introduced by
There is no parameter named $current. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
332
     * @return string rendered HTML
333
     */
334
    public function renderRepresentations($grid)
335
    {
336
        $current = $this->getUiModel()->representation;
337
        $representations = $grid::getRepresentations();
338
        if (count($representations) < 2) {
339
            return '';
340
        }
341
        if (!isset($representations[$current])) {
342
            $current = key($representations);
343
        }
344
        $items = [];
345
        foreach ($representations as $key => $data) {
346
            $items[] = [
347
                'label' => $data['label'],
348
                'url' => Url::current(['representation' => $key]),
349
            ];
350
        }
351
352
        return ButtonDropdown::widget([
353
            'label' => Yii::t('hipanel:synt', 'View') . ': ' . $representations[$current]['label'],
354
            'options' => ['class' => 'btn-default btn-sm'],
355
            'dropdown' => [
356
                'items' => $items,
357
            ],
358
        ]);
359
    }
360
361
    public function renderSorter(array $options)
362
    {
363
        return LinkSorter::widget(array_merge([
364
            'show' => true,
365
            'uiModel' => $this->getUiModel(),
366
            'dataProvider' => $this->dataProvider,
367
            'sort' => $this->dataProvider->getSort(),
368
            'buttonClass' => 'btn btn-default dropdown-toggle btn-sm',
369
        ], $options));
370
    }
371
372
    public function getViewPath()
373
    {
374
        return parent::getViewPath() . DIRECTORY_SEPARATOR . (new \ReflectionClass($this))->getShortName();
375
    }
376
377
    public function getBulkFormId()
378
    {
379
        return 'bulk-' . Inflector::camel2id($this->model->formName());
380
    }
381
382
    public function beginBulkForm($action = '')
383
    {
384
        echo Html::beginForm($action, 'POST', ['id' => $this->getBulkFormId()]);
385
    }
386
387
    public function endBulkForm()
388
    {
389
        echo Html::endForm();
390
    }
391
392 View Code Duplication
    public function renderBulkButton($text, $action, $color = 'default')
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...
393
    {
394
        return Html::submitButton($text, [
395
            'class' => "btn btn-$color btn-sm",
396
            'form' => $this->getBulkFormId(),
397
            'formmethod' => 'POST',
398
            'formaction' => $action,
399
        ]);
400
    }
401
402
    /**
403
     * @return string
404
     */
405
    public function getLayout()
406
    {
407
        if ($this->_layout === null) {
408
            $this->_layout = $this->detectLayout();
409
        }
410
        return $this->_layout;
411
    }
412
413
    /**
414
     * @param string $layout
415
     */
416
    public function setLayout($layout)
417
    {
418
        $this->_layout = $layout;
419
    }
420
}
421