Mark V
1: <?php
2: namespace MOC\V\Component\Document\Vendor\UniversalXml\Source;
3:
4: /**
5: * Class Node
6: *
7: * @package MOC\V\Component\Document\Vendor\UniversalXml\Source
8: */
9: class Node extends NodeType
10: {
11:
12: /** @var null|int $Position */
13: private $Position = null;
14: /** @var null|Node $Parent */
15: private $Parent = null;
16: /** @var Node[] $ChildList */
17: private $ChildList = array();
18:
19: private $Name = null;
20: private $Content = null;
21: private $AttributeList = array();
22:
23: /**
24: * @param Token|null $Token
25: */
26: function __construct(Token $Token = null)
27: {
28:
29: if (null !== $Token) {
30: $this->Name = $Token->getName();
31: $this->AttributeList = $Token->getAttributeList();
32: $this->Position = $Token->getPosition();
33: unset( $Token );
34: }
35: }
36:
37: /**
38: * @return int|null
39: */
40: public function getPosition()
41: {
42:
43: return $this->Position;
44: }
45:
46: /**
47: * @return null|Node
48: */
49: public function getParent()
50: {
51:
52: return $this->Parent;
53: }
54:
55: /**
56: * @param Node $Value
57: *
58: * @return Node
59: */
60: public function setParent(Node $Value)
61: {
62:
63: $this->Parent = $Value;
64:
65: return $this;
66: }
67:
68: /**
69: * @param $Name
70: * @param null $AttributeList
71: * @param null $Index
72: * @param bool $Recursive
73: * @param bool $NameIsRegExp
74: * @param bool $AttributeIsFuzzy
75: *
76: * @return bool|Node
77: */
78: public function getChild(
79: $Name,
80: $AttributeList = null,
81: $Index = null,
82: $Recursive = true,
83: $NameIsRegExp = false,
84: $AttributeIsFuzzy = false
85: ) {
86:
87: /** @var Node $Node */
88: foreach ($this->ChildList as $Node) {
89: if ($Node->getName() == $Name || ( $NameIsRegExp && preg_match($Name, $Node->getName()) )) {
90: if ($AttributeList === null && $Index === null) {
91: return $Node;
92: } else {
93: if ($Index === null) {
94: if ($Node->getAttributeList() == $AttributeList) {
95: return $Node;
96: }
97: if ($AttributeIsFuzzy) {
98: $Fuzzy = true;
99: $Haystack = $Node->getAttributeList();
100: foreach ((array)$AttributeList as $Key => $Value) {
101: if (!isset( $Haystack[$Key] ) || $Haystack[$Key] != $Value) {
102: $Fuzzy = false;
103: }
104: }
105: if ($Fuzzy) {
106: return $Node;
107: }
108: }
109: } else {
110: if ($AttributeList === null) {
111: if ($Index === 0) {
112: return $Node;
113: } else {
114: $Index--;
115: }
116: } else {
117: if ($Node->getAttributeList() == $AttributeList && $Index === 0) {
118: return $Node;
119: } else {
120: if ($Node->getAttributeList() == $AttributeList) {
121: $Index--;
122: }
123: }
124: }
125: }
126: }
127: }
128: if (true === $Recursive && !empty( $Node->ChildList )) {
129: if (false !== ( $Result = $Node->getChild($Name, $AttributeList, $Index, $Recursive, $NameIsRegExp) )
130: ) {
131: if (!is_object($Result)) {
132: $Index = $Result;
133: } else {
134: return $Result;
135: }
136: }
137: }
138: }
139: if ($Index !== null) {
140: return $Index;
141: } else {
142: return false;
143: }
144: }
145:
146: /**
147: * @return null
148: */
149: public function getName()
150: {
151:
152: return $this->Name;
153: }
154:
155: /**
156: * @param $Value
157: *
158: * @return Node
159: */
160: public function setName($Value)
161: {
162:
163: $this->Name = $Value;
164:
165: return $this;
166: }
167:
168: /**
169: * @return array
170: */
171: public function getAttributeList()
172: {
173:
174: return $this->AttributeList;
175: }
176:
177: /**
178: * @return int
179: */
180: public function getChildListCount()
181: {
182:
183: return count($this->getChildList());
184: }
185:
186: /**
187: * @return Node[]
188: */
189: public function getChildList()
190: {
191:
192: return $this->ChildList;
193: }
194:
195: /**
196: * @param Node[] $NodeList
197: *
198: * @return Node
199: */
200: public function setChildList($NodeList)
201: {
202:
203: $this->ChildList = array();
204: array_walk($NodeList, function (Node $Node, $Index, Node $Self) {
205:
206: $Self->addChild($Node);
207: }, $this);
208:
209: return $this;
210: }
211:
212: /**
213: * @param Node $Node
214: * @param null|Node $After
215: *
216: * @return Node
217: */
218: public function addChild(Node $Node, Node $After = null)
219: {
220:
221: if ($After === null) {
222: $Node->setParent($this);
223: array_push($this->ChildList, $Node);
224: $this->Content = null;
225: $this->setType(self::TYPE_STRUCTURE);
226: } else {
227: $this->injectChild($Node, $After);
228: }
229:
230: return $this;
231: }
232:
233: /**
234: * @param Node $Inject
235: * @param Node $After
236: */
237: private function injectChild(Node $Inject, Node $After)
238: {
239:
240: $Index = array_search($After, $this->ChildList) + 1;
241: $Left = array_slice($this->ChildList, 0, $Index, true);
242: $Right = array_slice($this->ChildList, $Index, null, true);
243: $this->setChildList(array_merge($Left, array($Inject), $Right));
244: }
245:
246: /**
247: * @param $Name
248: *
249: * @return null
250: */
251: public function getAttribute($Name)
252: {
253:
254: if (isset( $this->AttributeList[$Name] )) {
255: return $this->AttributeList[$Name];
256: } else {
257: return null;
258: }
259: }
260:
261: /**
262: * @param string $Name
263: * @param null|mixed $Value
264: *
265: * @return Node
266: */
267: public function setAttribute($Name, $Value = null)
268: {
269:
270: if ($Value === null) {
271: unset( $this->AttributeList[$Name] );
272: } else {
273: $this->AttributeList[$Name] = $Value;
274: }
275:
276: return $this;
277: }
278:
279: /**
280: * @return string
281: */
282: public function getCode()
283: {
284:
285: $FuncArgs = func_get_args();
286: if (empty( $FuncArgs )) {
287: $FuncArgs[0] = false;
288: $FuncArgs[1] = 0;
289: }
290: // BUILD STRUCTURE STRING
291: $Result = ''
292: .( !$FuncArgs[0] ? '<?xml version="1.0" encoding="utf-8" standalone="yes"?>'."\n" : "\n" )
293: .str_repeat("\t", $FuncArgs[1]);
294: if ($this->getType() == self::TYPE_COMMENT) {
295: $Result .= '<!-- '.$this->getContent().' //-->';
296: } else {
297: $Result .= '<'.trim($this->getName().' '.$this->getAttributeString());
298: }
299: if ($this->getContent() === null && empty( $this->ChildList )) {
300: $Result .= ' />';
301: } else {
302: if ($this->getType() == self::TYPE_CONTENT) {
303: $Result .= '>'.$this->getContent().'</'.$this->getName().'>';
304: } else {
305: if ($this->getType() == self::TYPE_CDATA) {
306: $Result .= '><![CDATA['.$this->getContent().']]></'.$this->getName().'>';
307: } else {
308: if ($this->getType() == self::TYPE_STRUCTURE) {
309: $Result .= '>';
310: /** @var Node $Node */
311: foreach ($this->ChildList as $Node) {
312: $Result .= $Node->getCode(true, $FuncArgs[1] + 1);
313: }
314: $Result .= "\n".str_repeat("\t", $FuncArgs[1]).'</'.$this->getName().'>';
315: }
316: }
317: }
318: }
319:
320: // RETURN STRUCTURE
321: return $Result;
322: }
323:
324: /**
325: * @return null
326: */
327: public function getContent()
328: {
329:
330: return $this->Content;
331: }
332:
333: /**
334: * @param null $Value
335: *
336: * @return Node
337: */
338: public function setContent($Value = null)
339: {
340:
341: if (preg_match('![<>&]!is', $Value)) {
342: $this->setType(self::TYPE_CDATA);
343: } else {
344: $this->setType(self::TYPE_CONTENT);
345: }
346: if (strlen($Value) == 0) {
347: $this->Content = null;
348: } else {
349: $this->Content = $Value;
350: }
351: $this->ChildList = array();
352:
353: return $this;
354: }
355:
356: /**
357: * @return string
358: */
359: public function getAttributeString()
360: {
361:
362: $AttributeList = $this->AttributeList;
363: array_walk($AttributeList, create_function('&$Value,$Key', '$Value = $Key.\'="\'.$Value.\'"\';'));
364:
365: return implode(' ', $AttributeList);
366: }
367:
368: public function __destruct()
369: {
370:
371: /** @var Node $Node */
372: unset( $this->Parent );
373: array_walk($this->ChildList, function (Node $Node) {
374:
375: $Node->__destruct();
376: });
377: unset( $this );
378: }
379: }
380: