friendship ended with social-app. php is my new best friend
1<?php
2
3namespace Masterminds\HTML5\Serializer;
4
5/**
6 * Traverser for walking a DOM tree.
7 *
8 * This is a concrete traverser designed to convert a DOM tree into an
9 * HTML5 document. It is not intended to be a generic DOMTreeWalker
10 * implementation.
11 *
12 * @see http://www.w3.org/TR/2012/CR-html5-20121217/syntax.html#serializing-html-fragments
13 */
14class Traverser
15{
16 /**
17 * Namespaces that should be treated as "local" to HTML5.
18 */
19 protected static $local_ns = array(
20 'http://www.w3.org/1999/xhtml' => 'html',
21 'http://www.w3.org/1998/Math/MathML' => 'math',
22 'http://www.w3.org/2000/svg' => 'svg',
23 );
24
25 protected $dom;
26
27 protected $options;
28
29 protected $encode = false;
30
31 protected $rules;
32
33 protected $out;
34
35 /**
36 * Create a traverser.
37 *
38 * @param \DOMNode|\DOMNodeList $dom The document or node to traverse.
39 * @param resource $out A stream that allows writing. The traverser will output into this
40 * stream.
41 * @param array $options An array of options for the traverser as key/value pairs. These include:
42 * - encode_entities: A bool to specify if full encding should happen for all named
43 * charachter references. Defaults to false which escapes &'<>".
44 * - output_rules: The path to the class handling the output rules.
45 */
46 public function __construct($dom, $out, RulesInterface $rules, $options = array())
47 {
48 $this->dom = $dom;
49 $this->out = $out;
50 $this->rules = $rules;
51 $this->options = $options;
52
53 $this->rules->setTraverser($this);
54 }
55
56 /**
57 * Tell the traverser to walk the DOM.
58 *
59 * @return resource $out Returns the output stream.
60 */
61 public function walk()
62 {
63 if ($this->dom instanceof \DOMDocument) {
64 $this->rules->document($this->dom);
65 } elseif ($this->dom instanceof \DOMDocumentFragment) {
66 // Document fragments are a special case. Only the children need to
67 // be serialized.
68 if ($this->dom->hasChildNodes()) {
69 $this->children($this->dom->childNodes);
70 }
71 } // If NodeList, loop
72 elseif ($this->dom instanceof \DOMNodeList) {
73 // If this is a NodeList of DOMDocuments this will not work.
74 $this->children($this->dom);
75 } // Else assume this is a DOMNode-like datastructure.
76 else {
77 $this->node($this->dom);
78 }
79
80 return $this->out;
81 }
82
83 /**
84 * Process a node in the DOM.
85 *
86 * @param mixed $node A node implementing \DOMNode.
87 */
88 public function node($node)
89 {
90 // A listing of types is at http://php.net/manual/en/dom.constants.php
91 switch ($node->nodeType) {
92 case XML_ELEMENT_NODE:
93 $this->rules->element($node);
94 break;
95 case XML_TEXT_NODE:
96 $this->rules->text($node);
97 break;
98 case XML_CDATA_SECTION_NODE:
99 $this->rules->cdata($node);
100 break;
101 case XML_PI_NODE:
102 $this->rules->processorInstruction($node);
103 break;
104 case XML_COMMENT_NODE:
105 $this->rules->comment($node);
106 break;
107 // Currently we don't support embedding DTDs.
108 default:
109 //print '<!-- Skipped -->';
110 break;
111 }
112 }
113
114 /**
115 * Walk through all the nodes on a node list.
116 *
117 * @param \DOMNodeList $nl A list of child elements to walk through.
118 */
119 public function children($nl)
120 {
121 foreach ($nl as $node) {
122 $this->node($node);
123 }
124 }
125
126 /**
127 * Is an element local?
128 *
129 * @param mixed $ele An element that implement \DOMNode.
130 *
131 * @return bool true if local and false otherwise.
132 */
133 public function isLocalElement($ele)
134 {
135 $uri = $ele->namespaceURI;
136 if (empty($uri)) {
137 return false;
138 }
139
140 return isset(static::$local_ns[$uri]);
141 }
142}