Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.86% covered (success)
92.86%
26 / 28
75.00% covered (warning)
75.00%
6 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
EntityNamespace
92.86% covered (success)
92.86%
26 / 28
75.00% covered (warning)
75.00%
6 / 8
18.12
0.00% covered (danger)
0.00%
0 / 1
 getRegularExpression
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 convert
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 toClass
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParentNamespace
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getChildNamespace
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toTestNamespace
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getClasses
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
4.05
 getMethods
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
7.05
1<?php
2namespace Apie\Common\ValueObjects;
3
4use Apie\Core\Attributes\Description;
5use Apie\Core\Lists\ReflectionClassList;
6use Apie\Core\Lists\ReflectionMethodList;
7use Apie\Core\ValueObjects\Interfaces\HasRegexValueObjectInterface;
8use Apie\Core\ValueObjects\Interfaces\StringValueObjectInterface;
9use Apie\Core\ValueObjects\IsStringWithRegexValueObject;
10use ReflectionClass;
11use ReflectionMethod;
12use Symfony\Component\Finder\Finder;
13
14/**
15 * Value object that represents a PHP class namespace.
16 *
17 * Example values:
18 * "Apie\Common\"
19 * "Symfony\Component\"
20 */
21#[Description('A PHP class namespace with trailing slash, for example: "Symfony\Component\\"')]
22final class EntityNamespace implements StringValueObjectInterface, HasRegexValueObjectInterface
23{
24    use IsStringWithRegexValueObject;
25
26    public static function getRegularExpression(): string
27    {
28        return '/^([A-Z][a-zA-Z0-9]*\\\\)+$/';
29    }
30
31    protected function convert(string $input): string
32    {
33        return str_ends_with($input, '\\') ? $input : ($input . '\\');
34    }
35
36    /**
37     * @return ReflectionClass<object>
38     */
39    public function toClass(string $className): ReflectionClass
40    {
41        return new ReflectionClass($this->internal . $className);
42    }
43
44    public function getParentNamespace(): self
45    {
46        $internal = explode('\\', rtrim($this->internal, '\\'));
47        array_pop($internal);
48        return new self(implode('\\', $internal));
49    }
50
51    public function getChildNamespace(string $childNamespace): self
52    {
53        return new self($this->internal . $childNamespace);
54    }
55
56    public function toTestNamespace(): self
57    {
58        $internal = explode('\\', rtrim($this->internal, '\\'));
59        $last = array_pop($internal);
60        array_push($internal, 'Tests', $last);
61        return new self(implode('\\', $internal));
62    }
63
64    /**
65     * Returns all classes found in $path assuming the namespace of this value object.
66     */
67    public function getClasses(string $path): ReflectionClassList
68    {
69        $classes = [];
70        if (!file_exists($path) || !is_dir($path)) {
71            return new ReflectionClassList([]);
72        }
73        foreach (Finder::create()->in($path)->files()->name('*.php')->depth('== 0') as $file) {
74            $classes[] = $this->toClass($file->getBasename('.php'));
75        }
76        sort($classes);
77        return new ReflectionClassList($classes);
78    }
79
80    /**
81     * Returns all non-magic methods found in $path assuming the namespace of this value object.
82     */
83    public function getMethods(string $path): ReflectionMethodList
84    {
85        $methods = [];
86        if (!file_exists($path) || !is_dir($path)) {
87            return new ReflectionMethodList([]);
88        }
89        foreach (Finder::create()->in($path)->files()->name('*.php')->depth('== 0') as $file) {
90            $class = $this->toClass($file->getBasename('.php'));
91            foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
92                if (strpos($method->name, '__') !== 0 || $method->name === '__invoke') {
93                    $methods[] = $method;
94                }
95            }
96        }
97        sort($methods);
98        return new ReflectionMethodList($methods);
99    }
100}