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
Push — master ( 64c81c...585b6c )
by Sebastian
05:28 queued 20s
created

DocumentList::getRecord()   F

Complexity

Conditions 34
Paths 13

Size

Total Lines 163
Code Lines 102

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 102
c 0
b 0
f 0
dl 0
loc 163
rs 3.3333
cc 34
nc 13
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
 */
29
class DocumentList implements \ArrayAccess, \Countable, \Iterator, \TYPO3\CMS\Core\SingletonInterface
30
{
31
    /**
32
     * This holds the number of documents in the list
33
     * @see \Countable
34
     *
35
     * @var integer
36
     * @access protected
37
     */
38
    protected $count = 0;
39
40
    /**
41
     * This holds the list entries in sorted order
42
     * @see \ArrayAccess
43
     *
44
     * @var array
45
     * @access protected
46
     */
47
    protected $elements = [];
48
49
    /**
50
     * This holds the list's metadata
51
     *
52
     * @var array
53
     * @access protected
54
     */
55
    protected $metadata = [];
56
57
    /**
58
     * This holds the current list position
59
     * @see \Iterator
60
     *
61
     * @var integer
62
     * @access protected
63
     */
64
    protected $position = 0;
65
66
    /**
67
     * This holds the full records of already processed list elements
68
     *
69
     * @var array
70
     * @access protected
71
     */
72
    protected $records = [];
73
74
    /**
75
     * Instance of \Kitodo\Dlf\Common\Solr class
76
     *
77
     * @var \Kitodo\Dlf\Common\Solr
78
     * @access protected
79
     */
80
    protected $solr;
81
82
    /**
83
     * This holds the Solr metadata configuration
84
     *
85
     * @var array
86
     * @access protected
87
     */
88
    protected $solrConfig = [];
89
90
    /**
91
     * This adds an array of elements at the given position to the list
92
     *
93
     * @access public
94
     *
95
     * @param array $elements: Array of elements to add to list
96
     * @param integer $position: Numeric position for including
97
     *
98
     * @return void
99
     */
100
    public function add(array $elements, $position = -1)
101
    {
102
        $position = MathUtility::forceIntegerInRange($position, 0, $this->count, $this->count);
103
        if (!empty($elements)) {
104
            array_splice($this->elements, $position, 0, $elements);
105
            $this->count = count($this->elements);
106
        }
107
    }
108
109
    /**
110
     * This counts the elements
111
     * @see \Countable::count()
112
     *
113
     * @access public
114
     *
115
     * @return integer The number of elements in the list
116
     */
117
    public function count()
118
    {
119
        return $this->count;
120
    }
121
122
    /**
123
     * This returns the current element
124
     * @see \Iterator::current()
125
     *
126
     * @access public
127
     *
128
     * @return array The current element
129
     */
130
    public function current()
131
    {
132
        if ($this->valid()) {
133
            return $this->getRecord($this->elements[$this->position]);
134
        } else {
135
            Helper::devLog('Invalid position "' . $this->position . '" for list element', DEVLOG_SEVERITY_NOTICE);
136
            return;
137
        }
138
    }
139
140
    /**
141
     * This returns the full record of any list element
142
     *
143
     * @access protected
144
     *
145
     * @param mixed $element: The list element
146
     *
147
     * @return mixed The element's full record
148
     */
149
    protected function getRecord($element)
150
    {
151
        if (
152
            is_array($element)
153
            && array_keys($element) == ['u', 'h', 's', 'p']
154
        ) {
155
            // Return already processed record if possible.
156
            if (!empty($this->records[$element['u']])) {
157
                return $this->records[$element['u']];
158
            }
159
            $record = [
160
                'uid' => $element['u'],
161
                'page' => 1,
162
                'preview' => '',
163
                'subparts' => $element['p']
164
            ];
165
            // Check if it's a list of database records or Solr documents.
166
            if (
167
                !empty($this->metadata['options']['source'])
168
                && $this->metadata['options']['source'] == 'collection'
169
            ) {
170
                /** @var QueryBuilder $queryBuilder */
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);
0 ignored issues
show
Bug Best Practice introduced by
The property $service is declared protected in Kitodo\Dlf\Common\Solr. Since you implement __get, consider adding a @property or @property-read.
Loading history...
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
                /** @var QueryBuilder $queryBuilder */
571
                $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
572
                    ->getQueryBuilderForTable('tx_dlf_metadata');
573
574
                // Load index configuration.
575
                $result = $queryBuilder
576
                    ->select(
577
                        'tx_dlf_metadata.index_name AS index_name',
578
                        'tx_dlf_metadata.index_tokenized AS index_tokenized',
579
                        'tx_dlf_metadata.index_indexed AS index_indexed'
580
                    )
581
                    ->from('tx_dlf_metadata')
582
                    ->where(
583
                        $queryBuilder->expr()->eq('tx_dlf_metadata.is_listed', 1),
584
                        $queryBuilder->expr()->eq('tx_dlf_metadata.pid', intval($this->metadata['options']['pid'])),
585
                        Helper::whereExpression('tx_dlf_metadata')
586
                    )
587
                    ->orderBy('tx_dlf_metadata.sorting', 'ASC')
588
                    ->execute();
589
590
                while ($resArray = $result->fetch()) {
591
                    $this->solrConfig[$resArray['index_name']] = $resArray['index_name'] . '_' . ($resArray['index_tokenized'] ? 't' : 'u') . 's' . ($resArray['index_indexed'] ? 'i' : 'u');
592
                }
593
                // Add static fields.
594
                $this->solrConfig['type'] = 'type';
595
            } else {
596
                return FALSE;
597
            }
598
        }
599
        return TRUE;
600
    }
