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