Passed
Push — main ( b1fbff...0e72dc )
by Johny
02:35
created

ExtensionsDocs::getExtensions()   C

Complexity

Conditions 15
Paths 65

Size

Total Lines 84
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 46
dl 0
loc 84
c 0
b 0
f 0
rs 5.9166
cc 15
nc 65
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Script;
6
7
use DummyGenerator\Container\DefinitionContainer;
8
use DummyGenerator\Container\DefinitionContainerBuilder;
9
use DummyGenerator\Container\DefinitionContainerInterface;
10
use DummyGenerator\DefinitionPack\DefinitionPack;
11
use DummyGenerator\Definitions\Extension\ExtensionInterface;
12
use DummyGenerator\DummyGenerator;
13
14
class ExtensionsDocs
15
{
16
    private bool $withDetails = false;
17
    private DefinitionContainerInterface $definitionContainer;
18
19
    public function __construct(?DefinitionContainer $definitionContainer = null)
20
    {
21
        if ($definitionContainer === null) {
22
            $this->definitionContainer = DefinitionContainerBuilder::all();
23
        }
24
    }
25
26
    public function withDetails(): self
27
    {
28
        $this->withDetails = true;
29
30
        return $this;
31
    }
32
33
    /**
34
     * @return array<string, array<string, string>>
35
     */
36
    public function getExtensions(): array
37
    {
38
        $generator = new DummyGenerator($this->definitionContainer);
39
        $definitions = $this->getDefinitions();
40
41
        $extensions = [];
42
        $errors = [];
43
44
        foreach ($definitions as $id => $extension) {
45
            if (!$this->definitionContainer->has($id)) {
46
                continue;
47
            }
48
49
            $extensionClass = $this->definitionContainer->get($id);
50
51
            if (!$extensionClass instanceof ExtensionInterface) {
52
                continue;
53
            }
54
55
            $extensions[$id] = [];
56
            $refl = new \ReflectionObject($extensionClass);
57
58
            foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflmethod) {
59
                $methodName = $reflmethod->name;
60
61
                if ($reflmethod->isConstructor() || str_starts_with($methodName, 'with')) {
62
                    continue;
63
                }
64
                $parameters = [];
65
66
                foreach ($reflmethod->getParameters() as $reflparameter) {
67
                    $parameter = [];
68
                    $parameter['name'] = '$' . $reflparameter->getName();
69
                    $parameter['type'] = $this->getTypes($reflparameter->getType());
70
71
72
                    if ($reflparameter->isDefaultValueAvailable()) {
73
                        $parameter['default'] = $reflparameter->getDefaultValue();
74
                    }
75
76
                    $parameters[] = $parameter;
77
                }
78
79
                $parametersJoined = [];
80
81
                foreach ($parameters as $parameter) {
82
                    if ($this->withDetails && !empty($parameter['type'])) {
83
                        $parametersString = $parameter['type'] . ' ' . $parameter['name'];
84
                    } else {
85
                        $parametersString = $parameter['name'];
86
                    }
87
88
                    if (!empty($parameter['default'])) {
89
                        $parametersString .= ' = ' . $parameter['default'];
90
                    }
91
92
                    $parametersJoined[] = $parametersString;
93
                }
94
95
                $parametersString = implode(', ', $parametersJoined);
96
97
                try {
98
                    $example = $generator->$methodName();
99
                } catch (\Throwable $e) {
100
                    $errors[$methodName] = $e->getMessage();
101
                    $example = '';
102
                }
103
104
                $example = $this->formatExample($example);
105
                $returnTypes = $this->getTypes($reflmethod->getReturnType());
106
107
                if ($this->withDetails) {
108
                    $extensions[$id][$methodName . ' (' . $parametersString . ')'] = '(' . $returnTypes . ') ' . $example;
109
                } else {
110
                    $extensions[$id][$methodName . '(' . $parametersString . ')'] = $example;
111
                }
112
            }
113
        }
114
115
        // it might be easier to go with this, instead of returning
116
        // file_put_contents('docs_result_'.uniqid('', true).'.txt', print_r($extensions, true));
117
        // var_export($errors);
118
119
        return $extensions;
120
    }
121
122
    /**
123
     * @return array<string, class-string<ExtensionInterface>>
124
     */
125
    private function getDefinitions(): array
126
    {
127
        $definitions = [];
128
        $definitionPack = new DefinitionPack();
129
        $definitions = array_merge($definitions, $definitionPack->baseExtensions());
130
        $definitions = array_merge($definitions, $definitionPack->defaultExtensions());
131
        $definitions = array_merge($definitions, $definitionPack->complementaryExtensions());
132
133
        return $definitions;
134
    }
135
136
    private function getTypes(?\ReflectionType $type): string
137
    {
138
        $result = null;
139
140
        if ($type instanceof \ReflectionNamedType) {
141
            return $type->getName();
142
        }
143
144
        $multiple = [];
145
146
        if ($type instanceof \ReflectionUnionType || $type instanceof \ReflectionIntersectionType) {
147
            foreach ($type->getTypes() as $item) {
148
                $multiple[] = $this->getTypes($item);
149
            }
150
            $result = implode('|', $multiple);
151
        }
152
153
        return $result ?? 'mixed';
154
    }
155
156
    private function formatExample(mixed $example): string
157
    {
158
        if (is_array($example)) {
159
            $result = "['" . implode("', '", $example) . "']";
160
        } elseif ($example instanceof \DateTimeInterface) {
161
            $result = "DateTimeImmutable('" . $example->format('Y-m-d H:i:s') . "')";
162
        } else {
163
            $result = var_export($example, true);
164
        }
165
166
        return $result;
167
    }
168
}
169