1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\PhpGenerator;
9:
10: use Nette;
11: use Nette\Utils\Strings;
12:
13:
14: 15: 16: 17: 18: 19:
20: class ClassType
21: {
22: use Nette\SmartObject;
23:
24: const TYPE_CLASS = 'class';
25:
26: const TYPE_INTERFACE = 'interface';
27:
28: const TYPE_TRAIT = 'trait';
29:
30:
31: private $namespace;
32:
33:
34: private $name;
35:
36:
37: private $type = 'class';
38:
39:
40: private $final = FALSE;
41:
42:
43: private $abstract = FALSE;
44:
45:
46: private $extends = [];
47:
48:
49: private $implements = [];
50:
51:
52: private $traits = [];
53:
54:
55: private ;
56:
57:
58: private $consts = [];
59:
60:
61: private $properties = [];
62:
63:
64: private $methods = [];
65:
66:
67: 68: 69: 70:
71: public static function from($from)
72: {
73: return (new Factory)->fromClassReflection(
74: $from instanceof \ReflectionClass ? $from : new \ReflectionClass($from)
75: );
76: }
77:
78:
79: public function __construct($name = NULL, PhpNamespace $namespace = NULL)
80: {
81: $this->setName($name);
82: $this->namespace = $namespace;
83: }
84:
85:
86: 87: 88:
89: public function __toString()
90: {
91: $consts = [];
92: foreach ($this->consts as $const) {
93: $consts[] = Helpers::formatDocComment($const->getComment())
94: . ($const->getVisibility() ? $const->getVisibility() . ' ' : '')
95: . 'const ' . $const->getName() . ' = ' . Helpers::dump($const->getValue()) . ";\n";
96: }
97:
98: $properties = [];
99: foreach ($this->properties as $property) {
100: $properties[] = Helpers::formatDocComment($property->getComment())
101: . ($property->getVisibility() ?: 'public') . ($property->isStatic() ? ' static' : '') . ' $' . $property->getName()
102: . ($property->value === NULL ? '' : ' = ' . Helpers::dump($property->value))
103: . ";\n";
104: }
105:
106: $mapper = function (array $arr) {
107: return $this->namespace ? array_map([$this->namespace, 'unresolveName'], $arr) : $arr;
108: };
109:
110: return Strings::normalize(
111: Helpers::formatDocComment($this->comment . "\n")
112: . ($this->abstract ? 'abstract ' : '')
113: . ($this->final ? 'final ' : '')
114: . ($this->name ? "$this->type $this->name " : '')
115: . ($this->extends ? 'extends ' . implode(', ', $mapper((array) $this->extends)) . ' ' : '')
116: . ($this->implements ? 'implements ' . implode(', ', $mapper($this->implements)) . ' ' : '')
117: . ($this->name ? "\n" : '') . "{\n"
118: . Strings::indent(
119: ($this->traits ? 'use ' . implode(";\nuse ", $mapper($this->traits)) . ";\n\n" : '')
120: . ($this->consts ? implode('', $consts) . "\n" : '')
121: . ($this->properties ? implode("\n", $properties) . "\n" : '')
122: . ($this->methods ? "\n" . implode("\n\n\n", $this->methods) . "\n\n" : ''), 1)
123: . '}'
124: ) . ($this->name ? "\n" : '');
125: }
126:
127:
128: 129: 130:
131: public function getNamespace()
132: {
133: return $this->namespace;
134: }
135:
136:
137: 138: 139: 140:
141: public function setName($name)
142: {
143: $this->name = $name;
144: return $this;
145: }
146:
147:
148: 149: 150:
151: public function getName()
152: {
153: return $this->name;
154: }
155:
156:
157: 158: 159: 160:
161: public function setType($type)
162: {
163: if (!in_array($type, ['class', 'interface', 'trait'], TRUE)) {
164: throw new Nette\InvalidArgumentException('Argument must be class|interface|trait.');
165: }
166: $this->type = $type;
167: return $this;
168: }
169:
170:
171: 172: 173:
174: public function getType()
175: {
176: return $this->type;
177: }
178:
179:
180: 181: 182: 183:
184: public function setFinal($state = TRUE)
185: {
186: $this->final = (bool) $state;
187: return $this;
188: }
189:
190:
191: 192: 193:
194: public function isFinal()
195: {
196: return $this->final;
197: }
198:
199:
200: 201: 202: 203:
204: public function setAbstract($state = TRUE)
205: {
206: $this->abstract = (bool) $state;
207: return $this;
208: }
209:
210:
211: 212: 213:
214: public function isAbstract()
215: {
216: return $this->abstract;
217: }
218:
219:
220: 221: 222: 223:
224: public function setExtends($types)
225: {
226: if (!is_string($types) && !(is_array($types) && array_filter($types, 'is_string') === $types)) {
227: throw new Nette\InvalidArgumentException('Argument must be string or string[].');
228: }
229: $this->extends = $types;
230: return $this;
231: }
232:
233:
234: 235: 236:
237: public function getExtends()
238: {
239: return $this->extends;
240: }
241:
242:
243: 244: 245: 246:
247: public function addExtend($type)
248: {
249: $this->extends = (array) $this->extends;
250: $this->extends[] = (string) $type;
251: return $this;
252: }
253:
254:
255: 256: 257: 258:
259: public function setImplements(array $types)
260: {
261: $this->implements = $types;
262: return $this;
263: }
264:
265:
266: 267: 268:
269: public function getImplements()
270: {
271: return $this->implements;
272: }
273:
274:
275: 276: 277: 278:
279: public function addImplement($type)
280: {
281: $this->implements[] = (string) $type;
282: return $this;
283: }
284:
285:
286: 287: 288: 289:
290: public function setTraits(array $traits)
291: {
292: $this->traits = $traits;
293: return $this;
294: }
295:
296:
297: 298: 299:
300: public function getTraits()
301: {
302: return $this->traits;
303: }
304:
305:
306: 307: 308: 309:
310: public function addTrait($trait)
311: {
312: $this->traits[] = (string) $trait;
313: return $this;
314: }
315:
316:
317: 318: 319: 320:
321: public function ($val)
322: {
323: $this->comment = $val ? (string) $val : NULL;
324: return $this;
325: }
326:
327:
328: 329: 330:
331: public function ()
332: {
333: return $this->comment;
334: }
335:
336:
337: 338: 339: 340:
341: public function ($val)
342: {
343: $this->comment .= $this->comment ? "\n$val" : $val;
344: return $this;
345: }
346:
347:
348:
349: public function setDocuments(array $s)
350: {
351: trigger_error(__METHOD__ . '() is deprecated, use similar setComment()', E_USER_DEPRECATED);
352: return $this->setComment(implode("\n", $s));
353: }
354:
355:
356:
357: public function getDocuments()
358: {
359: trigger_error(__METHOD__ . '() is deprecated, use similar getComment()', E_USER_DEPRECATED);
360: return $this->comment ? [$this->comment] : [];
361: }
362:
363:
364:
365: public function addDocument($s)
366: {
367: trigger_error(__METHOD__ . '() is deprecated, use addComment()', E_USER_DEPRECATED);
368: return $this->addComment($s);
369: }
370:
371:
372: 373: 374: 375:
376: public function setConsts(array $consts)
377: {
378: return $this->setConstants($consts);
379: }
380:
381:
382: 383: 384: 385:
386: public function getConsts()
387: {
388: return array_map(function ($const) { return $const->getValue(); }, $this->consts);
389: }
390:
391:
392: 393: 394: 395: 396: 397:
398: public function addConst($name, $value)
399: {
400: $this->addConstant($name, $value);
401: return $this;
402: }
403:
404:
405: 406: 407:
408: public function setConstants(array $consts)
409: {
410: $this->consts = [];
411: foreach ($consts as $k => $v) {
412: $const = $v instanceof Constant ? $v : (new Constant($k))->setValue($v);
413: $this->consts[$const->getName()] = $const;
414: }
415: return $this;
416: }
417:
418:
419: 420: 421:
422: public function getConstants()
423: {
424: return $this->consts;
425: }
426:
427:
428: 429: 430: 431: 432:
433: public function addConstant($name, $value)
434: {
435: return $this->consts[$name] = (new Constant($name))->setValue($value);
436: }
437:
438:
439: 440: 441: 442:
443: public function setProperties(array $props)
444: {
445: $this->properties = [];
446: foreach ($props as $v) {
447: if (!$v instanceof Property) {
448: throw new Nette\InvalidArgumentException('Argument must be Nette\PhpGenerator\Property[].');
449: }
450: $this->properties[$v->getName()] = $v;
451: }
452: return $this;
453: }
454:
455:
456: 457: 458:
459: public function getProperties()
460: {
461: return $this->properties;
462: }
463:
464:
465: 466: 467:
468: public function getProperty($name)
469: {
470: if (!isset($this->properties[$name])) {
471: throw new Nette\InvalidArgumentException("Property '$name' not found.");
472: }
473: return $this->properties[$name];
474: }
475:
476:
477: 478: 479: 480: 481:
482: public function addProperty($name, $value = NULL)
483: {
484: return $this->properties[$name] = (new Property($name))->setValue($value);
485: }
486:
487:
488: 489: 490: 491:
492: public function setMethods(array $methods)
493: {
494: $this->methods = [];
495: foreach ($methods as $v) {
496: if (!$v instanceof Method) {
497: throw new Nette\InvalidArgumentException('Argument must be Nette\PhpGenerator\Method[].');
498: }
499: $this->methods[$v->getName()] = $v->setNamespace($this->namespace);
500: }
501: return $this;
502: }
503:
504:
505: 506: 507:
508: public function getMethods()
509: {
510: return $this->methods;
511: }
512:
513:
514: 515: 516:
517: public function getMethod($name)
518: {
519: if (!isset($this->methods[$name])) {
520: throw new Nette\InvalidArgumentException("Method '$name' not found.");
521: }
522: return $this->methods[$name];
523: }
524:
525:
526: 527: 528: 529:
530: public function addMethod($name)
531: {
532: $method = (new Method($name))->setNamespace($this->namespace);
533: if ($this->type === 'interface') {
534: $method->setVisibility(NULL)->setBody(FALSE);
535: } else {
536: $method->setVisibility('public');
537: }
538: return $this->methods[$name] = $method;
539: }
540:
541: }
542: