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: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
46: class ClassType extends Nette\Object
47: {
48:
49: private $name;
50:
51:
52: private $type = 'class';
53:
54:
55: private $final;
56:
57:
58: private $abstract;
59:
60:
61: private $extends = array();
62:
63:
64: private $implements = array();
65:
66:
67: private $traits = array();
68:
69:
70: private $documents = array();
71:
72:
73: private $consts = array();
74:
75:
76: private $properties = array();
77:
78:
79: private $methods = array();
80:
81:
82:
83: public static function from($from)
84: {
85: $from = $from instanceof \ReflectionClass ? $from : new \ReflectionClass($from);
86: $class = new static($from->getShortName());
87: $class->type = $from->isInterface() ? 'interface' : (PHP_VERSION_ID >= 50400 && $from->isTrait() ? 'trait' : 'class');
88: $class->final = $from->isFinal();
89: $class->abstract = $from->isAbstract() && $class->type === 'class';
90: $class->implements = $from->getInterfaceNames();
91: $class->documents = preg_replace('#^\s*\* ?#m', '', trim($from->getDocComment(), "/* \r\n"));
92: $namespace = $from->getNamespaceName();
93: if ($from->getParentClass()) {
94: $class->extends = $from->getParentClass()->getName();
95: if ($namespace) {
96: $class->extends = Strings::startsWith($class->extends, "$namespace\\") ? substr($class->extends, strlen($namespace) + 1) : '\\' . $class->extends;
97: }
98: $class->implements = array_diff($class->implements, $from->getParentClass()->getInterfaceNames());
99: }
100: if ($namespace) {
101: foreach ($class->implements as & $interface) {
102: $interface = Strings::startsWith($interface, "$namespace\\") ? substr($interface, strlen($namespace) + 1) : '\\' . $interface;
103: }
104: }
105: foreach ($from->getProperties() as $prop) {
106: if ($prop->getDeclaringClass() == $from) {
107: $class->properties[$prop->getName()] = Property::from($prop);
108: }
109: }
110: foreach ($from->getMethods() as $method) {
111: if ($method->getDeclaringClass() == $from) {
112: $class->methods[$method->getName()] = Method::from($method);
113: }
114: }
115: return $class;
116: }
117:
118:
119: public function __construct($name = NULL)
120: {
121: $this->name = $name;
122: }
123:
124:
125:
126: public function addConst($name, $value)
127: {
128: $this->consts[$name] = $value;
129: return $this;
130: }
131:
132:
133:
134: public function addProperty($name, $value = NULL)
135: {
136: $property = new Property;
137: return $this->properties[$name] = $property->setName($name)->setValue($value);
138: }
139:
140:
141:
142: public function addMethod($name)
143: {
144: $method = new Method;
145: if ($this->type === 'interface') {
146: $method->setVisibility('')->setBody(FALSE);
147: } else {
148: $method->setVisibility('public');
149: }
150: return $this->methods[$name] = $method->setName($name);
151: }
152:
153:
154:
155: public function __toString()
156: {
157: $consts = array();
158: foreach ($this->consts as $name => $value) {
159: $consts[] = "const $name = " . Helpers::dump($value) . ";\n";
160: }
161: $properties = array();
162: foreach ($this->properties as $property) {
163: $properties[] = ($property->documents ? str_replace("\n", "\n * ", "/**\n" . implode("\n", (array) $property->documents)) . "\n */\n" : '')
164: . $property->visibility . ($property->static ? ' static' : '') . ' $' . $property->name
165: . ($property->value === NULL ? '' : ' = ' . Helpers::dump($property->value))
166: . ";\n";
167: }
168: return Strings::normalize(
169: ($this->documents ? str_replace("\n", "\n * ", "/**\n" . implode("\n", (array) $this->documents)) . "\n */\n" : '')
170: . ($this->abstract ? 'abstract ' : '')
171: . ($this->final ? 'final ' : '')
172: . $this->type . ' '
173: . $this->name . ' '
174: . ($this->extends ? 'extends ' . implode(', ', (array) $this->extends) . ' ' : '')
175: . ($this->implements ? 'implements ' . implode(', ', (array) $this->implements) . ' ' : '')
176: . "\n{\n\n"
177: . Strings::indent(
178: ($this->traits ? "use " . implode(', ', (array) $this->traits) . ";\n\n" : '')
179: . ($this->consts ? implode('', $consts) . "\n\n" : '')
180: . ($this->properties ? implode("\n", $properties) . "\n\n" : '')
181: . implode("\n\n\n", $this->methods), 1)
182: . "\n\n}") . "\n";
183: }
184:
185: }
186: