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
Push — master ( cc354f...2af0ad )
by joseph
12s
created

UnusedRelationsRemover::getEntitySubSubFqn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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