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 (#101)
by joseph
18:59
created

getPluralSingularFromEntitySubFqn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\CodeGeneration;
4
5
use Symfony\Component\Finder\Finder;
6
use Symfony\Component\Finder\SplFileInfo;
7
8
/**
9
 * Class UnusedCodeRemover
10
 *
11
 * Finds and removes generated code that does not seem to be used
12
 *
13
 * Caution - this is destructive - do not use in a dirty repo!!!
14
 *
15
 * @package EdmondsCommerce\DoctrineStaticMeta\CodeGeneration
16
 */
17
class UnusedRelationsRemover
18
{
19
    /**
20
     * @var array
21
     */
22
    private $filesRemoved = [];
23
    /**
24
     * @var string
25
     */
26
    private $pathToProjectRoot;
27
    /**
28
     * @var string
29
     */
30
    private $projectRootNamespace;
31
    /**
32
     * @var array
33
     */
34
    private $relationTraits = [];
35
    /**
36
     * @var array
37
     */
38
    private $entitySubFqnsToName = [];
39
    /**
40
     * @var array
41
     */
42
    private $entityPaths = [];
43
44
45 2
    public function run(string $pathToProjectRoot, string $projectRootNamespace): array
46
    {
47 2
        $this->pathToProjectRoot    = $pathToProjectRoot;
48 2
        $this->projectRootNamespace = $projectRootNamespace;
49 2
        $this->initArrayOfRelationTraits();
50 2
        $this->initAllEntitySubFqns();
51 2
        foreach (\array_keys($this->entitySubFqnsToName) as $entitySubFqn) {
52 2
            $this->removeUnusedEntityRelations($entitySubFqn);
53
        }
54
55 2
        return $this->filesRemoved;
56
    }
57
58 2
    private function initArrayOfRelationTraits(): void
59
    {
60 2
        $this->relationTraits = [];
61 2
        $pluralRelations      = $this->getFileInfoObjectsInDirs(
62
            [
63 2
                __DIR__ . '/../../codeTemplates/src/Entity/Relations/TemplateEntity/Traits/HasTemplateEntities',
64
            ]
65
        );
66 2
        foreach ($pluralRelations as $pluralRelation) {
67 2
            $realPath                                  = $pluralRelation->getRealPath();
68 2
            $this->relationTraits['plural'][$realPath] = $this->convertPathToNamespace(
69 2
                $this->getSubPathFromSrcAndTrimExtension(
70 2
                    $realPath
71
                )
72
            );
73
        }
74 2
        $singularRelations = $this->getFileInfoObjectsInDirs(
75
            [
76 2
                __DIR__ . '/../../codeTemplates/src/Entity/Relations/TemplateEntity/Traits/HasTemplateEntity',
77
            ]
78
        );
79 2
        foreach ($singularRelations as $singularRelation) {
80 2
            $realPath                                    = $singularRelation->getRealPath();
81 2
            $this->relationTraits['singular'][$realPath] = $this->convertPathToNamespace(
82 2
                $this->getSubPathFromSrcAndTrimExtension(
83 2
                    $realPath
84
                )
85
            );
86
        }
87 2
    }
88
89
    /**
90
     * @param array $dirs
91
     *
92
     * @return array|SplFileInfo[]
93
     */
94 2
    private function getFileInfoObjectsInDirs(array $dirs): array
95
    {
96 2
        $finder   = new Finder();
97 2
        $iterable = $finder->files()->in($dirs);
98
99 2
        return iterator_to_array($iterable);
100
    }
101
102 2
    private function convertPathToNamespace(string $path): string
103
    {
104 2
        return \str_replace('/', '\\', $path);
105
    }
106
107 2
    private function getSubPathFromSrcAndTrimExtension(string $path): string
108
    {
109 2
        $subPath = substr($path, strpos($path, 'src') + 3);
110 2
        $subPath = substr($subPath, 0, strpos($subPath, '.php'));
111
112 2
        return $subPath;
113
    }
114
115 2
    private function initAllEntitySubFqns(): void
116
    {
117 2
        $files                     = $this->getFileInfoObjectsInDirs([$this->pathToProjectRoot . '/src/Entities']);
118 2
        $this->entitySubFqnsToName = [];
119 2
        foreach ($files as $file) {
120 2
            $realPath                                 = $file->getRealPath();
121 2
            $this->entityPaths[$realPath]             = \file_get_contents($realPath);
122 2
            $entitySubFqn                             = $this->getEntitySubFqnFromEntityFilePath($realPath);
123 2
            $this->entitySubFqnsToName[$entitySubFqn] = $this->getPluralSingularFromEntitySubFqn($entitySubFqn);
124
        }
125 2
    }
126
127 2
    private function getEntitySubFqnFromEntityFilePath(string $path): string
128
    {
129 2
        $subPath = $this->getSubPathFromSrcAndTrimExtension($path);
130
131 2
        return \str_replace('/', '\\', $subPath);
132
    }
133
134 2
    private function getPluralSingularFromEntitySubFqn(string $entitySubFqn): array
135
    {
136 2
        $entityFqn = $this->projectRootNamespace . $entitySubFqn;
137
138
        return [
139 2
            'singular' => ucfirst($entityFqn::getSingular()),
140 2
            'plural'   => ucfirst($entityFqn::getPlural()),
141
        ];
142
    }
143
144 2
    private function removeUnusedEntityRelations(string $entitySubFqn): void
145
    {
146 2
        $entitySubSubFqn = $this->getEntitySubSubFqn($entitySubFqn);
147 2
        $hasPlural       = $this->removeRelationsBySingularOrPlural('plural', $entitySubSubFqn);
148 2
        $hasSingular     = $this->removeRelationsBySingularOrPlural('singular', $entitySubSubFqn);
149
150 2
        if (false === $hasPlural && false === $hasSingular) {
151 2
            $this->removeAllRelationFilesForEntity($entitySubSubFqn);
152
153 2
            return;
154
        }
155 1
        if (false === $hasPlural) {
156 1
            $this->removeHasPluralOrSingularInterfaceAndAbstract(
157 1
                'plural',
158 1
                $entitySubFqn,
159 1
                $entitySubSubFqn
160
            );
161
        }
162
163 1
        if (false === $hasSingular) {
164 1
            $this->removeHasPluralOrSingularInterfaceAndAbstract(
165 1
                'singular',
166 1
                $entitySubFqn,
167 1
                $entitySubSubFqn
168
            );
169
        }
170 1
    }
171
172 2
    private function getEntitySubSubFqn(string $entitySubFqn): string
173
    {
174 2
        return substr($entitySubFqn, \strlen('\\Entities\\'));
175
    }
176
177 2
    private function removeRelationsBySingularOrPlural(string $singularOrPlural, string $entitySubSubFqn): bool
178
    {
179 2
        $foundUsedRelations = false;
180
181 2
        foreach ($this->relationTraits[$singularOrPlural] as $relationTrait) {
182 2
            $relationType = $this->getRelationType($relationTrait);
183 2
            $pattern      = $this->getRegexForRelationTraitUseStatement($entitySubSubFqn, $relationType);
184 2
            foreach ($this->entityPaths as $entityFileContents) {
185 2
                if (1 === \preg_match($pattern, $entityFileContents)) {
186 1
                    $foundUsedRelations = true;
187 2
                    continue 2;
188
                }
189
            }
190 2
            $this->removeRelation($entitySubSubFqn, $relationType);
191
        }
192
193 2
        return $foundUsedRelations;
194
    }
195
196 2
    private function getRelationType(string $relationTraitSubFqn)
197
    {
198 2
        return preg_split(
199 2
            '%\\\\HasTemplateEntit(y|ies)\\\\HasTemplateEntit(y|ies)%',
200 2
            $relationTraitSubFqn
201 2
        )[1];
202
    }
203
204 2
    private function getRegexForRelationTraitUseStatement(string $entitySubSubFqn, string $relationType): string
205
    {
206 2
        $entitySubSubFqn = \str_replace('\\', '\\\\', $entitySubSubFqn);
207
208
        return <<<REGEXP
209 2
%use .+?\\\\Entity\\\\Relations\\\\$entitySubSubFqn([^;]+?)$relationType%
210
REGEXP;
211
    }
212
213 2
    private function removeRelation(string $entitySubSubFqn, string $relationType): void
214
    {
215 2
        $directory = $this->getPathToRelationRootForEntity($entitySubSubFqn);
216 2
        if (!\is_dir($directory)) {
217
            return;
218
        }
219 2
        $finder = (new Finder())->files()
220 2
                                ->in($directory)
221 2
                                ->path('%^(Interfaces|Traits).+?' . $relationType . '%');
222 2
        $this->removeFoundFiles($finder);
223 2
    }
224
225 2
    private function getPathToRelationRootForEntity(string $entitySubSubFqn): string
226
    {
227 2
        return $this->pathToProjectRoot
228 2
               . '/src/Entity/Relations/'
229 2
               . \str_replace(
230 2
                   '\\',
231 2
                   '/',
232 2
                   $entitySubSubFqn
233
               );
234
    }
235
236 2
    private function removeFoundFiles(Finder $finder): void
237
    {
238 2
        foreach ($finder as $fileInfo) {
239 2
            $this->removeFile($fileInfo->getRealPath());
240
        }
241 2
    }
242
243 2
    private function removeFile(string $path): void
244
    {
245 2
        if (!\file_exists($path)) {
246
            return;
247
        }
248 2
        $this->filesRemoved[] = $path;
249 2
        unlink($path);
250 2
    }
251
252 2
    private function removeAllRelationFilesForEntity(string $entitySubSubFqn): void
253
    {
254 2
        $relationsPath = $this->getPathToRelationRootForEntity($entitySubSubFqn);
255
        $directories   = [
256 2
            "$relationsPath/Traits",
257 2
            "$relationsPath/Interfaces",
258
        ];
259 2
        foreach ($directories as $directory) {
260 2
            if (!\is_dir($directory)) {
261
                continue;
262
            }
263 2
            $finder = (new Finder())->files()
264 2
                                    ->in($directory);
265 2
            $this->removeFoundFiles($finder);
266
        }
267 2
    }
268
269 1
    private function removeHasPluralOrSingularInterfaceAndAbstract(
270
        string $pluralOrSingular,
271
        string $entitySubFqn,
272
        string $entitySubSubFqn
273
    ): void {
274 1
        $directory = $this->getPathToRelationRootForEntity($entitySubSubFqn);
275 1
        if (!\is_dir($directory)) {
276
            return;
277
        }
278 1
        $hasName = $this->entitySubFqnsToName[$entitySubFqn][$pluralOrSingular];
279 1
        $finder  = (new Finder())->files()
280 1
                                 ->in($directory)
281 1
                                 ->path(
282 1
                                     '%^(Interfaces|Traits).+?Has' . $hasName . '(/|Abstract\.php|Interface\.php)%'
283
                                 );
284 1
        $this->removeFoundFiles($finder);
285 1
    }
286
}
287