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 (#54)
by joseph
28:13 queued 24:17
created

NamespaceHelper::getObjectFqn()   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
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 1
crap 1
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\CodeGeneration;
4
5
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\AbstractCommand;
6
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\AbstractGenerator;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\RelationsGenerator;
8
use EdmondsCommerce\DoctrineStaticMeta\Config;
9
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
10
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
11
12
/**
13
 * Class NamespaceHelper
14
 *
15
 * Pure functions for working with namespaces and to calculate namespaces
16
 *
17
 * @package EdmondsCommerce\DoctrineStaticMeta\CodeGeneration
18
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
19
 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
20
 */
21
class NamespaceHelper
22
{
23 3
    public function cropSuffix(string $fqn, string $suffix):string
24
    {
25 3
        return \substr($fqn, 0, - \strlen($suffix));
26
    }
27
28
    /**
29
     * @param mixed|object $object
30
     *
31
     * @see https://gist.github.com/ludofleury/1708784
32
     * @return string
33
     */
34 6
    public function getObjectFqn($object): string
35
    {
36 6
        return \get_class($object);
37
    }
38
39
    /**
40
     * @param mixed|object $object
41
     *
42
     * @return string
43
     * @throws \ReflectionException
44
     */
45 1
    public function getObjectShortName($object): string
46
    {
47 1
        $exp = explode('\\', $this->getObjectFqn($object));
48
49 1
        return end($exp);
50
    }
51
52
    /**
53
     * Get the basename of a namespace
54
     *
55
     * @param string $namespace
56
     *
57
     * @return string
58
     */
59 5
    public function basename(string $namespace): string
60
    {
61 5
        $strrpos = \strrpos($namespace, '\\');
62 5
        if (false === $strrpos) {
63
            return $namespace;
64
        }
65
66 5
        return $this->tidy(\substr($namespace, $strrpos + 1));
67
    }
68
69
    /**
70
     * Checks and tidies up a given namespace
71
     *
72
     * @param string $namespace
73
     *
74
     * @return string
75
     * @throws \RuntimeException
76
     */
77 106
    public function tidy(string $namespace): string
78
    {
79 106
        if (false !== strpos($namespace, '/')) {
80
            throw new \RuntimeException('Invalid namespace '.$namespace);
81
        }
82
        #remove repeated separators
83 106
        $namespace = preg_replace(
84 106
            '#'.'\\\\'.'+#',
85 106
            '\\',
86 106
            $namespace
87
        );
88
89 106
        return $namespace;
90
    }
91
92
    /**
93
     * Generate a tidy root namespace without a leading \
94
     *
95
     * @param string $namespace
96
     *
97
     * @return string
98
     */
99 104
    public function root(string $namespace): string
100
    {
101 104
        return $this->tidy(ltrim($namespace, '\\'));
102
    }
103
104
    /**
105
     * Work out the entity namespace root from a single entity reflection object.
106
     *
107
     * @param \ReflectionClass $entityReflection
108
     *
109
     * @return string
110
     */
111 1
    public function getEntityNamespaceRootFromEntityReflection(
112
        \ReflectionClass $entityReflection
113
    ): string {
114 1
        return $this->tidy(
115 1
            $this->getNamespaceRootToDirectoryFromFqn(
116 1
                $entityReflection->getName(),
117 1
                AbstractGenerator::ENTITIES_FOLDER_NAME
118
            )
119
        );
120
    }
121
122
    /**
123
     * Get the namespace root up to and including a specified directory
124
     *
125
     * @param string $fqn
126
     * @param string $directory
127
     *
128
     * @return null|string
129
     */
130 1
    public function getNamespaceRootToDirectoryFromFqn(string $fqn, string $directory): ?string
131
    {
132 1
        $strPos = \strrpos(
133 1
            $fqn,
134 1
            $directory
135
        );
136 1
        if (false !== $strPos) {
137 1
            return $this->tidy(\substr($fqn, 0, $strPos + \strlen($directory)));
138
        }
139
140
        return null;
141
    }
142
143
    /**
144
     * Get the sub path for an Entity file, start from the Entities path - normally `/path/to/project/src/Entities`
145
     *
146
     * @param string $entityFqn
147
     *
148
     * @return string
149
     */
150 3
    public function getEntityFileSubPath(
151
        string $entityFqn
152
    ): string {
153 3
        return $this->getEntitySubPath($entityFqn).'.php';
154
    }
155
156
    /**
157
     * Get the folder structure for an Entity, start from the Entities path - normally `/path/to/project/src/Entities`
158
     *
159
     * This is not the path to the file, but the sub path of directories for storing entity related items.
160
     *
161
     * @param string $entityFqn
162
     *
163
     * @return string
164
     */
165 5
    public function getEntitySubPath(
166
        string $entityFqn
167
    ): string {
168 5
        $entityPath = str_replace(
169 5
            '\\',
170 5
            '/',
171 5
            $this->getEntitySubNamespace($entityFqn)
172
        );
173
174 5
        return '/'.$entityPath;
175
    }
176
177
    /**
178
     * Get the Namespace for an Entity, start from the Entities Fully Qualified Name base - normally
179
     * `\My\Project\Entities\`
180
     *
181
     * @param string $entityFqn
182
     *
183
     * @return string
184
     */
185 47
    public function getEntitySubNamespace(
186
        string $entityFqn
187
    ): string {
188 47
        return $this->tidy(
189 47
            \substr(
190 47
                $entityFqn,
191 47
                \strrpos(
192 47
                    $entityFqn,
193 47
                    '\\'.AbstractGenerator::ENTITIES_FOLDER_NAME.'\\'
194
                )
195 47
                + \strlen('\\'.AbstractGenerator::ENTITIES_FOLDER_NAME.'\\')
196
            )
197
        );
198
    }
199
200
    /**
201
     * Get the Fully Qualified Namespace root for Traits for the specified Entity
202
     *
203
     * @param string $entityFqn
204
     *
205
     * @return string
206
     */
207 1
    public function getTraitsNamespaceForEntity(
208
        string $entityFqn
209
    ): string {
210 1
        $traitsNamespace = $this->getProjectNamespaceRootFromEntityFqn($entityFqn)
211 1
                           .AbstractGenerator::ENTITY_RELATIONS_NAMESPACE
212 1
                           .'\\'.$this->getEntitySubNamespace($entityFqn)
213 1
                           .'\\Traits';
214
215 1
        return $traitsNamespace;
216
    }
217
218
    /**
219
     * Use the fully qualified name of two Entities to calculate the Project Namespace Root
220
     *
221
     * - note: this assumes a single namespace level for entities, eg `Entities`
222
     *
223
     * @param string $entityFqn
224
     *
225
     * @return string
226
     */
227 6
    public function getProjectNamespaceRootFromEntityFqn(string $entityFqn): string
228
    {
229 6
        return $this->tidy(
230 6
            \substr(
231 6
                $entityFqn,
232 6
                0,
233 6
                \strrpos(
234 6
                    $entityFqn,
235 6
                    '\\'.AbstractGenerator::ENTITIES_FOLDER_NAME.'\\'
236
                )
237
            )
238
        );
239
    }
240
241
    /**
242
     * Get the Fully Qualified Namespace for the "HasEntities" interface for the specified Entity
243
     *
244
     * @param string $entityFqn
245
     *
246
     * @return string
247
     */
248 2
    public function getHasPluralInterfaceFqnForEntity(
249
        string $entityFqn
250
    ): string {
251 2
        $interfaceNamespace = $this->getInterfacesNamespaceForEntity($entityFqn);
252
253 2
        return $interfaceNamespace.'\\Has'.ucfirst($entityFqn::getPlural()).'Interface';
254
    }
255
256
    /**
257
     * Get the Fully Qualified Namespace root for Interfaces for the specified Entity
258
     *
259
     * @param string $entityFqn
260
     *
261
     * @return string
262
     */
263 4
    public function getInterfacesNamespaceForEntity(
264
        string $entityFqn
265
    ): string {
266 4
        $interfacesNamespace = $this->getProjectNamespaceRootFromEntityFqn($entityFqn)
267 4
                               .AbstractGenerator::ENTITY_RELATIONS_NAMESPACE
268 4
                               .'\\'.$this->getEntitySubNamespace($entityFqn)
269 4
                               .'\\Interfaces';
270
271 4
        return $this->tidy($interfacesNamespace);
272
    }
273
274
    /**
275
     * Get the Fully Qualified Namespace for the "HasEntity" interface for the specified Entity
276
     *
277
     * @param string $entityFqn
278
     *
279
     * @return string
280
     * @throws DoctrineStaticMetaException
281
     */
282 1
    public function getHasSingularInterfaceFqnForEntity(
283
        string $entityFqn
284
    ): string {
285
        try {
286 1
            $interfaceNamespace = $this->getInterfacesNamespaceForEntity($entityFqn);
287
288 1
            return $interfaceNamespace.'\\Has'.ucfirst($entityFqn::getSingular()).'Interface';
289
        } catch (\Exception $e) {
290
            throw new DoctrineStaticMetaException('Exception in '.__METHOD__.': '.$e->getMessage(), $e->getCode(), $e);
291
        }
292
    }
293
294
    /**
295
     * Get the Fully Qualified Namespace for the Relation Trait for a specific Entity and hasType
296
     *
297
     * @param string      $hasType
298
     * @param string      $ownedEntityFqn
299
     * @param string|null $projectRootNamespace
300
     * @param string      $srcFolder
301
     *
302
     * @return string
303
     * @throws DoctrineStaticMetaException
304
     */
305 23
    public function getOwningTraitFqn(
306
        string $hasType,
307
        string $ownedEntityFqn,
308
        ?string $projectRootNamespace = null,
309
        string $srcFolder = AbstractCommand::DEFAULT_SRC_SUBFOLDER
310
    ): string {
311
        try {
312 23
            $ownedHasName = $this->getOwnedHasName($hasType, $ownedEntityFqn, $srcFolder, $projectRootNamespace);
0 ignored issues
show
Bug introduced by
It seems like $projectRootNamespace can also be of type null; however, parameter $projectRootNamespace of EdmondsCommerce\Doctrine...lper::getOwnedHasName() does only seem to accept string, 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

312
            $ownedHasName = $this->getOwnedHasName($hasType, $ownedEntityFqn, $srcFolder, /** @scrutinizer ignore-type */ $projectRootNamespace);
Loading history...
313 23
            if (null === $projectRootNamespace) {
314
                $projectRootNamespace = $this->getProjectRootNamespaceFromComposerJson($srcFolder);
315
            }
316 23
            list($ownedClassName, , $ownedSubDirectories) = $this->parseFullyQualifiedName(
317 23
                $ownedEntityFqn,
318 23
                $srcFolder,
319 23
                $projectRootNamespace
320
            );
321 23
            $traitSubDirectories = \array_slice($ownedSubDirectories, 2);
322 23
            $owningTraitFqn      = $this->getOwningRelationsRootFqn(
323 23
                $projectRootNamespace,
324 23
                $traitSubDirectories
325
            );
326 23
            $owningTraitFqn      .= $ownedClassName.'\\Traits\\Has'.$ownedHasName
327 23
                                    .'\\Has'.$ownedHasName.$this->stripPrefixFromHasType($hasType);
328
329 23
            return $this->tidy($owningTraitFqn);
330
        } catch (\Exception $e) {
331
            throw new DoctrineStaticMetaException('Exception in '.__METHOD__.': '.$e->getMessage(), $e->getCode(), $e);
332
        }
333
    }
334
335
    /**
336
     * Based on the $hasType, we calculate exactly what type of `Has` we have
337
     *
338
     * @param string $hasType
339
     * @param string $ownedEntityFqn
340
     * @param string $srcOrTestSubFolder
341
     *
342
     * @param string $projectRootNamespace
343
     *
344
     * @return string
345
     * @SuppressWarnings(PHPMD.StaticAccess)
346
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
347
     */
348 23
    public function getOwnedHasName(
349
        string $hasType,
350
        string $ownedEntityFqn,
351
        string $srcOrTestSubFolder,
352
        string $projectRootNamespace
353
    ): string {
354 23
        $parsedFqn = $this->parseFullyQualifiedName(
355 23
            $ownedEntityFqn,
356 23
            $srcOrTestSubFolder,
357 23
            $projectRootNamespace
358
        );
359
360 23
        $subDirectories = $parsedFqn[2];
361
362 23
        if (\in_array(
363 23
            $hasType,
364 23
            RelationsGenerator::HAS_TYPES_PLURAL,
365 23
            true
366
        )) {
367 23
            return $this->getPluralNamespacedName($ownedEntityFqn, $subDirectories);
368
        }
369
370 7
        return $this->getSingularNamespacedName($ownedEntityFqn, $subDirectories);
371
    }
372
373
    /**
374
     * @param string $ownedEntityFqn
375
     * @param string $srcOrTestSubFolder
376
     * @param string $projectRootNamespace
377
     *
378
     * @return string
379
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
380
     */
381 23
    public function getReciprocatedHasName(
382
        string $ownedEntityFqn,
383
        string $srcOrTestSubFolder,
384
        string $projectRootNamespace
385
    ): string {
386 23
        $parsedFqn = $this->parseFullyQualifiedName(
387 23
            $ownedEntityFqn,
388 23
            $srcOrTestSubFolder,
389 23
            $projectRootNamespace
390
        );
391
392 23
        $subDirectories = $parsedFqn[2];
393
394 23
        return $this->getSingularNamespacedName($ownedEntityFqn, $subDirectories);
395
    }
396
397
    /**
398
     * @param string $entityFqn
399
     * @param array  $subDirectories
400
     *
401
     * @return string
402
     * @SuppressWarnings(PHPMD.StaticAccess)
403
     */
404 26
    public function getSingularNamespacedName(string $entityFqn, array $subDirectories): string
405
    {
406 26
        $singular = \ucfirst(MappingHelper::getSingularForFqn($entityFqn));
407
408 26
        return $this->getNamespacedName($singular, $subDirectories);
409
    }
410
411
    /**
412
     * @param string $entityFqn
413
     * @param array  $subDirectories
414
     *
415
     * @return string
416
     * @SuppressWarnings(PHPMD.StaticAccess)
417
     */
418 26
    public function getPluralNamespacedName(string $entityFqn, array $subDirectories): string
419
    {
420 26
        $plural = \ucfirst(MappingHelper::getPluralForFqn($entityFqn));
421
422 26
        return $this->getNamespacedName($plural, $subDirectories);
423
    }
424
425
    /**
426
     * @param string $entityName
427
     * @param array  $subDirectories
428
     *
429
     * @return string
430
     */
431 26
    public function getNamespacedName(string $entityName, array $subDirectories): string
432
    {
433 26
        $noEntitiesDirectory = \array_slice($subDirectories, 2);
434 26
        $namespacedName      = \array_merge($noEntitiesDirectory, [$entityName]);
435
436 26
        return \ucfirst(\implode('', $namespacedName));
437
    }
438
439
    /**
440
     * Read src autoloader from composer json
441
     *
442
     * @param string $dirForNamespace
443
     *
444
     * @return string
445
     * @throws DoctrineStaticMetaException
446
     * @SuppressWarnings(PHPMD.StaticAccess)
447
     */
448 105
    public function getProjectRootNamespaceFromComposerJson(
449
        string $dirForNamespace = 'src'
450
    ): string {
451
        try {
452 105
            $dirForNamespace = trim($dirForNamespace, '/');
453 105
            $json            = json_decode(
454 105
                file_get_contents(Config::getProjectRootDirectory().'/composer.json'),
455 105
                true
456
            );
457
            /**
458
             * @var string[][][][] $json
459
             */
460 105
            if (isset($json['autoload']['psr-4'])) {
461 105
                foreach ($json['autoload']['psr-4'] as $namespace => $dirs) {
462 105
                    foreach ($dirs as $dir) {
463 105
                        $dir = trim($dir, '/');
464 105
                        if ($dir === $dirForNamespace) {
465 105
                            return $this->tidy(rtrim($namespace, '\\'));
466
                        }
467
                    }
468
                }
469
            }
470
        } catch (\Exception $e) {
471
            throw new DoctrineStaticMetaException('Exception in '.__METHOD__.': '.$e->getMessage(), $e->getCode(), $e);
472
        }
473
        throw new DoctrineStaticMetaException('Failed to find psr-4 namespace root');
474
    }
475
476
    /**
477
     * From the fully qualified name, parse out:
478
     *  - class name,
479
     *  - namespace
480
     *  - the namespace parts not including the project root namespace
481
     *
482
     * @param string $fqn
483
     *
484
     * @param string $srcOrTestSubFolder
485
     *
486
     * @param string $projectRootNamespace
487
     *
488
     * @return array [$className,$namespace,$subDirectories]
489
     * @throws DoctrineStaticMetaException
490
     */
491 104
    public function parseFullyQualifiedName(
492
        string $fqn,
493
        string $srcOrTestSubFolder,
494
        string $projectRootNamespace = null
495
    ): array {
496
        try {
497 104
            $fqn                  = $this->root($fqn);
498 104
            $projectRootNamespace = $this->root($projectRootNamespace);
0 ignored issues
show
Bug introduced by
It seems like $projectRootNamespace can also be of type null; however, parameter $namespace of EdmondsCommerce\Doctrine...NamespaceHelper::root() does only seem to accept string, 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

498
            $projectRootNamespace = $this->root(/** @scrutinizer ignore-type */ $projectRootNamespace);
Loading history...
499 104
            if (null === $projectRootNamespace) {
0 ignored issues
show
introduced by
The condition null === $projectRootNamespace is always false.
Loading history...
500
                $projectRootNamespace = $this->getProjectRootNamespaceFromComposerJson($srcOrTestSubFolder);
501
            }
502 104
            if (false === \strpos($fqn, $projectRootNamespace)) {
503
                throw new DoctrineStaticMetaException(
504
                    'The $fqn ['.$fqn.'] does not contain the project root namespace'
505
                    .' ['.$projectRootNamespace.'] - are you sure it is the correct FQN?'
506
                );
507
            }
508 104
            $fqnParts       = explode('\\', $fqn);
509 104
            $className      = array_pop($fqnParts);
510 104
            $namespace      = implode('\\', $fqnParts);
511 104
            $rootParts      = explode('\\', $projectRootNamespace);
512 104
            $subDirectories = [];
513 104
            foreach ($fqnParts as $k => $fqnPart) {
514 104
                if (isset($rootParts[$k]) && $rootParts[$k] === $fqnPart) {
515 104
                    continue;
516
                }
517 104
                $subDirectories[] = $fqnPart;
518
            }
519 104
            array_unshift($subDirectories, $srcOrTestSubFolder);
520
521
            return [
522 104
                $className,
523 104
                $this->root($namespace),
524 104
                $subDirectories,
525
            ];
526
        } catch (\Exception $e) {
527
            throw new DoctrineStaticMetaException('Exception in '.__METHOD__.': '.$e->getMessage(), $e->getCode(), $e);
528
        }
529
    }
530
531
    /**
532
     * Get the Namespace root for Entity Relations
533
     *
534
     * @param string $projectRootNamespace
535
     * @param array  $subDirectories
536
     *
537
     * @return string
538
     */
539 23
    public function getOwningRelationsRootFqn(
540
        string $projectRootNamespace,
541
        array $subDirectories
542
    ): string {
543
        $relationsRootFqn = $projectRootNamespace
544 23
                            .AbstractGenerator::ENTITY_RELATIONS_NAMESPACE.'\\';
545 23
        if (count($subDirectories) > 0) {
546 23
            $relationsRootFqn .= implode('\\', $subDirectories).'\\';
547
        }
548
549 23
        return $this->tidy($relationsRootFqn);
550
    }
551
552
    /**
553
     * Normalise a has type, removing prefixes that are not required
554
     *
555
     * Inverse hasTypes use the standard template without the prefix
556
     * The exclusion ot this are the ManyToMany and OneToOne relations
557
     *
558
     * @param string $hasType
559
     *
560
     * @return string
561
     */
562 23
    public function stripPrefixFromHasType(
563
        string $hasType
564
    ): string {
565
        foreach ([
566 23
                     RelationsGenerator::INTERNAL_TYPE_MANY_TO_MANY,
567
                     RelationsGenerator::INTERNAL_TYPE_ONE_TO_ONE,
568
                 ] as $noStrip) {
569 23
            if (false !== strpos($hasType, $noStrip)) {
570 23
                return $hasType;
571
            }
572
        }
573
574
        foreach ([
575 6
                     RelationsGenerator::INTERNAL_TYPE_ONE_TO_MANY,
576
                     RelationsGenerator::INTERNAL_TYPE_MANY_TO_ONE,
577
                 ] as $stripAll) {
578 6
            if (false !== strpos($hasType, $stripAll)) {
579 6
                return str_replace(
580
                    [
581 6
                        RelationsGenerator::PREFIX_OWNING,
582
                        RelationsGenerator::PREFIX_INVERSE,
583
                    ],
584 6
                    '',
585 6
                    $hasType
586
                );
587
            }
588
        }
589
590
        return str_replace(
591
            [
592
                RelationsGenerator::PREFIX_INVERSE,
593
            ],
594
            '',
595
            $hasType
596
        );
597
    }
598
599
    /**
600
     * Get the Fully Qualified Namespace for the Relation Interface for a specific Entity and hasType
601
     *
602
     * @param string      $hasType
603
     * @param string      $ownedEntityFqn
604
     * @param string|null $projectRootNamespace
605
     * @param string      $srcFolder
606
     *
607
     * @return string
608
     * @throws DoctrineStaticMetaException
609
     */
610 23
    public function getOwningInterfaceFqn(
611
        string $hasType,
612
        string $ownedEntityFqn,
613
        string $projectRootNamespace = null,
614
        string $srcFolder = AbstractCommand::DEFAULT_SRC_SUBFOLDER
615
    ): string {
616
        try {
617 23
            $ownedHasName = $this->getOwnedHasName($hasType, $ownedEntityFqn, $srcFolder, $projectRootNamespace);
0 ignored issues
show
Bug introduced by
It seems like $projectRootNamespace can also be of type null; however, parameter $projectRootNamespace of EdmondsCommerce\Doctrine...lper::getOwnedHasName() does only seem to accept string, 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

617
            $ownedHasName = $this->getOwnedHasName($hasType, $ownedEntityFqn, $srcFolder, /** @scrutinizer ignore-type */ $projectRootNamespace);
Loading history...
618 23
            if (null === $projectRootNamespace) {
619
                $projectRootNamespace = $this->getProjectRootNamespaceFromComposerJson($srcFolder);
620
            }
621 23
            list($ownedClassName, , $ownedSubDirectories) = $this->parseFullyQualifiedName(
622 23
                $ownedEntityFqn,
623 23
                $srcFolder,
624 23
                $projectRootNamespace
625
            );
626 23
            $interfaceSubDirectories = \array_slice($ownedSubDirectories, 2);
627 23
            $owningInterfaceFqn      = $this->getOwningRelationsRootFqn(
628 23
                $projectRootNamespace,
629 23
                $interfaceSubDirectories
630
            );
631 23
            $owningInterfaceFqn      .= '\\'.$ownedClassName.'\\Interfaces\\Has'.$ownedHasName.'Interface';
632
633 23
            return $this->tidy($owningInterfaceFqn);
634
        } catch (\Exception $e) {
635
            throw new DoctrineStaticMetaException('Exception in '.__METHOD__.': '.$e->getMessage(), $e->getCode(), $e);
636
        }
637
    }
638
}
639