GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#82)
by
unknown
01:49
created

ScrollPager.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace kop\y2sp;
4
5
use kop\y2sp\assets\InfiniteAjaxScrollAsset;
6
use Yii;
7
use yii\base\InvalidConfigException;
8
use yii\base\Widget;
9
use yii\helpers\ArrayHelper;
10
use yii\helpers\Json;
11
use yii\i18n\PhpMessageSource;
12
use yii\web\JsExpression;
13
use yii\web\View;
14
use yii\widgets\LinkPager;
15
16
/**
17
 * ScrollPager turns your regular paginated page into an infinite scrolling page using AJAX.
18
 *
19
 * ScrollPager works with a [[Pagination]] object which specifies the totally number of pages and the current page number.
20
 *
21
 * <br>
22
 * <i>Example usage:</i>
23
 * <code>
24
 * echo ListView::widget([
25
 *      'dataProvider' => $dataProvider,
26
 *      'itemOptions' => ['class' => 'item'],
27
 *      'itemView' => '_item_view',
28
 *      'pager' => ['class' => \kop\y2sp\ScrollPager::className()]
29
 * ]);
30
 * </code>
31
 *
32
 * This widget is using {@link http://infiniteajaxscroll.com/ JQuery Infinite Ajax Scroll plugin}.
33
 *
34
 * @link      http://kop.github.io/yii2-scroll-pager Y2SP project page.
35
 * @license   https://github.com/kop/yii2-scroll-pager/blob/master/LICENSE.md MIT
36
 *
37
 * @author    Ivan Koptiev <[email protected]>
38
 */
