1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\PhpGenerator;
9:
10: use Nette;
11:
12:
13: 14: 15:
16: class Factory
17: {
18: use Nette\SmartObject;
19:
20: 21: 22:
23: public function fromClassReflection(\ReflectionClass $from)
24: {
25: if (PHP_VERSION_ID >= 70000 && $from->isAnonymous()) {
26: $class = new ClassType;
27: } else {
28: $class = new ClassType($from->getShortName(), new PhpNamespace($from->getNamespaceName()));
29: }
30: $class->setType($from->isInterface() ? 'interface' : ($from->isTrait() ? 'trait' : 'class'));
31: $class->setFinal($from->isFinal() && $class->getType() === 'class');
32: $class->setAbstract($from->isAbstract() && $class->getType() === 'class');
33: $class->setImplements($from->getInterfaceNames());
34: $class->setComment(Helpers::unformatDocComment((string) $from->getDocComment()));
35: if ($from->getParentClass()) {
36: $class->setExtends($from->getParentClass()->getName());
37: $class->setImplements(array_diff($class->getImplements(), $from->getParentClass()->getInterfaceNames()));
38: }
39: $props = $methods = [];
40: foreach ($from->getProperties() as $prop) {
41: if ($prop->isDefault() && $prop->getDeclaringClass()->getName() === $from->getName()) {
42: $props[] = $this->fromPropertyReflection($prop);
43: }
44: }
45: $class->setProperties($props);
46: foreach ($from->getMethods() as $method) {
47: if ($method->getDeclaringClass()->getName() === $from->getName()) {
48: $methods[] = $this->fromMethodReflection($method)->setNamespace($class->getNamespace());
49: }
50: }
51: $class->setMethods($methods);
52: return $class;
53: }
54:
55:
56: 57: 58:
59: public function fromMethodReflection(\ReflectionMethod $from)
60: {
61: $method = new Method($from->getName());
62: $method->setParameters(array_map([$this, 'fromParameterReflection'], $from->getParameters()));
63: $method->setStatic($from->isStatic());
64: $isInterface = $from->getDeclaringClass()->isInterface();
65: $method->setVisibility($from->isPrivate() ? 'private' : ($from->isProtected() ? 'protected' : ($isInterface ? null : 'public')));
66: $method->setFinal($from->isFinal());
67: $method->setAbstract($from->isAbstract() && !$isInterface);
68: $method->setBody($from->isAbstract() ? false : '');
69: $method->setReturnReference($from->returnsReference());
70: $method->setVariadic($from->isVariadic());
71: $method->setComment(Helpers::unformatDocComment($from->getDocComment()));
72: if (PHP_VERSION_ID >= 70000 && $from->hasReturnType()) {
73: $method->setReturnType((string) $from->getReturnType());
74: $method->setReturnNullable($from->getReturnType()->allowsNull());
75: }
76: return $method;
77: }
78:
79:
80: 81: 82:
83: public function fromFunctionReflection(\ReflectionFunction $from)
84: {
85: $function = $from->isClosure() ? new Closure : new GlobalFunction($from->getName());
86: $function->setParameters(array_map([$this, 'fromParameterReflection'], $from->getParameters()));
87: $function->setReturnReference($from->returnsReference());
88: $function->setVariadic($from->isVariadic());
89: if (!$from->isClosure()) {
90: $function->setComment(Helpers::unformatDocComment($from->getDocComment()));
91: }
92: if (PHP_VERSION_ID >= 70000 && $from->hasReturnType()) {
93: $function->setReturnType((string) $from->getReturnType());
94: $function->setReturnNullable($from->getReturnType()->allowsNull());
95: }
96: return $function;
97: }
98:
99:
100: 101: 102:
103: public function fromParameterReflection(\ReflectionParameter $from)
104: {
105: $param = new Parameter($from->getName());
106: $param->setReference($from->isPassedByReference());
107: if (PHP_VERSION_ID >= 70000) {
108: $param->setTypeHint($from->hasType() ? (string) $from->getType() : null);
109: $param->setNullable($from->hasType() && $from->getType()->allowsNull());
110: } elseif ($from->isArray() || $from->isCallable()) {
111: $param->setTypeHint($from->isArray() ? 'array' : 'callable');
112: } else {
113: try {
114: $param->setTypeHint($from->getClass() ? $from->getClass()->getName() : null);
115: } catch (\ReflectionException $e) {
116: if (preg_match('#Class (.+) does not exist#', $e->getMessage(), $m)) {
117: $param->setTypeHint($m[1]);
118: } else {
119: throw $e;
120: }
121: }
122: }
123: if ($from->isDefaultValueAvailable()) {
124: $param->setOptional(true);
125: $param->setDefaultValue($from->isDefaultValueConstant()
126: ? new PhpLiteral($from->getDefaultValueConstantName())
127: : $from->getDefaultValue());
128: $param->setNullable($param->isNullable() && $param->getDefaultValue() !== null);
129: }
130: return $param;
131: }
132:
133:
134: 135: 136:
137: public function fromPropertyReflection(\ReflectionProperty $from)
138: {
139: $prop = new Property($from->getName());
140: $defaults = $from->getDeclaringClass()->getDefaultProperties();
141: $prop->setValue(isset($defaults[$prop->getName()]) ? $defaults[$prop->getName()] : null);
142: $prop->setStatic($from->isStatic());
143: $prop->setVisibility($from->isPrivate() ? 'private' : ($from->isProtected() ? 'protected' : 'public'));
144: $prop->setComment(Helpers::unformatDocComment($from->getDocComment()));
145: return $prop;
146: }
147: }
148: