Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

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.
Passed
Pull Request — master (#430)
by Alexander
03:51
created

DocumentList::__isset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 2
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Kitodo\Dlf\Common;
4
5
/**
6
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
7
 *
8
 * This file is part of the Kitodo and TYPO3 projects.
9
 *
10
 * @license GNU General Public License version 3 or later.
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 */
14
15
use TYPO3\CMS\Core\Database\ConnectionPool;
16
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
17
use TYPO3\CMS\Core\Utility\GeneralUtility;
18
use TYPO3\CMS\Core\Utility\MathUtility;
19
20
/**
21
 * List class for the 'dlf' extension
22
 *
23
 * @author Sebastian Meyer <[email protected]>
24
 * @author Frank Ulrich Weber <[email protected]>
25
 * @package TYPO3
26
 * @subpackage dlf
27
 * @access public
28
 * @property array $metadata This holds the list's metadata
29
 */
30
class DocumentList implements \ArrayAccess, \Countable, \Iterator, \TYPO3\CMS\Core\SingletonInterface
31
{
32
    /**
33
     * This holds the number of documents in the list
34
     * @see \Countable
35
     *
36
     * @var integer
37
     * @access protected
38
     */
39
    protected $count = 0;
40
41
    /**
42
     * This holds the list entries in sorted order
43
     * @see \ArrayAccess
44
     *
45
     * @var array
46
     * @access protected
47
     */
48
    protected $elements = [];
49
50
    /**
51
     * This holds the list's metadata
52
     *
53
     * @var array
54
     * @access protected
55
     */
56
    protected $metadata = [];
57
58
    /**
59
     * This holds the current list position
60
     * @see \Iterator
61
     *
62
     * @var integer
63
     * @access protected
64
     */
65
    protected $position = 0;
66
67
    /**
68
     * This holds the full records of already processed list elements
69
     *
70
     * @var array
71
     * @access protected
72
     */
73
    protected $records = [];
74
75
    /**
76
     * Instance of \Kitodo\Dlf\Common\Solr class
77
     *
78
     * @var \Kitodo\Dlf\Common\Solr
79
     * @access protected
80
     */
81
    protected $solr;
82
83
    /**
84
     * This holds the Solr metadata configuration
85
     *
86
     * @var array
87
     * @access protected
88
     */
89
    protected $solrConfig = [];
90
91
    /**
92
     * This adds an array of elements at the given position to the list
93
     *
94
     * @access public
95
     *
96
     * @param array $elements: Array of elements to add to list
97
     * @param integer $position: Numeric position for including
98
     *
99
     * @return void
100
     */
101
    public function add(array $elements, $position = -1)
102
    {
103
        $position = MathUtility::forceIntegerInRange($position, 0, $this->count, $this->count);
104
        if (!empty($elements)) {
105
            array_splice($this->elements, $position, 0, $elements);
106
            $this->count = count($this->elements);
107
        }
108
    }
109
110
    /**
111
     * This counts the elements
112
     * @see \Countable::count()
113
     *
114
     * @access public
115
     *
116
     * @return integer The number of elements in the list
117
     */
118
    public function count()
119
    {
120
        return $this->count;
121
    }
122
123
    /**
124
     * This returns the current element
125
     * @see \Iterator::current()
126
     *
127
     * @access public
128
     *
129
     * @return array The current element
130
     */
131
    public function current()
132
    {
133
        if ($this->valid()) {
134
            return $this->getRecord($this->elements[$this->position]);
135
        } else {
136
            Helper::devLog('Invalid position "' . $this->position . '" for list element', DEVLOG_SEVERITY_NOTICE);
137
            return;
138
        }
139
    }
140
141
    /**
142
     * This returns the full record of any list element
143
     *
144
     * @access protected
145
     *
146
     * @param mixed $element: The list element
147
     *
148
     * @return mixed The element's full record
149
     */
150
    protected function getRecord($element)
151
    {
152
        if (
153
            is_array($element)
154
            && array_keys($element) == ['u', 'h', 's', 'p']
155
        ) {
156
            // Return already processed record if possible.
157
            if (!empty($this->records[$element['u']])) {
158
                return $this->records[$element['u']];
159
            }
160
            $record = [
161
                'uid' => $element['u'],
162
                'page' => 1,
163
                'preview' => '',
164
                'subparts' => $element['p']
165
            ];
166
            // Check if it's a list of database records or Solr documents.
167
            if (
168
                !empty($this->metadata['options']['source'])
169
                && $this->metadata['options']['source'] == 'collection'
170
            ) {
171
                $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
172
                    ->getQueryBuilderForTable('tx_dlf_documents');
173
174
                // Get document's thumbnail and metadata from database.
175
                $result = $queryBuilder
176
                    ->select(
177
                        'tx_dlf_documents.uid AS uid',
178
                        'tx_dlf_documents.thumbnail AS thumbnail',
179
                        'tx_dlf_documents.metadata AS metadata'
180
                    )
181
                    ->from('tx_dlf_documents')
182
                    ->where(
183
                        $queryBuilder->expr()->orX(
184
                            $queryBuilder->expr()->eq('tx_dlf_documents.uid', intval($record['uid'])),
185
                            $queryBuilder->expr()->eq('tx_dlf_documents.partof', intval($record['uid']))
186
                        ),
187
                        Helper::whereExpression('tx_dlf_documents')
188
                    )
189
                    ->execute();
190
191
                // Process results.
192
                while ($resArray = $result->fetch()) {
193
                    // Prepare document's metadata.
194
                    $metadata = unserialize($resArray['metadata']);
195
                    if (
196
                        !empty($metadata['type'][0])
197
                        && MathUtility::canBeInterpretedAsInteger($metadata['type'][0])
198
                    ) {
199
                        $metadata['type'][0] = Helper::getIndexNameFromUid($metadata['type'][0], 'tx_dlf_structures', $this->metadata['options']['pid']);
200
                    }
201
                    if (
202
                        !empty($metadata['owner'][0])
203
                        && MathUtility::canBeInterpretedAsInteger($metadata['owner'][0])
204
                    ) {
205
                        $metadata['owner'][0] = Helper::getIndexNameFromUid($metadata['owner'][0], 'tx_dlf_libraries', $this->metadata['options']['pid']);
206
                    }
207
                    if (
208
                        !empty($metadata['collection'])
209
                        && is_array($metadata['collection'])
210
                    ) {
211
                        foreach ($metadata['collection'] as $i => $collection) {
212
                            if (MathUtility::canBeInterpretedAsInteger($collection)) {
213
                                $metadata['collection'][$i] = Helper::getIndexNameFromUid($metadata['collection'][$i], 'tx_dlf_collections', $this->metadata['options']['pid']);
214
                            }
215
                        }
216
                    }
217
                    // Add metadata to list element.
218
                    if ($resArray['uid'] == $record['uid']) {
219
                        $record['thumbnail'] = $resArray['thumbnail'];
220
                        $record['metadata'] = $metadata;
221
                    } elseif (($key = array_search(['u' => $resArray['uid']], $record['subparts'], TRUE)) !== FALSE) {
222
                        $record['subparts'][$key] = [
223
                            'uid' => $resArray['uid'],
224
                            'page' => 1,
225
                            'preview' => (!empty($record['subparts'][$key]['h']) ? $record['subparts'][$key]['h'] : ''),
226
                            'thumbnail' => $resArray['thumbnail'],
227
                            'metadata' => $metadata
228
                        ];
229
                    }
230
                }
231
            } elseif (
232
                !empty($this->metadata['options']['source'])
233
                && $this->metadata['options']['source'] == 'search'
234
            ) {
235
                if ($this->solrConnect()) {
236
                    $params = [];
237
                    // Restrict the fields to the required ones
238
                    $params['fields'] = 'uid,id,toplevel,thumbnail,page';
239
                    foreach ($this->solrConfig as $solr_name) {
240
                        $params['fields'] .= ',' . $solr_name;
241
                    }
242
                    // If it is a fulltext search, enable highlighting.
243
                    if ($this->metadata['fulltextSearch']) {
244
                        $params['component'] = [
245
                            'highlighting' => [
246
                                'query' => Solr::escapeQuery($this->metadata['searchString']),
247
                                'field' => 'fulltext',
248
                                'usefastvectorhighlighter' => TRUE
249
                            ]
250
                        ];
251
                    }
252
                    // Set additional query parameters.
253
                    $params['start'] = 0;
254
                    // Set reasonable limit for safety reasons.
255
                    // We don't expect to get more than 10.000 hits per UID.
256
                    $params['rows'] = 10000;
257
                    // Take over existing filter queries.
258
                    $params['filterquery'] = isset($this->metadata['options']['params']['filterquery']) ? $this->metadata['options']['params']['filterquery'] : [];
259
                    // Extend filter query to get all documents with the same UID.
260
                    foreach ($params['filterquery'] as $key => $value) {
261
                        if (isset($value['query'])) {
262
                            $params['filterquery'][$key]['query'] = $value['query'] . ' OR toplevel:true';
263
                        }
264
                    }
265
                    // Add filter query to get all documents with the required uid.
266
                    $params['filterquery'][] = ['query' => 'uid:' . Solr::escapeQuery($record['uid'])];
267
                    // Add sorting.
268
                    $params['sort'] = $this->metadata['options']['params']['sort'];
269
                    // Set query.
270
                    $params['query'] = $this->metadata['options']['select'] . ' OR toplevel:true';
271
                    // Perform search for all documents with the same uid that either fit to the search or marked as toplevel.
272
                    $selectQuery = $this->solr->service->createSelect($params);
273
                    $result = $this->solr->service->select($selectQuery);
274
                    // If it is a fulltext search, fetch the highlighting results.
275
                    if ($this->metadata['fulltextSearch']) {
276
                        $highlighting = $result->getHighlighting();
277
                    }
278
                    // Process results.
279
                    foreach ($result as $resArray) {
280
                        // Prepare document's metadata.
281
                        $metadata = [];
282
                        foreach ($this->solrConfig as $index_name => $solr_name) {
283
                            if (!empty($resArray->$solr_name)) {
284
                                $metadata[$index_name] = (is_array($resArray->$solr_name) ? $resArray->$solr_name : [$resArray->$solr_name]);
285
                            }
286
                        }
287
                        // Add metadata to list elements.
288
                        if ($resArray->toplevel) {
289
                            $record['thumbnail'] = $resArray->thumbnail;
290
                            $record['metadata'] = $metadata;
291
                        } else {
292
                            $highlightedDoc = !empty($highlighting) ? $highlighting->getResult($resArray->id) : NULL;
293
                            $highlight = !empty($highlightedDoc) ? $highlightedDoc->getField('fulltext')[0] : '';
294
                            $record['subparts'][$resArray->id] = [
295
                                'uid' => $resArray->uid,
296
                                'page' => $resArray->page,
297
                                'preview' => $highlight,
298
                                'thumbnail' => $resArray->thumbnail,
299
                                'metadata' => $metadata
300
                            ];
301
                        }
302
                    }
303
                }
304
            }
305
            // Save record for later usage.
306
            $this->records[$element['u']] = $record;
307
        } else {
308
            Helper::devLog('No UID of list element to fetch full record', DEVLOG_SEVERITY_NOTICE);
309
            $record = $element;
310
        }
311
        return $record;
312
    }
313
314
    /**
315
     * This returns the current position
316
     * @see \Iterator::key()
317
     *
318
     * @access public
319
     *
320
     * @return integer The current position
321
     */
322
    public function key()
323
    {
324
        return $this->position;
325
    }
326
327
    /**
328
     * This moves the element at the given position up or down
329
     *
330
     * @access public
331
     *
332
     * @param integer $position: Numeric position for moving
333
     * @param integer $steps: Amount of steps to move up or down
334
     *
335
     * @return void
336
     */
337
    public function move($position, $steps)
338
    {
339
        $position = intval($position);
340
        // Check if list position is valid.
341
        if (
342
            $position < 0
343
            || $position >= $this->count
344
        ) {
345
            Helper::devLog('Invalid position "' . $position . '" for element moving', DEVLOG_SEVERITY_WARNING);
346
            return;
347
        }
348
        $steps = intval($steps);
349
        // Check if moving given amount of steps is possible.
350
        if (($position + $steps) < 0
351
            || ($position + $steps) >= $this->count
352
        ) {
353
            Helper::devLog('Invalid steps "' . $steps . '" for moving element at position "' . $position . '"', DEVLOG_SEVERITY_WARNING);
354
            return;
355
        }
356
        $element = $this->remove($position);
357
        $this->add([$element], $position + $steps);
358
    }
359
360
    /**
361
     * This moves the element at the given position up
362
     *
363
     * @access public
364
     *
365
     * @param integer $position: Numeric position for moving
366
     *
367
     * @return void
368
     */
369
    public function moveUp($position)
370
    {
371
        $this->move($position, -1);
372
    }
373
374
    /**
375
     * This moves the element at the given position down
376
     *
377
     * @access public
378
     *
379
     * @param integer $position: Numeric position for moving
380
     *
381
     * @return void
382
     */
383
    public function moveDown($position)
384
    {
385
        $this->move($position, 1);
386
    }
387
388
    /**
389
     * This increments the current list position
390
     * @see \Iterator::next()
391
     *
392
     * @access public
393
     *
394
     * @return void
395
     */
396
    public function next()
397
    {
398
        $this->position++;
399
    }
400
401
    /**
402
     * This checks if an offset exists
403
     * @see \ArrayAccess::offsetExists()
404
     *
405
     * @access public
406
     *
407
     * @param mixed $offset: The offset to check
408
     *
409
     * @return boolean Does the given offset exist?
410
     */
411
    public function offsetExists($offset)
412
    {
413
        return isset($this->elements[$offset]);
414
    }
415
416
    /**
417
     * This returns the element at the given offset
418
     * @see \ArrayAccess::offsetGet()
419
     *
420
     * @access public
421
     *
422
     * @param mixed $offset: The offset to return
423
     *
424
     * @return array The element at the given offset
425
     */
426
    public function offsetGet($offset)
427
    {
428
        if ($this->offsetExists($offset)) {
429
            return $this->getRecord($this->elements[$offset]);
430
        } else {
431
            Helper::devLog('Invalid offset "' . $offset . '" for list element', DEVLOG_SEVERITY_NOTICE);
432
            return;
433
        }
434
    }
435
436
    /**
437
     * This sets the element at the given offset
438
     * @see \ArrayAccess::offsetSet()
439
     *
440
     * @access public
441
     *
442
     * @param mixed $offset: The offset to set (non-integer offsets will be appended)
443
     * @param mixed $value: The value to set
444
     *
445
     * @return void
446
     */
447
    public function offsetSet($offset, $value)
448
    {
449
        if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($offset)) {
450
            $this->elements[$offset] = $value;
451
        } else {
452
            $this->elements[] = $value;
453
        }
454
        // Re-number the elements.
455
        $this->elements = array_values($this->elements);
456
        $this->count = count($this->elements);
457
    }
458
459
    /**
460
     * This removes the element at the given position from the list
461
     *
462
     * @access public
463
     *
464
     * @param integer $position: Numeric position for removing
465
     *
466
     * @return array The removed element
467
     */
468
    public function remove($position)
469
    {
470
        $position = intval($position);
471
        if (
472
            $position < 0
473
            || $position >= $this->count
474
        ) {
475
            Helper::devLog('Invalid position "' . $position . '" for element removing', DEVLOG_SEVERITY_WARNING);
476
            return;
477
        }
478
        $removed = array_splice($this->elements, $position, 1);
479
        $this->count = count($this->elements);
480
        return $this->getRecord($removed[0]);
481
    }
482
483
    /**
484
     * This removes elements at the given range from the list
485
     *
486
     * @access public
487
     *
488
     * @param integer $position: Numeric position for start of range
489
     * @param integer $length: Numeric position for length of range
490
     *
491
     * @return array The indizes of the removed elements
492
     */
493
    public function removeRange($position, $length)
494
    {
495
        $position = intval($position);
496
        if (
497
            $position < 0
498
            || $position >= $this->count
499
        ) {
500
            Helper::devLog('Invalid position "' . $position . '" for element removing', DEVLOG_SEVERITY_WARNING);
501
            return;
502
        }
503
        $removed = array_splice($this->elements, $position, $length);
504
        $this->count = count($this->elements);
505
        return $removed;
506
    }
507
508
    /**
509
     * This clears the current list
510
     *
511
     * @access public
512
     *
513
     * @return void
514
     */
515
    public function reset()
516
    {
517
        $this->elements = [];
518
        $this->records = [];
519
        $this->metadata = [];
520
        $this->count = 0;
521
        $this->position = 0;
522
    }
523
524
    /**
525
     * This resets the list position
526
     * @see \Iterator::rewind()
527
     *
528
     * @access public
529
     *
530
     * @return void
531
     */
532
    public function rewind()
533
    {
534
        $this->position = 0;
535
    }
536
537
    /**
538
     * This saves the current list
539
     *
540
     * @access public
541
     *
542
     * @param integer $pid: PID for saving in database
543
     *
544
     * @return void
545
     */
546
    public function save($pid = 0)
547
    {
548
        $pid = max(intval($pid), 0);
549
        // If no PID is given, save to the user's session instead
550
        if ($pid > 0) {
551
            // TODO: Liste in Datenbank speichern (inkl. Sichtbarkeit, Beschreibung, etc.)
552
        } else {
553
            Helper::saveToSession([$this->elements, $this->metadata], get_class($this));
554
        }
555
    }
556
557
    /**
558
     * Connects to Solr server.
559
     *
560
     * @access protected
561
     *
562
     * @return boolean TRUE on success or FALSE on failure
563
     */
564
    protected function solrConnect()
565
    {
566
        // Get Solr instance.
567
        if (!$this->solr) {
568
            // Connect to Solr server.
569
            if ($this->solr = Solr::getInstance($this->metadata['options']['core'])) {
570
                $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
571
                    ->getQueryBuilderForTable('tx_dlf_metadata');
572
573
                // Load index configuration.
574
                $result = $queryBuilder
575
                    ->select(
576
                        'tx_dlf_metadata.index_name AS index_name',
577
                        'tx_dlf_metadata.index_tokenized AS index_tokenized',
578
                        'tx_dlf_metadata.index_indexed AS index_indexed'
579
                    )
580
                    ->from('tx_dlf_metadata')
581
                    ->where(
582
                        $queryBuilder->expr()->eq('tx_dlf_metadata.is_listed', 1),
583
                        $queryBuilder->expr()->eq('tx_dlf_metadata.pid', intval($this->metadata['options']['pid'])),
584
                        Helper::whereExpression('tx_dlf_metadata')
585
                    )
586
                    ->orderBy('tx_dlf_metadata.sorting', 'ASC')
587
                    ->execute();
588
589
                while ($resArray = $result->fetch()) {
590
                    $this->solrConfig[$resArray['index_name']] = $resArray['index_name'] . '_' . ($resArray['index_tokenized'] ? 't' : 'u') . 's' . ($resArray['index_indexed'] ? 'i' : 'u');
591
                }
592
                // Add static fields.
593
                $this->solrConfig['type'] = 'type';
594
            } else {
595
                return FALSE;
596
            }
597
        }
598
        return TRUE;
599
    }
600
601
    /**
602
     * This sorts the current list by the given field
603
     *
604
     * @access public
605
     *
606
     * @param string $by: Sort the list by this field
607
     * @param boolean $asc: Sort ascending?
608
     *
609
     * @return void
610
     */
611
    public function sort($by, $asc = TRUE)
612
    {
613
        $newOrder = [];
614
        $nonSortable = [];
615
        foreach ($this->elements as $num => $element) {
616
            // Is this element sortable?
617
            if (!empty($element['s'][$by])) {
618
                $newOrder[$element['s'][$by] . str_pad($num, 6, '0', STR_PAD_LEFT)] = $element;
619
            } else {
620
                $nonSortable[] = $element;
621
            }
622
        }
623
        // Reorder elements.
624
        if ($asc) {
625
            ksort($newOrder, SORT_LOCALE_STRING);
626
        } else {
627
            krsort($newOrder, SORT_LOCALE_STRING);
628
        }
629
        // Add non sortable elements to the end of the list.
630
        $newOrder = array_merge(array_values($newOrder), $nonSortable);
631
        // Check if something is missing.
632
        if ($this->count == count($newOrder)) {
633
            $this->elements = $newOrder;
634
        } else {
635
            Helper::devLog('Sorted list elements do not match unsorted elements', DEVLOG_SEVERITY_ERROR);
636
        }
637
    }
638
639
    /**
640
     * This unsets the element at the given offset
641
     * @see \ArrayAccess::offsetUnset()
642
     *
643
     * @access public
644
     *
645
     * @param mixed $offset: The offset to unset
646
     *
647
     * @return void
648
     */
649
    public function offsetUnset($offset)
650
    {
651
        unset($this->elements[$offset]);
652
        // Re-number the elements.
653
        $this->elements = array_values($this->elements);
654
        $this->count = count($this->elements);
655
    }
656
657
    /**
658
     * This checks if the current list position is valid
659
     * @see \Iterator::valid()
660
     *
661
     * @access public
662
     *
663
     * @return boolean Is the current list position valid?
664
     */
665
    public function valid()
666
    {
667
        return isset($this->elements[$this->position]);
668
    }
669
670
    /**
671
     * This returns $this->metadata via __get()
672
     *
673
     * @access protected
674
     *
675
     * @return array The list's metadata
676
     */
677
    protected function _getMetadata()
678
    {
679
        return $this->metadata;
680
    }
681
682
    /**
683
     * This sets $this->metadata via __set()
684
     *
685
     * @access protected
686
     *
687
     * @param array $metadata: Array of new metadata
688
     *
689
     * @return void
690
     */
691
    protected function _setMetadata(array $metadata = [])
692
    {
693
        $this->metadata = $metadata;
694
    }
695
696
    /**
697
     * This is the constructor
698
     *
699
     * @access public
700
     *
701
     * @param array $elements: Array of documents initially setting up the list
702
     * @param array $metadata: Array of initial metadata
703
     *
704
     * @return void
705
     */
706
    public function __construct(array $elements = [], array $metadata = [])
707
    {
708
        if (
709
            empty($elements)
710
            && empty($metadata)
711
        ) {
712
            // Let's check the user's session.
713
            $sessionData = Helper::loadFromSession(get_class($this));
714
            // Restore list from session data.
715
            if (is_array($sessionData)) {
716
                if (is_array($sessionData[0])) {
717
                    $this->elements = $sessionData[0];
718
                }
719
                if (is_array($sessionData[1])) {
720
                    $this->metadata = $sessionData[1];
721
                }
722
            }
723
        } else {
724
            // Add metadata to the list.
725
            $this->metadata = $metadata;
726
            // Add initial set of elements to the list.
727
            $this->elements = $elements;
728
        }
729
        $this->count = count($this->elements);
730
    }
731
732
    /**
733
     * This magic method is invoked each time a clone is called on the object variable
734
     *
735
     * @access protected
736
     *
737
     * @return void
738
     */
739
    protected function __clone()
740
    {
741
        // This method is defined as protected because singleton objects should not be cloned.
742
    }
743
744
    /**
745
     * This magic method is called each time an invisible property is referenced from the object
746
     *
747
     * @access public
748
     *
749
     * @param string $var: Name of variable to get
750
     *
751
     * @return mixed Value of $this->$var
752
     */
753
    public function __get($var)
754
    {
755
        $method = '_get' . ucfirst($var);
756
        if (
757
            !property_exists($this, $var)
758
            || !method_exists($this, $method)
759
        ) {
760
            Helper::devLog('There is no getter function for property "' . $var . '"', DEVLOG_SEVERITY_WARNING);
761
            return;
762
        } else {
763
            return $this->$method();
764
        }
765
    }
766
767
    /**
768
     * This magic method is called each time an invisible property is checked for isset() or empty()
769
     *
770
     * @access public
771
     *
772
     * @param string $var: Name of variable to check
773
     *
774
     * @return boolean TRUE if variable is set and not empty, FALSE otherwise
775
     */
776
    public function __isset($var) {
777
        return !empty($this->__get($var));
778
    }
779
780
    /**
781
     * This magic method is called each time an invisible property is referenced from the object
782
     *
783
     * @access public
784
     *
785
     * @param string $var: Name of variable to set
786
     * @param mixed $value: New value of variable
787
     *
788
     * @return void
789
     */
790
    public function __set($var, $value)
791
    {
792
        $method = '_set' . ucfirst($var);
793
        if (
794
            !property_exists($this, $var)
795
            || !method_exists($this, $method)
796
        ) {
797
            Helper::devLog('There is no setter function for property "' . $var . '"', DEVLOG_SEVERITY_WARNING);
798
        } else {
799
            $this->$method($value);
800
        }
801
    }
802
803
    /**
804
     * This magic method is executed prior to any serialization of the object
805
     * @see __wakeup()
806
     *
807
     * @access public
808
     *
809
     * @return array Properties to be serialized
810
     */
811
    public function __sleep()
812
    {
813
        return ['elements', 'metadata'];
814
    }
815
816
    /**
817
     * This magic method is executed after the object is deserialized
818
     * @see __sleep()
819
     *
820
     * @access public
821
     *
822
     * @return void
823
     */
824
    public function __wakeup()
825
    {
826
        $this->count = count($this->elements);
827
    }
828
}
829