Blendable::getSeedKey()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 12
c 1
b 0
f 0
nc 6
nop 1
dl 0
loc 20
rs 9.8666
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: joshgulledge
5
 * Date: 3/5/18
6
 * Time: 11:14 AM
7
 */
8
9
namespace LCI\Blend\Blendable;
10
11
use LCI\Blend\Blender;
12
use LCI\Blend\Exception\BlendableException;
13
use LCI\Blend\Exception\BlendableKeyLengthException;
14
15
abstract class Blendable implements BlendableInterface
16
{
17
    /** @var  \modx */
0 ignored issues
show
Bug introduced by
The type modx was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
    protected $modx;
19
20
    /** @var  Blender */
21
    protected $blender;
22
23
    /** @var string ~ blend or revert */
24
    protected $type = 'blend';
25
26
    /** @var string  */
27
    protected $opt_cache_key = '';
28
29
    /** @var array  */
30
    protected $seedCacheOptions = [];
31
32
    /** @var array  */
33
    protected $historyCacheOptions = [];
34
35
    /** @var string */
36
    protected $seeds_dir = '';
37
38
    /** @var int $cache_life in seconds, 0 is forever */
39
    protected $cache_life = 0;
40
41
    /** @var bool  */
42
    protected $error = false;
43
44
    /** @var array  */
45
    protected $error_messages = [];
46
47
    /** @var null|\xPDOSimpleObject  */
0 ignored issues
show
Bug introduced by
The type xPDOSimpleObject was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
48
    protected $xPDOSimpleObject = null;
49
50
    /** @var string ex: modResource */
51
    protected $xpdo_simple_object_class = '';
52
53
    /** @var string  */
54
    protected $unique_key_column = 'name';
55
56
    /** @var array set when a change of name/alias has been done */
57
    protected $unique_key_history = [];
58
59
    /** @var int if there is a DB char length define it */
60
    protected $unique_key_length_limit = 0;
61
62
    /** @var array ~ this should match data to be inserted via xPDO, ex [column_name => value, ...] */
63
    protected $blendable_xpdo_simple_object_data = [
64
        'name' => ''
65
    ];
66
67
    /** @var array ~ ['setMethodName' => 'setMethodActualName', 'setDoNotUseMethod' => false] overwrite in child classes */
68
    protected $load_from_array_aliases = [];
69
70
    /** @var array ~ list any fields/columns to be ignored on making seeds, like id */
71
    protected $ignore_seed_fields = ['id'];
72
73
    /** @var array ~ xPDOSimpleObject->fromArray() */
74
    protected $current_xpdo_simple_object_data = [];
75
76
    /** @var array  */
77
    protected $related_data = [];
78
79
    /** @var bool  */
80
    protected $exists = false;
81
82
    /** @var bool  */
83
    protected $debug = false;
84
85
    /**
86
     * Blendable constructor.
87
     *
88
     * @param \modx $modx
89
     * @param Blender $blender
90
     * @param string|array $unique_value
91
     * @throws BlendableKeyLengthException
92
     */
93
    public function __construct(\modx $modx, Blender $blender, $unique_value = '')
94
    {
95
        $this->modx = $modx;
96
        $this->blender = $blender;
97
        if (method_exists($this, 'loadProperties')) {
98
            $this->loadProperties();
99
        }
100
101
        $this->seedCacheOptions = [
102
            \xPDO::OPT_CACHE_KEY => $this->opt_cache_key,
0 ignored issues
show
Bug introduced by
The type xPDO was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
103
            \xPDO::OPT_CACHE_PATH => $this->blender->getSeedsPath()
104
        ];
105
106
        $this->historyCacheOptions = [
107
            \xPDO::OPT_CACHE_KEY => $this->opt_cache_key,
108
            \xPDO::OPT_CACHE_PATH => $this->blender->getHistoryPath()
109
        ];
110
111
        $this->setUniqueCriteria($unique_value);
112
        if (!empty($unique_value)) {
113
            $this->loadObject();
114
        }
115
    }
116
117
    /**
118
     * @return bool
119
     */
120
    public function isDebug()
121
    {
122
        return $this->debug;
123
    }
124
125
    /**
126
     * @param bool $debug
127
     *
128
     * @return $this
129
     */
130
    public function setDebug($debug)
131
    {
132
        $this->debug = $debug;
133
        return $this;
134
    }
135
136
    /**
137
     * @return string
138
     */
139
    public function getSeedsDir()
140
    {
141
        return $this->seeds_dir;
142
    }
143
144
    /**
145
     * @param string $dir ~ will be the directory name for seeds and history
146
     *
147
     * @return $this
148
     */
149
    public function setSeedsDir($dir)
150
    {
151
        $this->seeds_dir = (string)$dir;
152
        if (!empty($this->seeds_dir)) {
153
            $this->seedCacheOptions[\xPDO::OPT_CACHE_PATH] = $this->blender->getSeedsPath().$dir.'/';
154
            $this->historyCacheOptions[\xPDO::OPT_CACHE_PATH] = $this->blender->getHistoryPath().$dir.'/';
155
        }
156
        return $this;
157
    }
158
159
    /**
160
     * @return bool
161
     */
162
    public function isExists()
163
    {
164
        return $this->exists;
165
    }
166
167
    /**
168
     * @return bool
169
     */
170
    public function isError()
171
    {
172
        return $this->error;
173
    }
174
175
    /**
176
     * @return array
177
     */
178
    public function getErrorMessages()
179
    {
180
        return $this->error_messages;
181
    }
182
183
    /**
184
     * @param string $type ~ seed or revert
185
     * @return string
186
     */
187
    public function getSeedKey($type = 'seed')
188
    {
189
        $name = $this->blendable_xpdo_simple_object_data[$this->unique_key_column];
190
        if (method_exists($this, 'getFieldName')) {
191
            $name = $this->getFieldName();
192
        }
193
        $key = $this->blender->getSeedKeyFromName($name);
194
195
        switch ($type) {
196
            case 'revert':
197
                $seed_key = 'revert-'.$key;
198
                break;
199
200
            case 'seed':
201
                // no break
202
            default:
203
                $seed_key = $key;
204
        }
205
206
        return $seed_key;
207
    }
208
209
    /**
210
     * @return null|\xPDOSimpleObject
211
     */
212
    public function getXPDOSimpleObject()
213
    {
214
        return $this->xPDOSimpleObject;
215
    }
216
217
    /**
218
     * @param array $data ~ must be in the format: array('columns' => [], 'primaryKeyHistory' => [], 'related' => [])
219
     * @param bool $overwrite
220
     * @return bool
221
     */
222
    public function blendFromArray($data, $overwrite = false)
223
    {
224
        if (isset($data['columns'])) {
225
            $this->blendable_xpdo_simple_object_data = $data['columns'];
226
        }
227
        if (isset($data['primaryKeyHistory']) && $data['primaryKeyHistory']) {
228
            $this->unique_key_history = $data['primaryKeyHistory'];
229
        } else {
230
            $this->unique_key_history = [];
231
        }
232
233
        if (isset($data['related']) && $data['related']) {
234
            $this->related_data = $data['related'];
235
        } else {
236
            $this->related_data = [];
237
        }
238
239
        return $this->blend($overwrite);
240
    }
241
    /**
242
     * @param string $seed_key
243
     * @param bool $overwrite
244
     *
245
     * @return bool
246
     * @throws BlendableException
247
     */
248
    public function blendFromSeed($seed_key, $overwrite = false)
249
    {
250
        $this->loadObjectDataFromSeed($seed_key);
251
        return $this->blend($overwrite);
252
    }
253
254
    /**
255
     * @param bool $overwrite
256
     *
257
     * @return bool
258
     */
259
    public function blend($overwrite = false)
260
    {
261
        if ($this->type == 'blend') {
262
            /** @var \LCI\Blend\Blendable\Blendable $currentVersion */
263
            $currentVersion = $this->getCurrentVersion();
264
            $currentVersion
265
                ->setRelatedData($this->related_data)
266
                ->makeHistory();
267
        }
268
269
        $this->modx->invokeEvent(
270
            'OnBlendBeforeSave',
271
            [
272
                'blender' => $this->blender,
273
                'blendable' => $this,
274
                'data' => &$this->blendable_xpdo_simple_object_data,
275
                'type' => $this->type,
276
                'xPDOClass' => $this->xpdo_simple_object_class,
277
                'xPDOSimpleObject' => &$this->xPDOSimpleObject
278
            ]
279
        );
280
281
        $save = $this->save($overwrite);
282
283
        if ($save) {
284
            $this->modx->invokeEvent(
285
                'OnBlendAfterSave',
286
                [
287
                    'blender' => $this->blender,
288
                    'blendable' => $this,
289
                    'data' => &$this->blendable_xpdo_simple_object_data,
290
                    'type' => $this->type,
291
                    'xPDOClass' => $this->xpdo_simple_object_class,
292
                    'xPDOSimpleObject' => &$this->xPDOSimpleObject
293
                ]
294
            );
295
        }
296
297
        return $save;
298
    }
299
300
    /**
301
     * @param bool $make_revert_seed
302
     * @return bool
303
     */
304
    public function delete($make_revert_seed = true)
305
    {
306
        if ($make_revert_seed) {
307
            $this->makeHistory();
308
        }
309
        $removed = false;
310
        if (!is_object($this->xPDOSimpleObject)) {
311
            $this->blender->out($this->blendable_xpdo_simple_object_data[$this->unique_key_column].' of xPDO class '.
312
                $this->xpdo_simple_object_class.' was not found, could not be removed/deleted', true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type integer expected by parameter $verbose of LCI\Blend\Blender::out(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

312
                $this->xpdo_simple_object_class.' was not found, could not be removed/deleted', /** @scrutinizer ignore-type */ true);
Loading history...
313
314
        } elseif ($this->xPDOSimpleObject->remove()) {
315
            $this->onDeleteRevertRelatedPieces();
316
            if ($this->isDebug()) {
317
                $this->blender->out($this->blendable_xpdo_simple_object_data[$this->unique_key_column].' has been removed/deleted');
318
            }
319
            $removed = true;
320
321
        } else {
322
            if ($this->isDebug()) {
323
                $this->blender->out($this->blendable_xpdo_simple_object_data[$this->unique_key_column].' did not remove/delete', true);
324
            }
325
        }
326
327
        return $removed;
328
    }
329
330
    /**
331
     * @return bool
332
     */
333
    public function revertBlend()
334
    {
335
        $seed_key = $this->getSeedKey('revert');
336
        $this->type = 'revert';
337
        if (!$this->loadObjectDataFromHistorySeed($seed_key) || !$this->blendable_xpdo_simple_object_data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->blendable_xpdo_simple_object_data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
338
            return $this->delete(false);
339
        }
340
341
        return $this->blend(true);
342
    }
343
344
    /**
345
     * @return string ~ the related seed key
346
     */
347
    public function seed()
348
    {
349
        // No IDs! must get the alias and get a seed key,
350
        $seed_key = $this->getSeedKey();
351
352
        $data = $this->seedToArray('seed', $seed_key);
353
354
        // now cache it:
355
        $this->modx->cacheManager->set(
356
            $seed_key,
357
            $data,
358
            $this->cache_life,
359
            $this->seedCacheOptions
360
        );
361
362
        return $seed_key;
363
    }
364
365
    /**
366
     * @return string ~ the related seed key
367
     */
368
    public function makeHistory()
369
    {
370
        $seed_key = $this->getSeedKey('revert');
371
372
        $data = $this->seedToArray('revert', $seed_key);
373
374
        // now cache it:
375
        $this->modx->cacheManager->set(
376
            $seed_key,
377
            $data,
378
            $this->cache_life,
379
            $this->historyCacheOptions
380
        );
381
382
        return $seed_key;
383
    }
384
385
    /**
386
     * @param string $type ~ seed or revert
387
     * @param string $seed_key
388
     * @return array
389
     */
390
    public function seedToArray($type = 'seed', $seed_key = '')
391
    {
392
        if (is_object($this->xPDOSimpleObject)) {
393
            $this->current_xpdo_simple_object_data = $this->xPDOSimpleObject->toArray();
394
395
            foreach ($this->current_xpdo_simple_object_data as $column => $value) {
396
                if (in_array($column, $this->ignore_seed_fields)) {
397
                    continue;
398
                }
399
                // Any child class can create a seed method, an example for modResource:
400
                // seedTemplate(1) and would return the string name
401
                $method = 'seed'.$this->makeStudyCase($column);
402
                if (method_exists($this, $method)) {
403
                    $value = $this->$method($value);
404
                }
405
                $this->blendable_xpdo_simple_object_data[$column] = $value;
406
            }
407
408
            $this->seedRelated($type);
409
410
            $data = [
411
                'columns' => $this->blendable_xpdo_simple_object_data,
412
                'primaryKeyHistory' => $this->unique_key_history,
413
                'related' => $this->related_data
414
            ];
415
416
        } elseif ($type == 'revert') {
417
418
            $data = [
419
                'columns' => false,
420
                'primaryKeyHistory' => [],
421
                'related' => []
422
            ];
423
424
            if ($this->isDebug()) {
425
                $this->blender->out('Data not found to make seed: '.$seed_key);
426
            }
427
428
        } elseif ($type == 'seed') {
429
            if ($this->isDebug()) {
430
                $this->blender->out('Data not found to make seed: '.$seed_key);
431
            }
432
        }
433
434
        // https://docs.modx.com/revolution/2.x/developing-in-modx/other-development-resources/class-reference/modx/modx.invokeevent
435
        $this->modx->invokeEvent(
436
            'OnBlendSeed',
437
            [
438
                'blender' => $this->blender,
439
                'blendable' => $this,
440
                'type' => $type,
441
                'xPDOClass' => $this->xpdo_simple_object_class,
442
                'xPDOSimpleObject' => &$this->xPDOSimpleObject,
443
                'data' => &$data
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.
Loading history...
444
            ]
445
        );
446
447
        return $data;
448
    }
449
450
    /**
451
     * @param bool $overwrite
452
     *
453
     * @return bool
454
     */
455
    protected function save($overwrite = false)
456
    {
457
        $saved = false;
458
459
        if (is_object($this->xPDOSimpleObject)) {
460
            if (!$overwrite) {
461
                $this->error = true;
462
                $this->error_messages['exits'] = $this->xpdo_simple_object_class.': '.
463
                    $this->blendable_xpdo_simple_object_data[$this->unique_key_column].' already exists ';
464
                return $saved;
465
            }
466
        } else {
467
            $this->xPDOSimpleObject = $this->modx->newObject($this->xpdo_simple_object_class);
468
        }
469
470
        $this->xPDOSimpleObject->set($this->unique_key_column, $this->blendable_xpdo_simple_object_data[$this->unique_key_column]);
471
472
        foreach ($this->blendable_xpdo_simple_object_data as $column => $value) {
473
            // Any child class can create a convert method, an example for modResource:
474
            // convertTemplate('String name') and would return the numeric ID
475
            $method = 'convert'.$this->makeStudyCase($column);
476
            if (method_exists($this, $method)) {
477
                $value = $this->$method($value);
478
            }
479
            $this->xPDOSimpleObject->set($column, $value);
480
        }
481
482
        if (method_exists($this, 'getPropertiesData')) {
483
            $this->xPDOSimpleObject->set('properties', $this->getPropertiesData());
484
        }
485
486
        $this->attachRelatedPieces();
487
488
        if ($this->xPDOSimpleObject->save()) {
489
            $this->attachRelatedPiecesAfterSave();
490
            if ($this->isDebug()) {
491
                $this->blender->out($this->blendable_xpdo_simple_object_data[$this->unique_key_column].' has been installed/saved');
492
            }
493
            $saved = true;
494
495
        } else {
496
            if ($this->isDebug()) {
497
                $this->blender->out($this->blendable_xpdo_simple_object_data[$this->unique_key_column].' did not install/update', true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type integer expected by parameter $verbose of LCI\Blend\Blender::out(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

497
                $this->blender->out($this->blendable_xpdo_simple_object_data[$this->unique_key_column].' did not install/update', /** @scrutinizer ignore-type */ true);
Loading history...
498
            }
499
500
        }
501
502
        return $saved;
503
    }
504
505
    protected function getUniqueCriteria()
506
    {
507
        return [
508
            $this->unique_key_column => $this->blendable_xpdo_simple_object_data[$this->unique_key_column]
509
        ];
510
    }
511
512
    /**
513
     * @param string|array $criteria
514
     * @throws BlendableKeyLengthException
515
     */
516
    protected function setUniqueCriteria($criteria)
517
    {
518
        if ($this->unique_key_length_limit > 0 && is_string($criteria) && strlen($criteria) > $this->unique_key_length_limit) {
519
            throw new BlendableKeyLengthException(
520
                'Error: '.$this->unique_key_column . ' is limited to '.
521
                $this->unique_key_length_limit .' and '.$criteria.' is '. strlen($criteria) . ' characters'
522
            );
523
        }
524
525
        $this->blendable_xpdo_simple_object_data[$this->unique_key_column] = $criteria;
526
    }
527
528
    /**
529
     * Will load an existing xPDOSimpleObject if it exists, child class needs to class this one
530
     * @return $this
531
     */
532
    protected function loadObject()
533
    {
534
        $this->xPDOSimpleObject = $this->modx->getObject($this->xpdo_simple_object_class, $this->getUniqueCriteria());
535
536
        if (is_object($this->xPDOSimpleObject)) {
537
            $this->exists = true;
538
            $this->current_xpdo_simple_object_data = $this->xPDOSimpleObject->toArray();
539
            $this->loadFromArray($this->current_xpdo_simple_object_data);
540
            // load related data:
541
            $this->loadRelatedData();
542
        }
543
544
        return $this;
545
    }
546
547
    /**
548
     * @param array $data ~ convert the db data object to blend portable data
549
     *
550
     * @return $this
551
     */
552
    protected function loadFromArray($data = [])
553
    {
554
        foreach ($data as $column => $value) {
555
556
            if ($column == 'content_type' && $this->xpdo_simple_object_class == 'modResource') {
557
                // modResource has both contentType and content_type, ignore the 2nd
558
                continue;
559
            }
560
561
            $method_name = 'seed'.$this->makeStudyCase($column);
562
563
            if (method_exists($this, $method_name) && !is_null($value)) {
564
                if ($this->isDebug()) {
565
                    $this->blender->out(__METHOD__.' call: '.$method_name.' V: '.$value);
566
                }
567
                $value = $this->$method_name($value);
568
            }
569
570
            $method_name = 'setField'.$this->makeStudyCase($column);
571
572
            if (isset($this->load_from_array_aliases[$method_name])) {
573
                $method_name = $this->load_from_array_aliases[$method_name];
574
575
                if (!$method_name) {
576
                    continue;
577
                }
578
            }
579
580
            if (method_exists($this, $method_name) && !is_null($value)) {
581
                if ($this->isDebug()) {
582
                    $this->blender->out(__METHOD__.' call: '.$method_name.' V: '.$value);
583
                }
584
                $this->$method_name($value);
585
                
586
            } elseif ($this->isDebug()) {
587
                $this->blender->out(__METHOD__.' missing: '.$method_name.' V: '.print_r($value, true), true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type integer expected by parameter $verbose of LCI\Blend\Blender::out(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

587
                $this->blender->out(__METHOD__.' missing: '.$method_name.' V: '.print_r($value, true), /** @scrutinizer ignore-type */ true);
Loading history...
588
            }
589
        }
590
591
        return $this;
592
    }
593
594
    /**
595
     * Override in child classes
596
     */
597
    protected function loadRelatedData()
598
    {
599
        $this->modx->invokeEvent(
600
            'OnBlendLoadRelatedData',
601
            [
602
                'blender' => $this->blender,
603
                'blendable' => $this,
604
                'data' => &$this->blendable_xpdo_simple_object_data,
605
                'type' => $this->type,
606
                'xPDOClass' => $this->xpdo_simple_object_class,
607
                'xPDOSimpleObject' => &$this->xPDOSimpleObject
608
            ]
609
        );
610
    }
611
612
    /**
613
     * @param string $seed_key
614
     *
615
     * @return bool|array
616
     * @throws BlendableException
617
     */
618
    protected function loadObjectDataFromSeed($seed_key)
619
    {
620
        $data = $this->modx->cacheManager->get($seed_key, $this->seedCacheOptions);
621
        if ($data == false) {
622
            if ($this->type == 'blend') {
623
                $this->blender->outError('Error: Seed could not be found: '.$seed_key);
624
                throw new BlendableException('Error: Seed could not be found: '.$seed_key . ' in '. print_r($this->seedCacheOptions, true));
625
            }
626
627
        } else {
628
            $this->blendable_xpdo_simple_object_data = $data['columns'];
629
            $this->unique_key_history = $data['primaryKeyHistory'];
630
            $this->related_data = $data['related'];
631
        }
632
633
        return $data;
634
    }
635
636
    /**
637
     * @param string $seed_key
638
     * @return mixed
639
     */
640
    protected function loadObjectDataFromHistorySeed($seed_key)
641
    {
642
        $data = $this->modx->cacheManager->get($seed_key, $this->historyCacheOptions);
643
644
        if (is_array($data)) {
645
            $this->blendable_xpdo_simple_object_data = $data['columns'];
646
            $this->unique_key_history = $data['primaryKeyHistory'];
647
            $this->related_data = $data['related'];
648
        }
649
650
        return $data;
651
    }
652
653
    /**
654
     * @param string $name
655
     * @return string
656
     */
657
    protected function makeStudyCase($name)
658
    {
659
        if ($name == 'templatename') {
660
            $name = 'templateName';
661
        }
662
663
        $StudyName = '';
664
        $parts = explode('_', $name);
665
        foreach ($parts as $part) {
666
            $StudyName .= ucfirst($part);
667
        }
668
669
        return $StudyName;
670
    }
671
672
    /**
673
     * This method is called just before blend/save()
674
     */
675
    protected function attachRelatedPieces()
676
    {
677
678
    }
679
680
    /**
681
     * This method is called just after a successful blend/save()
682
     */
683
    protected function attachRelatedPiecesAfterSave()
684
    {
685
686
    }
687
688
    /**
689
     *
690
     */
691
    protected function onDeleteRevertRelatedPieces()
692
    {
693
694
    }
695
696
    /**
697
     * @var string $type blend or revert
698
     */
699
    protected function seedRelated($type = 'blend')
700
    {
701
        // load related data:
702
        $this->loadRelatedData();
703
704
    }
705
706
    /**
707
     * @return array
708
     */
709
    public function getRelatedData()
710
    {
711
        return $this->related_data;
712
    }
713
714
    /**
715
     * @param array $data
716
     *
717
     * @return $this
718
     */
719
    public function setRelatedData($data)
720
    {
721
        $this->related_data = $data;
722
        return $this;
723
    }
724
725
}