601
602
    /**
603
     * This sorts the current list by the given field
604
     *
605
     * @access public
606
     *
607
     * @param string $by: Sort the list by this field
608
     * @param boolean $asc: Sort ascending?
609
     *
610
     * @return void
611
     */
612
    public function sort($by, $asc = TRUE)
613
    {
614
        $newOrder = [];
615
        $nonSortable = [];
616
        foreach ($this->elements as $num => $element) {
617
            // Is this element sortable?
618
            if (!empty($element['s'][$by])) {
619
                $newOrder[$element['s'][$by] . str_pad($num, 6, '0', STR_PAD_LEFT)] = $element;
620
            } else {
621
                $nonSortable[] = $element;
622
            }
623
        }
624
        // Reorder elements.
625
        if ($asc) {
626
            ksort($newOrder, SORT_LOCALE_STRING);
627
        } else {
628
            krsort($newOrder, SORT_LOCALE_STRING);
629
        }
630
        // Add non sortable elements to the end of the list.
631
        $newOrder = array_merge(array_values($newOrder), $nonSortable);
632
        // Check if something is missing.
633
        if ($this->count == count($newOrder)) {
634
            $this->elements = $newOrder;
635
        } else {
636
            Helper::devLog('Sorted list elements do not match unsorted elements', DEVLOG_SEVERITY_ERROR);
637
        }
638
    }
639
640
    /**
641
     * This unsets the element at the given offset
642
     * @see \ArrayAccess::offsetUnset()
643
     *
644
     * @access public
645
     *
646
     * @param mixed $offset: The offset to unset
647
     *
648
     * @return void
649
     */
650
    public function offsetUnset($offset)
651
    {
652
        unset($this->elements[$offset]);
653
        // Re-number the elements.
654
        $this->elements = array_values($this->elements);
655
        $this->count = count($this->elements);
656
    }
657
658
    /**
659
     * This checks if the current list position is valid
660
     * @see \Iterator::valid()
661
     *
662
     * @access public
663
     *
664
     * @return boolean Is the current list position valid?
665
     */
666
    public function valid()
667
    {
668
        return isset($this->elements[$this->position]);
669
    }
670
671
    /**
672
     * This returns $this->metadata via __get()
673
     *
674
     * @access protected
675
     *
676
     * @return array The list's metadata
677
     */
678
    protected function _getMetadata()
679
    {
680
        return $this->metadata;
681
    }
682
683
    /**
684
     * This sets $this->metadata via __set()
685
     *
686
     * @access protected
687
     *
688
     * @param array $metadata: Array of new metadata
689
     *
690
     * @return void
691
     */
692
    protected function _setMetadata(array $metadata = [])
693
    {
694
        $this->metadata = $metadata;
695
    }
696
697
    /**
698
     * This is the constructor
699
     *
700
     * @access public
701
     *
702
     * @param array $elements: Array of documents initially setting up the list
703
     * @param array $metadata: Array of initial metadata
704
     *
705
     * @return void
706
     */
707
    public function __construct(array $elements = [], array $metadata = [])
708
    {
709
        if (
710
            empty($elements)
711
            && empty($metadata)
712
        ) {
713
            // Let's check the user's session.
714
            $sessionData = Helper::loadFromSession(get_class($this));
715
            // Restore list from session data.
716
            if (is_array($sessionData)) {
717
                if (is_array($sessionData[0])) {
718
                    $this->elements = $sessionData[0];
719
                }
720
                if (is_array($sessionData[1])) {
721
                    $this->metadata = $sessionData[1];
722
                }
723
            }
724
        } else {
725
            // Add metadata to the list.
726
            $this->metadata = $metadata;
727
            // Add initial set of elements to the list.
728
            $this->elements = $elements;
729
        }
730
        $this->count = count($this->elements);
731
    }
732
733
    /**
734
     * This magic method is invoked each time a clone is called on the object variable
735
     * (This method is defined as private/protected because singleton objects should not be cloned)
736
     *
737
     * @access protected
738
     *
739
     * @return void
740
     */
741
    protected function __clone()
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 referenced from the object
769
     *
770
     * @access public
771
     *
772
     * @param string $var: Name of variable to set
773
     * @param mixed $value: New value of variable
774
     *
775
     * @return void
776
     */
777
    public function __set($var, $value)
778
    {
779
        $method = '_set' . ucfirst($var);
780
        if (
781
            !property_exists($this, $var)
782
            || !method_exists($this, $method)
783
        ) {
784
            Helper::devLog('There is no setter function for property "' . $var . '"', DEVLOG_SEVERITY_WARNING);
785
        } else {
786
            $this->$method($value);
787
        }
788
    }
789
790
    /**
791
     * This magic method is executed prior to any serialization of the object
792
     * @see __wakeup()
793
     *
794
     * @access public
795
     *
796
     * @return array Properties to be serialized
797
     */
798
    public function __sleep()
799
    {
800
        return ['elements', 'metadata'];
801
    }
802
803
    /**
804
     * This magic method is executed after the object is deserialized
805
     * @see __sleep()
806
     *
807
     * @access public
808
     *
809
     * @return void
810
     */
811
    public function __wakeup()
812
    {
813
        $this->count = count($this->elements);
814
    }
815
}
816