1: <?php
2: namespace Pharborist\Objects;
3:
4: use Pharborist\CommaListNode;
5: use Pharborist\DocCommentTrait;
6: use Pharborist\ExpressionNode;
7: use Pharborist\Filter;
8: use Pharborist\FormatterFactory;
9: use Pharborist\Functions\FunctionDeclarationNode;
10: use Pharborist\Namespaces\IdentifierNameTrait;
11: use Pharborist\Namespaces\NameNode;
12: use Pharborist\NodeCollection;
13: use Pharborist\StatementBlockNode;
14: use Pharborist\StatementNode;
15: use Pharborist\Token;
16:
17: 18: 19: 20: 21: 22:
23: abstract class SingleInheritanceNode extends StatementNode {
24: use DocCommentTrait;
25: use IdentifierNameTrait;
26:
27: 28: 29:
30: protected $extends;
31:
32: 33: 34:
35: protected $implements;
36:
37: 38: 39:
40: protected $statements;
41:
42: 43: 44:
45: public function getExtends() {
46: return $this->extends;
47: }
48:
49: 50: 51: 52:
53: public function setExtends($extends) {
54: if ($extends === NULL) {
55: if (isset($this->extends)) {
56:
57: $this->extends->previous()->remove();
58:
59: $this->extends->previous()->remove();
60:
61: $this->extends->previous()->remove();
62:
63: $this->extends->remove();
64: }
65: }
66: else {
67: if (is_string($extends)) {
68: $extends = NameNode::create($extends);
69: }
70: if (isset($this->extends)) {
71: $this->extends->replaceWith($extends);
72: }
73: else {
74: $this->name->after([
75: Token::space(),
76: Token::_extends(),
77: Token::space(),
78: $extends
79: ]);
80: }
81: $this->extends = $extends;
82: }
83: return $this;
84: }
85:
86: 87: 88:
89: public function getImplementList() {
90: return $this->implements;
91: }
92:
93: 94: 95:
96: public function getImplements() {
97: return $this->implements->getItems();
98: }
99:
100: 101: 102: 103: 104:
105: public function setImplements($implements) {
106: if ($implements === NULL) {
107: if (isset($this->implements)) {
108:
109: $this->implements->previous()->remove();
110:
111: $this->implements->previous()->remove();
112:
113: $this->implements->previous()->remove();
114:
115: $this->implements->remove();
116: }
117: }
118: else {
119:
120: if (is_string($implements)) {
121: $implements = NameNode::create($implements);
122: }
123: if ($implements instanceof NameNode) {
124: $implementList = new CommaListNode();
125: $implementList->append($implements);
126: $implements = $implementList;
127: }
128: if (is_array($implements)) {
129: $implementList = new CommaListNode();
130: foreach ($implements as $implement) {
131: if (is_string($implement)) {
132: $implementList->append(NameNode::create($implement));
133: }
134: elseif ($implement instanceof NameNode) {
135: $implementList->append($implement);
136: }
137: else {
138: throw new \InvalidArgumentException('Invalid $implements argument');
139: }
140: }
141: $implements = $implementList;
142: }
143:
144: if (isset($this->implements)) {
145: $this->implements->replaceWith($implements);
146: }
147: else {
148: $after = isset($this->extends) ? $this->extends : $this->name;
149: $after->after([
150: Token::space(),
151: Token::_implements(),
152: Token::space(),
153: $implements
154: ]);
155: }
156: $this->implements = $implements;
157: }
158: return $this;
159: }
160:
161: 162: 163:
164: public function getBody() {
165: return $this->statements;
166: }
167:
168: 169: 170:
171: public function getStatements() {
172: return $this->statements->getStatements();
173: }
174:
175: 176: 177: 178: 179: 180: 181: 182: 183: 184:
185: public function appendMethod($method) {
186: if ($method instanceof FunctionDeclarationNode) {
187: $method = ClassMethodNode::fromFunction($method);
188: }
189: elseif (is_string($method)) {
190: $method = ClassMethodNode::create($method);
191: }
192: $this->statements->lastChild()->before($method);
193: FormatterFactory::format($this);
194: return $this;
195: }
196:
197: 198: 199: 200: 201: 202: 203: 204: 205:
206: public function hasProperty($name) {
207: return in_array(ltrim($name, '$'), $this->getPropertyNames());
208: }
209:
210: 211: 212: 213: 214:
215: public function getPropertyNames() {
216: return array_map(function (ClassMemberNode $property) {
217: return ltrim($property->getName(), '$');
218: }, $this->getAllProperties()->toArray());
219: }
220:
221: 222: 223:
224: public function getAllProperties() {
225: $properties = [];
226:
227: foreach ($this->statements->children(Filter::isInstanceOf('\Pharborist\Objects\ClassMemberListNode')) as $node) {
228: $properties = array_merge($properties, $node->getMembers()->toArray());
229: }
230: return new NodeCollection($properties, FALSE);
231: }
232:
233: 234: 235: 236: 237: 238: 239: 240:
241: public function hasMethod($name) {
242: return in_array($name, $this->getMethodNames());
243: }
244:
245: 246: 247: 248: 249:
250: public function getMethodNames() {
251: return array_map(function (ClassMethodNode $node) {
252: return $node->getName()->getText();
253: }, $this->getAllMethods()->toArray());
254: }
255:
256: 257: 258:
259: public function getAllMethods() {
260: return $this->statements->children(Filter::isInstanceOf('\Pharborist\Objects\ClassMethodNode'));
261: }
262:
263: 264: 265: 266: 267: 268: 269: 270:
271: public function getProperty($name) {
272: $name = ltrim($name, '$');
273:
274: $properties = $this
275: ->getAllProperties()
276: ->filter(function (ClassMemberNode $property) use ($name) {
277: return ltrim($property->getName(), '$') === $name;
278: });
279: return $properties->isEmpty() ? NULL : $properties[0];
280: }
281:
282: 283: 284: 285: 286: 287: 288: 289:
290: public function getMethod($name) {
291: $methods = $this
292: ->getAllMethods()
293: ->filter(function (ClassMethodNode $method) use ($name) {
294: return $method->getName()->getText() === $name;
295: });
296: return $methods->isEmpty() ? NULL : $methods[0];
297: }
298:
299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309:
310: public function createProperty($name, ExpressionNode $value = NULL, $visibility = 'public') {
311: return $this->appendProperty(ClassMemberNode::create($name, $value, $visibility));
312: }
313:
314: 315: 316: 317: 318: 319:
320: public function appendProperty($property) {
321: if (is_string($property)) {
322: $property = ClassMemberListNode::create($property);
323: }
324: $properties = $this->statements->children(Filter::isInstanceOf('\Pharborist\ClassMemberListNode'));
325: if ($properties->count() === 0) {
326: $this->statements->firstChild()->after($property);
327: }
328: else {
329: $properties->last()->after($property);
330: }
331: FormatterFactory::format($this);
332: return $this;
333: }
334: }
335: