GitHub Access Token became invalid

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

AbstractGenerator   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 616
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 616
rs 8.2378
c 0
b 0
f 0
wmc 41

24 Methods

Rating   Name   Duplication   Size   Complexity  
A findReplaceRegex() 0 10 1
A replaceEntityRepositoriesNamespace() 0 9 1
A __construct() 0 13 1
A replaceFieldInterfaceNamespace() 0 14 2
A setSrcSubFolderName() 0 5 1
A replaceEntitiesNamespace() 0 12 2
A replaceName() 0 15 1
A copyTemplateAndGetPath() 0 17 3
A replaceFieldTraitNamespace() 0 14 2
A replaceEntityInterfaceNamespace() 0 9 1
A createSubDirectoriesAndGetPath() 0 21 4
A replaceEntityNamespace() 0 12 2
A setTestSubFolderName() 0 5 1
A setProjectRootNamespace() 0 5 1
A parseFullyQualifiedName() 0 7 2
A replacePluralName() 0 12 1
B setNamespaceFromPath() 0 36 2
A replaceProjectNamespace() 0 9 1
A findReplace() 0 10 1
A copyTemplateDirectoryAndGetPath() 0 16 2
A getFilesystem() 0 3 1
B renamePathBasename() 0 20 5
A getPathFromNameAndSubDirs() 0 5 1
A setPathToProjectRoot() 0 9 2

How to fix   Complexity   

Complex Class

