Completed
Pull Request — master (#67)
by
unknown
02:21
created

AbstractPhpStruct::create()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
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
declare(strict_types=1);
18
19
namespace gossi\codegen\model;
20
21
use gossi\codegen\model\parts\DocblockPart;
22
use gossi\codegen\model\parts\LongDescriptionPart;
23
use gossi\codegen\model\parts\QualifiedNamePart;
24
use gossi\codegen\utils\TypeUtils;
25
use gossi\docblock\Docblock;
26
use phootwork\collection\Map;
27
use phootwork\collection\Set;
28
29
/**
30
 * Represents an abstract php structure (class, trait or interface).
31
 *
32
 * @author Johannes M. Schmitt <[email protected]>
33
 * @author Thomas Gossmann
34
 */
35
abstract class AbstractPhpStruct extends AbstractModel implements NamespaceInterface, DocblockInterface {
36
37
	use DocblockPart;
38
	use LongDescriptionPart;
39
	use QualifiedNamePart;
40
41
	/** @var Map|string[] */
42
	private $useStatements;
43
44
	/** @var Set|string[] */
45
	private $requiredFiles;
46
47
	/** @var Map|PhpMethod[] */
48
	private $methods;
49
50
	/**
51
	 * Creates a new struct
52
	 *
53
	 * @param string $name the fqcn
54
	 * @return static
55
	 */
56 13
	public static function create(?string $name = null) {
57 13
		return new static($name);
58
	}
59
60
    public static function fromName(string $name): self
61
    {
62
        $ref = new \ReflectionClass($name);
63
64
        return static::fromFile($ref->getFileName());
65
    }
66
67
	/**
68
	 * Creates a new struct
69
	 *
70
	 * @param string $name the fqcn
71
	 */
72 57
	public function __construct(?string $name = null) {
73 57
		$this->setQualifiedName($name);
74 57
		$this->docblock = new Docblock();
75 57
		$this->useStatements = new Map();
76 57
		$this->requiredFiles = new Set();
77 57
		$this->methods = new Map();
78 57
	}
79
80
	/**
81
	 * Sets requried files
82
	 *
83
	 * @param array $files
84
	 * @return $this
85
	 */
86 1
	public function setRequiredFiles(array $files) {
87 1
		$this->requiredFiles = new Set($files);
88
89 1
		return $this;
90
	}
91
92
	/**
93
	 * Adds a new required file
94
	 *
95
	 * @param string $file
96
	 * @return $this
97
	 */
98 2
	public function addRequiredFile(string $file) {
99 2
		$this->requiredFiles->add($file);
100
101 2
		return $this;
102
	}
103
104
	/**
105
	 * Returns required files
106
	 *
107
	 * @return Set collection of filenames
108
	 */
109 17
	public function getRequiredFiles(): Set {
110 17
		return $this->requiredFiles;
111
	}
112
113
	/**
114
	 * Sets use statements
115
	 *
116
	 * @see #addUseStatement
117
	 * @see #declareUses()
118
	 * @param array $useStatements
119
	 * @return $this
120
	 */
121 1
	public function setUseStatements(array $useStatements) {
122 1
		$this->useStatements->clear();
123 1
		foreach ($useStatements as $alias => $useStatement) {
124 1
			$this->addUseStatement($useStatement, $alias);
125
		}
126
127 1
		return $this;
128
	}
129
130
	/**
131
	 * Adds a use statement with an optional alias
132
	 *
133
	 * @param string|PhpTypeInterface $qualifiedName
134
	 * @param null|string $alias
135
	 * @return $this
136
	 */
137 13
	public function addUseStatement($qualifiedName, string $alias = null) {
138 13
        if ($qualifiedName instanceof PhpTypeInterface) {
139 8
            $qualifiedName = $qualifiedName->getQualifiedName();
140
        }
141
142 13
        if (TypeUtils::isGlobalQualifiedName($qualifiedName) || TypeUtils::isNativeType($qualifiedName)) {
143 7
            return $this;
144
        }
145
146 7
	    if ($qualifiedName === $this->getNamespace()) {
147
	        return $this;
148
        }
149 7
		if (!is_string($alias)) {
150 6
			if (false === strpos($qualifiedName, '\\')) {
151 2
				$alias = $qualifiedName;
152
			} else {
153 6
				$alias = substr($qualifiedName, strrpos($qualifiedName, '\\') + 1);
154
			}
155
		}
156
157 7
		$this->useStatements->set($alias, $qualifiedName);
158
159 7
		return $this;
160
	}
161
162
	/**
163
	 * Clears all use statements
164
	 *
165
	 * @return $this
166
	 */
167 1
	public function clearUseStatements() {
168 1
		$this->useStatements->clear();
169
170 1
		return $this;
171
	}
172
173
	/**
174
	 * Declares multiple use statements at once.
175
	 *
176
	 * @param ... use statements multiple qualified names
177
	 * @return $this
178
	 */
179 1
	public function declareUses(string ...$uses) {
180 1
		foreach ($uses as $name) {
181 1
			$this->declareUse($name);
182
		}
183 1
		return $this;
184
	}
185
186
	/**
187
	 * Declares a "use $fullClassName" with " as $alias" if $alias is available,
188
	 * and returns its alias (or not qualified classname) to be used in your actual
189
	 * php code.
190
	 *
191
	 * If the class has already been declared you get only the set alias.
192
	 *
193
	 * @param string $qualifiedName
194
	 * @param null|string $alias
195
	 * @return string the used alias
196
	 */
197 1
	public function declareUse(string $qualifiedName, string $alias = null) {
198 1
		$qualifiedName = trim($qualifiedName, '\\');
199 1
		if (!$this->hasUseStatement($qualifiedName)) {
200 1
			$this->addUseStatement($qualifiedName, $alias);
201
		}
202 1
		return $this->getUseAlias($qualifiedName);
203
	}
204
205
	/**
206
	 * Returns whether the given use statement is present
207
	 *
208
	 * @param string $qualifiedName
209
	 * @return bool
210
	 */
211 3
	public function hasUseStatement(string $qualifiedName): bool {
212 3
		return $this->useStatements->contains($qualifiedName);
213
	}
214
215
	/**
216
	 * Returns the usable alias for a qualified name
217
	 *
218
	 * @param string $qualifiedName
219
	 * @return string the alias
220
	 */
221 1
	public function getUseAlias(string $qualifiedName): string {
222 1
		return $this->useStatements->getKey($qualifiedName);
223
	}
224
225
	/**
226
	 * Removes a use statement
227
	 *
228
	 * @param string $qualifiedName
229
	 * @return $this
230
	 */
231 3
	public function removeUseStatement(string $qualifiedName) {
232 3
		$this->useStatements->remove($this->useStatements->getKey($qualifiedName));
233 3
		return $this;
234
	}
235
236
	/**
237
	 * Returns all use statements
238
	 *
239
	 * @return Map collection of use statements
240
	 */
241 20
	public function getUseStatements(): Map {
242 20
		return $this->useStatements;
243
	}
244
245
	/**
246
	 * Sets a collection of methods
247
	 *
248
	 * @param PhpMethod[] $methods
249
	 * @return $this
250
	 */
251 1
	public function setMethods(array $methods) {
252 1
		foreach ($this->methods as $method) {
253 1
			$method->setParent(null);
254
		}
255
256 1
		$this->methods->clear();
257 1
		foreach ($methods as $method) {
258 1
			$this->addMethod($method);
259
		}
260
261 1
		return $this;
262
	}
263
264
	/**
265
	 * Adds a method
266
	 *
267
	 * @param PhpMethod $method
268
	 * @return $this
269
	 */
270 16
	public function addMethod(PhpMethod $method) {
271 16
		$method->setParent($this);
272 16
		$this->methods->set($method->getName(), $method);
273 16
		$types = $method->getTypes();
274 16
        if ($types) {
275 16
            foreach ($types as $type) {
276 4
                $this->addUseStatement($type);
277 4
                $method->addType($type);
278
            }
279
        }
280
281 16
        foreach ($method->getParameters() as $parameter) {
282 11
            $types = $parameter->getTypes();
283 11
            if ($types) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $types of type array<string|gossi\codeg...model\PhpTypeInterface> is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
284 11
                foreach ($types as $type) {
285 5
                    $this->addUseStatement($type);
286 5
                    $parameter->addType($type);
287
                }
288
            }
289
        }
290
291 16
        return $this;
292
	}
293
294
	/**
295
	 * Removes a method
296
	 *
297
	 * @param string|PhpMethod $nameOrMethod method name or Method instance
298
	 * @throws \InvalidArgumentException if the method cannot be found
299
	 * @return $this
300
	 */
301 2
	public function removeMethod($nameOrMethod) {
302 2
		if ($nameOrMethod instanceof PhpMethod) {
303 1
			$nameOrMethod = $nameOrMethod->getName();
304
		}
305
306 2
		if (!$this->methods->has($nameOrMethod)) {
307 1
			throw new \InvalidArgumentException(sprintf('The method "%s" does not exist.', $nameOrMethod));
308
		}
309 1
		$m = $this->methods->get($nameOrMethod);
310 1
		$m->setParent(null);
311 1
		$this->methods->remove($nameOrMethod);
312
313 1
		return $this;
314
	}
315
316
	/**
317
	 * Checks whether a method exists or not
318
	 *
319
	 * @param string|PhpMethod $nameOrMethod method name or Method instance
320
	 * @return bool `true` if it exists and `false` if not
321
	 */
322 2
	public function hasMethod($nameOrMethod): bool {
323 2
		if ($nameOrMethod instanceof PhpMethod) {
324 1
			$nameOrMethod = $nameOrMethod->getName();
325
		}
326
327 2
		return $this->methods->has($nameOrMethod);
328
	}
329
330
	/**
331
	 * Returns a method
332
	 *
333
	 * @param string $nameOrMethod the methods name
334
	 * @throws \InvalidArgumentException if the method cannot be found
335
	 * @return PhpMethod
336
	 */
337 10
	public function getMethod($nameOrMethod): PhpMethod {
338 10
		if ($nameOrMethod instanceof PhpMethod) {
339 1
			$nameOrMethod = $nameOrMethod->getName();
340
		}
341
342 10
		if (!$this->methods->has($nameOrMethod)) {
343 2
			throw new \InvalidArgumentException(sprintf('The method "%s" does not exist.', $nameOrMethod));
344
		}
345
346 9
		return $this->methods->get($nameOrMethod);
347
	}
348
349
	/**
350
	 * Returns all methods
351
	 *
352
	 * @return Map|PhpMethod[] collection of methods
353
	 */
354 17
	public function getMethods(): Map {
355 17
		return $this->methods;
356
	}
357
358
	/**
359
	 * Returns all method names
360
	 *
361
	 * @return Set
362
	 */
363 1
	public function getMethodNames(): Set {
364 1
		return $this->methods->keys();
365
	}
366
367
	/**
368
	 * Clears all methods
369
	 *
370
	 * @return $this
371
	 */
372 1
	public function clearMethods() {
373 1
		foreach ($this->methods as $method) {
374 1
			$method->setParent(null);
375
		}
376 1
		$this->methods->clear();
377
378 1
		return $this;
379
	}
380
381
	/**
382
	 * Generates a docblock from provided information
383
	 *
384
	 * @return $this
385
	 */
386 11
	public function generateDocblock() {
387 11
		$docblock = $this->getDocblock();
388 11
		$docblock->setShortDescription($this->getDescription());
389 11
		$docblock->setLongDescription($this->getLongDescription());
390
391 11
		foreach ($this->methods as $method) {
392 7
			$method->generateDocblock();
393
		}
394
395 11
		return $this;
396
	}
397
}
398