Passed
Push — master ( 5545f1...83deac )
by Kirill
03:22
created

ClassDeclaration::constant()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Reactor;
13
14
use Doctrine\Inflector\Rules\English\InflectorFactory;
15
use Spiral\Reactor\Aggregator\Constants;
16
use Spiral\Reactor\Aggregator\Methods;
17
use Spiral\Reactor\Aggregator\Properties;
18
use Spiral\Reactor\Exception\ReactorException;
19
use Spiral\Reactor\Partial\Constant;
20
use Spiral\Reactor\Partial\Method;
21
use Spiral\Reactor\Partial\Property;
22
use Spiral\Reactor\Traits\CommentTrait;
23
use Spiral\Reactor\Traits\NamedTrait;
24
25
/**
26
 * Class declaration.
27
 */
28
class ClassDeclaration extends AbstractDeclaration implements ReplaceableInterface, NamedInterface
29
{
30
    use NamedTrait;
31
    use CommentTrait;
32
33
    /** @var string */
34
    private $extends = '';
35
36
    /** @var array */
37
    private $interfaces = [];
38
39
    /** @var array */
40
    private $traits = [];
41
42
    /** @var Constants */
43
    private $constants;
44
45
    /** @var Properties */
46
    private $properties;
47
48
    /** @var Methods */
49
    private $methods;
50
51
    /**
52
     * @param string $name
53
     * @param string $extends
54
     * @param array $interfaces
55
     * @param string $comment
56
     *
57
     * @throws ReactorException When name is invalid.
58
     */
59
    public function __construct(
60
        string $name,
61
        string $extends = '',
62
        array $interfaces = [],
63
        string $comment = ''
64
    ) {
65
        $this->setName($name);
66
67
        if (! empty($extends)) {
68
            $this->setExtends($extends);
69
        }
70
71
        $this->setInterfaces($interfaces);
72
        $this->initComment($comment);
73
74
        $this->constants = new Constants([]);
75
        $this->properties = new Properties([]);
76
        $this->methods = new Methods([]);
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function setName(string $name): ClassDeclaration
83
    {
84
        $this->name = (new InflectorFactory())->build()->classify($name);
85
86
        return $this;
87
    }
88
89
    /**
90
     * @return string
91
     */
92
    public function getExtends(): string
93
    {
94
        return $this->extends;
95
    }
96
97
    /**
98
     * @param string $class Class name.
99
     * @return self
100
     */
101
    public function setExtends($class): ClassDeclaration
102
    {
103
        $this->extends = ltrim($class, '\\');
104
105
        return $this;
106
    }
107
108
    /**
109
     * @param string $interface
110
     * @return bool
111
     */
112
    public function hasInterface(string $interface): bool
113
    {
114
        $interface = ltrim($interface, '\\');
115
116
        return isset($this->interfaces[$interface]);
117
    }
118
119
    /**
120
     * @param string $interface
121
     * @return self
122
     */
123
    public function addInterface(string $interface): ClassDeclaration
124
    {
125
        $this->interfaces[ltrim($interface, '\\')] = true;
126
127
        return $this;
128
    }
129
130
    /**
131
     * @param string $interface
132
     * @return self
133
     */
134
    public function removeInterface(string $interface): ClassDeclaration
135
    {
136
        unset($this->interfaces[ltrim($interface, '\\')]);
137
138
        return $this;
139
    }
140
141
    /**
142
     * Declared interfaces.
143
     *
144
     * @return array
145
     */
146
    public function getInterfaces(): array
147
    {
148
        return array_keys($this->interfaces);
149
    }
150
151
    /**
152
     * Declare class interfaces.
153
     *
154
     * @param array $interfaces
155
     * @return self
156
     */
157
    public function setInterfaces(array $interfaces): ClassDeclaration
158
    {
159
        $this->interfaces = [];
160
        foreach ($interfaces as $interface) {
161
            $this->addInterface($interface);
162
        }
163
164
        return $this;
165
    }
166
167
    /**
168
     * @param string $class
169
     * @return bool
170
     */
171
    public function hasTrait(string $class): bool
172
    {
173
        $class = ltrim($class, '\\');
174
175
        return isset($this->traits[$class]);
176
    }
177
178
    /**
179
     * @param string $class
180
     * @return self
181
     */
182
    public function removeTrait(string $class): ClassDeclaration
183
    {
184
        unset($this->traits[ltrim($class, '\\')]);
185
186
        return $this;
187
    }
188
189
    /**
190
     * @return array
191
     */
192
    public function getTraits(): array
193
    {
194
        return array_keys($this->traits);
195
    }
196
197
    /**
198
     * Declare class traits.
199
     *
200
     * @param array $traits
201
     * @return self
202
     */
203
    public function setTraits(array $traits): ClassDeclaration
204
    {
205
        $this->traits = [];
206
        foreach ($traits as $trait) {
207
            $this->addTrait($trait);
208
        }
209
210
        return $this;
211
    }
212
213
    /**
214
     * @param string $class
215
     * @return self
216
     */
217
    public function addTrait(string $class): ClassDeclaration
218
    {
219
        $this->traits[ltrim($class, '\\')] = true;
220
221
        return $this;
222
    }
223
224
    /**
225
     * @return Constants|Constant[]
226
     */
227
    public function getConstants(): Constants
228
    {
229
        return $this->constants;
230
    }
231
232
    /**
233
     * @param string $name
234
     * @return Constant
235
     */
236
    public function constant(string $name): Constant
237
    {
238
        return $this->constants->get($name);
239
    }
240
241
    /**
242
     * @return Properties|Property[]
243
     */
244
    public function getProperties(): Properties
245
    {
246
        return $this->properties;
247
    }
248
249
    /**
250
     * @param string $name
251
     * @return Property
252
     */
253
    public function property(string $name): Property
254
    {
255
        return $this->properties->get($name);
256
    }
257
258
    /**
259
     * @return Methods|Method[]
260
     */
261
    public function getMethods(): Methods
262
    {
263
        return $this->methods;
264
    }
265
266
    /**
267
     * @param string $name
268
     * @return Method
269
     */
270
    public function method(string $name): Method
271
    {
272
        return $this->methods->get($name);
273
    }
274
275
    /**
276
     * {@inheritdoc}
277
     * @return self
278
     */
279
    public function replace($search, $replace): ClassDeclaration
280
    {
281
        $this->constants->replace($search, $replace);
282
        $this->properties->replace($search, $replace);
283
        $this->methods->replace($search, $replace);
284
285
        return $this;
286
    }
287
288
    /**
289
     * @param int $indentLevel
290
     * @return string
291
     */
292
    public function render(int $indentLevel = 0): string
293
    {
294
        $result = '';
295
296
        if (! $this->docComment->isEmpty()) {
297
            $result .= $this->docComment->render($indentLevel) . "\n";
298
        }
299
300
        //Class header
301
        $header = "class {$this->getName()}";
302
303
        //Rendering extends
304
        if (! empty($this->extends)) {
305
            $header .= " extends {$this->extends}";
306
        }
307
308
        if (! empty($this->interfaces)) {
309
            $interfaces = implode(', ', array_keys($this->interfaces));
310
            $header .= " implements {$interfaces}";
311
        }
312
313
        $result .= $this->addIndent($header, $indentLevel) . "\n";
314
        $result .= $this->addIndent('{', $indentLevel) . "\n";
315
316
        //Rendering class body
317
        $result .= $this->renderBody($indentLevel);
318
319
        $result = rtrim($result, "\n") . "\n";
320
        $result .= $this->addIndent('}', $indentLevel);
321
322
        return $result;
323
    }
324
325
    /**
326
     * @param int $indentLevel
327
     * @return string
328
     */
329
    protected function renderBody(int $indentLevel): string
330
    {
331
        $result = '';
332
        if (! empty($this->traits)) {
333
            $result .= $this->renderTraits($indentLevel + 1) . "\n\n";
334
        }
335
336
        if (! $this->constants->isEmpty()) {
337
            $result .= $this->constants->render($indentLevel + 1) . "\n\n";
338
        }
339
340
        if (! $this->properties->isEmpty()) {
341
            $result .= $this->properties->render($indentLevel + 1) . "\n\n";
342
        }
343
344
        if (! $this->methods->isEmpty()) {
345
            $result .= $this->methods->render($indentLevel + 1) . "\n\n";
346
        }
347
348
        return $result;
349
    }
350
351
    /**
352
     * @param int $indentLevel
353
     * @return string
354
     */
355
    private function renderTraits(int $indentLevel = 0): string
356
    {
357
        $lines = [];
358
        foreach ($this->traits as $class => $options) {
359
            $lines[] = $this->addIndent("use {$class};", $indentLevel);
360
        }
361
362
        return implode("\n", $lines);
363
    }
364
}
365