Test Setup Failed
Push — master ( fe5747...32c7c7 )
by Josh
03:18
created

Blender::cacheUserInstallConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 2
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: jgulledge
5
 * Date: 9/29/2017
6
 * Time: 3:33 PM
7
 */
8
9
namespace LCI\Blend;
10
11
use LCI\Blend\Helpers\Format;
12
use LCI\Blend\Migrations\MigrationsCreator;
13
use LCI\Blend\Model\xPDO\BlendMigrations;
14
use 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...
15
use LCI\Blend\Blendable\Chunk;
16
use LCI\Blend\Blendable\Context;
17
use LCI\Blend\Blendable\MediaSource;
18
use LCI\Blend\Blendable\Plugin;
19
use LCI\Blend\Blendable\Resource;
20
use LCI\Blend\Blendable\Snippet;
21
use LCI\Blend\Blendable\SystemSetting;
22
use LCI\Blend\Blendable\Template;
23
use LCI\Blend\Blendable\TemplateVariable;
24
use LCI\Blend\Helpers\SimpleCache;
25
use LCI\MODX\Console\Helpers\UserInteractionHandler;
26
use PHPUnit\Runner\Exception;
27
28
class Blender
29
{
30
    /** @var string ~ version number of the project */
31
    private $version = '1.0.0 beta';
32
33
    /** @var array a list of valid upgrade migrations */
34
    protected $update_migrations = [
35
        '0.9.7' => 'v0_9_7_update',
36
        '0.9.8' => 'v0_9_8_update',
37
        '0.9.9' => 'v0_9_9_update',
38
        '0.9.10' => 'v0_9_10_update',
39
        '0.9.11' => 'v0_9_11_update',
40
        '1.0.0 beta' => 'v1_0_0_beta_update'
41
    ];
42
43
    /** @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...
44
    protected $modx;
45
46
    /** @var array  */
47
    protected $modx_version_info = [];
48
49
    /** @var \LCI\MODX\Console\Helpers\UserInteractionHandler */
50
    protected $userInteractionHandler;
51
52
    /** @var array  */
53
    protected $config = [];
54
55
    /** @var boolean|array  */
56
    protected $blendMigrations = false;
57
58
    /** @var  \Tagger */
0 ignored issues
show
Bug introduced by
The type Tagger 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...
59
    protected $tagger;
60
61
    protected $resource_id_map = [];
62
63
    protected $resource_seek_key_map = [];
64
65
    protected $category_map = [];
66
67
    /** @var string date('Y_m_d_His') */
68
    protected $seeds_dir = '';
69
70
    /** @var int  */
71
    protected $xpdo_version = 3;
72
73
    protected $blend_class_object = 'BlendMigrations';
74
75
    protected $blend_package = 'blend';
76
77
    /**
78
     * Stockpile constructor.
79
     *
80
     * @param \modX $modx
81
     * @param UserInteractionHandler $userInteractionHandler
82
     * @param array $config
83
     */
84
    public function __construct(modX $modx, UserInteractionHandler $userInteractionHandler, $config=[])
85
    {
86
        $this->modx = $modx;
87
88
        $this->modx_version_info = $this->modx->getVersionData();
89
90
        $this->userInteractionHandler = $userInteractionHandler;
91
92
        if (version_compare($this->modx_version_info['full_version'], '3.0') >= 0 ) {
93
            $this->xpdo_version = 3;
94
            $this->blend_class_object = 'LCI\\Blend\\Model\\xPDO\\BlendMigrations';
95
            $this->blend_package = 'LCI\\Blend\\Model\\xPDO';
96
97
        } else {
98
            $this->xpdo_version = 2;
99
        }
100
101
        $blend_modx_migration_dir = dirname(__DIR__);
102
        if (isset($config['blend_modx_migration_dir'])) {
103
            $blend_modx_migration_dir = $config['blend_modx_migration_dir'];
104
        }
105
106
        $this->config = [
107
            'migration_templates_path' => __DIR__. '/Migrations/templates/',
108
            'migrations_path' => $blend_modx_migration_dir.'database/migrations/',
109
            'seeds_path' => $blend_modx_migration_dir.'database/seeds/',
110
            'model_dir' => __DIR__ . ($this->xpdo_version >= 3 ? '/' : '/xpdo2/'),
111
            'extras' => [
112
                'tagger' => false
113
            ]
114
        ];
115
        $this->config = array_merge($this->config, $config);
116
117
        $this->seeds_dir = date('Y_m_d_His');
118
119
        $tagger_path = $this->modx->getOption('tagger.core_path', null, $this->modx->getOption('core_path') . 'components/tagger/') . 'model/tagger/';
120
        if (is_dir($tagger_path)) {
121
            $this->config['extras']['tagger'] = true;
122
            /** @var \Tagger $tagger */
123
            $this->tagger = $this->modx->getService('tagger', 'Tagger', $tagger_path, []);
124
        }
125
126
        if ($this->xpdo_version >= 3) {
127
            $this->modx->setPackage($this->blend_package, $this->config['model_dir']);
128
129
        } else {
130
            $this->modx->addPackage($this->blend_package, $this->config['model_dir']);
131
        }
132
    }
133
134
    /**
135
     * @return string
136
     */
137
    public function getBlendClassObject()
138
    {
139
        return $this->blend_class_object;
140
    }
141
142
    /**
143
     * @return UserInteractionHandler
144
     */
145
    public function getUserInteractionHandler()
146
    {
147
        return $this->userInteractionHandler;
148
    }
149
150
    /**
151
     * @return string
152
     */
153
    public function getVersion()
154
    {
155
        return $this->version;
156
    }
157
158
    /**
159
     * @return string
160
     */
161
    public function getSeedsDir()
162
    {
163
        return $this->seeds_dir;
164
    }
165
166
    /**
167
     * @param string $seeds_dir ~ local folder
168
     *
169
     * @return Blender
170
     */
171
    public function setSeedsDir($seeds_dir)
172
    {
173
        $this->seeds_dir = $seeds_dir;
174
        return $this;
175
    }
176
177
    /**
178
     * @param null $directory_key
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $directory_key is correct as it would always require null to be passed?
Loading history...
179
     * @return string
180
     */
181
    public function getSeedsPath($directory_key=null)
182
    {
183
        $seed_path = $this->config['seeds_path'];
184
        if (!empty($directory_key)) {
185
            $seed_path .= trim($directory_key, '/') . DIRECTORY_SEPARATOR;
186
        }
187
        return $seed_path;
188
    }
189
190
    /**
191
     * @return string
192
     */
193
    public function getMigrationPath()
194
    {
195
        return $this->config['migrations_path'];
196
    }
197
198
    /**
199
     * @param bool $reload
200
     * @param string $dir
201
     * @param int $count
202
     * @param int $id
203
     * @param string $name
204
     *
205
     * @return array ~ array of \BlendMigrations
206
     */
207
    public function getBlendMigrationCollection($reload=false, $dir='ASC', $count=0, $id=0, $name=null)
208
    {
209
        if (!$this->blendMigrations || $reload) {
210
            $blendMigrations = [];
211
212
            /** @var \xPDOQuery $query */
213
            $query = $this->modx->newQuery($this->blend_class_object);
214
            if ($id > 0 ) {
215
                $query->where(['id' => $id]);
216
            } elseif (!empty($name)) {
217
                $query->where(['name' => $name]);
218
            }
219
            // @TODO need a ran sequence column to better order of down
220
            $query->sortBy('name', $dir);
221
            if ($count > 0 ) {
222
                $query->limit($count);
223
            }
224
            $query->prepare();
225
            //echo 'SQL: '.$query->toSQL();
226
            $migrationCollection = $this->modx->getCollection($this->blend_class_object, $query);
227
228
            /** @var \BlendMigrations $migration */
229
            foreach ($migrationCollection as $migration) {
230
                $blendMigrations[$migration->get('name')] = $migration;
231
            }
232
            $this->blendMigrations = $blendMigrations;
233
        }
234
        return $this->blendMigrations;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->blendMigrations also could return the type true which is incompatible with the documented return type array.
Loading history...
235
    }
236
237
    /**
238
     * @return \Tagger
239
     */
240
    public function getTagger()
241
    {
242
        return $this->tagger;
243
    }
244
245
    public function getCategoryMap($refresh=false)
246
    {
247
        if (count($this->category_map) == 0 || $refresh) {
248
            $this->category_map = [
249
                'ids' => [],
250
                'names' => [],
251
                'lineage' => []
252
            ];
253
            $query = $this->modx->newQuery('modCategory');
254
            $query->sortBy('parent');
255
            $query->sortBy('rank');
256
            $categories = $this->modx->getCollection('modCategory', $query);
257
            foreach ($categories as $category) {
258
                $category_data = $category->toArray();
259
260
                $this->category_map['ids'][$category->get('id')] = $category_data;
261
262
                $key = trim($category->get('category'));
263
                // This is not unique!
264
                $this->category_map['names'][$key] = $category_data;
265
266
                // Get the lineage: Parent=>Child=>Grand Child as key
267
                $lineage = $key;
268
                if ($category_data['parent'] > 0 && isset($this->category_map['ids'][$category_data['parent']]) && isset($this->category_map['ids'][$category_data['parent']]['lineage'])) {
269
                    $lineage = $this->category_map['ids'][$category_data['parent']]['lineage'].'=>'.$key;
270
                } elseif ($category_data['parent'] > 0) {
271
                    //$this->out('DID NOT FIND PARENT?? '. print_r($category_data, true), true);
272
                }
273
274
                $this->category_map['ids'][$category->get('id')]['lineage'] = $lineage;
275
276
                $this->category_map['lineage'][$lineage] = $category->toArray();
277
            }
278
        }
279
        return $this->category_map;
280
    }
281
282
    /**
283
     * Use this method with your IDE to help manually build a Chunk with PHP
284
     * @param string $name
285
     * @return Chunk
286
     */
287
    public function getBlendableChunk($name)
288
    {
289
        /** @var \LCI\Blend\Blendable\Chunk $chunk */
290
        $chunk =  new Chunk($this->modx, $this, $name);
291
        return $chunk->setSeedsDir($this->getSeedsDir());
292
    }
293
    /**
294
     * @param array $chunks
295
     * @param string $seeds_dir
296
     */
297
    public function blendManyChunks($chunks=[], $seeds_dir='')
298
    {
299
        // will update if element does exist or create new
300
        foreach ($chunks as $seed_key) {
301
            /** @var \LCI\Blend\Blendable\Chunk $blendChunk */
302
            $blendChunk = new Chunk($this->modx, $this, $this->getNameFromSeedKey($seed_key));
303
            if (!empty($seeds_dir)) {
304
                $blendChunk->setSeedsDir($seeds_dir);
305
            }
306
            if ($blendChunk->blendFromSeed($seed_key)) {
307
                $this->out($seed_key.' has been blended into ID: ');
308
309
            } elseif($blendChunk->isExists()) {
310
                // @TODO prompt Do you want to blend Y/N/Compare
311
                $this->out($seed_key.' chunk already exists', true);
312
                if ($this->prompt('Would you like to update?', 'Y') === 'Y') {
313
                    if ($blendChunk->blendFromSeed($seed_key, true)) {
314
                        $this->out($seed_key.' has been blended');
315
                    }
316
                }
317
            } else {
318
                $this->out('There was an error saving '.$seed_key, true);
319
            }
320
        }
321
    }
322
323
    /**
324
     * @param array $chunks
325
     * @param string $seeds_dir
326
     */
327
    public function revertBlendManyChunks($chunks=[], $seeds_dir='')
328
    {
329
        // will update if system setting does exist or create new
330
        foreach ($chunks as $seed_key) {
331
            /** @var \LCI\Blend\Blendable\Chunk $blendChunk */
332
            $blendChunk = new Chunk($this->modx, $this, $this->getNameFromSeedKey($seed_key));
333
            if (!empty($seeds_dir)) {
334
                $blendChunk->setSeedsDir($seeds_dir);
335
            }
336
337
            if ( $blendChunk->revertBlend() ) {
338
                $this->out($blendChunk->getFieldName().' chunk has been reverted to '.$seeds_dir);
339
340
            } else {
341
                $this->out($blendChunk->getFieldName().' chunk was not reverted', true);
342
            }
343
        }
344
    }
345
346
    /**
347
     * Use this method with your IDE to help manually build a Chunk with PHP
348
     * @param string $key
349
     * @return Context
350
     */
351
    public function getBlendableContext($key)
352
    {
353
        /** @var \LCI\Blend\Blendable\Context $chunk */
354
        $context =  new Context($this->modx, $this, $key);
355
        return $context->setSeedsDir($this->getSeedsDir());
356
    }
357
358
    /**
359
     * @param array $contexts
360
     * @param string $seeds_dir
361
     */
362
    public function blendManyContexts($contexts=[], $seeds_dir='')
363
    {
364
        // will update if element does exist or create new
365
        foreach ($contexts as $seed_key) {
366
            /** @var \LCI\Blend\Blendable\Context $blendContext */
367
            $blendContext = new Context($this->modx, $this, $this->getNameFromSeedKey($seed_key));
368
            if (!empty($seeds_dir)) {
369
                $blendContext->setSeedsDir($seeds_dir);
370
            }
371
            if ($blendContext->blendFromSeed($seed_key)) {
372
                $this->out($seed_key.' has been blended ');
373
374
            } elseif($blendContext->isExists()) {
375
                // @TODO prompt Do you want to blend Y/N/Compare
376
                $this->out($seed_key.' chunk already exists', true);
377
                if ($this->prompt('Would you like to update?', 'Y') === 'Y') {
378
                    if ($blendContext->blendFromSeed($seed_key, true)) {
379
                        $this->out($seed_key.' has been blended');
380
                    }
381
                }
382
            } else {
383
                $this->out('There was an error saving '.$seed_key, true);
384
            }
385
        }
386
    }
387
388
    /**
389
     * @param array $contexts
390
     * @param string $seeds_dir
391
     */
392
    public function revertBlendManyContexts($contexts=[], $seeds_dir='')
393
    {
394
        // will update if system setting does exist or create new
395
        foreach ($contexts as $seed_key) {
396
            /** @var \LCI\Blend\Blendable\Context $blendContext */
397
            $blendContext = new Context($this->modx, $this, $this->getNameFromSeedKey($seed_key));
398
            if (!empty($seeds_dir)) {
399
                $blendContext->setSeedsDir($seeds_dir);
400
            }
401
402
            if ( $blendContext->revertBlend() ) {
403
                $this->out($blendContext->getFieldKey().' context has been reverted to '.$seeds_dir);
404
405
            } else {
406
                $this->out($blendContext->getFieldKey().' context was not reverted', true);
407
            }
408
        }
409
    }
410
411
412
    /**
413
     * @param string $name
414
     * @return \LCI\Blend\Blendable\MediaSource
415
     */
416
    public function getBlendableMediaSource($name)
417
    {
418
        /** @var \LCI\Blend\Blendable\MediaSource $mediaSource */
419
        $mediaSource =  new MediaSource($this->modx, $this, $name);
420
        return $mediaSource
421
            ->setFieldName($name)
422
            ->setSeedsDir($this->getSeedsDir());
423
    }
424
425
    /**
426
     * @param array $media_sources
427
     * @param string $seeds_dir
428
     */
429
    public function blendManyMediaSources($media_sources=[], $seeds_dir='')
430
    {
431
        // will update if element does exist or create new
432
        foreach ($media_sources as $seed_key) {
433
            /** @var \LCI\Blend\Blendable\MediaSource $blendMediaSource */
434
            $blendMediaSource = new MediaSource($this->modx, $this);
435
            if (!empty($seeds_dir)) {
436
                $blendMediaSource->setSeedsDir($seeds_dir);
437
            }
438
            if ($blendMediaSource->blendFromSeed($seed_key)) {
439
                $this->out($seed_key.' has been blended into ID: ');
440
441
            } elseif($blendMediaSource->isExists()) {
442
                // @TODO add Compare as option
443
                $this->out($seed_key.' media source already exists', true);
444
                if ($this->prompt('Would you like to update?', 'Y') === 'Y') {
445
                    if ($blendMediaSource->blendFromSeed($seed_key, true)) {
446
                        $this->out($seed_key.' has been blended');
447
                    }
448
                }
449
            } else {
450
                $this->out('There was an error saving '.$seed_key, true);
451
            }
452
        }
453
    }
454
455
    /**
456
     * @param array $media_sources
457
     * @param string $seeds_dir
458
     */
459
    public function revertBlendManyMediaSources($media_sources=[], $seeds_dir='')
460
    {
461
        // will update if system setting does exist or create new
462
        foreach ($media_sources as $seed_key) {
463
            /** @var \LCI\Blend\Blendable\MediaSource $blendMediaSource */
464
            $blendMediaSource = new MediaSource($this->modx, $this, $this->getNameFromSeedKey($seed_key));
465
            if (!empty($seeds_dir)) {
466
                $blendMediaSource->setSeedsDir($seeds_dir);
467
            }
468
469
            if ( $blendMediaSource->revertBlend() ) {
470
                $this->out($blendMediaSource->getFieldName().' media source has been reverted to '.$seeds_dir);
471
472
            } else {
473
                $this->out($blendMediaSource->getFieldName().' media source was not reverted', true);
474
            }
475
        }
476
    }
477
478
    /**
479
     * Use this method with your IDE to help manually build a Plugin with PHP
480
     * @param string $name
481
     * @return \LCI\Blend\Blendable\Plugin
482
     */
483
    public function getBlendablePlugin($name)
484
    {
485
        /** @var \LCI\Blend\Blendable\Plugin $plugin */
486
        $plugin =  new Plugin($this->modx, $this, $name);
487
        return $plugin->setSeedsDir($this->getSeedsDir());
488
    }
489
490
    /**
491
     * @param array $plugins
492
     * @param string $seeds_dir
493
     */
494
    public function blendManyPlugins($plugins=[], $seeds_dir='')
495
    {
496
        // will update if element does exist or create new
497
        foreach ($plugins as $seed_key) {
498
            /** @var \LCI\Blend\Blendable\Plugin $blendPlugin */
499
            $blendPlugin = new Plugin($this->modx, $this, $this->getNameFromSeedKey($seed_key));
500
            if (!empty($seeds_dir)) {
501
                $blendPlugin->setSeedsDir($seeds_dir);
502
            }
503
            if ($blendPlugin->blendFromSeed($seed_key)) {
504
                $this->out($seed_key.' has been blended into ID: ');
505
506
            } elseif($blendPlugin->isExists()) {
507
                // @TODO prompt Do you want to blend Y/N/Compare
508
                $this->out($seed_key.' plugin already exists', true);
509
                if ($this->prompt('Would you like to update?', 'Y') === 'Y') {
510
                    if ($blendPlugin->blendFromSeed($seed_key, true)) {
511
                        $this->out($seed_key.' has been blended');
512
                    }
513
                }
514
            } else {
515
                $this->out('There was an error saving '.$seed_key, true);
516
            }
517
        }
518
    }
519
520
    /**
521
     * @param array $plugins
522
     * @param string $seeds_dir
523
     */
524
    public function revertBlendManyPlugins($plugins=[], $seeds_dir='')
525
    {
526
        // will update if system setting does exist or create new
527
        foreach ($plugins as $seed_key) {
528
            /** @var \LCI\Blend\Blendable\Plugin $blendPlugin */
529
            $blendPlugin = new Plugin($this->modx, $this);
530
            if (!empty($seeds_dir)) {
531
                $blendPlugin->setSeedsDir($seeds_dir);
532
            }
533
534
            if ( $blendPlugin->revertBlend() ) {
535
                $this->out($blendPlugin->getFieldName().' plugin has been reverted to '.$seeds_dir);
536
537
            } else {
538
                $this->out($blendPlugin->getFieldName().' plugin was not reverted', true);
539
            }
540
        }
541
    }
542
543
    /**
544
     * Use this method with your IDE to help manually build a Snippet with PHP
545
     * @param string $name
546
     * @return \LCI\Blend\Blendable\Snippet
547
     */
548
    public function getBlendableSnippet($name)
549
    {
550
        /** @var Snippet $snippet */
551
        $snippet =  new Snippet($this->modx, $this, $name);
552
        return $snippet->setSeedsDir($this->getSeedsDir());
553
    }
554
555
    /**
556
     * @param array $snippets
557
     * @param string $seeds_dir
558
     */
559
    public function blendManySnippets($snippets=[], $seeds_dir='')
560
    {
561
        // will update if element does exist or create new
562
        foreach ($snippets as $seed_key) {
563
            /** @var \LCI\Blend\Blendable\Snippet $blendSnippet */
564
            $blendSnippet = new Snippet($this->modx, $this, $this->getNameFromSeedKey($seed_key));
565
            if (!empty($seeds_dir)) {
566
                $blendSnippet->setSeedsDir($seeds_dir);
567
            }
568
            if ($blendSnippet->blendFromSeed($seed_key)) {
569
                $this->out($seed_key.' has been blended');
570
571
            } elseif($blendSnippet->isExists()) {
572
                // @TODO prompt Do you want to blend Y/N/Compare
573
                $this->out($seed_key.' snippet already exists', true);
574
                if ($this->prompt('Would you like to update?', 'Y') === 'Y') {
575
                    if ($blendSnippet->blendFromSeed($seed_key, true)) {
576
                        $this->out($seed_key.' has been blended');
577
                    }
578
                }
579
            } else {
580
                $this->out('There was an error saving '.$seed_key, true);
581
            }
582
        }
583
    }
584
    /**
585
     * @param array $snippets
586
     * @param string $seeds_dir
587
     */
588
    public function revertBlendManySnippets($snippets=[], $seeds_dir='')
589
    {
590
        // will update if system setting does exist or create new
591
        foreach ($snippets as $seed_key) {
592
            /** @var Snippet $blendSnippet */
593
            $blendSnippet = new Snippet($this->modx, $this, $this->getNameFromSeedKey($seed_key));
594
            if (!empty($seeds_dir)) {
595
                $blendSnippet->setSeedsDir($seeds_dir);
596
            }
597
598
            if ( $blendSnippet->revertBlend() ) {
599
                $this->out($blendSnippet->getFieldName().' snippet has been reverted to '.$seeds_dir);
600
601
            } else {
602
                $this->out($blendSnippet->getFieldName().' snippet was not reverted', true);
603
            }
604
        }
605
    }
606
607
    /**
608
     * Use this method with your IDE to manually build a template
609
     * @param string $name
610
     * @return \LCI\Blend\Blendable\Template
611
     */
612
    public function getBlendableTemplate($name)
613
    {
614
        /** @var \LCI\Blend\Blendable\Template $template */
615
        $template =  new Template($this->modx, $this, $name);
616
        return $template->setSeedsDir($this->seeds_dir);
617
    }
618
619
    /**
620
     * @param array $templates
621
     * @param string $seeds_dir
622
     * @param bool $overwrite
623
     */
624
    public function blendManyTemplates($templates=[], $seeds_dir='', $overwrite=false)
625
    {
626
        // will update if template does exist or create new
627
        foreach ($templates as $seed_key) {
628
629
            /** @var \LCI\Blend\Blendable\Template $blendTemplate */
630
            $blendTemplate = new Template($this->modx, $this, $this->getNameFromSeedKey($seed_key));
631
            if (!empty($seeds_dir)) {
632
                $blendTemplate->setSeedsDir($seeds_dir);
633
            }
634
            if ($blendTemplate->blendFromSeed($seed_key, $overwrite)) {
635
                $this->out($seed_key.' has been blended');
636
637
            } elseif($blendTemplate->isExists()) {
638
                $this->out($seed_key.' template already exists', true);
639
                if ($this->prompt('Would you like to update?', 'Y') === 'Y') {
640
                    if ($blendTemplate->blendFromSeed($seed_key, true)) {
641
                        $this->out($seed_key.' has been blended');
642
                    }
643
                }
644
            } else {
645
                $this->out('There was an error saving '.$seed_key, true);
646
            }
647
        }
648
    }
649
650
    /**
651
     * @param array $templates
652
     * @param string $seeds_dir
653
     */
654
    public function revertBlendManyTemplates($templates=[], $seeds_dir='')
655
    {
656
        // will update if system setting does exist or create new
657
        foreach ($templates as $seed_key) {
658
            /** @var \LCI\Blend\Blendable\Template $blendTemplate */
659
            $blendTemplate = new Template($this->modx, $this, $this->getNameFromSeedKey($seed_key));
660
            if (!empty($seeds_dir)) {
661
                $blendTemplate->setSeedsDir($seeds_dir);
662
            }
663
664
            if ( $blendTemplate->revertBlend() ) {
665
                $this->out($blendTemplate->getFieldName().' template has been reverted to '.$seeds_dir);
666
667
            } else {
668
                $this->out($blendTemplate->getFieldName().' template was not reverted', true);
669
            }
670
        }
671
    }
672
673
    /**
674
     * Use this method with your IDE to manually build a template variable
675
     * @param string $name
676
     * @return TemplateVariable
677
     */
678
    public function getBlendableTemplateVariable($name)
679
    {
680
        /** @var \LCI\Blend\Blendable\TemplateVariable $tv */
681
        $tv =  new TemplateVariable($this->modx, $this, $name);
682
        return $tv->setSeedsDir($this->seeds_dir);
683
    }
684
685
    /**
686
     * @param string $alias
687
     * @param  string $context
688
     * @return \LCI\Blend\Blendable\Resource
689
     */
690
    public function getBlendableResource($alias, $context='web')
691
    {
692
        /** @var \LCI\Blend\Blendable\Resource $resource */
693
        $resource =  new Resource($this->modx, $this, $alias, $context);
694
        return $resource
695
            ->setSeedsDir($this->getSeedsDir());
696
    }
697
    /**
698
     * @param array $resources
699
     * @param string $seeds_dir
700
     * @param bool $overwrite
701
     *
702
     * @return bool
703
     */
704
    public function blendManyResources($resources=[], $seeds_dir='', $overwrite=false)
705
    {
706
        $saved = true;
707
        // will update if resource does exist or create new
708
        foreach ($resources as $context => $seeds) {
709
            foreach ($seeds as $seed_key) {
710
                /** @var \LCI\Blend\Blendable\Resource $blendResource */
711
                $blendResource = new Resource($this->modx, $this, $this->getAliasFromSeedKey($seed_key), $context);
712
713
                if (!empty($seeds_dir)) {
714
                    $blendResource->setSeedsDir($seeds_dir);
715
                }
716
717
                if ($blendResource->blendFromSeed($seed_key, $overwrite)) {
718
                    $this->out($seed_key . ' has been blended into ID: ');
719
720
                } elseif ($blendResource->isExists()) {
721
                    // @TODO prompt Do you want to blend Y/N/Compare
722
                    $this->out($seed_key . ' already exists', true);
723
                    if ($this->prompt('Would you like to update?', 'Y') === 'Y') {
724
                        if ($blendResource->blendFromSeed($seed_key, true)) {
725
                            $this->out($seed_key . ' has been blended into ID: ');
726
                        }
727
                    }
728
                } else {
729
                    $this->out('There was an error saving ' . $seed_key, true);
730
                    echo 'There was an error saving ' . $seed_key; exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
731
                    $saved = false;
0 ignored issues
show
Unused Code introduced by
$saved = false is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
732
                }
733
            }
734
        }
735
736
        return $saved;
737
    }
738
739
    /**
740
     * @param array $resources
741
     * @param string $seeds_dir
742
     * @param bool $overwrite
743
     *
744
     * @return bool
745
     */
746
    public function revertBlendManyResources($resources=[], $seeds_dir='', $overwrite=false)
0 ignored issues
show
Unused Code introduced by
The parameter $overwrite is not used and could be removed. ( Ignorable by Annotation )

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

746
    public function revertBlendManyResources($resources=[], $seeds_dir='', /** @scrutinizer ignore-unused */ $overwrite=false)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
747
    {
748
        $saved = true;
749
        // will update if resource does exist or create new
750
        foreach ($resources as $context => $seeds) {
751
            foreach ($seeds as $seed_key) {
752
                /** @var \LCI\Blend\Blendable\Resource $blendResource */
753
                $blendResource = new Resource($this->modx, $this, $this->getAliasFromSeedKey($seed_key), $context);
754
755
                if (!empty($seeds_dir)) {
756
                    $blendResource->setSeedsDir($seeds_dir);
757
                }
758
                if ($blendResource->revertBlend()) {
759
                    $this->out($seed_key . ' has been reverted ');
760
761
                } else {
762
                    $this->out('There was an error reverting resource ' . $seed_key, true);
763
                    $saved = false;
764
                }
765
            }
766
        }
767
768
        return $saved;
769
    }
770
771
    /**
772
     * @param string $key
773
     * @return \LCI\Blend\Blendable\SystemSetting
774
     */
775
    public function getBlendableSystemSetting($key='')
776
    {
777
        /** @var \LCI\Blend\Blendable\SystemSetting $systemSetting */
778
        $systemSetting =  new SystemSetting($this->modx, $this, $key);
779
        return $systemSetting->setSeedsDir($this->getSeedsDir());
780
    }
781
782
    /**
783
     * @param array $settings ~ [ ['name' => 'mySystemSetting', 'value' => 'myValue'], ..]
784
     * @param string $seeds_dir
785
     *
786
     * @return bool
787
     */
788
    public function blendManySystemSettings($settings=[], $seeds_dir='')
789
    {
790
        $success = true;
791
        // will update if system setting does exist or create new
792
        foreach ($settings as $data) {
793
            if (isset($data['columns'])) {
794
                $setting = $data['columns'];
795
            } else {
796
                $setting = $data;
797
                $data['columns'] = $data;
798
            }
799
800
            if (isset($setting['key'])) {
801
                $key = $setting['key'];
802
803
            } elseif (isset($setting['name'])) {
804
                $key = $setting['name'];
805
806
            } else {
807
                // Error: no name/key
808
                $success = false;
809
                continue;
810
            }
811
812
            $systemSetting = $this->getBlendableSystemSetting($key);
813
            if (!empty($seeds_dir)) {
814
                $systemSetting->setSeedsDir($seeds_dir);
815
            }
816
817
            if ($systemSetting->blendFromArray($data, true)) {
818
                $this->out($systemSetting->getFieldName().' setting has been blended');
819
            } else {
820
                $success = false;
821
            }
822
        }
823
824
        return $success;
825
    }
826
827
    /**
828
     * @param array $settings ~ [ ['name' => 'mySystemSetting', 'value' => 'myValue'], ..]
829
     * @param string $seeds_dir
830
     *
831
     * @return bool
832
     */
833
    public function revertBlendManySystemSettings($settings=[], $seeds_dir='')
834
    {
835
        $success = true;
836
        // will update if system setting does exist or create new
837
        foreach ($settings as $data) {
838
            if (isset($data['columns'])) {
839
                $setting = $data['columns'];
840
            } else {
841
                $setting = $data;
842
                $data['columns'] = $data;
843
            }
844
845
            if (isset($setting['key'])) {
846
                $key = $setting['key'];
847
848
            } elseif (isset($setting['name'])) {
849
                $key = $setting['name'];
850
851
            } else {
852
                // Error: no name/key
853
                $success = false;
854
                continue;
855
            }
856
857
            $systemSetting = $this->getBlendableSystemSetting($key);
858
859
            if (!empty($seeds_dir)) {
860
                $systemSetting->setSeedsDir($seeds_dir);
861
            }
862
863
            if ( $systemSetting->revertBlend() ) {
864
                $this->out($systemSetting->getFieldName().' setting has been reverted to '.$seeds_dir);
865
866
            } else {
867
                $this->out($systemSetting->getFieldName().' setting was not reverted', true);
868
                $success = false;
869
            }
870
        }
871
872
        return $success;
873
    }
874
875
    /**
876
     * @param string $question
877
     * @param string $default
878
     *
879
     * @return mixed
880
     */
881
    protected function prompt($question, $default='')
882
    {
883
        return $this->userInteractionHandler->promptInput($question, $default);
884
    }
885
886
    /**
887
     * @param string $question
888
     * @param bool $default
889
     * @return bool
890
     */
891
    protected function promptConfirm($question, $default=true)
892
    {
893
        return $this->userInteractionHandler->promptConfirm($question, $default);
894
    }
895
896
    /**
897
     * @param string $question
898
     * @param string|mixed $default
899
     * @param array $options ~ ex: ['Option1' => 'value', 'Option2' => 'value2', ...]
900
     * @return mixed ~ selected value
901
     */
902
    protected function promptSelectOneOption($question, $default, $options=[])
903
    {
904
        return $this->userInteractionHandler->promptSelectOneOption($question, $default, $options);
905
    }
906
907
    /**
908
     * @param string $question
909
     * @param string|mixed $default
910
     * @param array $options ~ ex: ['Option1' => 'value', 'Option2' => 'value2', ...]
911
     * @return array ~ array of selected values
912
     */
913
    protected function promptSelectMultipleOptions($question, $default, $options=[])
914
    {
915
        return $this->userInteractionHandler->promptSelectMultipleOptions($question, $default, $options);
916
    }
917
918
    /**
919
     * @param string $message
920
     * @param bool $error
921
     */
922
    public function out($message, $error=false)
923
    {
924
        if ($error) {
925
            $this->userInteractionHandler->tellUser($message, userInteractionHandler::MASSAGE_ERROR);
926
927
        } else {
928
            $this->userInteractionHandler->tellUser($message, userInteractionHandler::MASSAGE_STRING);
929
        }
930
    }
931
932
    /**
933
     * @param string $message
934
     */
935
    public function outSuccess($message)
936
    {
937
        $this->userInteractionHandler->tellUser($message, userInteractionHandler::MASSAGE_SUCCESS);
938
    }
939
940
    /**
941
     * @param string $name
942
     * @param string $server_type
943
     * @param string|null $migration_path
944
     *
945
     * @return bool
946
     */
947
    public function createBlankMigrationClassFile($name, $server_type='master', $migration_path=null)
948
    {
949
        $migrationCreator = new MigrationsCreator($this->userInteractionHandler);
950
951
        if (empty($migration_path)) {
952
            $migration_path = $this->getMigrationPath();
953
        }
954
955
        $success = $migrationCreator
956
            ->setPathTimeStamp($this->getSeedsDir())
957
            ->setName($name)
958
            ->setDescription('')
959
            ->setServerType($server_type)
960
            ->setMigrationsPath($migration_path)
961
            ->createBlankMigrationClassFile();
962
963
        $this->logCreatedMigration($migrationCreator->getLogData());
964
        return $success;
965
    }
966
967
    /**
968
     * @param \xPDOQuery|array|null $criteria
0 ignored issues
show
Bug introduced by
The type xPDOQuery 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...
969
     * @param string $server_type
970
     * @param string $name
971
     * @param bool $create_migration_file
972
     *
973
     * @return array
974
     */
975
    public function makeChunkSeeds($criteria, $server_type='master', $name=null, $create_migration_file=true)
976
    {
977
        $keys = [];
978
        $collection = $this->modx->getCollection('modChunk', $criteria);
979
980
        foreach ($collection as $chunk) {
981
            /** @var \LCI\Blend\Blendable\Chunk $blendChunk */
982
            $blendChunk = new Chunk($this->modx, $this, $chunk->get('name'));
983
            $seed_key = $blendChunk
984
                ->setSeedsDir($this->getMigrationName('chunk', $name))
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type string; however, parameter $name of LCI\Blend\Blender::getMigrationName() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

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

984
                ->setSeedsDir($this->getMigrationName('chunk', /** @scrutinizer ignore-type */ $name))
Loading history...
985
                ->seed();
986
            $this->out("Chunk: ".$chunk->get('name').' Key: '.$seed_key);
987
            $keys[] = $seed_key;
988
        }
989
990
        if ($create_migration_file) {
991
            /** @var MigrationsCreator $migrationCreator */
992
            $migrationCreator = new MigrationsCreator($this->userInteractionHandler, $keys);
993
994
            $migrationCreator
995
                ->setPathTimeStamp($this->getSeedsDir())
996
                ->setName($name)
997
                ->setDescription('')
998
                ->setServerType($server_type)
999
                ->setMigrationsPath($this->getMigrationPath())
1000
                ->createChunkMigrationClassFile();
1001
1002
            $this->logCreatedMigration($migrationCreator->getLogData());
1003
        }
1004
        return $keys;
1005
    }
1006
1007
    /**
1008
     * @param \xPDOQuery|array|null $criteria
1009
     * @param string $server_type
1010
     * @param string $name
1011
     * @param bool $create_migration_file
1012
     *
1013
     * @return array
1014
     */
1015
    public function makeContextSeeds($criteria, $server_type='master', $name=null, $create_migration_file=true)
1016
    {
1017
        $keys = [];
1018
        $collection = $this->modx->getCollection('modContext', $criteria);
1019
1020
        foreach ($collection as $context) {
1021
            /** @var Context $blendContext */
1022
            $blendContext = new Context($this->modx, $this, $context->get('key'));
1023
            $seed_key = $blendContext
1024
                ->setSeedsDir($this->getMigrationName('context', $name))
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type string; however, parameter $name of LCI\Blend\Blender::getMigrationName() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

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

1024
                ->setSeedsDir($this->getMigrationName('context', /** @scrutinizer ignore-type */ $name))
Loading history...
1025
                ->seed();
1026
            $this->out("Context: ".$context->get('name').' Key: '.$seed_key);
1027
            $keys[] = $seed_key;
1028
        }
1029
1030
        if ($create_migration_file) {
1031
            /** @var MigrationsCreator $migrationCreator */
1032
            $migrationCreator = new MigrationsCreator($this->userInteractionHandler, $keys);
1033
1034
            $migrationCreator
1035
                ->setPathTimeStamp($this->getSeedsDir())
1036
                ->setName($name)
1037
                ->setDescription('')
1038
                ->setServerType($server_type)
1039
                ->setMigrationsPath($this->getMigrationPath())
1040
                ->createContextMigrationClassFile();
1041
1042
            $this->logCreatedMigration($migrationCreator->getLogData());
1043
        }
1044
        return $keys;
1045
    }
1046
1047
    /**
1048
     * @param \xPDOQuery|array|null $criteria
1049
     * @param string $server_type
1050
     * @param string $name
1051
     * @param bool $create_migration_file
1052
     *
1053
     * @return array
1054
     */
1055
    public function makeMediaSourceSeeds($criteria, $server_type='master', $name=null, $create_migration_file=true)
1056
    {
1057
        $keys = [];
1058
        $collection = $this->modx->getCollection('modMediaSource', $criteria);
1059
1060
        foreach ($collection as $mediaSource) {
1061
            /** @var MediaSource $blendMediaSource */
1062
            $blendMediaSource = new MediaSource($this->modx, $this, $mediaSource->get('name'));
1063
            $seed_key = $blendMediaSource
1064
                ->setSeedsDir($this->getMigrationName('mediaSource', $name))
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type string; however, parameter $name of LCI\Blend\Blender::getMigrationName() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

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

1064
                ->setSeedsDir($this->getMigrationName('mediaSource', /** @scrutinizer ignore-type */ $name))
Loading history...
1065
                ->seed();
1066
            $this->out("Media Source: ".$mediaSource->get('name').' Key: '.$seed_key);
1067
            $keys[] = $seed_key;
1068
        }
1069
1070
        if ($create_migration_file) {
1071
            /** @var MigrationsCreator $migrationCreator */
1072
            $migrationCreator = new MigrationsCreator($this->userInteractionHandler, $keys);
1073
1074
            $migrationCreator
1075
                ->setPathTimeStamp($this->getSeedsDir())
1076
                ->setName($name)
1077
                ->setDescription('')
1078
                ->setServerType($server_type)
1079
                ->setMigrationsPath($this->getMigrationPath())
1080
                ->createMediaSourceMigrationClassFile();
1081
1082
            $this->logCreatedMigration($migrationCreator->getLogData());
1083
        }
1084
        return $keys;
1085
    }
1086
1087
    /**
1088
     * @param \xPDOQuery|array|null $criteria
1089
     * @param string $server_type
1090
     * @param string $name
1091
     * @param bool $create_migration_file
1092
     *
1093
     * @return array
1094
     */
1095
    public function makePluginSeeds($criteria, $server_type='master', $name=null, $create_migration_file=true)
1096
    {
1097
        $keys = [];
1098
        $collection = $this->modx->getCollection('modPlugin', $criteria);
1099
1100
        foreach ($collection as $plugin) {
1101
            /** @var \LCI\Blend\Blendable\Plugin $blendPlugin */
1102
            $blendPlugin = new Plugin($this->modx, $this, $plugin->get('name'));
1103
            $seed_key = $blendPlugin
1104
                ->setSeedsDir($this->getMigrationName('plugin', $name))
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type string; however, parameter $name of LCI\Blend\Blender::getMigrationName() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

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

1104
                ->setSeedsDir($this->getMigrationName('plugin', /** @scrutinizer ignore-type */ $name))
Loading history...
1105
                ->seed();
1106
            $this->out("Plugin: ".$plugin->get('name').' Key: '.$seed_key);
1107
            $keys[] = $seed_key;
1108
        }
1109
1110
        if ($create_migration_file) {
1111
            /** @var MigrationsCreator $migrationCreator */
1112
            $migrationCreator = new MigrationsCreator($this->userInteractionHandler, $keys);
1113
1114
            $migrationCreator
1115
                ->setPathTimeStamp($this->getSeedsDir())
1116
                ->setName($name)
1117
                ->setDescription('')
1118
                ->setServerType($server_type)
1119
                ->setMigrationsPath($this->getMigrationPath())
1120
                ->createPluginMigrationClassFile();
1121
1122
            $this->logCreatedMigration($migrationCreator->getLogData());
1123
        }
1124
        return $keys;
1125
    }
1126
1127
    /**
1128
     * @param \xPDOQuery|array|null $criteria
1129
     * @param string $server_type
1130
     * @param string $name
1131
     * @param bool $create_migration_file
1132
     *
1133
     * @return array
1134
     */
1135
    public function makeResourceSeeds($criteria, $server_type='master', $name=null, $create_migration_file=true)
1136
    {
1137
        $keys = [
1138
            'web' => []
1139
        ];
1140
1141
        $collection = $this->modx->getCollection('modResource', $criteria);
1142
        foreach ($collection as $resource) {
1143
            $blendResource = new Resource($this->modx, $this, $resource->get('alias'), $resource->get('context_key'));
1144
            $seed_key = $blendResource
1145
                ->setSeedsDir($this->getMigrationName('resource', $name))
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type string; however, parameter $name of LCI\Blend\Blender::getMigrationName() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

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

1145
                ->setSeedsDir($this->getMigrationName('resource', /** @scrutinizer ignore-type */ $name))
Loading history...
1146
                ->seed($resource);
1147
            $this->out("ID: ".$resource->get('id').' Key: '.$seed_key);
1148
1149
            if (!isset($keys[$resource->get('context_key')])) {
1150
                $keys[$resource->get('context_key')] = [];
1151
            }
1152
1153
            $keys[$resource->get('context_key')][] = $seed_key;
1154
        }
1155
1156
        if ($create_migration_file) {
1157
            /** @var MigrationsCreator $migrationCreator */
1158
            $migrationCreator = new MigrationsCreator($this->userInteractionHandler, $keys);
1159
1160
            $migrationCreator
1161
                ->setPathTimeStamp($this->getSeedsDir())
1162
                ->setName($name)
1163
                ->setDescription('')
1164
                ->setServerType($server_type)
1165
                ->setMigrationsPath($this->getMigrationPath())
1166
                ->createResourceMigrationClassFile();
1167
1168
            $this->logCreatedMigration($migrationCreator->getLogData());
1169
        }
1170
        return $keys;
1171
    }
1172
1173
    /**
1174
     * @param \xPDOQuery|array|null $criteria
1175
     * @param string $server_type
1176
     * @param string $name
1177
     * @param bool $create_migration_file
1178
     *
1179
     * @return array
1180
     */
1181
    public function makeSnippetSeeds($criteria, $server_type='master', $name=null, $create_migration_file=true)
1182
    {
1183
        $keys = [];
1184
        $collection = $this->modx->getCollection('modSnippet', $criteria);
1185
1186
        foreach ($collection as $snippet) {
1187
            /** @var \LCI\Blend\Blendable\Snippet $blendSnippet */
1188
            $blendSnippet = new Snippet($this->modx, $this, $snippet->get('name'));
1189
            $seed_key = $blendSnippet
1190
                ->setSeedsDir($this->getMigrationName('snippet', $name))
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type string; however, parameter $name of LCI\Blend\Blender::getMigrationName() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

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

1190
                ->setSeedsDir($this->getMigrationName('snippet', /** @scrutinizer ignore-type */ $name))
Loading history...
1191
                ->seed();
1192
            $this->out("Snippet: ".$snippet->get('name').' Key: '.$seed_key);
1193
            $keys[] = $seed_key;
1194
        }
1195
1196
        if ($create_migration_file) {
1197
            /** @var MigrationsCreator $migrationCreator */
1198
            $migrationCreator = new MigrationsCreator($this->userInteractionHandler, $keys);
1199
1200
            $migrationCreator
1201
                ->setPathTimeStamp($this->getSeedsDir())
1202
                ->setName($name)
1203
                ->setDescription('')
1204
                ->setServerType($server_type)
1205
                ->setMigrationsPath($this->getMigrationPath())
1206
                ->createSnippetMigrationClassFile();
1207
1208
            $this->logCreatedMigration($migrationCreator->getLogData());
1209
        }
1210
        return $keys;
1211
    }
1212
1213
    /**
1214
     * @param \xPDOQuery|array|null $criteria
1215
     * @param string $server_type
1216
     * @param string $name
1217
     * @param bool $create_migration_file
1218
     *
1219
     * @return array
1220
     */
1221
    public function makeSystemSettingSeeds($criteria, $server_type='master', $name=null, $create_migration_file=true)
1222
    {
1223
        $collection = $this->modx->getCollection('modSystemSetting', $criteria);
1224
1225
        $setting_data = [];
1226
        foreach ($collection as $setting) {
1227
            /** @var \LCI\Blend\Blendable\SystemSetting $blendableSetting */
1228
            $blendableSetting = $this->getBlendableSystemSetting($setting->get('key'));
1229
            $setting_data[] = $blendableSetting->seedToArray();
1230
        }
1231
1232
        // https://docs.modx.com/revolution/2.x/developing-in-modx/other-development-resources/class-reference/modx/modx.invokeevent
1233
        $this->modx->invokeEvent(
1234
            'OnBlendSeedSystemSettings',
1235
            [
1236
                'blender' => $this,
1237
                'data' => &$setting_data
1238
            ]
1239
        );
1240
1241
        if ($create_migration_file) {
1242
            /** @var MigrationsCreator $migrationCreator */
1243
            $migrationCreator = new MigrationsCreator($this->userInteractionHandler, $setting_data);
1244
1245
            $migrationCreator
1246
                ->setPathTimeStamp($this->getSeedsDir())
1247
                ->setName($name)
1248
                ->setDescription('')
1249
                ->setServerType($server_type)
1250
                ->setMigrationsPath($this->getMigrationPath())
1251
                ->createSystemSettingsMigrationClassFile();
1252
1253
            $this->logCreatedMigration($migrationCreator->getLogData());
1254
        }
1255
        return $setting_data;
1256
    }
1257
1258
    /**
1259
     * @param \xPDOQuery|array|null $criteria
1260
     * @param string $server_type
1261
     * @param string $name
1262
     * @param bool $create_migration_file
1263
     *
1264
     * @return array
1265
     */
1266
    public function makeTemplateSeeds($criteria, $server_type='master', $name=null, $create_migration_file=true)
1267
    {
1268
        $keys = [];
1269
        $collection = $this->modx->getCollection('modTemplate', $criteria);
1270
1271
        foreach ($collection as $template) {
1272
            //exit();
1273
            /** @var \LCI\Blend\Blendable\Template $blendTemplate */
1274
            $blendTemplate = new Template($this->modx, $this, $template->get('templatename'));
1275
            $seed_key = $blendTemplate
1276
                ->setSeedsDir($this->getMigrationName('template', $name))
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type string; however, parameter $name of LCI\Blend\Blender::getMigrationName() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

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

1276
                ->setSeedsDir($this->getMigrationName('template', /** @scrutinizer ignore-type */ $name))
Loading history...
1277
                ->seed();
1278
            $this->out("Template ID: ".$template->get('id').' Key: '.$seed_key);
1279
            $keys[] = $seed_key;
1280
        }
1281
1282
        if ($create_migration_file) {
1283
            /** @var MigrationsCreator $migrationCreator */
1284
            $migrationCreator = new MigrationsCreator($this->userInteractionHandler, $keys);
1285
1286
            $migrationCreator
1287
                ->setPathTimeStamp($this->getSeedsDir())
1288
                ->setName($name)
1289
                ->setDescription('')
1290
                ->setServerType($server_type)
1291
                ->setMigrationsPath($this->getMigrationPath())
1292
                ->createTemplateMigrationClassFile();
1293
1294
            $this->logCreatedMigration($migrationCreator->getLogData());
1295
        }
1296
        return $keys;
1297
    }
1298
1299
    /**
1300
     * @param string $server_type
1301
     * @param null|string $name
1302
     */
1303
    public function makeSiteSeed($server_type='master', $name=null)
1304
    {
1305
        $site_data = [
1306
            'mediaSources' => $this->makeMediaSourceSeeds(null, $server_type, $name, false),
1307
            'contexts' => $this->makeContextSeeds(null, $server_type, $name, false),
1308
            'chunks' => $this->makeChunkSeeds(null, $server_type, $name, false),
1309
            'plugins' => $this->makePluginSeeds(null, $server_type, $name, false),
1310
            'resources' => $this->makeResourceSeeds(null, $server_type, $name, false),
1311
            'snippets' => $this->makeSnippetSeeds(null, $server_type, $name, false),
1312
            'systemSettings' => $this->makeSystemSettingSeeds(null, $server_type, $name, false),
1313
            'templates' => $this->makeTemplateSeeds(null, $server_type, $name, false)
1314
        ];
1315
1316
        /** @var MigrationsCreator $migrationCreator */
1317
        $migrationCreator = new MigrationsCreator($this->userInteractionHandler, $site_data);
1318
1319
        $migrationCreator
1320
            ->setPathTimeStamp($this->getSeedsDir())
1321
            ->setName($name)
1322
            ->setDescription('')
1323
            ->setServerType($server_type)
1324
            ->setMigrationsPath($this->getMigrationPath())
1325
            ->createSiteMigrationClassFile();
1326
1327
        $this->logCreatedMigration($migrationCreator->getLogData());
1328
    }
1329
1330
    /**
1331
     * @param string $method
1332
     * @param bool $prompt
1333
     */
1334
    public function install($method='up', $prompt=false)
1335
    {
1336
        $migration_name = 'install_blender';
1337
        $custom_migration_dir = __DIR__.'/Migrations/Blend/';
1338
1339
        $this->runInstallMigration($migration_name, $custom_migration_dir, null, $method, $prompt);
1340
    }
1341
1342
    /**
1343
     * @param string $migration_name
1344
     * @param string|null $custom_migration_path
1345
     * @param string|null $seed_root_path
1346
     * @param string $method
1347
     * @param bool $prompt
1348
     */
1349
    protected function runInstallMigration($migration_name, $custom_migration_path=null, $seed_root_path=null, $method='up', $prompt=false)
1350
    {
1351
        // new blender for each instance
1352
        $config = $this->config;
1353
1354
        if (!empty($custom_migration_path)) {
1355
            $config['migrations_path'] = $custom_migration_path;
1356
        }
1357
        if (!empty($seed_root_path)) {
1358
            $config['seeds_path'] = $seed_root_path;
1359
        }
1360
1361
        $blender = new Blender($this->modx, $this->getUserInteractionHandler(), $config);
1362
1363
        /** @var Migrations $migrationProcessClass */
1364
        $migrationProcessClass = $blender->loadMigrationClass($migration_name, $blender);
1365
1366
        if (!$migrationProcessClass instanceof Migrations) {
0 ignored issues
show
introduced by
$migrationProcessClass is always a sub-type of LCI\Blend\Migrations. If $migrationProcessClass can have other possible types, add them to src/Blender.php:1363.
Loading history...
1367
            $this->out('File is not an instance of LCI\Blend\Migrations: '.$migration_name, true);
1368
            $this->out('Did not process, verify it is in the proper directory', true);
1369
1370
        } elseif ($method == 'up' && !$this->isBlendInstalledInModx()) {
1371
1372
            $migrationProcessClass->up();
1373
1374
            /** @var \BlendMigrations $migration */
1375
            $migration = $this->modx->newObject($this->blend_class_object);
1376
            if ($migration) {
0 ignored issues
show
introduced by
$migration is of type BlendMigrations, thus it always evaluated to true. If $migration can have other possible types, add them to src/Blender.php:1374
Loading history...
1377
                $migration->set('name', $migration_name);
1378
                $migration->set('type', 'master');
1379
                $migration->set('description', $migrationProcessClass->getDescription());
1380
                $migration->set('version', $migrationProcessClass->getVersion());
1381
                $migration->set('status', 'up_complete');
1382
                $migration->set('created_at', date('Y-m-d H:i:s'));
1383
                $migration->set('processed_at', date('Y-m-d H:i:s'));
1384
                if ($migration->save() ) {
1385
                    $this->outSuccess($migration_name.' ran and logged');
1386
                } else {
1387
                    $this->out($migration_name . ' did not log correctly', true);
1388
                }
1389
1390
                // does the migration directory exist?
1391
                if (!file_exists($this->getMigrationPath())) {
1392
                    $create = true;
1393
                    if ($prompt) {
1394
                        $response = $this->prompt('Create the following directory for migration files? (y/n) '.PHP_EOL
1395
                            .$this->getMigrationPath(), 'y');
1396
                        if (strtolower(trim($response)) != 'y') {
1397
                            $create = false;
1398
                        }
1399
                    }
1400
                    if ($create) {
1401
                        mkdir($this->getMigrationPath(), 0700, true);
1402
                        $this->outSuccess('Created migration directory: '. $this->getMigrationPath());
1403
                    }
1404
                }
1405
1406
            } else {
1407
                $this->out($migration_name . ' did not log correctly', true);
1408
            }
1409
1410
        } elseif ($method == 'down') {
1411
            $migrationProcessClass->down();
1412
1413
            /** @var \BlendMigrations $migration */
1414
            $migration = $this->modx->getObject($this->blend_class_object, ['name' => $migration_name]);
1415
            if ($migration) {
0 ignored issues
show
introduced by
$migration is of type BlendMigrations, thus it always evaluated to true. If $migration can have other possible types, add them to src/Blender.php:1413
Loading history...
1416
                $migration->set('name', $migration_name);
1417
                $migration->set('description', $migrationProcessClass->getDescription());
1418
                $migration->set('version', $migrationProcessClass->getVersion());
1419
                $migration->set('status', 'down_complete');
1420
                $migration->set('processed_at', date('Y-m-d H:i:s'));
1421
                $migration->save();
1422
            }
1423
1424
        }
1425
    }
1426
1427
    /**
1428
     * @param string $method
1429
     */
1430
    public function update($method='up')
1431
    {
1432
        $current_vesion = $this->modx->getOption('blend.version');
1433
1434
        // new blender for each instance
1435
        $config = $this->config;
1436
        $config['migrations_path'] = __DIR__.'/Migrations/Blend/';
1437
1438
        $blender = new Blender($this->modx, $this->getUserInteractionHandler(), $config);
1439
1440
        foreach ($this->update_migrations as $v => $migration_name) {
1441
            if (version_compare($v, $current_vesion) === 1 ) {
1442
                // can not use as xPDO get queries fill the SELECT with the DB fields and since we are adding one this is a SQL error
1443
                //$blender->runMigration($method, 'master', 0, 0, $migration_name);
1444
1445
                /** @var Migrations $migrationProcessClass */
1446
                $migrationProcessClass = $this->loadMigrationClass($migration_name, $blender);
1447
1448
                if (!$migrationProcessClass instanceof Migrations) {
1449
                    $this->out('File is not an instance of LCI\Blend\Migrations: '.$migration_name, true);
1450
                    $this->out('Did not process, verify it is in the proper directory', true);
1451
1452
                } elseif ($method == 'up' && $this->isBlendInstalledInModx()) {
1453
1454
                    $migrationProcessClass->up();
1455
1456
                    /** @var \BlendMigrations $migration */
1457
                    $migration = $this->modx->newObject($this->blend_class_object);
1458
                    if ($migration) {
1459
                        $migration->set('name', $migration_name);
1460
                        $migration->set('type', 'master');
1461
                        $migration->set('description', $migrationProcessClass->getDescription());
1462
                        $migration->set('version', $migrationProcessClass->getVersion());
1463
                        $migration->set('status', 'up_complete');
1464
                        $migration->set('created_at', date('Y-m-d H:i:s'));
1465
                        $migration->set('processed_at', date('Y-m-d H:i:s'));
1466
                        if ($migration->save() ) {
1467
                            $this->outSuccess('Blend updated to '.$v);
1468
                        } else {
1469
                            $this->out('Blend did not update to '.$v, true);
1470
                        }
1471
1472
                    } else {
1473
                        $this->out('Blender could not save the update to '.$v, true);
1474
                    }
1475
1476
                } elseif ($method == 'down') {
1477
                    $migrationProcessClass->down();
1478
1479
                    /** @var \BlendMigrations $migration */
1480
                    $migration = $this->modx->getObject($this->blend_class_object, ['name' => $migration_name]);
1481
                    if ($migration) {
1482
                        $migration->set('name', $migration_name);
1483
                        $migration->set('description', $migrationProcessClass->getDescription());
1484
                        $migration->set('version', $migrationProcessClass->getVersion());
1485
                        $migration->set('status', 'down_complete');
1486
                        $migration->set('processed_at', date('Y-m-d H:i:s'));
1487
                        $migration->save();
1488
                    }
1489
1490
                }
1491
1492
            }
1493
        }
1494
1495
    }
1496
1497
    /**
1498
     * @return bool
1499
     */
1500
    public function requireUpdate()
1501
    {
1502
        $upgrade = false;
1503
1504
        $current_vesion = $this->modx->getOption('blend.version');
1505
        //                                      FILE version,        DB Version
1506
        if ( $this->isBlendInstalledInModx() && ( !$current_vesion || version_compare($this->getVersion(), $current_vesion)) ) {
1507
            $upgrade = true;
1508
        }
1509
1510
        return $upgrade;
1511
    }
1512
1513
    /**
1514
     * @return bool
1515
     */
1516
    public function isBlendInstalledInModx()
1517
    {
1518
        try {
1519
            $table = $this->modx->getTableName($this->blend_class_object);
1520
            if ($this->modx->query("SELECT 1 FROM {$table} LIMIT 1") === false) {
1521
                return false;
1522
            }
1523
        } catch (Exception $exception) {
1524
            // We got an exception == table not found
1525
            return false;
1526
        }
1527
1528
        /** @var \xPDOQuery $query */
1529
        $query = $this->modx->newQuery($this->blend_class_object);
1530
        $query->select('id');
1531
        $query->where([
1532
            'name' => 'install_blender',
1533
            'status' => 'up_complete'
1534
        ]);
1535
        $query->sortBy('name');
1536
1537
        $installMigration = $this->modx->getObject($this->blend_class_object, $query);
1538
        if ($installMigration instanceof \BlendMigrations || $installMigration instanceof \LCI\Blend\Model\xPDO\BlendMigrations) {
1539
            return true;
1540
        }
1541
1542
        return false;
1543
    }
1544
    /**
1545
     * @param string $method
1546
     * @param string $type
1547
     * @param int $count
1548
     * @param int $id
1549
     * @param string $name
1550
     */
1551
    public function runMigration($method='up', $type='master', $count=0, $id=0, $name=null)
1552
    {
1553
        $dir = 'ASC';
1554
        if ($method == 'down') {
1555
            $dir = 'DESC';
1556
        } else {
1557
            $count = 0;
1558
        }
1559
        // 1. Get all migrations currently in DB:
1560
        $blendMigrations = $this->getBlendMigrationCollection(false, $dir, $count, $id, $name);
1561
1562
        // 2. Load migration files:
1563
        if ($method == 'up') {
1564
            if ($this->retrieveMigrationFiles()) {
1565
                // this is needed just to insure that the order is correct and any new files
1566
                $blendMigrations = $this->getBlendMigrationCollection(true, $dir, $count, $id, $name);
1567
            }
1568
        }
1569
1570
        // 3. now run migration if proper
1571
        /** @var \BlendMigrations $migration */
1572
        foreach ($blendMigrations as $name => $migration) {
1573
            if ($id > 0 && $migration->get('id') != $id) {
1574
                continue;
1575
            }
1576
            /** @var string $name */
1577
            $name = $migration->get('name');
1578
1579
            /** @var string $status ~ ready|up_complete|down_complete*/
1580
            $status = $migration->get('status');
1581
1582
            /** @var string $server_type */
1583
            $server_type = $migration->get('type');
1584
1585
            if ( ($server_type != $type) || ($method == 'up' && $status == 'up_complete') || ($method == 'down' && $status != 'up_complete') ) {
1586
                continue;
1587
            }
1588
1589
            // new blender for each instance
1590
            $blender = new Blender($this->modx, $this->getUserInteractionHandler(), $this->config);
1591
1592
            /** @var Migrations $migrationProcessClass */
1593
            $migrationProcessClass = $this->loadMigrationClass($name, $blender);
1594
1595
            if ($migrationProcessClass instanceof Migrations) {
1596
                $this->out('Load Class: '.$name.' M: '.$method);
1597
                if ($method == 'up') {
1598
                    $migrationProcessClass->up();
1599
                    $this->out('Run up: '.$name);
1600
                    $migration->set('status', 'up_complete');
1601
                    $migration->set('processed_at', date('Y-m-d H:i:s'));
1602
                    $migration->save();
1603
1604
                } elseif ($method == 'down') {
1605
                    $migrationProcessClass->down();
1606
                    $migration->set('status', 'down_complete');
1607
                    $migration->set('processed_at', date('Y-m-d H:i:s'));
1608
                    $migration->save();
1609
1610
                } else {
1611
                    // error
1612
                }
1613
            } else {
1614
                // error
1615
            }
1616
        }
1617
    }
1618
1619
    /**
1620
     * @return bool ~ true if new migrations were found
1621
     */
1622
    public function retrieveMigrationFiles()
1623
    {
1624
        // 1. Get all migrations currently in DB:
1625
        $migrationCollection = $this->modx->getCollection($this->blend_class_object);
1626
1627
        $blendMigrations = [];
1628
1629
        /** @var \BlendMigrations $migration */
1630
        foreach ($migrationCollection as $migration) {
1631
            $blendMigrations[$migration->get('name')] = $migration;
1632
        }
1633
1634
        $migration_dir = $this->getMigrationPath();
1635
        $this->out('Searching '.$migration_dir);
1636
1637
        $reload = false;
1638
        /** @var \DirectoryIterator $file */
1639
        foreach (new \DirectoryIterator($this->getMigrationPath()) as $file) {
1640
            if ($file->isFile() && $file->getExtension() == 'php') {
1641
1642
                $name = $file->getBasename('.php');
1643
                // @TODO query DB! and test this method
1644
                if (!isset($blendMigrations[$name])) {
1645
                    $this->out('Create new '.$name);
1646
                    /** @var Migrations $migrationProcessClass */
1647
                    $migrationProcessClass = $this->loadMigrationClass($name, $this);
1648
1649
                    /** @var \BlendMigrations $migration */
1650
                    $migration = $this->modx->newObject($this->blend_class_object);
1651
                    $migration->set('name', $name);
1652
                    $migration->set('status', 'ready');
1653
                    if ($migrationProcessClass instanceof Migrations) {
1654
                        $migration->set('description', $migrationProcessClass->getDescription());
1655
                        $migration->set('version', $migrationProcessClass->getVersion());
1656
                        $migration->set('author', $migrationProcessClass->getAuthor());
1657
                    }
1658
                    if (!$migration->save()) {
1659
                        exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1660
                    };
1661
1662
                    $reload = true;
1663
                }
1664
            }
1665
        }
1666
        return $reload;
1667
    }
1668
1669
    /**
1670
     * @param string $name
1671
     * @param Blender $blender
1672
     *
1673
     * @return bool|Migrations
1674
     */
1675
    protected function loadMigrationClass($name, Blender $blender)
1676
    {
1677
        $migrationProcessClass = false;
1678
1679
        $file = $blender->getMigrationPath().$name.'.php';
1680
        if (file_exists($file)) {
1681
            require_once $file;
1682
1683
            if(class_exists($name)) {
1684
                /** @var Migrations $migrationProcessClass */
1685
                $migrationProcessClass = new $name($this->modx, $blender);
1686
            }
1687
        }
1688
1689
        return $migrationProcessClass;
1690
    }
1691
1692
    /**
1693
     * @param $type
1694
     * @param null $name
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $name is correct as it would always require null to be passed?
Loading history...
1695
     * @return string
1696
     */
1697
    public function getMigrationName($type, $name=null)
1698
    {
1699
        $format = new Format($this->seeds_dir);
1700
        return $format->getMigrationName($type, $name);
1701
    }
1702
1703
    /**
1704
     * @param string $name
1705
     * @param string $type ~ chunk, plugin, resource, snippet, systemSettings, template, site
1706
     *
1707
     * @return bool
1708
     */
1709
    public function removeMigrationFile($name, $type)
1710
    {
1711
        // @TODO refactor for setting $name
1712
        $class_name = $this->getMigrationName($type, $name);
1713
1714
        $removed = false;
1715
        $migration_file = $this->getMigrationPath() . $class_name . '.php';
1716
        if (file_exists($migration_file)) {
1717
            if (unlink($migration_file)) {
1718
                $removed = true;
1719
                $migration = $this->modx->getObject($this->blend_class_object, ['name' => $class_name]);
1720
                if (is_object($migration) && $migration->remove()) {
1721
                    $this->out($class_name . ' migration has been removed from the blend_migrations table');
1722
1723
                }
1724
            } else {
1725
                $this->out($class_name . ' migration has not been removed from the blend_migrations table', true);
1726
            }
1727
1728
        } else {
1729
            $this->out($this->getMigrationPath() . $class_name . '.php migration could not be found to remove', true);
1730
        }
1731
1732
        return $removed;
1733
    }
1734
    /**
1735
     * @param int $id
1736
     *
1737
     * @return bool|array
1738
     */
1739
    public function getResourceSeedKeyFromID($id)
1740
    {
1741
        if (!isset($this->resource_id_map[$id])) {
1742
            $seed_key = $context = false;
1743
            $resource = $this->modx->getObject('modResource', $id);
1744
            if ($resource) {
1745
                $context = $resource->get('context_key');
1746
                if (!isset($this->resource_seek_key_map[$context])) {
1747
                    $this->resource_seek_key_map[$context] = [];
1748
                }
1749
                $seed_key = $this->getSeedKeyFromAlias($resource->get('alias'));
1750
                $this->resource_seek_key_map[$context][$seed_key] = $id;
1751
            }
1752
            $this->resource_id_map[$id] = [
1753
                'context' => $context,
1754
                'seed_key' => $seed_key
1755
            ];
1756
        }
1757
1758
        return $this->resource_id_map[$id];
1759
    }
1760
1761
    /**
1762
     * @param string $seed_key
1763
     * @param string $context
1764
     *
1765
     * @return bool|int
1766
     */
1767
    public function getResourceIDFromSeedKey($seed_key, $context='web')
1768
    {
1769
        if (!isset($this->resource_seek_key_map[$context])) {
1770
            $this->resource_seek_key_map[$context] = [];
1771
        }
1772
        if (!isset($this->resource_seek_key_map[$context][$seed_key])) {
1773
            $id = false;
1774
            $alias = $this->getAliasFromSeedKey($seed_key);
1775
            $resource = $this->modx->getObject('modResource', ['alias' => $alias, 'context_key' => $context]);
1776
            if ($resource) {
1777
                $id = $resource->get('id');
1778
                $this->resource_seek_key_map[$context][$seed_key] = $id;
1779
                $this->resource_id_map[$id] = [
1780
                    'context' => $context,
1781
                    'seed_key' => $seed_key
1782
                ];
1783
            }
1784
            $this->resource_seek_key_map[$context][$seed_key] = $id;
1785
        }
1786
1787
        return $this->resource_seek_key_map[$context][$seed_key];
1788
    }
1789
1790
    /**
1791
     * @param string $alias
1792
     *
1793
     * @return string
1794
     */
1795
    public function getSeedKeyFromAlias($alias)
1796
    {
1797
        return str_replace('/', '#', $alias);
1798
    }
1799
1800
    /**
1801
     * @param string $seed_key
1802
     *
1803
     * @return string
1804
     */
1805
    public function getAliasFromSeedKey($seed_key)
1806
    {
1807
        return str_replace('#', '/', $seed_key);
1808
    }
1809
1810
    /**
1811
     * @deprecated
1812
     * @param string $name
1813
     * @param string $type ~ template, template-variable, chunk, snippet or plugin
1814
     * @return string
1815
     */
1816
    public function getElementSeedKeyFromName($name, $type)
1817
    {
1818
        return $type.'_'.$this->getSeedKeyFromName($name);
1819
    }
1820
1821
    /**
1822
     * @param string $name
1823
     * @return string
1824
     */
1825
    public function getSeedKeyFromName($name)
1826
    {
1827
        // @TODO review
1828
        return str_replace('/', '#', $name);
1829
    }
1830
1831
    /**
1832
     * @param string $seed_key
1833
     * @return string
1834
     */
1835
    public function getNameFromSeedKey($seed_key)
1836
    {
1837
        return str_replace('#', '/', $seed_key);
1838
    }
1839
1840
    /**
1841
     * @param $data
1842
     */
1843
    protected function logCreatedMigration($data)
1844
    {
1845
        try {
1846
            /** @var BlendMigrations $migration */
1847
            $migration = $this->modx->newObject($this->blend_class_object);
1848
            if ($migration) {
0 ignored issues
show
introduced by
$migration is of type LCI\Blend\Model\xPDO\BlendMigrations, thus it always evaluated to true. If $migration can have other possible types, add them to src/Blender.php:1846
Loading history...
1849
                $migration->fromArray($data);
1850
                $migration->save();
1851
            }
1852
        } catch (Exception $exception) {
1853
            $this->out($exception->getMessage(), true);
1854
        }
1855
    }
1856
}
1857
/**
1858
 * id | element_class | name | data | action ??
1859
 */
1860