Complex classes like AbstractGenerator often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AbstractGenerator, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator;
4
5
use Doctrine\Common\Util\Inflector;
6
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\CodeHelper;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\AbstractCommand;
8
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
9
use EdmondsCommerce\DoctrineStaticMeta\Config;
10
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
11
use Symfony\Component\Filesystem\Filesystem;
12
13
abstract class AbstractGenerator
14
{
15
    public const TEMPLATE_PATH = __DIR__.'/../../../codeTemplates';
16
17
    public const ENTITIES_FOLDER_NAME = 'Entities';
18
19
    public const ENTITY_FOLDER_NAME = 'Entity';
20
21
    public const ENTITY_RELATIONS_FOLDER_NAME = '/'.self::ENTITY_FOLDER_NAME.'/Relations/';
22
23
    public const ENTITY_REPOSITORIES_FOLDER_NAME = '/'.self::ENTITY_FOLDER_NAME.'/Repositories/';
24
25
    public const ENTITY_FIELDS_FOLDER_NAME = '/'.self::ENTITY_FOLDER_NAME.'/Fields/';
26
27
    public const ENTITY_SAVERS_FOLDER_NAME = '/'.self::ENTITY_FOLDER_NAME.'/Savers/';
28
29
    public const ENTITY_INTERFACES_FOLDER_NAME = '/'.self::ENTITY_FOLDER_NAME.'/Interfaces/';
30
31
    public const ENTITY_TEMPLATE_PATH = self::TEMPLATE_PATH.'/src/'.self::ENTITIES_FOLDER_NAME
32
    .'/TemplateEntity.php';
33
34
    public const ENTITY_INTERFACE_TEMPLATE_PATH = self::TEMPLATE_PATH.'/src/'.self::ENTITY_INTERFACES_FOLDER_NAME
35
    .'/TemplateEntityInterface.php';
36
37
    public const ENTITY_TEST_TEMPLATE_PATH = self::TEMPLATE_PATH.'/tests/'.self::ENTITIES_FOLDER_NAME
38
    .'/TemplateEntityTest.php';
39
40
    public const ABSTRACT_ENTITY_TEST_TEMPLATE_PATH = self::TEMPLATE_PATH.'/tests/'.self::ENTITIES_FOLDER_NAME
41
    .'/AbstractEntityTest.php';
42
43
    public const PHPUNIT_BOOTSTRAP_TEMPLATE_PATH = self::TEMPLATE_PATH.'/tests/bootstrap.php';
44
45
    public const RELATIONS_TEMPLATE_PATH = self::TEMPLATE_PATH.'/src/'.self::ENTITY_RELATIONS_FOLDER_NAME
46
    .'/TemplateEntity';
47
48
    public const REPOSITORIES_TEMPLATE_PATH = self::TEMPLATE_PATH
49
    .'/src/'.self::ENTITY_REPOSITORIES_FOLDER_NAME
50
    .'/TemplateEntityRepository.php';
51
52
    public const ABSTRACT_ENTITY_REPOSITORY_TEMPLATE_PATH = self::TEMPLATE_PATH
53
    .'/src/'.self::ENTITY_REPOSITORIES_FOLDER_NAME
54
    .'/AbstractEntityRepository.php';
55
56
    public const FIELD_TRAIT_TEMPLATE_PATH = self::TEMPLATE_PATH.'/src/'
57
    .self::ENTITY_FIELDS_FOLDER_NAME
58
    .'/Traits/'
59
    .self::FIND_ENTITY_FIELD_NAME.'FieldTrait.php';
60
61
    public const FIELD_INTERFACE_TEMPLATE_PATH = self::TEMPLATE_PATH.'/src/'
62
    .self::ENTITY_FIELDS_FOLDER_NAME
63
    .'/Interfaces/'
64
    .self::FIND_ENTITY_FIELD_NAME.'FieldInterface.php';
65
66
    public const FIND_ENTITY_NAME = 'TemplateEntity';
67
68
    public const FIND_ENTITY_NAME_PLURAL = 'TemplateEntities';
69
70
    public const FIND_PROJECT_NAMESPACE = 'TemplateNamespace';
71
72
    public const FIND_ENTITIES_NAMESPACE = self::FIND_PROJECT_NAMESPACE.'\\Entities';
73
74
    public const FIND_ENTITY_NAMESPACE = self::FIND_PROJECT_NAMESPACE.'\\Entity';
75
76
    public const ENTITY_RELATIONS_NAMESPACE = '\\Entity\\Relations';
77
78
    public const FIND_ENTITY_RELATIONS_NAMESPACE = 'TemplateNamespace'.self::ENTITY_RELATIONS_NAMESPACE;
79
80
    public const ENTITY_REPOSITORIES_NAMESPACE = '\\Entity\\Repositories';
81
82
    public const ENTITY_SAVERS_NAMESPACE = '\\Entity\\Savers';
83
84
    public const FIND_ENTITY_REPOSITORIES_NAMESPACE = 'TemplateNamespace'.self::ENTITY_REPOSITORIES_NAMESPACE;
85
86
    public const ENTITY_INTERFACE_NAMESPACE = '\\Entity\\Interfaces';
87
88
    public const FIND_ENTITY_INTERFACE_NAMESPACE = 'TemplateNamespace'.self::ENTITY_INTERFACE_NAMESPACE;
89
90
    public const FIND_ENTITY_FIELD_NAME = 'TemplateFieldName';
91
92
    public const ENTITY_FIELD_NAMESPACE = '\\Entity\\Fields';
93
94
    public const ENTITY_FIELD_TRAIT_NAMESPACE = self::ENTITY_FIELD_NAMESPACE . '\\Traits';
95
96
    public const ENTITY_FIELD_INTERFACE_NAMESPACE = self::ENTITY_FIELD_NAMESPACE . '\\Interfaces';
97
98
    public const FIND_FIELD_TRAIT_NAMESPACE = self::FIND_PROJECT_NAMESPACE . self::ENTITY_FIELD_TRAIT_NAMESPACE;
99
100
    public const FIND_FIELD_INTERFACE_NAMESPACE = self::FIND_PROJECT_NAMESPACE . self::ENTITY_FIELD_INTERFACE_NAMESPACE;
101
102
    /**
103
     * @var string
104
     */
105
    protected $projectRootNamespace = '';
106
107
    /**
108
     * @var string
109
     */
110
    protected $pathToProjectRoot = '';
111
112
    /**
113
     * @var string
114
     */
115
    protected $srcSubFolderName = AbstractCommand::DEFAULT_SRC_SUBFOLDER;
116
117
    /**
118
     * @var string
119
     */
120
    protected $testSubFolderName = AbstractCommand::DEFAULT_TEST_SUBFOLDER;
121
122
    /**
123
     * @var Filesystem
124
     */
125
    protected $fileSystem;
126
127
    /**
128
     * @var FileCreationTransaction
129
     */
130
    protected $fileCreationTransaction;
131
132
    /**
133
     * @var NamespaceHelper
134
     */
135
    protected $namespaceHelper;
136
    /**
137
     * @var CodeHelper
138
     */
139
    protected $codeHelper;
140
141
    public function __construct(
142
        Filesystem $filesystem,
143
        FileCreationTransaction $fileCreationTransaction,
144
        NamespaceHelper $namespaceHelper,
145
        Config $config,
146
        CodeHelper $codeHelper
147
    ) {
148
        $this->fileSystem = $filesystem;
149
        $this->fileCreationTransaction = $fileCreationTransaction;
150
        $this->namespaceHelper = $namespaceHelper;
151
        $this->setProjectRootNamespace($this->namespaceHelper->getProjectRootNamespaceFromComposerJson());
152
        $this->setPathToProjectRoot($config::getProjectRootDirectory());
153
        $this->codeHelper = $codeHelper;
154
    }
155
156
    /**
157
     * @param string $projectRootNamespace
158
     *
159
     * @return $this
160
     */
161
    public function setProjectRootNamespace(string $projectRootNamespace): AbstractGenerator
162
    {
163
        $this->projectRootNamespace = rtrim($projectRootNamespace, '\\');
164
165
        return $this;
166
    }
167
168
    /**
169
     * @param string $pathToProjectRoot
170
     *
171
     * @return $this
172
     * @throws \RuntimeException
173
     */
174
    public function setPathToProjectRoot(string $pathToProjectRoot): AbstractGenerator
175
    {
176
        $realPath = \realpath($pathToProjectRoot);
177
        if (false === $realPath) {
178
            throw new \RuntimeException('Invalid path to project root '.$pathToProjectRoot);
179
        }
180
        $this->pathToProjectRoot = $realPath;
181
182
        return $this;
183
    }
184
185
    /**
186
     * @param string $srcSubFolderName
187
     *
188
     * @return $this
189
     */
190
    public function setSrcSubFolderName(string $srcSubFolderName): AbstractGenerator
191
    {
192
        $this->srcSubFolderName = $srcSubFolderName;
193
194
        return $this;
195
    }
196
197
    /**
198
     * @param string $testSubFolderName
199
     *
200
     * @return $this
201
     */
202
    public function setTestSubFolderName(string $testSubFolderName): AbstractGenerator
203
    {
204
        $this->testSubFolderName = $testSubFolderName;
205
206
        return $this;
207
    }
208
209
210
    protected function getFilesystem(): Filesystem
211
    {
212
        return $this->fileSystem;
213
    }
214
215
    /**
216
     * From the fully qualified name, parse out:
217
     *  - class name,
218
     *  - namespace
219
     *  - the namespace parts not including the project root namespace
220
     *
221
     * @param string $fqn
222
     *
223
     * @param string $srcOrTestSubFolder
224
     *
225
     * @return array [$className,$namespace,$subDirectories]
226
     * @throws DoctrineStaticMetaException
227
     */
228
    protected function parseFullyQualifiedName(string $fqn, string $srcOrTestSubFolder = null): array
229
    {
230
        if (null === $srcOrTestSubFolder) {
231
            $srcOrTestSubFolder = $this->srcSubFolderName;
232
        }
233
234
        return $this->namespaceHelper->parseFullyQualifiedName($fqn, $srcOrTestSubFolder, $this->projectRootNamespace);
235
    }
236
237
    /**
238
     * @param array $subDirectories
239
     *
240
     * @return string
241
     * @throws DoctrineStaticMetaException
242
     */
243
    protected function createSubDirectoriesAndGetPath(array $subDirectories): string
244
    {
245
        $filesystem = $this->getFilesystem();
246
        $path = $this->pathToProjectRoot;
247
        if (!$filesystem->exists($path)) {
248
            throw new DoctrineStaticMetaException("path to project root $path does not exist");
249
        }
250
        foreach ($subDirectories as $sd) {
251
            $path .= "/$sd";
252
            try {
253
                $filesystem->mkdir($path);
254
            } catch (\Exception $e) {
255
                throw new DoctrineStaticMetaException(
256
                    'Exception in '.__METHOD__.': '.$e->getMessage(),
257
                    $e->getCode(),
258
                    $e
259
                );
260
            }
261
        }
262
263
        return realpath($path);
264
    }
265
266
    /**
267
     * @param string $templatePath
268
     * @param string $destPath
269
     *
270
     * @return string
271
     * @throws DoctrineStaticMetaException
272
     */
273
    protected function copyTemplateDirectoryAndGetPath(
274
        string $templatePath,
275
        string $destPath
276
    ): string {
277
        $filesystem = $this->getFilesystem();
278
        $realTemplatePath = realpath($templatePath);
279
        if (false === $realTemplatePath) {
280
            throw new DoctrineStaticMetaException('path '.$templatePath.' does not exist');
281
        }
282
        $relativeDestPath = $filesystem->makePathRelative($destPath, $this->pathToProjectRoot);
283
        $subDirectories = explode('/', $relativeDestPath);
284
        $path = $this->createSubDirectoriesAndGetPath($subDirectories);
285
        $filesystem->mirror($realTemplatePath, $path);
286
        $this->fileCreationTransaction::setPathCreated($path);
287
288
        return $path;
289
    }
290
291
    /**
292
     * @param string $templatePath
293
     * @param string $destinationFileName
294
     * @param array $subDirectories
295
     *
296
     * @return string
297
     * @throws DoctrineStaticMetaException
298
     */
299
    protected function copyTemplateAndGetPath(
300
        string $templatePath,
301
        string $destinationFileName,
302
        array $subDirectories
303
    ): string {
304
        try {
305
            $path = $this->createSubDirectoriesAndGetPath($subDirectories);
306
            if (false === strpos($destinationFileName, '.php')) {
307
                $destinationFileName = "$destinationFileName.php";
308
            }
309
            $filePath = "$path/$destinationFileName";
310
            $this->getFilesystem()->copy($templatePath, $filePath, true);
311
            $this->fileCreationTransaction::setPathCreated($filePath);
312
313
            return $filePath;
314
        } catch (\Exception $e) {
315
            throw new DoctrineStaticMetaException('Exception in '.__METHOD__.': '.$e->getMessage(), $e->getCode(), $e);
316
        }
317
    }
318
319
    /**
320
     * @param string $find
321
     * @param string $replace
322
     * @param string $filePath
323
     *
324
     * @return AbstractGenerator
325
     */
326
    protected function findReplace(
327
        string $find,
328
        string $replace,
329
        string $filePath
330
    ): AbstractGenerator {
331
        $contents = file_get_contents($filePath);
332
        $contents = str_replace($find, $replace, $contents);
333
        file_put_contents($filePath, $contents);
334
335
        return $this;
336
    }
337
338
    /**
339
     * @param string $find
340
     * @param string $replace
341
     * @param string $filePath
342
     *
343
     * @return AbstractGenerator
344
     */
345
    protected function findReplaceRegex(
346
        string $find,
347
        string $replace,
348
        string $filePath
349
    ): AbstractGenerator {
350
        $contents = file_get_contents($filePath);
351
        $contents = preg_replace($find, $replace, $contents);
352
        file_put_contents($filePath, $contents);
353
354
        return $this;
355
    }
356
357
    /**
358
     * @param string $replacement
359
     * @param string $filePath
360
     * @param string $findName
361
     *
362
     * @return AbstractGenerator
363
     * @SuppressWarnings(PHPMD.StaticAccess)
364
     */
365
    protected function replaceName(
366
        string $replacement,
367
        string $filePath,
368
        $findName = self::FIND_ENTITY_NAME
369
    ): AbstractGenerator {
370
        $this->findReplace($findName, $replacement, $filePath);
371
        $this->findReplace(\lcfirst($findName), \lcfirst($replacement), $filePath);
372
        $this->findReplace(\strtoupper($findName), \strtoupper($replacement), $filePath);
373
        $this->findReplace(
374
            \strtoupper(Inflector::tableize($findName)),
375
            \strtoupper(Inflector::tableize($replacement)),
376
            $filePath
377
        );
378
379
        return $this;
380
    }
381
382
    /**
383
     * @param string $replacement
384
     * @param string $filePath
385
     *
386
     * @return AbstractGenerator
387
     * @SuppressWarnings(PHPMD.StaticAccess)
388
     */
389
    protected function replacePluralName(string $replacement, string $filePath): AbstractGenerator
390
    {
391
        $this->findReplace(self::FIND_ENTITY_NAME_PLURAL, $replacement, $filePath);
392
        $this->findReplace(\lcfirst(self::FIND_ENTITY_NAME_PLURAL), \lcfirst($replacement), $filePath);
393
        $this->findReplace(\strtoupper(self::FIND_ENTITY_NAME_PLURAL), \strtoupper($replacement), $filePath);
394
        $this->findReplace(
395
            \strtoupper(Inflector::tableize(self::FIND_ENTITY_NAME_PLURAL)),
396
            \strtoupper(Inflector::tableize($replacement)),
397
            $filePath
398
        );
399
400
        return $this;
401
    }
402
403
    /**
404
     * @param string $replacement
405
     * @param string $filePath
406
     *
407
     * @return AbstractGenerator
408
     * @throws \RuntimeException
409
     */
410
    protected function replaceEntitiesNamespace(string $replacement, string $filePath): AbstractGenerator
411
    {
412
        if (false === strpos($replacement, '\\Entities')) {
413
            throw new \RuntimeException('$replacement '.$replacement.' does not contain \\Entities\\');
414
        }
415
        $this->findReplace(
416
            self::FIND_ENTITIES_NAMESPACE,
417
            $this->namespaceHelper->tidy($replacement),
418
            $filePath
419
        );
420
421
        return $this;
422
    }
423
424
    /**
425
     * @param string $replacement
426
     * @param string $filePath
427
     *
428
     * @return AbstractGenerator
429
     * @throws \RuntimeException
430
     */
431
    protected function replaceEntityNamespace(string $replacement, string $filePath): AbstractGenerator
432
    {
433
        if (false === strpos($replacement, '\\Entity')) {
434
            throw new \RuntimeException('$replacement '.$replacement.' does not contain \\Entity\\');
435
        }
436
        $this->findReplace(
437
            self::FIND_ENTITY_NAMESPACE,
438
            $this->namespaceHelper->tidy($replacement),
439
            $filePath
440
        );
441
442
        return $this;
443
    }
444
445
    /**
446
     * @param string $replacement
447
     * @param string $filePath
448
     *
449
     * @return AbstractGenerator
450
     * @throws \RuntimeException
451
     */
452
    protected function replaceFieldTraitNamespace(string $replacement, string $filePath): AbstractGenerator
453
    {
454
        if (false === strpos($replacement, self::ENTITY_FIELD_TRAIT_NAMESPACE)) {
455
            throw new \RuntimeException(
456
                '$replacement '.$replacement.' does not contain ' . self::ENTITY_FIELD_TRAIT_NAMESPACE
457
            );
458
        }
459
        $this->findReplace(
460
            self::FIND_FIELD_TRAIT_NAMESPACE,
461
            $this->namespaceHelper->tidy($replacement),
462
            $filePath
463
        );
464
465
        return $this;
466
    }
467
468
    /**
469
     * @param string $replacement
470
     * @param string $filePath
471
     *
472
     * @return AbstractGenerator
473
     * @throws \RuntimeException
474
     */
475
    protected function replaceFieldInterfaceNamespace(string $replacement, string $filePath): AbstractGenerator
476
    {
477
        if (false === strpos($replacement, self::ENTITY_FIELD_INTERFACE_NAMESPACE)) {
478
            throw new \RuntimeException(
479
                '$replacement '.$replacement.' does not contain ' . self::ENTITY_FIELD_INTERFACE_NAMESPACE
480
            );
481
        }
482
        $this->findReplace(
483
            self::FIND_FIELD_INTERFACE_NAMESPACE,
484
            $this->namespaceHelper->tidy($replacement),
485
            $filePath
486
        );
487
488
        return $this;
489
    }
490
491
    /**
492
     * @param string $replacement
493
     * @param string $filePath
494
     *
495
     * @return AbstractGenerator
496
     */
497
    protected function replaceProjectNamespace(string $replacement, string $filePath): AbstractGenerator
498
    {
499
        $this->findReplace(
500
            self::FIND_PROJECT_NAMESPACE,
501
            $this->namespaceHelper->tidy($replacement),
502
            $filePath
503
        );
504
505
        return $this;
506
    }
507
508
    /**
509
     * @param string $replacement
510
     * @param string $filePath
511
     *
512
     * @return AbstractGenerator
513
     */
514
    protected function replaceEntityRepositoriesNamespace(string $replacement, string $filePath): AbstractGenerator
515
    {
516
        $this->findReplace(
517
            self::FIND_ENTITY_REPOSITORIES_NAMESPACE,
518
            $this->namespaceHelper->tidy($replacement),
519
            $filePath
520
        );
521
522
        return $this;
523
    }
524
525
    /**
526
     * @param string $replacement
527
     * @param string $filePath
528
     *
529
     * @return AbstractGenerator
530
     */
531
    protected function replaceEntityInterfaceNamespace(string $replacement, string $filePath): AbstractGenerator
532
    {
533
        $this->findReplace(
534
            self::FIND_ENTITY_INTERFACE_NAMESPACE,
535
            $this->namespaceHelper->tidy($replacement),
536
            $filePath
537
        );
538
539
        return $this;
540
    }
541
542
543
    /**
544
     * Totally replace the defined namespace in a class/trait
545
     * with a namespace calculated from the path of the file
546
     *
547
     * @param string $filePath
548
     *
549
     * @return AbstractGenerator
550
     * @throws DoctrineStaticMetaException
551
     */
552
    protected function setNamespaceFromPath(string $filePath): AbstractGenerator
553
    {
554
        $pathForNamespace = substr(
555
            $filePath,
556
            strpos(
557
                $filePath,
558
                $this->srcSubFolderName
559
            )
560
            + strlen($this->srcSubFolderName)
561
            + 1
562
        );
563
        $pathForNamespace = substr($pathForNamespace, 0, strrpos($pathForNamespace, '/'));
564
        $namespaceToSet = $this->projectRootNamespace
565
            .'\\'.implode(
566
                '\\',
567
                explode(
568
                    '/',
569
                    $pathForNamespace
570
                )
571
            );
572
        $contents = file_get_contents($filePath);
573
        $contents = preg_replace(
574
            '%namespace[^:]+?;%',
575
            "namespace $namespaceToSet;",
576
            $contents,
577
            1,
578
            $count
579
        );
580
        if ($count !== 1) {
581
            throw new DoctrineStaticMetaException(
582
                'Namespace replace count is '.$count.', should be 1 when updating file: '.$filePath
583
            );
584
        }
585
        file_put_contents($filePath, $contents);
586
587
        return $this;
588
    }
589
590
    /**
591
     * Move the basename of a path to the find/replaced version
592
     *
593
     * Then return the updated path
594
     *
595
     * @param string $find
596
     * @param string $replace
597
     * @param string $path
598
     *
599
     * @return string
600
     * @throws DoctrineStaticMetaException
601
     */
602
    protected function renamePathBasename(string $find, string $replace, string $path): string
603
    {
604
        $basename = basename($path);
605
        $newBasename = str_replace($find, $replace, $basename);
606
        $moveTo = \dirname($path).'/'.$newBasename;
607
        if ($moveTo === $path) {
608
            return $path;
609
        }
610
        if (is_dir($moveTo) || file_exists($moveTo)) {
611
            throw new DoctrineStaticMetaException(
612
                "Error trying to move:\n[$path]\n to \n[$moveTo]\ndestination already exists"
613
            );
614
        }
615
        try {
616
            $this->getFilesystem()->rename($path, $moveTo);
617
        } catch (\Exception $e) {
618
            throw new DoctrineStaticMetaException('Exception in '.__METHOD__.': '.$e->getMessage(), $e->getCode(), $e);
619
        }
620
621
        return $moveTo;
622
    }
623
624
    protected function getPathFromNameAndSubDirs(string $name, array $subDirectories): string
625
    {
626
        $path = realpath($this->pathToProjectRoot).'/'.implode('/', $subDirectories).'/'.$name.'.php';
627
628
        return $path;
629
    }
630
}
631