39
class ScrollPager extends Widget
40
{
41
    /**
42
     * @const EXTENSION_TRIGGER IAS Extension "IASTriggerExtension".
43
     */
44
    const EXTENSION_TRIGGER = 'IASTriggerExtension';
45
46
    /**
47
     * @const EXTENSION_SPINNER IAS Extension "IASSpinnerExtension".
48
     */
49
    const EXTENSION_SPINNER = 'IASSpinnerExtension';
50
51
    /**
52
     * @const EXTENSION_NONE_LEFT IAS Extension "IASNoneLeftExtension".
53
     */
54
    const EXTENSION_NONE_LEFT = 'IASNoneLeftExtension';
55
56
    /**
57
     * @const EXTENSION_PAGING IAS Extension "IASPagingExtension".
58
     */
59
    const EXTENSION_PAGING = 'IASPagingExtension';
60
61
    /**
62
     * @const EXTENSION_HISTORY IAS Extension "IASHistoryExtension".
63
     */
64
    const EXTENSION_HISTORY = 'IASHistoryExtension';
65
66
    /**
67
     * @var string $container Enter the selector of the element containing your items that you want to paginate.
68
     */
69
    public $container = '.list-view';
70
71
    /**
72
     * @var string $item Enter the selector of the element that each item has.
73
     * Make sure the elements are inside the container element.
74
     */
75
    public $item = '.item';
76
77
    /**
78
     * @var string $paginationSelector Enter the selector of the element containing the pagination.
79
     */
80
    public $paginationSelector = '.list-view .pagination';
81
82
    /**
83
     * @var string $next Enter the selector of the link element that links to the next page.
84
     * The href attribute of this element will be used to get the items from the next page.
85
     * Make sure there is only one(1) element that matches the selector.
86
     */
87
    public $next = '.next a';
88
89
    /**
90
     * @var int $delay Minimal number of milliseconds to stay in a loading state.
91
     */
92
    public $delay = 600;
93
94
    /**
95
     * @var int $thresholdMargin On default IAS starts loading new items when you scroll to the latest .item element.
96
     * The negativeMargin will be added to the items' offset, giving you the ability to load new items earlier
97
     * (please note that the margin is always transformed to a negative integer).
98
     * <br><br>
99
     * <i>For example:</i>
100
     * <br>
101
     * Setting a negativeMargin of 250 means that IAS will start loading 250 pixel before the last item has scrolled into view.
102
     */
103
    public $negativeMargin = 10;
104
105
    /**
106
     * @var string $triggerText Text of trigger the link.
107
     * Default: "Load more items".
108
     */
109
    public $triggerText;
110
111
    /**
112
     * @var string $triggerTemplate Allows you to override the trigger html template.
113
     */
114
    public $triggerTemplate = '<div class="ias-trigger" style="text-align: center; cursor: pointer;"><a>{text}</a></div>';
115
116
    /**
117
     * @var string $triggerTextPrev Text of trigger the link previous page.
118
     */
119
    public $triggerTextPrev;
120
121
    /**
122
     * @var string $triggerTemplatePrev Allows you to override the trigger html template for previous page link.
123
     */
124
    public $triggerTemplatePrev = '<div class="ias-trigger" style="text-align: center; cursor: pointer;"><a>{text}</a></div>';
125
126
    /**
127
     * @var int $triggerOffset The number of pages which should load automatically.
128
     * After that the trigger is shown for every subsequent page.
129
     * <br><br>
130
     * <i>For example:</i>
131
     * <br>
132
     * if you set the offset to 2, the pages 2 and 3 (page 1 is always shown) would load automatically and for every
133
     * subsequent page the user has to press the trigger to load it.
134
     */
135
    public $triggerOffset = 0;
136
137
    /**
138
     * @var string $spinnerSrc The src attribute of the spinner image.
139
     */
140
    public $spinnerSrc;
141
142
    /**
143
     * @var string $spinnerTemplate Allows you to override the spinner html template.
144
     */
145
    public $spinnerTemplate = '<div class="ias-spinner" style="text-align: center;"><img src="{src}"/></div>';
146
147
    /**
148
     * @var string $noneLeftText Text of the "nothing left" message.
149
     * Default: "You reached the end".
150
     */
151
    public $noneLeftText;
152
153
    /**
154
     * @var string $noneLeftTemplate Allows you to override the "nothing left" message html template.
155
     */
156
    public $noneLeftTemplate = '<div class="ias-noneleft" style="text-align: center;">{text}</div>';
157
158
    /**
159
     * @var string $historyPrev Enter the selector of the link element that links to the previous page.
160
     * The href attribute of this element will be used to get the items from the previous page.
161
     * Make sure there is only one element that matches the selector.
162
     */
163
    public $historyPrev = '.previous';
164
165
    /**
166
     * @var string $overflowContainer A selector for "div" HTML element to use as an overflow container.
167
     * @see http://infiniteajaxscroll.com/examples/overflow.html
168
     */
169
    public $overflowContainer;
170
171
    /**
172
     * @var string|JsExpression $eventOnScroll Triggered when the visitors scrolls.
173
     * @see http://infiniteajaxscroll.com/docs/events.html
174
     */
175
    public $eventOnScroll;
176
177
    /**
178
     * @var string|JsExpression $eventOnLoad Triggered when a new url will be loaded from the server.
179
     * @see http://infiniteajaxscroll.com/docs/events.html
180
     */
181
    public $eventOnLoad;
182
183
    /**
184
     * @var string|JsExpression $eventOnLoaded Triggered after a new page was loaded from the server.
185
     * @see http://infiniteajaxscroll.com/docs/events.html
186
     */
187
    public $eventOnLoaded;
188
189
    /**
190
     * @var string|JsExpression $eventOnRender Triggered before new items will be rendered.
191
     * @see http://infiniteajaxscroll.com/docs/events.html
192
     */
193
    public $eventOnRender;
194
195
    /**
196
     * @var string|JsExpression $eventOnRendered Triggered after new items have rendered.
197
     * Note: This event is only fired once.
198
     * @see http://infiniteajaxscroll.com/docs/events.html
199
     */
200
    public $eventOnRendered;
201
202
    /**
203
     * @var string|JsExpression $eventOnNoneLeft Triggered when there are no more pages left.
204
     * @see http://infiniteajaxscroll.com/docs/events.html
205
     */
206
    public $eventOnNoneLeft;
207
208
    /**
209
     * @var string|JsExpression $eventOnNext Triggered when the next page should be loaded.
210
     * Happens before loading of the next page starts. With this event it is possible to cancel the loading of the next page.
211
     * You can do this by returning false from your callback.
212
     * @see http://infiniteajaxscroll.com/docs/events.html
213
     */
214
    public $eventOnNext;
215
216
    /**
217
     * @var string|JsExpression $eventOnReady Triggered when IAS and all the extensions have been initialized.
218
     * @see http://infiniteajaxscroll.com/docs/events.html
219
     */
220
    public $eventOnReady;
221
222
    /**
223
     * @var string|JsExpression $eventOnPageChange Triggered when a used scroll to another page.
224
     * @see http://infiniteajaxscroll.com/docs/extension-paging.html
225
     */
226
    public $eventOnPageChange;
227
228
    /**
229
     * @var array $enabledExtensions The list of the enabled plugin extensions.
230
     */
231
    public $enabledExtensions = [
232
        self::EXTENSION_TRIGGER,
233
        self::EXTENSION_SPINNER,
234
        self::EXTENSION_NONE_LEFT,
235
        self::EXTENSION_PAGING,
236
        self::EXTENSION_HISTORY
237
    ];
238
239
    /**
240
     * @var \yii\data\Pagination The pagination object that this pager is associated with.
241
     * You must set this property in order to make ScrollPager work.
242
     */
243
    public $pagination;
244
245
    /**
246
     * Initializes the pager.
247
     */
248
    public function init()
249
    {
250
        parent::init();
251
252
        // Register translations source
253
        Yii::$app->i18n->translations = ArrayHelper::merge(Yii::$app->i18n->translations, [
254
            'kop\y2sp' => [
255
                'class' => PhpMessageSource::className(),
256
                'basePath' => '@vendor/kop/yii2-scroll-pager/messages',
257
                'fileMap' => [
258
                    'kop\y2sp' => 'general.php'
259
                ]
260
            ]
261
        ]);
262
263
        // Register required assets
264
        $this->registerAssets();
265
266
        // Set default trigger text if not set
267
        if ($this->triggerText === null) {
268
            $this->triggerText = Yii::t('kop\y2sp', 'Load more items');
269
        }
270
271
        // Set default "none left" message text if not set
272
        if ($this->noneLeftText === null) {
273
            $this->noneLeftText = Yii::t('kop\y2sp', 'You reached the end');
274
        }
275
    }
276
277
    /**
278
     * Executes the widget.
279
     *
280
     * This overrides the parent implementation by initializing jQuery IAS and displaying the generated page buttons.
281
     *
282
     * @throws \yii\base\InvalidConfigException
283
     * @return mixed
284
     */
285
    public function run()
286
    {
287
        // Initialize jQuery IAS plugin
288
        $pluginSettings = Json::encode([
289
            'container' => $this->container,
290
            'item' => $this->item,
291
            'pagination' => $this->paginationSelector,
292
            'next' => $this->next,
293
            'delay' => $this->delay,
294
            'negativeMargin' => $this->negativeMargin
295
        ]);
296
        $initString = empty($this->overflowContainer)
297
            ? "var {$this->id}_ias = jQuery.ias({$pluginSettings});"
298
            : "var {$this->id}_ias = jQuery('{$this->overflowContainer}').ias({$pluginSettings});";
299
        $this->view->registerJs($initString, View::POS_READY, "{$this->id}_ias_main");
300
301
        // Register IAS extensions
302
        $this->registerExtensions([
303
            [
304
                'name' => self::EXTENSION_PAGING
305
            ],
306
            [
307
                'name' => self::EXTENSION_SPINNER,
308
                'options' =>
309
                    !empty($this->spinnerSrc)
310
                        ? ['html' => $this->spinnerTemplate, 'src' => $this->spinnerSrc]
311
                        : ['html' => $this->spinnerTemplate]
312
            ],
313
            [
314
                'name' => self::EXTENSION_TRIGGER,
315
                'options' => [
316
                    'text' => $this->triggerText,
317
                    'html' => $this->triggerTemplate,
318
                    'offset' => $this->triggerOffset,
319
                    'textPrev' => $this->triggerTextPrev,
320
                    'htmlPrev' => $this->triggerTemplatePrev,
321
                ]
322
            ],
323
            [
324
                'name' => self::EXTENSION_NONE_LEFT,
325
                'options' => [
326
                    'text' => $this->noneLeftText,
327
                    'html' => $this->noneLeftTemplate
328
                ]
329
            ],
330
            [
331
                'name' => self::EXTENSION_HISTORY,
332
                'options' => [
333
                    'prev' => $this->historyPrev
334
                ],
335
                'depends' => [
336
                    self::EXTENSION_TRIGGER,
337
                    self::EXTENSION_PAGING
338
                ]
339
            ]
340
        ]);
341
342
        // Register event handlers
343
        $this->registerEventHandlers([
344
            'scroll' => [],
345
            'load' => [],
346
            'loaded' => [],
347
            'render' => [],
348
            'rendered' => [],
349
            'noneLeft' => [],
350
            'next' => [],
351
            'ready' => [],
352
            'pageChange' => [
353
                self::EXTENSION_PAGING
354
            ]
355
        ]);
356
357
        // Render pagination links
358
        echo LinkPager::widget([
359
            'pagination' => $this->pagination,
360
            'options' => [
361
                'class' => 'pagination hidden'
362
            ]
363
        ]);
364
    }
365
366
    /**
367
     * Register required asset bundles.
368
     *
369
     * You can override this method in case if you want to use your own JQuery Infinite Ajax Scroll plugin files
370
     * (for example, some forked plugin version).
371
     */
372
    protected function registerAssets()
373
    {
374
        InfiniteAjaxScrollAsset::register($this->view);
375
    }
376
377
    /**
378
     * Register jQuery IAS extensions.
379
     *
380
     * This method takes jQuery IAS extensions definition as a parameter and registers this extensions.
381
     *
382
     * @param array $config jQuery IAS extensions definition.
383
     * @throws \yii\base\InvalidConfigException If extension dependencies are not met.
384
     */
385
    protected function registerExtensions(array $config)
386
    {
387
        foreach ($config as $entry) {
388
389
            // Parse config entry values
390
            $name = ArrayHelper::getValue($entry, 'name', false);
391
            $options = ArrayHelper::getValue($entry, 'options', '');
392
            $depends = ArrayHelper::getValue($entry, 'depends', []);
393
394
            // If extension is enabled
395
            if (in_array($name, $this->enabledExtensions)) {
396
397
                // Make sure dependencies are met
398 View Code Duplication
                if (!$this->checkEnabledExtensions($depends)) {
0 ignored issues
show
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...
399
                    throw new InvalidConfigException(
400
                        "Extension {$name} requires " . implode(', ', $depends) . " extensions to be enabled."
401
                    );
402
                }
403
404
                // Register extension
405
                $options = Json::encode($options);
406
                $this->view->registerJs(
407
                    "{$this->id}_ias.extension(new {$name}({$options}));",
408
                    View::POS_READY,
409
                    "{$this->id}_ias_{$name}"
410
                );
411
            }
412
        }
413
    }
414
415
    /**
416
     * Register jQuery IAS event handlers.
417
     *
418
     * This method takes jQuery IAS event handlers definition as a parameter and registers this event handlers.
419
     *
420
     * @param array $config jQuery IAS event handlers definition.
421
     * @throws \yii\base\InvalidConfigException If vent handlers dependencies are not met.
422
     */
423
    protected function registerEventHandlers(array $config)
424
    {
425
        foreach ($config as $name => $depends) {
426
427
            // If event is enabled
428
            $eventName = 'eventOn' . ucfirst($name);
429
            if (!empty($this->$eventName)) {
430
431
                // Make sure dependencies are met
432 View Code Duplication
                if (!$this->checkEnabledExtensions($depends)) {
0 ignored issues
show
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...
433
                    throw new InvalidConfigException(
434
                        "The \"{$name}\" event requires " . implode(', ', $depends) . " extensions to be enabled."
435
                    );
436
                }
437
438
                // Register event
439
                $this->view->registerJs(
440
                    "{$this->id}_ias.on('{$name}', {$this->$eventName});",
441
                    View::POS_READY,
442
                    "{$this->id}_ias_event_{$eventName}"
443
                );
444
            }
445
        }
446
    }
447
448
    /**
449
     * Check whether the given extensions are enabled.
450
     *
451
     * @param string|array $extensions Single or multiple extensions names.
452
     * @return bool Operation result.
453
     */
454
    protected function checkEnabledExtensions($extensions)
455
    {
456
        $extensions = (array)$extensions;
457
        if (empty($extensions)) {
458
            return true;
459
        } else {
460
            return (count(array_intersect($this->enabledExtensions, $extensions)) == count($extensions));
461
        }
462
    }
463
}
464