Passed
Push — master ( 04ad09...373749 )
by Francis
02:25
created

PhpDocBuilder::build()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 18
rs 9.9666
cc 4
nc 4
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Prometee\SwaggerClientBuilder\PhpBuilder\PhpDoc;
6
7
class PhpDocBuilder implements PhpDocBuilderInterface
8
{
9
    /** @var array */
10
    protected $lines = [];
11
    /** @var int */
12
    protected $wrapOn = 100;
13
14
    /**
15
     * {@inheritDoc}
16
     */
17
    public function configure(array $lines = [], int $wrapOn = 100)
18
    {
19
        $this->lines = $lines;
20
        $this->wrapOn = $wrapOn;
21
    }
22
23
    /**
24
     * {@inheritDoc}
25
     */
26
    public function addLine(string $line, string $type = ''): void
27
    {
28
        if (!isset($this->lines[$type])) {
29
            $this->lines[$type] = [];
30
        }
31
        foreach (explode("\n", $line) as $l) {
32
            $this->lines[$type][] = $l;
33
        }
34
    }
35
36
    /**
37
     * {@inheritDoc}
38
     */
39
    public function addDescriptionLine(string $line): void
40
    {
41
        $this->addLine($line, static::TYPE_DESCRIPTION);
42
    }
43
44
    /**
45
     * {@inheritDoc}
46
     */
47
    public function addEmptyLine(): void
48
    {
49
        $this->addDescriptionLine('');
50
    }
51
52
    /**
53
     * {@inheritDoc}
54
     */
55
    public function addVarLine(?string $line): void
56
    {
57
        $this->addLine($line, static::TYPE_VAR);
0 ignored issues
show
Bug introduced by
It seems like $line can also be of type null; however, parameter $line of Prometee\SwaggerClientBu...hpDocBuilder::addLine() 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

57
        $this->addLine(/** @scrutinizer ignore-type */ $line, static::TYPE_VAR);
Loading history...
58
    }
59
60
    /**
61
     * {@inheritDoc}
62
     */
63
    public function addParamLine(string $name, string $type = '', string $description = ''): void
64
    {
65
        $this->addLine(
66
            (empty($type) ? '' : $type . ' ') . $name . (empty($description) ? '' : ' ' . $description),
67
            static::TYPE_PARAM
68
        );
69
    }
70
71
    /**
72
     * {@inheritDoc}
73
     */
74
    public function addReturnLine(?string $line): void
75
    {
76
        $this->addLine($line, static::TYPE_RETURN);
0 ignored issues
show
Bug introduced by
It seems like $line can also be of type null; however, parameter $line of Prometee\SwaggerClientBu...hpDocBuilder::addLine() 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

76
        $this->addLine(/** @scrutinizer ignore-type */ $line, static::TYPE_RETURN);
Loading history...
77
    }
78
79
    /**
80
     * {@inheritDoc}
81
     */
82
    public function addThrowsLine(?string $line): void
83
    {
84
        $this->addLine($line, static::TYPE_THROWS);
0 ignored issues
show
Bug introduced by
It seems like $line can also be of type null; however, parameter $line of Prometee\SwaggerClientBu...hpDocBuilder::addLine() 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

84
        $this->addLine(/** @scrutinizer ignore-type */ $line, static::TYPE_THROWS);
Loading history...
85
    }
86
87
    /**
88
     * {@inheritDoc}
89
     */
90
    public function hasSingleVarLine(): bool
91
    {
92
        return isset($this->lines[static::TYPE_VAR])
93
            && count($this->lines) === 1
94
            && count($this->lines[static::TYPE_VAR]) === 1;
95
    }
96
97
    /**
98
     * {@inheritDoc}
99
     */
100
    public function build(string $indent = null): ?string
101
    {
102
        $phpdocLines = $this->buildLines();
103
104
        if (empty($phpdocLines)) {
105
            return null;
106
        }
107
108
        if ($this->hasSingleVarLine()) {
109
            return sprintf('%1$s/** %3$s */%2$s', $indent, "\n", $phpdocLines[0]);
110
        }
111
112
        $lines = [];
113
        foreach ($phpdocLines as $phpdocLine) {
114
            $lines[] = sprintf('%s * %s', $indent,$phpdocLine);
115
        }
116
117
        return sprintf('%1$s/**%2$s%3$s%2$s%1$s */%2$s', $indent, "\n", implode("\n", $lines));
118
    }
119
120
    /**
121
     * {@inheritDoc}
122
     */
123
    public function buildLines(): array
124
    {
125
        $phpdocLines = [];
126
        $previousType = null;
127
        $this->orderLines();
128
        foreach ($this->lines as $type => $lines) {
129
            if ($previousType === null) {
130
                $previousType = $type;
131
            }
132
            if ($previousType !== $type) {
133
                $phpdocLines[] = '';
134
                $previousType = $type;
135
            }
136
            $this->buildTypedLines($type, $lines, $phpdocLines);
137
        }
138
        return $phpdocLines;
139
    }
140
141
    /**
142
     * {@inheritDoc}
143
     */
144
    public function buildTypedLines(string $type, array $lines, array &$phpdocLines): void
145
    {
146
        foreach ($lines as $line) {
147
            $lineSuffix = ($type === static::TYPE_DESCRIPTION ? '' : '@' . $type . ' ');
148
            foreach (static::wrapLines($lineSuffix . $line, $this->wrapOn) as $i => $l) {
149
                $phpdocLines[] = ($i > 0 ? str_repeat(' ', strlen($lineSuffix)) : '') . $l;
150
            }
151
        }
152
    }
153
154
    /**
155
     * {@inheritDoc}
156
     */
157
    public static function wrapLines(string $line, int $wrapOn = 100): array
158
    {
159
        $lines = [];
160
        $currentLine = '';
161
        foreach (explode(' ', $line) as $word) {
162
            if (iconv_strlen($currentLine . ' ' . $word) > $wrapOn) {
163
                $lines[] = $currentLine;
164
                $currentLine = $word;
165
            } else {
166
                $currentLine .= (!empty($currentLine) ? ' ' : '') . $word;
167
            }
168
        }
169
        $lines[] = $currentLine;
170
171
        return $lines;
172
    }
173
174
    /**
175
     * {@inheritDoc}
176
     */
177
    public static function getPossibleTypesFromTypeNames(array $types = []): string
178
    {
179
        if (empty($types)) {
180
            return '';
181
        }
182
        $typesFound = [];
183
184
        foreach ($types as $type) {
185
            if ($type === null) {
186
                continue;
187
            }
188
            if (preg_match('#^\?#', $type)) {
189
                $typesFound[] = 'null';
190
            }
191
            $typesFound[] = ltrim($type, '?');
192
        }
193
194
        $typesFound = array_unique($typesFound);
195
196
        return implode('|', $typesFound);
197
    }
198
199
    /**
200
     * {@inheritDoc}
201
     */
202
    public function setWrapOn(int $wrapOn): void
203
    {
204
        $this->wrapOn = $wrapOn;
205
    }
206
207
    /**
208
     * {@inheritDoc}
209
     */
210
    public function getWrapOn(): int
211
    {
212
        return $this->wrapOn;
213
    }
214
215
    /**
216
     * {@inheritDoc}
217
     */
218
    public function orderLines(): void
219
    {
220
        uksort($this->lines, function ($k1, $k2) {
221
            $o1 = array_search($k1, static::LINE_TYPE_ORDER);
222
            $o2 = array_search($k2, static::LINE_TYPE_ORDER);
223
224
            return $o1 - $o2;
225
        });
226
    }
227
}
228