XmlStreamReader
3 weeks ago
partner-discount-sdk
3 weeks ago
api.php
3 weeks ago
arraytoxml.php
3 weeks ago
chunk.php
3 weeks ago
config.php
2 years ago
download.php
3 weeks ago
error.php
3 weeks ago
handler.php
3 weeks ago
helper.php
3 weeks ago
input.php
3 weeks ago
nested.php
3 weeks ago
rapidaddon.php
3 weeks ago
render.php
3 weeks ago
session.php
9 months ago
upload.php
3 weeks ago
zip.php
10 years ago
render.php
316 lines
| 1 | <?php |
| 2 | if ( ! class_exists('PMXI_Render')){ |
| 3 | |
| 4 | class PMXI_Render{ |
| 5 | |
| 6 | public function __construct(){ |
| 7 | |
| 8 | } |
| 9 | |
| 10 | public static function xml_find_repeating(DOMElement $el, $path = '/') |
| 11 | { |
| 12 | $path .= $el->nodeName; |
| 13 | if ( ! $el->parentNode instanceof DOMDocument) { |
| 14 | $path .= '[1]'; |
| 15 | } |
| 16 | $children = array(); |
| 17 | foreach ($el->childNodes as $child) { |
| 18 | if ($child instanceof DOMElement) { |
| 19 | if ( ! empty($children[$child->nodeName])) { |
| 20 | return $path . '/' . $child->nodeName; |
| 21 | } else { |
| 22 | $children[$child->nodeName] = true; |
| 23 | } |
| 24 | } |
| 25 | } |
| 26 | // reaching this point means we didn't find anything among current element children, so recursively ask children to find something in them |
| 27 | foreach ($el->childNodes as $child) { |
| 28 | if ($child instanceof DOMElement) { |
| 29 | $result = slef::xml_find_repeating($child, $path . '/'); |
| 30 | if ($result) { |
| 31 | return $result; |
| 32 | } |
| 33 | } |
| 34 | } |
| 35 | // reaching this point means we didn't find anything, so return element itself if the function was called for it |
| 36 | if ('/' . $el->nodeName == $path) { |
| 37 | return $path; |
| 38 | } |
| 39 | |
| 40 | return NULL; |
| 41 | } |
| 42 | |
| 43 | public static function render_csv_element(DOMElement $el, $shorten = false, $path = '/', $ind = 1, $lvl = 0) |
| 44 | { |
| 45 | $path .= $el->nodeName; |
| 46 | if ( ! $el->parentNode instanceof DOMDocument and $ind > 0) { |
| 47 | $path .= "[$ind]"; |
| 48 | } |
| 49 | |
| 50 | echo '<div class="xml-element csv_element lvl-' . esc_attr($lvl) . ' lvl-mod4-' . esc_attr($lvl % 4) . '" title="' . esc_attr($path) . '">'; |
| 51 | if ($el->hasChildNodes()) { |
| 52 | $is_render_collapsed = $ind > 1; |
| 53 | if ($lvl) echo '<div class="csv-tag opening"><span class="csv-tag-name">' . esc_html($el->nodeName) . '</span>'; echo '</div>'; |
| 54 | if (1 == $el->childNodes->length and $el->childNodes->item(0) instanceof DOMText) { |
| 55 | $child = $el->childNodes->item(0); |
| 56 | if (!empty($child->wholeText)){ |
| 57 | self::render_csv_text(trim($child->wholeText), $shorten, $is_render_collapsed); |
| 58 | } |
| 59 | elseif (is_callable(array($child, 'nodeValue'), true) && isset($child->nodeValue)){ |
| 60 | self::render_csv_text(trim($child->nodeValue), $shorten, $is_render_collapsed); |
| 61 | } |
| 62 | } else { |
| 63 | echo '<div class="csv-content' . ($is_render_collapsed ? ' collapsed' : '') . '">'; |
| 64 | $indexes = array(); |
| 65 | foreach ($el->childNodes as $child) { |
| 66 | if ($child instanceof DOMElement) { |
| 67 | empty($indexes[$child->nodeName]) and $indexes[$child->nodeName] = 0; $indexes[$child->nodeName]++; |
| 68 | self::render_csv_element($child, $shorten, $path . '/', $indexes[$child->nodeName], $lvl + 1); |
| 69 | } elseif ($child instanceof DOMText) { |
| 70 | self::render_csv_text(trim($child->wholeText), $shorten); |
| 71 | } elseif ($child instanceof DOMComment) { |
| 72 | if (preg_match('%\[pmxi_more:(\d+)\]%', $child->nodeValue, $mtch)) { |
| 73 | $no = intval($mtch[1]); |
| 74 | echo '<div class="xml-more">[ ⇓ ' . wp_kses( /* translators: 1: count, 2: element/elements label */ sprintf(__('<strong>%1$s</strong> %2$s more', 'wp-all-import'), intval($no), esc_html(_n('element', 'elements', $no, 'wp-all-import'))), array('strong' => array()) ) . ' ⇓ ]</div>'; |
| 75 | } |
| 76 | } |
| 77 | } |
| 78 | echo '</div>'; |
| 79 | } |
| 80 | //echo '<div class="xml-tag closing"><span class="xml-tag-name">' . $el->nodeName . '</span></div>'; |
| 81 | } else { |
| 82 | echo '<div class="xml-tag opening empty"><span class="xml-tag-name">' . wp_kses_post($el->nodeName) . '</span>'; self::render_xml_attributes($el); echo '</div>'; |
| 83 | } |
| 84 | echo '</div>'; |
| 85 | } |
| 86 | |
| 87 | protected static function render_csv_text($text, $shorten = false, $is_render_collapsed = false) |
| 88 | { |
| 89 | if (empty($text) and 0 !== (int)$text) { |
| 90 | return; // do not display empty text nodes |
| 91 | } |
| 92 | if (preg_match('%\[more:(\d+)\]%', $text, $mtch)) { |
| 93 | $no = intval($mtch[1]); |
| 94 | echo '<div class="xml-more">[ ⇓ ' . wp_kses( /* translators: 1: count, 2: element/elements label */ sprintf(__('<strong>%1$s</strong> %2$s more', 'wp-all-import'), intval($no), esc_html(_n('element', 'elements', $no, 'wp-all-import'))), array('strong' => array()) ) . ' ⇓ ]</div>'; |
| 95 | return; |
| 96 | } |
| 97 | $more = ''; |
| 98 | if ($shorten and preg_match('%^(.*?\s+){20}(?=\S)%', $text, $mtch)) { |
| 99 | $text = $mtch[0]; |
| 100 | $more = '<span class="xml-more">[' . esc_html__('more', 'wp-all-import') . ']</span>'; |
| 101 | } |
| 102 | $is_short = strlen($text) <= 40; |
| 103 | $newtext = htmlspecialchars($text); |
| 104 | //$newtext = preg_replace('%(?<!\s)\b(?!\s|\W[\w\s])|\w{20}%', '$0​', $newtext); // put explicit breaks for xml content to wrap |
| 105 | echo '<div class="xml-content textonly' . ($is_short ? ' short' : '') . ($is_render_collapsed ? ' collapsed' : '') . ' '. (is_numeric($text) ? 'is_numeric' : '') .'">' . wp_kses_post($newtext . $more) . '</div>'; |
| 106 | } |
| 107 | public static $option_paths = array(); |
| 108 | public static function render_xml_elements_for_filtring(DOMElement $el, $originPath ='', $lvl = 0){ |
| 109 | $path = $originPath; |
| 110 | if ("" != $path){ |
| 111 | if ($lvl > 1) $path .= "->" . $el->nodeName; else $path = $el->nodeName; |
| 112 | if (empty(self::$option_paths[$path])) |
| 113 | self::$option_paths[$path] = 1; |
| 114 | else |
| 115 | self::$option_paths[$path]++; |
| 116 | echo '<option value="'. esc_attr($path) .'['. esc_attr(self::$option_paths[$path]) .']">' . esc_html($path) . '['. esc_html(self::$option_paths[$path]) .']</option>'; |
| 117 | } |
| 118 | else $path = $el->nodeName; |
| 119 | |
| 120 | foreach ($el->attributes as $attr) { |
| 121 | if (empty($originPath)){ |
| 122 | echo '<option value="@' . esc_attr($attr->nodeName).'">@' . esc_html($attr->nodeName) . '</option>'; |
| 123 | } |
| 124 | else{ |
| 125 | echo '<option value="'. esc_attr($path) .'['. esc_attr(self::$option_paths[$path]) .']'. '/@' . esc_attr($attr->nodeName).'">'. esc_html($path) .'['. esc_html(self::$option_paths[$path]) .']'. '@' . esc_html($attr->nodeName) . '</option>'; |
| 126 | } |
| 127 | } |
| 128 | if ($el->hasChildNodes()) { |
| 129 | foreach ($el->childNodes as $child) { |
| 130 | if ($child instanceof DOMElement) |
| 131 | self::render_xml_elements_for_filtring($child, $path, $lvl + 1); |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | public static function render_xml_element(DOMElement $el, $shorten = false, $path = '/', $ind = 1, $lvl = 0) |
| 137 | { |
| 138 | // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound |
| 139 | $render_whole_tree = apply_filters('wp_all_import_is_render_whole_xml_tree', true); |
| 140 | |
| 141 | $path .= $el->nodeName; |
| 142 | $alternativePath = $path; |
| 143 | if ( ! $el->parentNode instanceof DOMDocument and $ind > 0) { |
| 144 | $path .= "[$ind]"; |
| 145 | } |
| 146 | |
| 147 | echo '<div class="xml-element lvl-' . esc_attr($lvl) . ' lvl-mod4-' . esc_attr($lvl % 4) . '" title="' . esc_attr($path) . '">'; |
| 148 | //if ($el->hasAttributes()){ |
| 149 | echo '<div class="xml-element-xpaths">'; self::render_element_xpaths($el, $alternativePath, $ind, $lvl); echo '</div>'; |
| 150 | //} |
| 151 | if ($el->hasChildNodes()) { |
| 152 | $is_render_collapsed = $ind > 1; |
| 153 | if ($el->childNodes->length > 1 or ! $el->childNodes->item(0) instanceof DOMText or strlen(trim($el->childNodes->item(0)->wholeText)) > 40) { |
| 154 | echo '<div class="xml-expander">' . ($is_render_collapsed ? '+' : '-') . '</div>'; |
| 155 | } |
| 156 | echo '<div class="xml-tag opening"><<span class="xml-tag-name">' . esc_html($el->nodeName) . '</span>'; self::render_xml_attributes($el, $path . '/'); echo '></div>'; |
| 157 | if (1 == $el->childNodes->length and $el->childNodes->item(0) instanceof DOMText) { |
| 158 | $item = $el->childNodes->item(0); |
| 159 | if (!empty($item->wholeText)){ |
| 160 | self::render_xml_text(trim($item->wholeText), $shorten, $is_render_collapsed); |
| 161 | } |
| 162 | else{ |
| 163 | self::render_xml_text(trim($item->nodeValue), $shorten, $is_render_collapsed); |
| 164 | } |
| 165 | } else { |
| 166 | echo '<div class="xml-content' . ($is_render_collapsed ? ' collapsed' : '') . '">'; |
| 167 | $indexes = array(); |
| 168 | foreach ($el->childNodes as $eli => $child) { |
| 169 | if ($child instanceof DOMElement) { |
| 170 | empty($indexes[$child->nodeName]) and $indexes[$child->nodeName] = 0; $indexes[$child->nodeName]++; |
| 171 | if ( $render_whole_tree || $indexes[$child->nodeName] === 1){ |
| 172 | self::render_xml_element($child, $shorten, $path . '/', $indexes[$child->nodeName], $lvl + 1); |
| 173 | } |
| 174 | } elseif ($child instanceof DOMCdataSection) { |
| 175 | self::render_xml_text(trim($child->wholeText), $shorten, false, true); |
| 176 | } elseif ($child instanceof DOMText) { |
| 177 | if ( $el->childNodes->item($eli - 1) and ($el->childNodes->item($eli - 1) instanceof DOMCdataSection) ){ |
| 178 | |
| 179 | } |
| 180 | elseif( $el->childNodes->item($eli + 1) and ($el->childNodes->item($eli + 1) instanceof DOMCdataSection) ){ |
| 181 | |
| 182 | } |
| 183 | else{ |
| 184 | self::render_xml_text(trim($child->wholeText), $shorten); |
| 185 | } |
| 186 | } elseif ($child instanceof DOMComment) { |
| 187 | if (preg_match('%\[pmxi_more:(\d+)\]%', $child->nodeValue, $mtch)) { |
| 188 | $no = intval($mtch[1]); |
| 189 | echo '<div class="xml-more">[ ⇓ ' . wp_kses( /* translators: 1: count, 2: element/elements label */ sprintf(__('<strong>%1$s</strong> %2$s more', 'wp-all-import'), intval($no), esc_html(_n('element', 'elements', $no, 'wp-all-import'))), array('strong' => array()) ) . ' ⇓ ]</div>'; |
| 190 | } |
| 191 | } |
| 192 | } |
| 193 | echo '</div>'; |
| 194 | } |
| 195 | echo '<div class="xml-tag closing"></<span class="xml-tag-name">' . esc_html($el->nodeName) . '</span>></div>'; |
| 196 | } else { |
| 197 | echo '<div class="xml-tag opening empty"><<span class="xml-tag-name">' . esc_html($el->nodeName) . '</span>'; self::render_xml_attributes($el); echo '/></div>'; |
| 198 | } |
| 199 | echo '</div>'; |
| 200 | } |
| 201 | |
| 202 | protected static function render_xml_text($text, $shorten = false, $is_render_collapsed = false, $is_cdata = false) |
| 203 | { |
| 204 | if (empty($text) and 0 !== (int)$text) { |
| 205 | return; // do not display empty text nodes |
| 206 | } |
| 207 | if (preg_match('%\[more:(\d+)\]%', $text, $mtch)) { |
| 208 | $no = intval($mtch[1]); |
| 209 | echo '<div class="xml-more">[ ⇓ ' . wp_kses( /* translators: 1: count, 2: element/elements label */ sprintf(__('<strong>%1$s</strong> %2$s more', 'wp-all-import'), intval($no), esc_html(_n('element', 'elements', $no, 'wp-all-import'))), array('strong' => array()) ) . ' ⇓ ]</div>'; |
| 210 | return; |
| 211 | } |
| 212 | $more = ''; |
| 213 | if ($shorten and preg_match('%^(.*?\s+){20}(?=\S)%', $text, $mtch)) { |
| 214 | $text = $mtch[0]; |
| 215 | $more = '<span class="xml-more">[' . esc_html__('more', 'wp-all-import') . ']</span>'; |
| 216 | } |
| 217 | $is_short = strlen($text) <= 40; |
| 218 | $text = htmlspecialchars($text); |
| 219 | if ($is_cdata){ |
| 220 | $text = "<span class='wpallimport-cdata'>" . htmlspecialchars("<![CDATA[") . "</span> " . $text . " <span class='wpallimport-cdata'>" . htmlspecialchars("]]>") . "</span>"; |
| 221 | } |
| 222 | //$text = preg_replace('%(?<!\s)\b(?!\s|\W[\w\s])|\w{20}%', '$0​', $text); // put explicit breaks for xml content to wrap |
| 223 | echo '<div class="xml-content textonly' . ($is_short ? ' short' : '') . ($is_render_collapsed ? ' collapsed' : '') . '">' . esc_html($text . $more) . '</div>'; |
| 224 | } |
| 225 | |
| 226 | public static function get_xml_path(DOMElement $el, DOMXPath $xpath) |
| 227 | { |
| 228 | for($p = '', $doc = $el; $doc and ! $doc instanceof DOMDocument; $doc = $doc->parentNode) { |
| 229 | if (($ind = $xpath->query('preceding-sibling::' . $doc->nodeName, $doc)->length)) { |
| 230 | $p = '[' . ++$ind . ']' . $p; |
| 231 | } elseif ( ! $doc->parentNode instanceof DOMDocument) { |
| 232 | $p = '[' . ($ind = 1) . ']' . $p; |
| 233 | } |
| 234 | $p = '/' . $doc->nodeName . $p; |
| 235 | } |
| 236 | return $p; |
| 237 | } |
| 238 | |
| 239 | protected static function render_xml_attributes(DOMElement $el, $path = '/') |
| 240 | { |
| 241 | foreach ($el->attributes as $attr) { |
| 242 | echo ' <span class="xml-attr" title="' . esc_attr($path) . '@' . esc_attr($attr->nodeName) . '"><span class="xml-attr-name">' . esc_html($attr->nodeName) . '</span>=<span class="xml-attr-value">"' . esc_attr($attr->value) . '"</span></span>'; |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | protected static function render_element_xpaths(DOMElement $el, $path = '/', $ind = 1, $lvl = 0){ |
| 247 | ?> |
| 248 | <ul id="menu-<?php echo esc_attr(str_replace('/', '-', $path)); ?>" class="ui-helper-hidden"> |
| 249 | <?php foreach ($el->attributes as $attr) : if ( empty($attr->value) ) continue; ?> |
| 250 | <li data-command="action1" title="<?php echo esc_attr($path . '[@'. $attr->nodeName .' = "' . $attr->value . '"]'); ?>"> |
| 251 | <a href="#"><?php echo wp_kses_post($path . '[@'. $attr->nodeName .' = "' . $attr->value) . '"]'; ?></a> |
| 252 | </li> |
| 253 | <li data-command="action2" title="<?php echo esc_attr($path . '[@'. $attr->nodeName .'[contains(.,"' . $attr->value . '")]]'); ?>"> |
| 254 | <a href="#"><?php echo wp_kses_post($path . '[@'. $attr->nodeName .'[contains(.,"' . $attr->value) . '")]]'; ?></a> |
| 255 | </li> |
| 256 | <?php endforeach; ?> |
| 257 | <?php |
| 258 | $altNode = null; |
| 259 | $altNodeText = null; |
| 260 | $parentNode = $el->parentNode; |
| 261 | $grandNode = $parentNode->parentNode; |
| 262 | |
| 263 | if ( ! $grandNode instanceof DOMDocument and $grandNode instanceof DOMElement ){ |
| 264 | |
| 265 | $equalsElements = 0; |
| 266 | foreach ($grandNode->childNodes as $child) { |
| 267 | if ($child instanceof DOMElement) { |
| 268 | if ($child->nodeName == $parentNode->nodeName){ |
| 269 | $equalsElements++; |
| 270 | if ($equalsElements > 1) |
| 271 | break; |
| 272 | } |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | if ($equalsElements > 1){ |
| 277 | if ($parentNode->hasChildNodes()) { |
| 278 | foreach ($parentNode->childNodes as $i => $child) { |
| 279 | if ($child instanceof DOMElement) { |
| 280 | if ($child->nodeName != $el->nodeName){ |
| 281 | $altNode = $child; |
| 282 | if ($child->hasChildNodes()){ |
| 283 | foreach ($child->childNodes as $i => $txtChild) { |
| 284 | if ($txtChild instanceof DOMText) { |
| 285 | $altNodeText = $txtChild; |
| 286 | break; |
| 287 | } |
| 288 | } |
| 289 | } |
| 290 | break; |
| 291 | } |
| 292 | } |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | if ( ! empty($altNode) and !empty($altNodeText) ){ |
| 297 | |
| 298 | $pathArgs = explode('/', $path); |
| 299 | array_pop($pathArgs); |
| 300 | array_pop($pathArgs); |
| 301 | $vpath = esc_attr(implode('/', $pathArgs) . '/' . $parentNode->nodeName . '[contains('. $altNode->nodeName .',"' . esc_attr($altNodeText->wholeText) . '")]/' . $el->nodeName); |
| 302 | ?> |
| 303 | <li data-command="action3" title="<?php echo esc_attr($vpath); ?>"> |
| 304 | <a href="#"><?php echo esc_html($vpath); ?></a> |
| 305 | </li> |
| 306 | <?php |
| 307 | |
| 308 | } |
| 309 | } |
| 310 | } |
| 311 | ?> |
| 312 | </ul> |
| 313 | <?php |
| 314 | } |
| 315 | } |
| 316 | } |