Completed
Pull Request — master (#68)
by Cristiano
05:36
created

AbstractPhpStruct   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 328
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 8

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 37
lcom 3
cbo 8
dl 0
loc 328
ccs 96
cts 96
cp 1
rs 9.44
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
/*
3
 * Copyright 2011 Johannes M. Schmitt <[email protected]>
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
namespace gossi\codegen\model;
19
20
use gossi\codegen\model\parts\DocblockPart;
21
use gossi\codegen\model\parts\LongDescriptionPart;
22
use gossi\codegen\model\parts\QualifiedNamePart;
23
use gossi\docblock\Docblock;
24
use phootwork\collection\Map;
25
use phootwork\collection\Set;
26
27
/**
28
 * Represents an abstract php structure (class, trait or interface).
29
 *
30
 * @author Johannes M. Schmitt <[email protected]>
31
 * @author Thomas Gossmann
32
 */
33
abstract class AbstractPhpStruct extends AbstractModel implements NamespaceInterface, DocblockInterface {
34
	use DocblockPart;
35
	use LongDescriptionPart;
36
	use QualifiedNamePart;
37
38
	/** @var Map */
39
	private Map $useStatements;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
40
41
	/** @var Set */
42
	private Set $requiredFiles;
43
44
	/** @var Map */
45
	private Map $methods;
46
47
	/**
48
	 * Creates a new struct
49
	 *
50
	 * @param string $name the fqcn
51
	 *
52
	 * @return static
53
	 */
54
	public static function create(string $name = ''): self {
55 13
		return new static($name);
56 13
	}
57
58
	/**
59
	 * Creates a new struct
60
	 *
61
	 * @param string $name the fqcn
62
	 */
63
	public function __construct(string $name = '') {
64 56
		$this->setQualifiedName($name);
65 56
		$this->docblock = new Docblock();
66 56
		$this->useStatements = new Map();
67 56
		$this->requiredFiles = new Set();
68 56
		$this->methods = new Map();
69 56
	}
70 56
71
	/**
72
	 * Sets requried files
73
	 *
74
	 * @param array|Set $files
75
	 *
76
	 * @return $this
77
	 */
78 1
	public function setRequiredFiles(array|Set $files): self {
79 1
		$this->requiredFiles = is_array($files) ? new Set($files) : $files;
80
81 1
		return $this;
82
	}
83
84
	/**
85
	 * Adds a new required file
86
	 *
87
	 * @param string $file
88
	 *
89
	 * @return $this
90 2
	 */
91 2
	public function addRequiredFile(string $file): self {
92
		$this->requiredFiles->add($file);
93 2
94
		return $this;
95
	}
96
97
	/**
98
	 * Returns required files
99
	 *
100
	 * @return Set collection of filenames
101 17
	 */
102 17
	public function getRequiredFiles(): Set {
103
		return $this->requiredFiles;
104
	}
105
106
	/**
107
	 * Sets use statements
108
	 *
109
	 * @see #addUseStatement
110
	 * @see #declareUses()
111
	 *
112
	 * @param array $useStatements
113 1
	 *
114 1
	 * @return $this
115 1
	 */
116 1
	public function setUseStatements(array $useStatements): self {
117
		$this->useStatements->clear();
118
		foreach ($useStatements as $alias => $useStatement) {
119 1
			$this->addUseStatement($useStatement, $alias);
120
		}
121
122
		return $this;
123
	}
124
125
	/**
126
	 * Adds a use statement with an optional alias
127
	 *
128
	 * @param string $qualifiedName
129 5
	 * @param string $alias
130 5
	 *
131 4
	 * @return $this
132 2
	 */
133
	public function addUseStatement(string $qualifiedName, string $alias = ''): self {
134 4
		if ($alias === '') {
135
			$alias = str_contains($qualifiedName, '\\') ?
136
				substr($qualifiedName, strrpos($qualifiedName, '\\') + 1) : $qualifiedName;
137
		}
138 5
139
		$this->useStatements->set($alias, $qualifiedName);
140 5
141
		return $this;
142
	}
143
144
	/**
145
	 * Clears all use statements
146
	 *
147
	 * @return $this
148 1
	 */
149 1
	public function clearUseStatements(): self {
150
		$this->useStatements->clear();
151 1
152
		return $this;
153
	}
154
155
	/**
156
	 * Declares multiple use statements at once.
157
	 *
158
	 * @param string ...$uses use statements multiple qualified names
159
	 *
160 1
	 * @return $this
161 1
	 */
162 1
	public function declareUses(string ...$uses): self {
163
		foreach ($uses as $name) {
164 1
			$this->declareUse($name);
165
		}
166
167
		return $this;
168
	}
169
170
	/**
171
	 * Declares a "use $fullClassName" with " as $alias" if $alias is available,
172
	 * and returns its alias (or not qualified classname) to be used in your actual
173
	 * php code.
174
	 *
175
	 * If the class has already been declared you get only the set alias.
176
	 *
177
	 * @param string $qualifiedName
178 1
	 * @param string $alias
179 1
	 *
180 1
	 * @return string the used alias
181 1
	 */
182
	public function declareUse(string $qualifiedName, string $alias = ''): string {
183 1
		$qualifiedName = trim($qualifiedName, '\\');
184
		if (!$this->hasUseStatement($qualifiedName)) {
185
			$this->addUseStatement($qualifiedName, $alias);
186
		}
187
188
		return $this->getUseAlias($qualifiedName);
189
	}
190
191
	/**
192 3
	 * Returns whether the given use statement is present
193 3
	 *
194
	 * @param string $qualifiedName
195
	 *
196
	 * @return bool
197
	 */
198
	public function hasUseStatement(string $qualifiedName): bool {
199
		return $this->useStatements->contains($qualifiedName);
200
	}
201
202 1
	public function hasUseStatementsToRender(): bool {
203 1
		if ($this->useStatements->isEmpty()) {
204
			return false;
205
		}
206
207
		return $this->useStatements->search(
208
			fn (string $stmt) => str_contains($stmt, '\\') || $this->getNamespace() !== ''
209
		);
210
	}
211
212 3
	/**
213 3
	 * Returns the usable alias for a qualified name
214 3
	 *
215
	 * @param string $qualifiedName
216
	 *
217
	 * @return string the alias
218
	 */
219
	public function getUseAlias(string $qualifiedName): string {
220
		return $this->useStatements->getKey($qualifiedName) ?? '';
221
	}
222 17
223 17
	/**
224
	 * Removes a use statement
225
	 *
226
	 * @param string $qualifiedName
227
	 *
228
	 * @return $this
229
	 */
230
	public function removeUseStatement(string $qualifiedName): self {
231
		if ($this->useStatements->contains($qualifiedName)) {
232 1
			$this->useStatements->remove($this->useStatements->getKey($qualifiedName));
233 1
		}
234 1
235
		return $this;
236
	}
237 1
238 1
	/**
239 1
	 * Returns all use statements
240
	 *
241
	 * @return Map collection of use statements
242 1
	 */
243
	public function getUseStatements(): Map {
244
		return $this->useStatements;
245
	}
246
247
	/**
248
	 * Sets a collection of methods
249
	 *
250
	 * @param PhpMethod[] $methods
251 15
	 *
252 15
	 * @return $this
253 15
	 */
254
	public function setMethods(array $methods): self {
255 15
		$this->clearMethods();
256
		foreach ($methods as $method) {
257
			$this->setMethod($method);
258
		}
259
260
		return $this;
261
	}
262
263
	/**
264
	 * Adds a method
265 2
	 *
266 2
	 * @param PhpMethod $method
267 1
	 *
268
	 * @return $this
269
	 */
270 2
	public function setMethod(PhpMethod $method): self {
271 1
		$method->setParent($this);
272
		$this->methods->set($method->getName(), $method);
273 1
274 1
		return $this;
275 1
	}
276
277 1
	/**
278
	 * Removes a method
279
	 *
280
	 * @param string|PhpMethod $nameOrMethod method name or Method instance
281
	 *
282
	 * @throws \InvalidArgumentException if the method cannot be found
283
	 *
284
	 * @return $this
285
	 */
286 2
	public function removeMethod(string|PhpMethod $nameOrMethod): self {
287 2
		$name = (string) $nameOrMethod;
288 1
289
		if (!$this->methods->has($name)) {
290
			throw new \InvalidArgumentException("The method `$name` does not exist.");
291 2
		}
292
		$m = $this->methods->get($name);
293
		$m->setParent(null);
294
		$this->methods->remove($name);
295
296
		return $this;
297
	}
298
299
	/**
300
	 * Checks whether a method exists or not
301 9
	 *
302 9
	 * @param string|PhpMethod $nameOrMethod method name or Method instance
303 1
	 *
304
	 * @return bool `true` if it exists and `false` if not
305
	 */
306 9
	public function hasMethod(string|PhpMethod $nameOrMethod): bool {
307 2
		return $this->methods->has((string) $nameOrMethod);
308
	}
309
310 8
	/**
311
	 * Returns a method
312
	 *
313
	 * @param string $name the methods name
314
	 *
315
	 * @throws \InvalidArgumentException if the method cannot be found
316
	 *
317
	 * @return PhpMethod
318 17
	 */
319 17
	public function getMethod(string $name): PhpMethod {
320
		if (!$this->methods->has($name)) {
321
			throw new \InvalidArgumentException("The method `$name` does not exist.");
322
		}
323
324
		return $this->methods->get($name);
325
	}
326
327 1
	/**
328 1
	 * Returns all methods
329
	 *
330
	 * @return Map collection of methods
331
	 */
332
	public function getMethods(): Map {
333
		return $this->methods;
334
	}
335
336 1
	/**
337 1
	 * Returns all method names
338 1
	 *
339
	 * @return Set
340 1
	 */
341
	public function getMethodNames(): Set {
342 1
		return $this->methods->keys();
343
	}
344
345
	/**
346
	 * Clears all methods
347
	 *
348
	 * @return $this
349
	 */
350 11
	public function clearMethods(): self {
351 11
		$this->methods->each(fn (string $key, PhpMethod $method) => $method->setParent(null));
352 11
		$this->methods->clear();
353 11
354
		return $this;
355 11
	}
356 7
357
	/**
358
	 * Generates a docblock from provided information
359 11
	 */
360
	public function generateDocblock(): void {
361
		$docblock = $this->getDocblock();
362
		$docblock->setShortDescription($this->getDescription());
363
		$docblock->setLongDescription($this->getLongDescription());
364
		$this->methods->each(fn (string $key, PhpMethod $method) => $method->generateDocblock());
365
	}
366
}
367