1: <?php declare(strict_types=1);
2:
3: namespace PhpParser;
4:
5: use PhpParser\Node\Arg;
6: use PhpParser\Node\Expr;
7: use PhpParser\Node\Expr\BinaryOp\Concat;
8: use PhpParser\Node\Identifier;
9: use PhpParser\Node\Name;
10: use PhpParser\Node\Scalar\String_;
11: use PhpParser\Node\Stmt\Use_;
12:
13: class BuilderFactory {
14: /**
15: * Creates an attribute node.
16: *
17: * @param string|Name $name Name of the attribute
18: * @param array $args Attribute named arguments
19: */
20: public function attribute($name, array $args = []): Node\Attribute {
21: return new Node\Attribute(
22: BuilderHelpers::normalizeName($name),
23: $this->args($args)
24: );
25: }
26:
27: /**
28: * Creates a namespace builder.
29: *
30: * @param null|string|Node\Name $name Name of the namespace
31: *
32: * @return Builder\Namespace_ The created namespace builder
33: */
34: public function namespace($name): Builder\Namespace_ {
35: return new Builder\Namespace_($name);
36: }
37:
38: /**
39: * Creates a class builder.
40: *
41: * @param string $name Name of the class
42: *
43: * @return Builder\Class_ The created class builder
44: */
45: public function class(string $name): Builder\Class_ {
46: return new Builder\Class_($name);
47: }
48:
49: /**
50: * Creates an interface builder.
51: *
52: * @param string $name Name of the interface
53: *
54: * @return Builder\Interface_ The created interface builder
55: */
56: public function interface(string $name): Builder\Interface_ {
57: return new Builder\Interface_($name);
58: }
59:
60: /**
61: * Creates a trait builder.
62: *
63: * @param string $name Name of the trait
64: *
65: * @return Builder\Trait_ The created trait builder
66: */
67: public function trait(string $name): Builder\Trait_ {
68: return new Builder\Trait_($name);
69: }
70:
71: /**
72: * Creates an enum builder.
73: *
74: * @param string $name Name of the enum
75: *
76: * @return Builder\Enum_ The created enum builder
77: */
78: public function enum(string $name): Builder\Enum_ {
79: return new Builder\Enum_($name);
80: }
81:
82: /**
83: * Creates a trait use builder.
84: *
85: * @param Node\Name|string ...$traits Trait names
86: *
87: * @return Builder\TraitUse The created trait use builder
88: */
89: public function useTrait(...$traits): Builder\TraitUse {
90: return new Builder\TraitUse(...$traits);
91: }
92:
93: /**
94: * Creates a trait use adaptation builder.
95: *
96: * @param Node\Name|string|null $trait Trait name
97: * @param Node\Identifier|string $method Method name
98: *
99: * @return Builder\TraitUseAdaptation The created trait use adaptation builder
100: */
101: public function traitUseAdaptation($trait, $method = null): Builder\TraitUseAdaptation {
102: if ($method === null) {
103: $method = $trait;
104: $trait = null;
105: }
106:
107: return new Builder\TraitUseAdaptation($trait, $method);
108: }
109:
110: /**
111: * Creates a method builder.
112: *
113: * @param string $name Name of the method
114: *
115: * @return Builder\Method The created method builder
116: */
117: public function method(string $name): Builder\Method {
118: return new Builder\Method($name);
119: }
120:
121: /**
122: * Creates a parameter builder.
123: *
124: * @param string $name Name of the parameter
125: *
126: * @return Builder\Param The created parameter builder
127: */
128: public function param(string $name): Builder\Param {
129: return new Builder\Param($name);
130: }
131:
132: /**
133: * Creates a property builder.
134: *
135: * @param string $name Name of the property
136: *
137: * @return Builder\Property The created property builder
138: */
139: public function property(string $name): Builder\Property {
140: return new Builder\Property($name);
141: }
142:
143: /**
144: * Creates a function builder.
145: *
146: * @param string $name Name of the function
147: *
148: * @return Builder\Function_ The created function builder
149: */
150: public function function(string $name): Builder\Function_ {
151: return new Builder\Function_($name);
152: }
153:
154: /**
155: * Creates a namespace/class use builder.
156: *
157: * @param Node\Name|string $name Name of the entity (namespace or class) to alias
158: *
159: * @return Builder\Use_ The created use builder
160: */
161: public function use($name): Builder\Use_ {
162: return new Builder\Use_($name, Use_::TYPE_NORMAL);
163: }
164:
165: /**
166: * Creates a function use builder.
167: *
168: * @param Node\Name|string $name Name of the function to alias
169: *
170: * @return Builder\Use_ The created use function builder
171: */
172: public function useFunction($name): Builder\Use_ {
173: return new Builder\Use_($name, Use_::TYPE_FUNCTION);
174: }
175:
176: /**
177: * Creates a constant use builder.
178: *
179: * @param Node\Name|string $name Name of the const to alias
180: *
181: * @return Builder\Use_ The created use const builder
182: */
183: public function useConst($name): Builder\Use_ {
184: return new Builder\Use_($name, Use_::TYPE_CONSTANT);
185: }
186:
187: /**
188: * Creates a class constant builder.
189: *
190: * @param string|Identifier $name Name
191: * @param Node\Expr|bool|null|int|float|string|array $value Value
192: *
193: * @return Builder\ClassConst The created use const builder
194: */
195: public function classConst($name, $value): Builder\ClassConst {
196: return new Builder\ClassConst($name, $value);
197: }
198:
199: /**
200: * Creates an enum case builder.
201: *
202: * @param string|Identifier $name Name
203: *
204: * @return Builder\EnumCase The created use const builder
205: */
206: public function enumCase($name): Builder\EnumCase {
207: return new Builder\EnumCase($name);
208: }
209:
210: /**
211: * Creates node a for a literal value.
212: *
213: * @param Expr|bool|null|int|float|string|array|\UnitEnum $value $value
214: */
215: public function val($value): Expr {
216: return BuilderHelpers::normalizeValue($value);
217: }
218:
219: /**
220: * Creates variable node.
221: *
222: * @param string|Expr $name Name
223: */
224: public function var($name): Expr\Variable {
225: if (!\is_string($name) && !$name instanceof Expr) {
226: throw new \LogicException('Variable name must be string or Expr');
227: }
228:
229: return new Expr\Variable($name);
230: }
231:
232: /**
233: * Normalizes an argument list.
234: *
235: * Creates Arg nodes for all arguments and converts literal values to expressions.
236: *
237: * @param array $args List of arguments to normalize
238: *
239: * @return list<Arg>
240: */
241: public function args(array $args): array {
242: $normalizedArgs = [];
243: foreach ($args as $key => $arg) {
244: if (!($arg instanceof Arg)) {
245: $arg = new Arg(BuilderHelpers::normalizeValue($arg));
246: }
247: if (\is_string($key)) {
248: $arg->name = BuilderHelpers::normalizeIdentifier($key);
249: }
250: $normalizedArgs[] = $arg;
251: }
252: return $normalizedArgs;
253: }
254:
255: /**
256: * Creates a function call node.
257: *
258: * @param string|Name|Expr $name Function name
259: * @param array $args Function arguments
260: */
261: public function funcCall($name, array $args = []): Expr\FuncCall {
262: return new Expr\FuncCall(
263: BuilderHelpers::normalizeNameOrExpr($name),
264: $this->args($args)
265: );
266: }
267:
268: /**
269: * Creates a method call node.
270: *
271: * @param Expr $var Variable the method is called on
272: * @param string|Identifier|Expr $name Method name
273: * @param array $args Method arguments
274: */
275: public function methodCall(Expr $var, $name, array $args = []): Expr\MethodCall {
276: return new Expr\MethodCall(
277: $var,
278: BuilderHelpers::normalizeIdentifierOrExpr($name),
279: $this->args($args)
280: );
281: }
282:
283: /**
284: * Creates a static method call node.
285: *
286: * @param string|Name|Expr $class Class name
287: * @param string|Identifier|Expr $name Method name
288: * @param array $args Method arguments
289: */
290: public function staticCall($class, $name, array $args = []): Expr\StaticCall {
291: return new Expr\StaticCall(
292: BuilderHelpers::normalizeNameOrExpr($class),
293: BuilderHelpers::normalizeIdentifierOrExpr($name),
294: $this->args($args)
295: );
296: }
297:
298: /**
299: * Creates an object creation node.
300: *
301: * @param string|Name|Expr $class Class name
302: * @param array $args Constructor arguments
303: */
304: public function new($class, array $args = []): Expr\New_ {
305: return new Expr\New_(
306: BuilderHelpers::normalizeNameOrExpr($class),
307: $this->args($args)
308: );
309: }
310:
311: /**
312: * Creates a constant fetch node.
313: *
314: * @param string|Name $name Constant name
315: */
316: public function constFetch($name): Expr\ConstFetch {
317: return new Expr\ConstFetch(BuilderHelpers::normalizeName($name));
318: }
319:
320: /**
321: * Creates a property fetch node.
322: *
323: * @param Expr $var Variable holding object
324: * @param string|Identifier|Expr $name Property name
325: */
326: public function propertyFetch(Expr $var, $name): Expr\PropertyFetch {
327: return new Expr\PropertyFetch($var, BuilderHelpers::normalizeIdentifierOrExpr($name));
328: }
329:
330: /**
331: * Creates a class constant fetch node.
332: *
333: * @param string|Name|Expr $class Class name
334: * @param string|Identifier|Expr $name Constant name
335: */
336: public function classConstFetch($class, $name): Expr\ClassConstFetch {
337: return new Expr\ClassConstFetch(
338: BuilderHelpers::normalizeNameOrExpr($class),
339: BuilderHelpers::normalizeIdentifierOrExpr($name)
340: );
341: }
342:
343: /**
344: * Creates nested Concat nodes from a list of expressions.
345: *
346: * @param Expr|string ...$exprs Expressions or literal strings
347: */
348: public function concat(...$exprs): Concat {
349: $numExprs = count($exprs);
350: if ($numExprs < 2) {
351: throw new \LogicException('Expected at least two expressions');
352: }
353:
354: $lastConcat = $this->normalizeStringExpr($exprs[0]);
355: for ($i = 1; $i < $numExprs; $i++) {
356: $lastConcat = new Concat($lastConcat, $this->normalizeStringExpr($exprs[$i]));
357: }
358: return $lastConcat;
359: }
360:
361: /**
362: * @param string|Expr $expr
363: */
364: private function normalizeStringExpr($expr): Expr {
365: if ($expr instanceof Expr) {
366: return $expr;
367: }
368:
369: if (\is_string($expr)) {
370: return new String_($expr);
371: }
372:
373: throw new \LogicException('Expected string or Expr');
374: }
375: }
376: