Completed
Push — master ( 0afa9f...d85d39 )
by Vitaly
03:05
created

ClassGenerator::code()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
cc 3
eloc 13
nc 3
nop 1
1
<?php declare(strict_types = 1);
2
/**
3
 * Created by Vitaly Iegorov <[email protected]>.
4
 * on 03.09.16 at 09:58
5
 */
6
namespace samsonphp\generator;
7
8
/**
9
 * Class generator class.
10
 *
11
 * @author Vitaly Egorov <[email protected]>
12
 */
13
class ClassGenerator extends AbstractGenerator
14
{
15
    /** OOP public visibility */
16
    const VISIBILITY_PUBLIC = 'public';
17
18
    /** OOP protected visibility */
19
    const VISIBILITY_PROTECTED = 'protected';
20
21
    /** OOP private visibility */
22
    const VISIBILITY_PRIVATE = 'private';
23
24
    /** @var string Class name */
25
    protected $className;
26
27
    /** @var string Class namespace */
28
    protected $namespace;
29
30
    /** @var array Collection of class uses */
31
    protected $uses;
32
33
    /** @var array Multiline class comment */
34
    protected $classComment;
35
36
    /** @var string Multiline file description */
37
    protected $fileDescription;
38
39
    /** @var array Class constants */
40
    protected $constants;
41
42
    /** @var array Class static properties */
43
    protected $staticProperties;
44
45
    /** @var array Class static methods */
46
    protected $staticMethods;
47
48
    /** @var array Class properties */
49
    protected $properties;
50
51
    /** @var array Class methods */
52
    protected $methods;
53
54
    /** @var bool Flag that class is abstract */
55
    protected $isAbstract;
56
57
    /** @var bool Flag that class is final */
58
    protected $isFinal;
59
60
    /**
61
     * ClassGenerator constructor.
62
     *
63
     * @param string           $className Class name
64
     * @param GenericGenerator $parent    Parent generator
65
     */
66
    public function __construct(string $className, GenericGenerator $parent = null)
67
    {
68
        $this->className = $className;
69
70
        parent::__construct($parent);
71
    }
72
73
    /**
74
     * Set class to be final.
75
     *
76
     * @return ClassGenerator
77
     */
78
    public function defFinal() : ClassGenerator
79
    {
80
        if ($this->isAbstract) {
81
            throw new \InvalidArgumentException('Class cannot be final as it is already abstract');
82
        }
83
84
        $this->isFinal = true;
85
86
        return $this;
87
    }
88
89
    /**
90
     * Set class to be abstract.
91
     *
92
     * @return ClassGenerator
93
     */
94
    public function defAbstract() : ClassGenerator
95
    {
96
        if ($this->isFinal) {
97
            throw new \InvalidArgumentException('Class cannot be abstract as it is already final');
98
        }
99
100
        $this->isAbstract = true;
101
102
        return $this;
103
    }
104
105
    /**
106
     * Set class file description.
107
     *
108
     * @param array $description Collection of class file description lines
109
     *
110
     * @return ClassGenerator
111
     */
112
    public function defDescription(array $description) : ClassGenerator
113
    {
114
        $commentsGenerator = new CommentsGenerator($this);
115
        foreach ($description as $line) {
116
            $commentsGenerator->defLine($line);
117
        }
118
119
        $this->fileDescription = $commentsGenerator->code();
120
121
        return $this;
122
    }
123
124
    /**
125
     * Set class namespace.
126
     *
127
     * @param string $namespace
128
     *
129
     * @return ClassGenerator
130
     */
131
    public function defNamespace(string $namespace) : ClassGenerator
132
    {
133
        $this->namespace = $namespace;
134
135
        return $this;
136
    }
137
138
    /**
139
     * Set class use.
140
     *
141
     * @param string $use
142
     *
143
     * @return ClassGenerator
144
     */
145
    public function defUse(string $use) : ClassGenerator
146
    {
147
        $this->uses[] = $use;
148
149
        return $this;
150
    }
151
152
    /**
153
     * Set protected class property.
154
     *
155
     * @param string $name Property name
156
     * @param mixed $value Property value
157
     *
158
     * @return PropertyGenerator
159
     */
160
    public function defProtectedProperty(string $name, $value) : PropertyGenerator
161
    {
162
        return $this->defProperty($name, $value)->defProtected();
163
    }
164
165
    /**
166
     * Set class property.
167
     *
168
     * @param string $name Property name
169
     * @param mixed $value Property value
170
     *
171
     * @return PropertyGenerator
172
     */
173
    public function defProperty(string $name, $value) : PropertyGenerator
174
    {
175
        return new PropertyGenerator($name, $value, $this);
176
    }
177
178
    /**
179
     * Set protected static class property.
180
     *
181
     * @param string $name Property name
182
     * @param mixed $value Property value
183
     *
184
     * @return PropertyGenerator
185
     */
186
    public function defProtectedStaticProperty(string $name, $value) : PropertyGenerator
187
    {
188
        return $this->defStaticProperty($name, $value)->defProtected();
189
    }
190
191
    /**
192
     * Set static class property.
193
     *
194
     * @param string $name Property name
195
     * @param mixed $value Property value
196
     *
197
     * @return PropertyGenerator
198
     */
199
    public function defStaticProperty(string $name, $value) : PropertyGenerator
200
    {
201
        return $this->defProperty($name, $value)->defStatic();
202
    }
203
204
    /**
205
     * {@inheritdoc}
206
     * @throws \InvalidArgumentException
207
     */
208
    public function code(int $indentation = 0) : string
209
    {
210
        if ($this->namespace === null) {
211
            throw new \InvalidArgumentException('Class namespace should be defined');
212
        }
213
214
        $formattedCode = [
215
            'namespace ' . $this->namespace . ';',
216
            '', // One empty line after namespace
217
            $this->buildDefinition(),
218
            '{'
219
        ];
220
221
        // Prepend file description if present
222
        if ($this->fileDescription !== null) {
223
            array_unshift($formattedCode, $this->fileDescription);
224
        }
225
226
        $formattedCode[] = '}';
227
228
        $this->generatedCode .= implode("\n" . $this->indentation($indentation), $formattedCode);
229
230
        return $this->generatedCode;
231
    }
232
233
    /**
234
     * Build function definition.
235
     *
236
     * @return string Function definition
237
     */
238
    protected function buildDefinition()
239
    {
240
        return ($this->isFinal ? 'final ' : '') .
241
        ($this->isAbstract ? 'abstract ' : '') .
242
        'class ' .
243
        $this->className;
244
    }
245
}
246