1: <?php
2:
3: /*
4: * The MIT License (MIT)
5: *
6: * Copyright (c) 2013 Jonathan Vollebregt (jnvsor@gmail.com), Rokas Šleinius (raveren@gmail.com)
7: *
8: * Permission is hereby granted, free of charge, to any person obtaining a copy of
9: * this software and associated documentation files (the "Software"), to deal in
10: * the Software without restriction, including without limitation the rights to
11: * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12: * the Software, and to permit persons to whom the Software is furnished to do so,
13: * subject to the following conditions:
14: *
15: * The above copyright notice and this permission notice shall be included in all
16: * copies or substantial portions of the Software.
17: *
18: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20: * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21: * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22: * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23: * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24: */
25:
26: namespace Kint\Parser;
27:
28: use DOMDocument;
29: use Exception;
30: use Kint\Object\BasicObject;
31: use Kint\Object\Representation\Representation;
32:
33: class XmlPlugin extends Plugin
34: {
35: /**
36: * Which method to parse the variable with.
37: *
38: * DOMDocument provides more information including the text between nodes,
39: * however it's memory usage is very high and it takes longer to parse and
40: * render. Plus it's a pain to work with. So SimpleXML is the default.
41: *
42: * @var string
43: */
44: public static $parse_method = 'SimpleXML';
45:
46: public function getTypes()
47: {
48: return array('string');
49: }
50:
51: public function getTriggers()
52: {
53: return Parser::TRIGGER_SUCCESS;
54: }
55:
56: public function parse(&$var, BasicObject &$o, $trigger)
57: {
58: if ('<?xml' !== \substr($var, 0, 5)) {
59: return;
60: }
61:
62: if (!\method_exists(\get_class($this), 'xmlTo'.self::$parse_method)) {
63: return;
64: }
65:
66: $xml = \call_user_func(array(\get_class($this), 'xmlTo'.self::$parse_method), $var, $o->access_path);
67:
68: if (empty($xml)) {
69: return;
70: }
71:
72: list($xml, $access_path, $name) = $xml;
73:
74: $base_obj = new BasicObject();
75: $base_obj->depth = $o->depth + 1;
76: $base_obj->name = $name;
77: $base_obj->access_path = $access_path;
78:
79: $r = new Representation('XML');
80: $r->contents = $this->parser->parse($xml, $base_obj);
81:
82: $o->addRepresentation($r, 0);
83: }
84:
85: protected static function xmlToSimpleXML($var, $parent_path)
86: {
87: try {
88: $errors = \libxml_use_internal_errors(true);
89: $xml = \simplexml_load_string($var);
90: \libxml_use_internal_errors($errors);
91: } catch (Exception $e) {
92: if (isset($errors)) {
93: \libxml_use_internal_errors($errors);
94: }
95:
96: return;
97: }
98:
99: if (!$xml) {
100: return;
101: }
102:
103: if (null === $parent_path) {
104: $access_path = null;
105: } else {
106: $access_path = 'simplexml_load_string('.$parent_path.')';
107: }
108:
109: $name = $xml->getName();
110:
111: return array($xml, $access_path, $name);
112: }
113:
114: /**
115: * Get the DOMDocument info.
116: *
117: * The documentation of DOMDocument::loadXML() states that while you can
118: * call it statically, it will give an E_STRICT warning. On my system it
119: * actually gives an E_DEPRECATED warning, but it works so we'll just add
120: * an error-silencing '@' to the access path.
121: *
122: * If it errors loading then we wouldn't have gotten this far in the first place.
123: *
124: * @param string $var The XML string
125: * @param null|string $parent_path The path to the parent, in this case the XML string
126: *
127: * @return null|array The root element DOMNode, the access path, and the root element name
128: */
129: protected static function xmlToDOMDocument($var, $parent_path)
130: {
131: // There's no way to check validity in DOMDocument without making errors. For shame!
132: if (!self::xmlToSimpleXML($var, $parent_path)) {
133: return null;
134: }
135:
136: $xml = new DOMDocument();
137: $xml->loadXML($var);
138: $xml = $xml->firstChild;
139:
140: if (null === $parent_path) {
141: $access_path = null;
142: } else {
143: $access_path = '@\\DOMDocument::loadXML('.$parent_path.')->firstChild';
144: }
145:
146: $name = $xml->nodeName;
147:
148: return array($xml, $access_path, $name);
149: }
150: }
151: