1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\PhpGenerator;
9:
10: use Nette,
11: 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: $class->properties[$prop->getName()] = Property::from($prop);
107: }
108: foreach ($from->getMethods() as $method) {
109: if ($method->getDeclaringClass() == $from) {
110: $class->methods[$method->getName()] = Method::from($method);
111: }
112: }
113: return $class;
114: }
115:
116:
117: public function __construct($name = NULL)
118: {
119: $this->name = $name;
120: }
121:
122:
123:
124: public function addConst($name, $value)
125: {
126: $this->consts[$name] = $value;
127: return $this;
128: }
129:
130:
131:
132: public function addProperty($name, $value = NULL)
133: {
134: $property = new Property;
135: return $this->properties[$name] = $property->setName($name)->setValue($value);
136: }
137:
138:
139:
140: public function addMethod($name)
141: {
142: $method = new Method;
143: if ($this->type === 'interface') {
144: $method->setVisibility('')->setBody(FALSE);
145: } else {
146: $method->setVisibility('public');
147: }
148: return $this->methods[$name] = $method->setName($name);
149: }
150:
151:
152:
153: public function __toString()
154: {
155: $consts = array();
156: foreach ($this->consts as $name => $value) {
157: $consts[] = "const $name = " . Helpers::dump($value) . ";\n";
158: }
159: $properties = array();
160: foreach ($this->properties as $property) {
161: $properties[] = ($property->documents ? str_replace("\n", "\n * ", "/**\n" . implode("\n", (array) $property->documents)) . "\n */\n" : '')
162: . $property->visibility . ($property->static ? ' static' : '') . ' $' . $property->name
163: . ($property->value === NULL ? '' : ' = ' . Helpers::dump($property->value))
164: . ";\n";
165: }
166: return Strings::normalize(
167: ($this->documents ? str_replace("\n", "\n * ", "/**\n" . implode("\n", (array) $this->documents)) . "\n */\n" : '')
168: . ($this->abstract ? 'abstract ' : '')
169: . ($this->final ? 'final ' : '')
170: . $this->type . ' '
171: . $this->name . ' '
172: . ($this->extends ? 'extends ' . implode(', ', (array) $this->extends) . ' ' : '')
173: . ($this->implements ? 'implements ' . implode(', ', (array) $this->implements) . ' ' : '')
174: . "\n{\n\n"
175: . Strings::indent(
176: ($this->traits ? "use " . implode(', ', (array) $this->traits) . ";\n\n" : '')
177: . ($this->consts ? implode('', $consts) . "\n\n" : '')
178: . ($this->properties ? implode("\n", $properties) . "\n\n" : '')
179: . implode("\n\n\n", $this->methods), 1)
180: . "\n\n}") . "\n";
181: }
182:
183: }
184: