@@ -17,296 +17,296 @@ |
||
| 17 | 17 | */ |
| 18 | 18 | class Service |
| 19 | 19 | { |
| 20 | - /** |
|
| 21 | - * This is the element map. It contains a list of XML elements (in clark |
|
| 22 | - * notation) as keys and PHP class names as values. |
|
| 23 | - * |
|
| 24 | - * The PHP class names must implement Sabre\Xml\Element. |
|
| 25 | - * |
|
| 26 | - * Values may also be a callable. In that case the function will be called |
|
| 27 | - * directly. |
|
| 28 | - * |
|
| 29 | - * @var array |
|
| 30 | - */ |
|
| 31 | - public $elementMap = []; |
|
| 32 | - |
|
| 33 | - /** |
|
| 34 | - * This is a list of namespaces that you want to give default prefixes. |
|
| 35 | - * |
|
| 36 | - * You must make sure you create this entire list before starting to write. |
|
| 37 | - * They should be registered on the root element. |
|
| 38 | - * |
|
| 39 | - * @var array |
|
| 40 | - */ |
|
| 41 | - public $namespaceMap = []; |
|
| 42 | - |
|
| 43 | - /** |
|
| 44 | - * This is a list of custom serializers for specific classes. |
|
| 45 | - * |
|
| 46 | - * The writer may use this if you attempt to serialize an object with a |
|
| 47 | - * class that does not implement XmlSerializable. |
|
| 48 | - * |
|
| 49 | - * Instead it will look at this classmap to see if there is a custom |
|
| 50 | - * serializer here. This is useful if you don't want your value objects |
|
| 51 | - * to be responsible for serializing themselves. |
|
| 52 | - * |
|
| 53 | - * The keys in this classmap need to be fully qualified PHP class names, |
|
| 54 | - * the values must be callbacks. The callbacks take two arguments. The |
|
| 55 | - * writer class, and the value that must be written. |
|
| 56 | - * |
|
| 57 | - * function (Writer $writer, object $value) |
|
| 58 | - * |
|
| 59 | - * @var array |
|
| 60 | - */ |
|
| 61 | - public $classMap = []; |
|
| 62 | - |
|
| 63 | - /** |
|
| 64 | - * A bitmask of the LIBXML_* constants. |
|
| 65 | - * |
|
| 66 | - * @var int |
|
| 67 | - */ |
|
| 68 | - public $options = 0; |
|
| 69 | - |
|
| 70 | - /** |
|
| 71 | - * Returns a fresh XML Reader. |
|
| 72 | - */ |
|
| 73 | - public function getReader(): Reader |
|
| 74 | - { |
|
| 75 | - $r = new Reader(); |
|
| 76 | - $r->elementMap = $this->elementMap; |
|
| 77 | - |
|
| 78 | - return $r; |
|
| 79 | - } |
|
| 80 | - |
|
| 81 | - /** |
|
| 82 | - * Returns a fresh xml writer. |
|
| 83 | - */ |
|
| 84 | - public function getWriter(): Writer |
|
| 85 | - { |
|
| 86 | - $w = new Writer(); |
|
| 87 | - $w->namespaceMap = $this->namespaceMap; |
|
| 88 | - $w->classMap = $this->classMap; |
|
| 89 | - |
|
| 90 | - return $w; |
|
| 91 | - } |
|
| 92 | - |
|
| 93 | - /** |
|
| 94 | - * Parses a document in full. |
|
| 95 | - * |
|
| 96 | - * Input may be specified as a string or readable stream resource. |
|
| 97 | - * The returned value is the value of the root document. |
|
| 98 | - * |
|
| 99 | - * Specifying the $contextUri allows the parser to figure out what the URI |
|
| 100 | - * of the document was. This allows relative URIs within the document to be |
|
| 101 | - * expanded easily. |
|
| 102 | - * |
|
| 103 | - * The $rootElementName is specified by reference and will be populated |
|
| 104 | - * with the root element name of the document. |
|
| 105 | - * |
|
| 106 | - * @param string|resource $input |
|
| 107 | - * |
|
| 108 | - * @throws ParseException |
|
| 109 | - * |
|
| 110 | - * @return array|object|string |
|
| 111 | - */ |
|
| 112 | - public function parse($input, string $contextUri = null, string &$rootElementName = null) |
|
| 113 | - { |
|
| 114 | - if (is_resource($input)) { |
|
| 115 | - // Unfortunately the XMLReader doesn't support streams. When it |
|
| 116 | - // does, we can optimize this. |
|
| 117 | - $input = (string) stream_get_contents($input); |
|
| 118 | - } |
|
| 119 | - |
|
| 120 | - // If input is empty, then it's safe to throw an exception |
|
| 121 | - if (empty($input)) { |
|
| 122 | - throw new ParseException('The input element to parse is empty. Do not attempt to parse'); |
|
| 123 | - } |
|
| 124 | - |
|
| 125 | - $r = $this->getReader(); |
|
| 126 | - $r->contextUri = $contextUri; |
|
| 127 | - $r->XML($input, null, $this->options); |
|
| 128 | - |
|
| 129 | - $result = $r->parse(); |
|
| 130 | - $rootElementName = $result['name']; |
|
| 131 | - |
|
| 132 | - return $result['value']; |
|
| 133 | - } |
|
| 134 | - |
|
| 135 | - /** |
|
| 136 | - * Parses a document in full, and specify what the expected root element |
|
| 137 | - * name is. |
|
| 138 | - * |
|
| 139 | - * This function works similar to parse, but the difference is that the |
|
| 140 | - * user can specify what the expected name of the root element should be, |
|
| 141 | - * in clark notation. |
|
| 142 | - * |
|
| 143 | - * This is useful in cases where you expected a specific document to be |
|
| 144 | - * passed, and reduces the amount of if statements. |
|
| 145 | - * |
|
| 146 | - * It's also possible to pass an array of expected rootElements if your |
|
| 147 | - * code may expect more than one document type. |
|
| 148 | - * |
|
| 149 | - * @param string|string[] $rootElementName |
|
| 150 | - * @param string|resource $input |
|
| 151 | - * |
|
| 152 | - * @throws ParseException |
|
| 153 | - * |
|
| 154 | - * @return array|object|string |
|
| 155 | - */ |
|
| 156 | - public function expect($rootElementName, $input, string $contextUri = null) |
|
| 157 | - { |
|
| 158 | - if (is_resource($input)) { |
|
| 159 | - // Unfortunately the XMLReader doesn't support streams. When it |
|
| 160 | - // does, we can optimize this. |
|
| 161 | - $input = (string) stream_get_contents($input); |
|
| 162 | - } |
|
| 163 | - |
|
| 164 | - // If input is empty, then it's safe to throw an exception |
|
| 165 | - if (empty($input)) { |
|
| 166 | - throw new ParseException('The input element to parse is empty. Do not attempt to parse'); |
|
| 167 | - } |
|
| 168 | - |
|
| 169 | - $r = $this->getReader(); |
|
| 170 | - $r->contextUri = $contextUri; |
|
| 171 | - $r->XML($input, null, $this->options); |
|
| 172 | - |
|
| 173 | - $rootElementName = (array) $rootElementName; |
|
| 174 | - |
|
| 175 | - foreach ($rootElementName as &$rEl) { |
|
| 176 | - if ('{' !== $rEl[0]) { |
|
| 177 | - $rEl = '{}'.$rEl; |
|
| 178 | - } |
|
| 179 | - } |
|
| 180 | - |
|
| 181 | - $result = $r->parse(); |
|
| 182 | - if (!in_array($result['name'], $rootElementName, true)) { |
|
| 183 | - throw new ParseException('Expected '.implode(' or ', $rootElementName).' but received '.$result['name'].' as the root element'); |
|
| 184 | - } |
|
| 185 | - |
|
| 186 | - return $result['value']; |
|
| 187 | - } |
|
| 188 | - |
|
| 189 | - /** |
|
| 190 | - * Generates an XML document in one go. |
|
| 191 | - * |
|
| 192 | - * The $rootElement must be specified in clark notation. |
|
| 193 | - * The value must be a string, an array or an object implementing |
|
| 194 | - * XmlSerializable. Basically, anything that's supported by the Writer |
|
| 195 | - * object. |
|
| 196 | - * |
|
| 197 | - * $contextUri can be used to specify a sort of 'root' of the PHP application, |
|
| 198 | - * in case the xml document is used as a http response. |
|
| 199 | - * |
|
| 200 | - * This allows an implementor to easily create URI's relative to the root |
|
| 201 | - * of the domain. |
|
| 202 | - * |
|
| 203 | - * @param string|array|object|XmlSerializable $value |
|
| 204 | - * |
|
| 205 | - * @return string |
|
| 206 | - */ |
|
| 207 | - public function write(string $rootElementName, $value, string $contextUri = null) |
|
| 208 | - { |
|
| 209 | - $w = $this->getWriter(); |
|
| 210 | - $w->openMemory(); |
|
| 211 | - $w->contextUri = $contextUri; |
|
| 212 | - $w->setIndent(true); |
|
| 213 | - $w->startDocument(); |
|
| 214 | - $w->writeElement($rootElementName, $value); |
|
| 215 | - |
|
| 216 | - return $w->outputMemory(); |
|
| 217 | - } |
|
| 218 | - |
|
| 219 | - /** |
|
| 220 | - * Map an XML element to a PHP class. |
|
| 221 | - * |
|
| 222 | - * Calling this function will automatically set up the Reader and Writer |
|
| 223 | - * classes to turn a specific XML element to a PHP class. |
|
| 224 | - * |
|
| 225 | - * For example, given a class such as : |
|
| 226 | - * |
|
| 227 | - * class Author { |
|
| 228 | - * public $firstName; |
|
| 229 | - * public $lastName; |
|
| 230 | - * } |
|
| 231 | - * |
|
| 232 | - * and an XML element such as: |
|
| 233 | - * |
|
| 234 | - * <author xmlns="http://example.org/ns"> |
|
| 235 | - * <firstName>...</firstName> |
|
| 236 | - * <lastName>...</lastName> |
|
| 237 | - * </author> |
|
| 238 | - * |
|
| 239 | - * These can easily be mapped by calling: |
|
| 240 | - * |
|
| 241 | - * $service->mapValueObject('{http://example.org}author', 'Author'); |
|
| 242 | - */ |
|
| 243 | - public function mapValueObject(string $elementName, string $className) |
|
| 244 | - { |
|
| 245 | - list($namespace) = self::parseClarkNotation($elementName); |
|
| 246 | - |
|
| 247 | - $this->elementMap[$elementName] = function (Reader $reader) use ($className, $namespace) { |
|
| 248 | - return \Sabre\Xml\Deserializer\valueObject($reader, $className, $namespace); |
|
| 249 | - }; |
|
| 250 | - $this->classMap[$className] = function (Writer $writer, $valueObject) use ($namespace) { |
|
| 251 | - return \Sabre\Xml\Serializer\valueObject($writer, $valueObject, $namespace); |
|
| 252 | - }; |
|
| 253 | - $this->valueObjectMap[$className] = $elementName; |
|
| 254 | - } |
|
| 255 | - |
|
| 256 | - /** |
|
| 257 | - * Writes a value object. |
|
| 258 | - * |
|
| 259 | - * This function largely behaves similar to write(), except that it's |
|
| 260 | - * intended specifically to serialize a Value Object into an XML document. |
|
| 261 | - * |
|
| 262 | - * The ValueObject must have been previously registered using |
|
| 263 | - * mapValueObject(). |
|
| 264 | - * |
|
| 265 | - * @param object $object |
|
| 266 | - * |
|
| 267 | - * @throws \InvalidArgumentException |
|
| 268 | - */ |
|
| 269 | - public function writeValueObject($object, string $contextUri = null) |
|
| 270 | - { |
|
| 271 | - if (!isset($this->valueObjectMap[get_class($object)])) { |
|
| 272 | - throw new \InvalidArgumentException('"'.get_class($object).'" is not a registered value object class. Register your class with mapValueObject.'); |
|
| 273 | - } |
|
| 274 | - |
|
| 275 | - return $this->write( |
|
| 276 | - $this->valueObjectMap[get_class($object)], |
|
| 277 | - $object, |
|
| 278 | - $contextUri |
|
| 279 | - ); |
|
| 280 | - } |
|
| 281 | - |
|
| 282 | - /** |
|
| 283 | - * Parses a clark-notation string, and returns the namespace and element |
|
| 284 | - * name components. |
|
| 285 | - * |
|
| 286 | - * If the string was invalid, it will throw an InvalidArgumentException. |
|
| 287 | - * |
|
| 288 | - * @throws \InvalidArgumentException |
|
| 289 | - */ |
|
| 290 | - public static function parseClarkNotation(string $str): array |
|
| 291 | - { |
|
| 292 | - static $cache = []; |
|
| 293 | - |
|
| 294 | - if (!isset($cache[$str])) { |
|
| 295 | - if (!preg_match('/^{([^}]*)}(.*)$/', $str, $matches)) { |
|
| 296 | - throw new \InvalidArgumentException('\''.$str.'\' is not a valid clark-notation formatted string'); |
|
| 297 | - } |
|
| 298 | - |
|
| 299 | - $cache[$str] = [ |
|
| 300 | - $matches[1], |
|
| 301 | - $matches[2], |
|
| 302 | - ]; |
|
| 303 | - } |
|
| 304 | - |
|
| 305 | - return $cache[$str]; |
|
| 306 | - } |
|
| 307 | - |
|
| 308 | - /** |
|
| 309 | - * A list of classes and which XML elements they map to. |
|
| 310 | - */ |
|
| 311 | - protected $valueObjectMap = []; |
|
| 20 | + /** |
|
| 21 | + * This is the element map. It contains a list of XML elements (in clark |
|
| 22 | + * notation) as keys and PHP class names as values. |
|
| 23 | + * |
|
| 24 | + * The PHP class names must implement Sabre\Xml\Element. |
|
| 25 | + * |
|
| 26 | + * Values may also be a callable. In that case the function will be called |
|
| 27 | + * directly. |
|
| 28 | + * |
|
| 29 | + * @var array |
|
| 30 | + */ |
|
| 31 | + public $elementMap = []; |
|
| 32 | + |
|
| 33 | + /** |
|
| 34 | + * This is a list of namespaces that you want to give default prefixes. |
|
| 35 | + * |
|
| 36 | + * You must make sure you create this entire list before starting to write. |
|
| 37 | + * They should be registered on the root element. |
|
| 38 | + * |
|
| 39 | + * @var array |
|
| 40 | + */ |
|
| 41 | + public $namespaceMap = []; |
|
| 42 | + |
|
| 43 | + /** |
|
| 44 | + * This is a list of custom serializers for specific classes. |
|
| 45 | + * |
|
| 46 | + * The writer may use this if you attempt to serialize an object with a |
|
| 47 | + * class that does not implement XmlSerializable. |
|
| 48 | + * |
|
| 49 | + * Instead it will look at this classmap to see if there is a custom |
|
| 50 | + * serializer here. This is useful if you don't want your value objects |
|
| 51 | + * to be responsible for serializing themselves. |
|
| 52 | + * |
|
| 53 | + * The keys in this classmap need to be fully qualified PHP class names, |
|
| 54 | + * the values must be callbacks. The callbacks take two arguments. The |
|
| 55 | + * writer class, and the value that must be written. |
|
| 56 | + * |
|
| 57 | + * function (Writer $writer, object $value) |
|
| 58 | + * |
|
| 59 | + * @var array |
|
| 60 | + */ |
|
| 61 | + public $classMap = []; |
|
| 62 | + |
|
| 63 | + /** |
|
| 64 | + * A bitmask of the LIBXML_* constants. |
|
| 65 | + * |
|
| 66 | + * @var int |
|
| 67 | + */ |
|
| 68 | + public $options = 0; |
|
| 69 | + |
|
| 70 | + /** |
|
| 71 | + * Returns a fresh XML Reader. |
|
| 72 | + */ |
|
| 73 | + public function getReader(): Reader |
|
| 74 | + { |
|
| 75 | + $r = new Reader(); |
|
| 76 | + $r->elementMap = $this->elementMap; |
|
| 77 | + |
|
| 78 | + return $r; |
|
| 79 | + } |
|
| 80 | + |
|
| 81 | + /** |
|
| 82 | + * Returns a fresh xml writer. |
|
| 83 | + */ |
|
| 84 | + public function getWriter(): Writer |
|
| 85 | + { |
|
| 86 | + $w = new Writer(); |
|
| 87 | + $w->namespaceMap = $this->namespaceMap; |
|
| 88 | + $w->classMap = $this->classMap; |
|
| 89 | + |
|
| 90 | + return $w; |
|
| 91 | + } |
|
| 92 | + |
|
| 93 | + /** |
|
| 94 | + * Parses a document in full. |
|
| 95 | + * |
|
| 96 | + * Input may be specified as a string or readable stream resource. |
|
| 97 | + * The returned value is the value of the root document. |
|
| 98 | + * |
|
| 99 | + * Specifying the $contextUri allows the parser to figure out what the URI |
|
| 100 | + * of the document was. This allows relative URIs within the document to be |
|
| 101 | + * expanded easily. |
|
| 102 | + * |
|
| 103 | + * The $rootElementName is specified by reference and will be populated |
|
| 104 | + * with the root element name of the document. |
|
| 105 | + * |
|
| 106 | + * @param string|resource $input |
|
| 107 | + * |
|
| 108 | + * @throws ParseException |
|
| 109 | + * |
|
| 110 | + * @return array|object|string |
|
| 111 | + */ |
|
| 112 | + public function parse($input, string $contextUri = null, string &$rootElementName = null) |
|
| 113 | + { |
|
| 114 | + if (is_resource($input)) { |
|
| 115 | + // Unfortunately the XMLReader doesn't support streams. When it |
|
| 116 | + // does, we can optimize this. |
|
| 117 | + $input = (string) stream_get_contents($input); |
|
| 118 | + } |
|
| 119 | + |
|
| 120 | + // If input is empty, then it's safe to throw an exception |
|
| 121 | + if (empty($input)) { |
|
| 122 | + throw new ParseException('The input element to parse is empty. Do not attempt to parse'); |
|
| 123 | + } |
|
| 124 | + |
|
| 125 | + $r = $this->getReader(); |
|
| 126 | + $r->contextUri = $contextUri; |
|
| 127 | + $r->XML($input, null, $this->options); |
|
| 128 | + |
|
| 129 | + $result = $r->parse(); |
|
| 130 | + $rootElementName = $result['name']; |
|
| 131 | + |
|
| 132 | + return $result['value']; |
|
| 133 | + } |
|
| 134 | + |
|
| 135 | + /** |
|
| 136 | + * Parses a document in full, and specify what the expected root element |
|
| 137 | + * name is. |
|
| 138 | + * |
|
| 139 | + * This function works similar to parse, but the difference is that the |
|
| 140 | + * user can specify what the expected name of the root element should be, |
|
| 141 | + * in clark notation. |
|
| 142 | + * |
|
| 143 | + * This is useful in cases where you expected a specific document to be |
|
| 144 | + * passed, and reduces the amount of if statements. |
|
| 145 | + * |
|
| 146 | + * It's also possible to pass an array of expected rootElements if your |
|
| 147 | + * code may expect more than one document type. |
|
| 148 | + * |
|
| 149 | + * @param string|string[] $rootElementName |
|
| 150 | + * @param string|resource $input |
|
| 151 | + * |
|
| 152 | + * @throws ParseException |
|
| 153 | + * |
|
| 154 | + * @return array|object|string |
|
| 155 | + */ |
|
| 156 | + public function expect($rootElementName, $input, string $contextUri = null) |
|
| 157 | + { |
|
| 158 | + if (is_resource($input)) { |
|
| 159 | + // Unfortunately the XMLReader doesn't support streams. When it |
|
| 160 | + // does, we can optimize this. |
|
| 161 | + $input = (string) stream_get_contents($input); |
|
| 162 | + } |
|
| 163 | + |
|
| 164 | + // If input is empty, then it's safe to throw an exception |
|
| 165 | + if (empty($input)) { |
|
| 166 | + throw new ParseException('The input element to parse is empty. Do not attempt to parse'); |
|
| 167 | + } |
|
| 168 | + |
|
| 169 | + $r = $this->getReader(); |
|
| 170 | + $r->contextUri = $contextUri; |
|
| 171 | + $r->XML($input, null, $this->options); |
|
| 172 | + |
|
| 173 | + $rootElementName = (array) $rootElementName; |
|
| 174 | + |
|
| 175 | + foreach ($rootElementName as &$rEl) { |
|
| 176 | + if ('{' !== $rEl[0]) { |
|
| 177 | + $rEl = '{}'.$rEl; |
|
| 178 | + } |
|
| 179 | + } |
|
| 180 | + |
|
| 181 | + $result = $r->parse(); |
|
| 182 | + if (!in_array($result['name'], $rootElementName, true)) { |
|
| 183 | + throw new ParseException('Expected '.implode(' or ', $rootElementName).' but received '.$result['name'].' as the root element'); |
|
| 184 | + } |
|
| 185 | + |
|
| 186 | + return $result['value']; |
|
| 187 | + } |
|
| 188 | + |
|
| 189 | + /** |
|
| 190 | + * Generates an XML document in one go. |
|
| 191 | + * |
|
| 192 | + * The $rootElement must be specified in clark notation. |
|
| 193 | + * The value must be a string, an array or an object implementing |
|
| 194 | + * XmlSerializable. Basically, anything that's supported by the Writer |
|
| 195 | + * object. |
|
| 196 | + * |
|
| 197 | + * $contextUri can be used to specify a sort of 'root' of the PHP application, |
|
| 198 | + * in case the xml document is used as a http response. |
|
| 199 | + * |
|
| 200 | + * This allows an implementor to easily create URI's relative to the root |
|
| 201 | + * of the domain. |
|
| 202 | + * |
|
| 203 | + * @param string|array|object|XmlSerializable $value |
|
| 204 | + * |
|
| 205 | + * @return string |
|
| 206 | + */ |
|
| 207 | + public function write(string $rootElementName, $value, string $contextUri = null) |
|
| 208 | + { |
|
| 209 | + $w = $this->getWriter(); |
|
| 210 | + $w->openMemory(); |
|
| 211 | + $w->contextUri = $contextUri; |
|
| 212 | + $w->setIndent(true); |
|
| 213 | + $w->startDocument(); |
|
| 214 | + $w->writeElement($rootElementName, $value); |
|
| 215 | + |
|
| 216 | + return $w->outputMemory(); |
|
| 217 | + } |
|
| 218 | + |
|
| 219 | + /** |
|
| 220 | + * Map an XML element to a PHP class. |
|
| 221 | + * |
|
| 222 | + * Calling this function will automatically set up the Reader and Writer |
|
| 223 | + * classes to turn a specific XML element to a PHP class. |
|
| 224 | + * |
|
| 225 | + * For example, given a class such as : |
|
| 226 | + * |
|
| 227 | + * class Author { |
|
| 228 | + * public $firstName; |
|
| 229 | + * public $lastName; |
|
| 230 | + * } |
|
| 231 | + * |
|
| 232 | + * and an XML element such as: |
|
| 233 | + * |
|
| 234 | + * <author xmlns="http://example.org/ns"> |
|
| 235 | + * <firstName>...</firstName> |
|
| 236 | + * <lastName>...</lastName> |
|
| 237 | + * </author> |
|
| 238 | + * |
|
| 239 | + * These can easily be mapped by calling: |
|
| 240 | + * |
|
| 241 | + * $service->mapValueObject('{http://example.org}author', 'Author'); |
|
| 242 | + */ |
|
| 243 | + public function mapValueObject(string $elementName, string $className) |
|
| 244 | + { |
|
| 245 | + list($namespace) = self::parseClarkNotation($elementName); |
|
| 246 | + |
|
| 247 | + $this->elementMap[$elementName] = function (Reader $reader) use ($className, $namespace) { |
|
| 248 | + return \Sabre\Xml\Deserializer\valueObject($reader, $className, $namespace); |
|
| 249 | + }; |
|
| 250 | + $this->classMap[$className] = function (Writer $writer, $valueObject) use ($namespace) { |
|
| 251 | + return \Sabre\Xml\Serializer\valueObject($writer, $valueObject, $namespace); |
|
| 252 | + }; |
|
| 253 | + $this->valueObjectMap[$className] = $elementName; |
|
| 254 | + } |
|
| 255 | + |
|
| 256 | + /** |
|
| 257 | + * Writes a value object. |
|
| 258 | + * |
|
| 259 | + * This function largely behaves similar to write(), except that it's |
|
| 260 | + * intended specifically to serialize a Value Object into an XML document. |
|
| 261 | + * |
|
| 262 | + * The ValueObject must have been previously registered using |
|
| 263 | + * mapValueObject(). |
|
| 264 | + * |
|
| 265 | + * @param object $object |
|
| 266 | + * |
|
| 267 | + * @throws \InvalidArgumentException |
|
| 268 | + */ |
|
| 269 | + public function writeValueObject($object, string $contextUri = null) |
|
| 270 | + { |
|
| 271 | + if (!isset($this->valueObjectMap[get_class($object)])) { |
|
| 272 | + throw new \InvalidArgumentException('"'.get_class($object).'" is not a registered value object class. Register your class with mapValueObject.'); |
|
| 273 | + } |
|
| 274 | + |
|
| 275 | + return $this->write( |
|
| 276 | + $this->valueObjectMap[get_class($object)], |
|
| 277 | + $object, |
|
| 278 | + $contextUri |
|
| 279 | + ); |
|
| 280 | + } |
|
| 281 | + |
|
| 282 | + /** |
|
| 283 | + * Parses a clark-notation string, and returns the namespace and element |
|
| 284 | + * name components. |
|
| 285 | + * |
|
| 286 | + * If the string was invalid, it will throw an InvalidArgumentException. |
|
| 287 | + * |
|
| 288 | + * @throws \InvalidArgumentException |
|
| 289 | + */ |
|
| 290 | + public static function parseClarkNotation(string $str): array |
|
| 291 | + { |
|
| 292 | + static $cache = []; |
|
| 293 | + |
|
| 294 | + if (!isset($cache[$str])) { |
|
| 295 | + if (!preg_match('/^{([^}]*)}(.*)$/', $str, $matches)) { |
|
| 296 | + throw new \InvalidArgumentException('\''.$str.'\' is not a valid clark-notation formatted string'); |
|
| 297 | + } |
|
| 298 | + |
|
| 299 | + $cache[$str] = [ |
|
| 300 | + $matches[1], |
|
| 301 | + $matches[2], |
|
| 302 | + ]; |
|
| 303 | + } |
|
| 304 | + |
|
| 305 | + return $cache[$str]; |
|
| 306 | + } |
|
| 307 | + |
|
| 308 | + /** |
|
| 309 | + * A list of classes and which XML elements they map to. |
|
| 310 | + */ |
|
| 311 | + protected $valueObjectMap = []; |
|
| 312 | 312 | } |
@@ -244,10 +244,10 @@ |
||
| 244 | 244 | { |
| 245 | 245 | list($namespace) = self::parseClarkNotation($elementName); |
| 246 | 246 | |
| 247 | - $this->elementMap[$elementName] = function (Reader $reader) use ($className, $namespace) { |
|
| 247 | + $this->elementMap[$elementName] = function(Reader $reader) use ($className, $namespace) { |
|
| 248 | 248 | return \Sabre\Xml\Deserializer\valueObject($reader, $className, $namespace); |
| 249 | 249 | }; |
| 250 | - $this->classMap[$className] = function (Writer $writer, $valueObject) use ($namespace) { |
|
| 250 | + $this->classMap[$className] = function(Writer $writer, $valueObject) use ($namespace) { |
|
| 251 | 251 | return \Sabre\Xml\Serializer\valueObject($writer, $valueObject, $namespace); |
| 252 | 252 | }; |
| 253 | 253 | $this->valueObjectMap[$className] = $elementName; |
@@ -37,64 +37,64 @@ |
||
| 37 | 37 | */ |
| 38 | 38 | class Elements implements Xml\Element |
| 39 | 39 | { |
| 40 | - /** |
|
| 41 | - * Value to serialize. |
|
| 42 | - * |
|
| 43 | - * @var array |
|
| 44 | - */ |
|
| 45 | - protected $value; |
|
| 40 | + /** |
|
| 41 | + * Value to serialize. |
|
| 42 | + * |
|
| 43 | + * @var array |
|
| 44 | + */ |
|
| 45 | + protected $value; |
|
| 46 | 46 | |
| 47 | - /** |
|
| 48 | - * Constructor. |
|
| 49 | - */ |
|
| 50 | - public function __construct(array $value = []) |
|
| 51 | - { |
|
| 52 | - $this->value = $value; |
|
| 53 | - } |
|
| 47 | + /** |
|
| 48 | + * Constructor. |
|
| 49 | + */ |
|
| 50 | + public function __construct(array $value = []) |
|
| 51 | + { |
|
| 52 | + $this->value = $value; |
|
| 53 | + } |
|
| 54 | 54 | |
| 55 | - /** |
|
| 56 | - * The xmlSerialize method is called during xml writing. |
|
| 57 | - * |
|
| 58 | - * Use the $writer argument to write its own xml serialization. |
|
| 59 | - * |
|
| 60 | - * An important note: do _not_ create a parent element. Any element |
|
| 61 | - * implementing XmlSerializable should only ever write what's considered |
|
| 62 | - * its 'inner xml'. |
|
| 63 | - * |
|
| 64 | - * The parent of the current element is responsible for writing a |
|
| 65 | - * containing element. |
|
| 66 | - * |
|
| 67 | - * This allows serializers to be re-used for different element names. |
|
| 68 | - * |
|
| 69 | - * If you are opening new elements, you must also close them again. |
|
| 70 | - */ |
|
| 71 | - public function xmlSerialize(Xml\Writer $writer) |
|
| 72 | - { |
|
| 73 | - Serializer\enum($writer, $this->value); |
|
| 74 | - } |
|
| 55 | + /** |
|
| 56 | + * The xmlSerialize method is called during xml writing. |
|
| 57 | + * |
|
| 58 | + * Use the $writer argument to write its own xml serialization. |
|
| 59 | + * |
|
| 60 | + * An important note: do _not_ create a parent element. Any element |
|
| 61 | + * implementing XmlSerializable should only ever write what's considered |
|
| 62 | + * its 'inner xml'. |
|
| 63 | + * |
|
| 64 | + * The parent of the current element is responsible for writing a |
|
| 65 | + * containing element. |
|
| 66 | + * |
|
| 67 | + * This allows serializers to be re-used for different element names. |
|
| 68 | + * |
|
| 69 | + * If you are opening new elements, you must also close them again. |
|
| 70 | + */ |
|
| 71 | + public function xmlSerialize(Xml\Writer $writer) |
|
| 72 | + { |
|
| 73 | + Serializer\enum($writer, $this->value); |
|
| 74 | + } |
|
| 75 | 75 | |
| 76 | - /** |
|
| 77 | - * The deserialize method is called during xml parsing. |
|
| 78 | - * |
|
| 79 | - * This method is called statically, this is because in theory this method |
|
| 80 | - * may be used as a type of constructor, or factory method. |
|
| 81 | - * |
|
| 82 | - * Often you want to return an instance of the current class, but you are |
|
| 83 | - * free to return other data as well. |
|
| 84 | - * |
|
| 85 | - * Important note 2: You are responsible for advancing the reader to the |
|
| 86 | - * next element. Not doing anything will result in a never-ending loop. |
|
| 87 | - * |
|
| 88 | - * If you just want to skip parsing for this element altogether, you can |
|
| 89 | - * just call $reader->next(); |
|
| 90 | - * |
|
| 91 | - * $reader->parseSubTree() will parse the entire sub-tree, and advance to |
|
| 92 | - * the next element. |
|
| 93 | - * |
|
| 94 | - * @return mixed |
|
| 95 | - */ |
|
| 96 | - public static function xmlDeserialize(Xml\Reader $reader) |
|
| 97 | - { |
|
| 98 | - return Deserializer\enum($reader); |
|
| 99 | - } |
|
| 76 | + /** |
|
| 77 | + * The deserialize method is called during xml parsing. |
|
| 78 | + * |
|
| 79 | + * This method is called statically, this is because in theory this method |
|
| 80 | + * may be used as a type of constructor, or factory method. |
|
| 81 | + * |
|
| 82 | + * Often you want to return an instance of the current class, but you are |
|
| 83 | + * free to return other data as well. |
|
| 84 | + * |
|
| 85 | + * Important note 2: You are responsible for advancing the reader to the |
|
| 86 | + * next element. Not doing anything will result in a never-ending loop. |
|
| 87 | + * |
|
| 88 | + * If you just want to skip parsing for this element altogether, you can |
|
| 89 | + * just call $reader->next(); |
|
| 90 | + * |
|
| 91 | + * $reader->parseSubTree() will parse the entire sub-tree, and advance to |
|
| 92 | + * the next element. |
|
| 93 | + * |
|
| 94 | + * @return mixed |
|
| 95 | + */ |
|
| 96 | + public static function xmlDeserialize(Xml\Reader $reader) |
|
| 97 | + { |
|
| 98 | + return Deserializer\enum($reader); |
|
| 99 | + } |
|
| 100 | 100 | } |
@@ -24,76 +24,76 @@ |
||
| 24 | 24 | */ |
| 25 | 25 | class Uri implements Xml\Element |
| 26 | 26 | { |
| 27 | - /** |
|
| 28 | - * Uri element value. |
|
| 29 | - * |
|
| 30 | - * @var string |
|
| 31 | - */ |
|
| 32 | - protected $value; |
|
| 27 | + /** |
|
| 28 | + * Uri element value. |
|
| 29 | + * |
|
| 30 | + * @var string |
|
| 31 | + */ |
|
| 32 | + protected $value; |
|
| 33 | 33 | |
| 34 | - /** |
|
| 35 | - * Constructor. |
|
| 36 | - * |
|
| 37 | - * @param string $value |
|
| 38 | - */ |
|
| 39 | - public function __construct($value) |
|
| 40 | - { |
|
| 41 | - $this->value = $value; |
|
| 42 | - } |
|
| 34 | + /** |
|
| 35 | + * Constructor. |
|
| 36 | + * |
|
| 37 | + * @param string $value |
|
| 38 | + */ |
|
| 39 | + public function __construct($value) |
|
| 40 | + { |
|
| 41 | + $this->value = $value; |
|
| 42 | + } |
|
| 43 | 43 | |
| 44 | - /** |
|
| 45 | - * The xmlSerialize method is called during xml writing. |
|
| 46 | - * |
|
| 47 | - * Use the $writer argument to write its own xml serialization. |
|
| 48 | - * |
|
| 49 | - * An important note: do _not_ create a parent element. Any element |
|
| 50 | - * implementing XmlSerializable should only ever write what's considered |
|
| 51 | - * its 'inner xml'. |
|
| 52 | - * |
|
| 53 | - * The parent of the current element is responsible for writing a |
|
| 54 | - * containing element. |
|
| 55 | - * |
|
| 56 | - * This allows serializers to be re-used for different element names. |
|
| 57 | - * |
|
| 58 | - * If you are opening new elements, you must also close them again. |
|
| 59 | - */ |
|
| 60 | - public function xmlSerialize(Xml\Writer $writer) |
|
| 61 | - { |
|
| 62 | - $writer->text( |
|
| 63 | - \Sabre\Uri\resolve( |
|
| 64 | - $writer->contextUri, |
|
| 65 | - $this->value |
|
| 66 | - ) |
|
| 67 | - ); |
|
| 68 | - } |
|
| 44 | + /** |
|
| 45 | + * The xmlSerialize method is called during xml writing. |
|
| 46 | + * |
|
| 47 | + * Use the $writer argument to write its own xml serialization. |
|
| 48 | + * |
|
| 49 | + * An important note: do _not_ create a parent element. Any element |
|
| 50 | + * implementing XmlSerializable should only ever write what's considered |
|
| 51 | + * its 'inner xml'. |
|
| 52 | + * |
|
| 53 | + * The parent of the current element is responsible for writing a |
|
| 54 | + * containing element. |
|
| 55 | + * |
|
| 56 | + * This allows serializers to be re-used for different element names. |
|
| 57 | + * |
|
| 58 | + * If you are opening new elements, you must also close them again. |
|
| 59 | + */ |
|
| 60 | + public function xmlSerialize(Xml\Writer $writer) |
|
| 61 | + { |
|
| 62 | + $writer->text( |
|
| 63 | + \Sabre\Uri\resolve( |
|
| 64 | + $writer->contextUri, |
|
| 65 | + $this->value |
|
| 66 | + ) |
|
| 67 | + ); |
|
| 68 | + } |
|
| 69 | 69 | |
| 70 | - /** |
|
| 71 | - * This method is called during xml parsing. |
|
| 72 | - * |
|
| 73 | - * This method is called statically, this is because in theory this method |
|
| 74 | - * may be used as a type of constructor, or factory method. |
|
| 75 | - * |
|
| 76 | - * Often you want to return an instance of the current class, but you are |
|
| 77 | - * free to return other data as well. |
|
| 78 | - * |
|
| 79 | - * Important note 2: You are responsible for advancing the reader to the |
|
| 80 | - * next element. Not doing anything will result in a never-ending loop. |
|
| 81 | - * |
|
| 82 | - * If you just want to skip parsing for this element altogether, you can |
|
| 83 | - * just call $reader->next(); |
|
| 84 | - * |
|
| 85 | - * $reader->parseSubTree() will parse the entire sub-tree, and advance to |
|
| 86 | - * the next element. |
|
| 87 | - * |
|
| 88 | - * @return mixed |
|
| 89 | - */ |
|
| 90 | - public static function xmlDeserialize(Xml\Reader $reader) |
|
| 91 | - { |
|
| 92 | - return new self( |
|
| 93 | - \Sabre\Uri\resolve( |
|
| 94 | - (string) $reader->contextUri, |
|
| 95 | - $reader->readText() |
|
| 96 | - ) |
|
| 97 | - ); |
|
| 98 | - } |
|
| 70 | + /** |
|
| 71 | + * This method is called during xml parsing. |
|
| 72 | + * |
|
| 73 | + * This method is called statically, this is because in theory this method |
|
| 74 | + * may be used as a type of constructor, or factory method. |
|
| 75 | + * |
|
| 76 | + * Often you want to return an instance of the current class, but you are |
|
| 77 | + * free to return other data as well. |
|
| 78 | + * |
|
| 79 | + * Important note 2: You are responsible for advancing the reader to the |
|
| 80 | + * next element. Not doing anything will result in a never-ending loop. |
|
| 81 | + * |
|
| 82 | + * If you just want to skip parsing for this element altogether, you can |
|
| 83 | + * just call $reader->next(); |
|
| 84 | + * |
|
| 85 | + * $reader->parseSubTree() will parse the entire sub-tree, and advance to |
|
| 86 | + * the next element. |
|
| 87 | + * |
|
| 88 | + * @return mixed |
|
| 89 | + */ |
|
| 90 | + public static function xmlDeserialize(Xml\Reader $reader) |
|
| 91 | + { |
|
| 92 | + return new self( |
|
| 93 | + \Sabre\Uri\resolve( |
|
| 94 | + (string) $reader->contextUri, |
|
| 95 | + $reader->readText() |
|
| 96 | + ) |
|
| 97 | + ); |
|
| 98 | + } |
|
| 99 | 99 | } |
@@ -24,125 +24,125 @@ |
||
| 24 | 24 | */ |
| 25 | 25 | class XmlFragment implements Element |
| 26 | 26 | { |
| 27 | - /** |
|
| 28 | - * The inner XML value. |
|
| 29 | - * |
|
| 30 | - * @var string |
|
| 31 | - */ |
|
| 32 | - protected $xml; |
|
| 27 | + /** |
|
| 28 | + * The inner XML value. |
|
| 29 | + * |
|
| 30 | + * @var string |
|
| 31 | + */ |
|
| 32 | + protected $xml; |
|
| 33 | 33 | |
| 34 | - /** |
|
| 35 | - * Constructor. |
|
| 36 | - */ |
|
| 37 | - public function __construct(string $xml) |
|
| 38 | - { |
|
| 39 | - $this->xml = $xml; |
|
| 40 | - } |
|
| 34 | + /** |
|
| 35 | + * Constructor. |
|
| 36 | + */ |
|
| 37 | + public function __construct(string $xml) |
|
| 38 | + { |
|
| 39 | + $this->xml = $xml; |
|
| 40 | + } |
|
| 41 | 41 | |
| 42 | - /** |
|
| 43 | - * Returns the inner XML document. |
|
| 44 | - */ |
|
| 45 | - public function getXml(): string |
|
| 46 | - { |
|
| 47 | - return $this->xml; |
|
| 48 | - } |
|
| 42 | + /** |
|
| 43 | + * Returns the inner XML document. |
|
| 44 | + */ |
|
| 45 | + public function getXml(): string |
|
| 46 | + { |
|
| 47 | + return $this->xml; |
|
| 48 | + } |
|
| 49 | 49 | |
| 50 | - /** |
|
| 51 | - * The xmlSerialize method is called during xml writing. |
|
| 52 | - * |
|
| 53 | - * Use the $writer argument to write its own xml serialization. |
|
| 54 | - * |
|
| 55 | - * An important note: do _not_ create a parent element. Any element |
|
| 56 | - * implementing XmlSerializable should only ever write what's considered |
|
| 57 | - * its 'inner xml'. |
|
| 58 | - * |
|
| 59 | - * The parent of the current element is responsible for writing a |
|
| 60 | - * containing element. |
|
| 61 | - * |
|
| 62 | - * This allows serializers to be re-used for different element names. |
|
| 63 | - * |
|
| 64 | - * If you are opening new elements, you must also close them again. |
|
| 65 | - */ |
|
| 66 | - public function xmlSerialize(Writer $writer) |
|
| 67 | - { |
|
| 68 | - $reader = new Reader(); |
|
| 50 | + /** |
|
| 51 | + * The xmlSerialize method is called during xml writing. |
|
| 52 | + * |
|
| 53 | + * Use the $writer argument to write its own xml serialization. |
|
| 54 | + * |
|
| 55 | + * An important note: do _not_ create a parent element. Any element |
|
| 56 | + * implementing XmlSerializable should only ever write what's considered |
|
| 57 | + * its 'inner xml'. |
|
| 58 | + * |
|
| 59 | + * The parent of the current element is responsible for writing a |
|
| 60 | + * containing element. |
|
| 61 | + * |
|
| 62 | + * This allows serializers to be re-used for different element names. |
|
| 63 | + * |
|
| 64 | + * If you are opening new elements, you must also close them again. |
|
| 65 | + */ |
|
| 66 | + public function xmlSerialize(Writer $writer) |
|
| 67 | + { |
|
| 68 | + $reader = new Reader(); |
|
| 69 | 69 | |
| 70 | - // Wrapping the xml in a container, so root-less values can still be |
|
| 71 | - // parsed. |
|
| 72 | - $xml = <<<XML |
|
| 70 | + // Wrapping the xml in a container, so root-less values can still be |
|
| 71 | + // parsed. |
|
| 72 | + $xml = <<<XML |
|
| 73 | 73 | <?xml version="1.0"?> |
| 74 | 74 | <xml-fragment xmlns="http://sabre.io/ns">{$this->getXml()}</xml-fragment> |
| 75 | 75 | XML; |
| 76 | 76 | |
| 77 | - $reader->xml($xml); |
|
| 77 | + $reader->xml($xml); |
|
| 78 | 78 | |
| 79 | - while ($reader->read()) { |
|
| 80 | - if ($reader->depth < 1) { |
|
| 81 | - // Skipping the root node. |
|
| 82 | - continue; |
|
| 83 | - } |
|
| 79 | + while ($reader->read()) { |
|
| 80 | + if ($reader->depth < 1) { |
|
| 81 | + // Skipping the root node. |
|
| 82 | + continue; |
|
| 83 | + } |
|
| 84 | 84 | |
| 85 | - switch ($reader->nodeType) { |
|
| 86 | - case Reader::ELEMENT: |
|
| 87 | - $writer->startElement( |
|
| 88 | - (string) $reader->getClark() |
|
| 89 | - ); |
|
| 90 | - $empty = $reader->isEmptyElement; |
|
| 91 | - while ($reader->moveToNextAttribute()) { |
|
| 92 | - switch ($reader->namespaceURI) { |
|
| 93 | - case '': |
|
| 94 | - $writer->writeAttribute($reader->localName, $reader->value); |
|
| 95 | - break; |
|
| 96 | - case 'http://www.w3.org/2000/xmlns/': |
|
| 97 | - // Skip namespace declarations |
|
| 98 | - break; |
|
| 99 | - default: |
|
| 100 | - $writer->writeAttribute((string) $reader->getClark(), $reader->value); |
|
| 101 | - break; |
|
| 102 | - } |
|
| 103 | - } |
|
| 104 | - if ($empty) { |
|
| 105 | - $writer->endElement(); |
|
| 106 | - } |
|
| 107 | - break; |
|
| 108 | - case Reader::CDATA: |
|
| 109 | - case Reader::TEXT: |
|
| 110 | - $writer->text( |
|
| 111 | - $reader->value |
|
| 112 | - ); |
|
| 113 | - break; |
|
| 114 | - case Reader::END_ELEMENT: |
|
| 115 | - $writer->endElement(); |
|
| 116 | - break; |
|
| 117 | - } |
|
| 118 | - } |
|
| 119 | - } |
|
| 85 | + switch ($reader->nodeType) { |
|
| 86 | + case Reader::ELEMENT: |
|
| 87 | + $writer->startElement( |
|
| 88 | + (string) $reader->getClark() |
|
| 89 | + ); |
|
| 90 | + $empty = $reader->isEmptyElement; |
|
| 91 | + while ($reader->moveToNextAttribute()) { |
|
| 92 | + switch ($reader->namespaceURI) { |
|
| 93 | + case '': |
|
| 94 | + $writer->writeAttribute($reader->localName, $reader->value); |
|
| 95 | + break; |
|
| 96 | + case 'http://www.w3.org/2000/xmlns/': |
|
| 97 | + // Skip namespace declarations |
|
| 98 | + break; |
|
| 99 | + default: |
|
| 100 | + $writer->writeAttribute((string) $reader->getClark(), $reader->value); |
|
| 101 | + break; |
|
| 102 | + } |
|
| 103 | + } |
|
| 104 | + if ($empty) { |
|
| 105 | + $writer->endElement(); |
|
| 106 | + } |
|
| 107 | + break; |
|
| 108 | + case Reader::CDATA: |
|
| 109 | + case Reader::TEXT: |
|
| 110 | + $writer->text( |
|
| 111 | + $reader->value |
|
| 112 | + ); |
|
| 113 | + break; |
|
| 114 | + case Reader::END_ELEMENT: |
|
| 115 | + $writer->endElement(); |
|
| 116 | + break; |
|
| 117 | + } |
|
| 118 | + } |
|
| 119 | + } |
|
| 120 | 120 | |
| 121 | - /** |
|
| 122 | - * The deserialize method is called during xml parsing. |
|
| 123 | - * |
|
| 124 | - * This method is called statically, this is because in theory this method |
|
| 125 | - * may be used as a type of constructor, or factory method. |
|
| 126 | - * |
|
| 127 | - * Often you want to return an instance of the current class, but you are |
|
| 128 | - * free to return other data as well. |
|
| 129 | - * |
|
| 130 | - * You are responsible for advancing the reader to the next element. Not |
|
| 131 | - * doing anything will result in a never-ending loop. |
|
| 132 | - * |
|
| 133 | - * If you just want to skip parsing for this element altogether, you can |
|
| 134 | - * just call $reader->next(); |
|
| 135 | - * |
|
| 136 | - * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
| 137 | - * the next element. |
|
| 138 | - * |
|
| 139 | - * @return mixed |
|
| 140 | - */ |
|
| 141 | - public static function xmlDeserialize(Reader $reader) |
|
| 142 | - { |
|
| 143 | - $result = new self($reader->readInnerXml()); |
|
| 144 | - $reader->next(); |
|
| 121 | + /** |
|
| 122 | + * The deserialize method is called during xml parsing. |
|
| 123 | + * |
|
| 124 | + * This method is called statically, this is because in theory this method |
|
| 125 | + * may be used as a type of constructor, or factory method. |
|
| 126 | + * |
|
| 127 | + * Often you want to return an instance of the current class, but you are |
|
| 128 | + * free to return other data as well. |
|
| 129 | + * |
|
| 130 | + * You are responsible for advancing the reader to the next element. Not |
|
| 131 | + * doing anything will result in a never-ending loop. |
|
| 132 | + * |
|
| 133 | + * If you just want to skip parsing for this element altogether, you can |
|
| 134 | + * just call $reader->next(); |
|
| 135 | + * |
|
| 136 | + * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
| 137 | + * the next element. |
|
| 138 | + * |
|
| 139 | + * @return mixed |
|
| 140 | + */ |
|
| 141 | + public static function xmlDeserialize(Reader $reader) |
|
| 142 | + { |
|
| 143 | + $result = new self($reader->readInnerXml()); |
|
| 144 | + $reader->next(); |
|
| 145 | 145 | |
| 146 | - return $result; |
|
| 147 | - } |
|
| 146 | + return $result; |
|
| 147 | + } |
|
| 148 | 148 | } |
@@ -72,7 +72,7 @@ |
||
| 72 | 72 | $xml = <<<XML |
| 73 | 73 | <?xml version="1.0"?> |
| 74 | 74 | <xml-fragment xmlns="http://sabre.io/ns">{$this->getXml()}</xml-fragment> |
| 75 | -XML; |
|
| 75 | +xml; |
|
| 76 | 76 | |
| 77 | 77 | $reader->xml($xml); |
| 78 | 78 | |
@@ -37,64 +37,64 @@ |
||
| 37 | 37 | */ |
| 38 | 38 | class KeyValue implements Xml\Element |
| 39 | 39 | { |
| 40 | - /** |
|
| 41 | - * Value to serialize. |
|
| 42 | - * |
|
| 43 | - * @var array |
|
| 44 | - */ |
|
| 45 | - protected $value; |
|
| 40 | + /** |
|
| 41 | + * Value to serialize. |
|
| 42 | + * |
|
| 43 | + * @var array |
|
| 44 | + */ |
|
| 45 | + protected $value; |
|
| 46 | 46 | |
| 47 | - /** |
|
| 48 | - * Constructor. |
|
| 49 | - */ |
|
| 50 | - public function __construct(array $value = []) |
|
| 51 | - { |
|
| 52 | - $this->value = $value; |
|
| 53 | - } |
|
| 47 | + /** |
|
| 48 | + * Constructor. |
|
| 49 | + */ |
|
| 50 | + public function __construct(array $value = []) |
|
| 51 | + { |
|
| 52 | + $this->value = $value; |
|
| 53 | + } |
|
| 54 | 54 | |
| 55 | - /** |
|
| 56 | - * The xmlSerialize method is called during xml writing. |
|
| 57 | - * |
|
| 58 | - * Use the $writer argument to write its own xml serialization. |
|
| 59 | - * |
|
| 60 | - * An important note: do _not_ create a parent element. Any element |
|
| 61 | - * implementing XmlSerializable should only ever write what's considered |
|
| 62 | - * its 'inner xml'. |
|
| 63 | - * |
|
| 64 | - * The parent of the current element is responsible for writing a |
|
| 65 | - * containing element. |
|
| 66 | - * |
|
| 67 | - * This allows serializers to be re-used for different element names. |
|
| 68 | - * |
|
| 69 | - * If you are opening new elements, you must also close them again. |
|
| 70 | - */ |
|
| 71 | - public function xmlSerialize(Xml\Writer $writer) |
|
| 72 | - { |
|
| 73 | - $writer->write($this->value); |
|
| 74 | - } |
|
| 55 | + /** |
|
| 56 | + * The xmlSerialize method is called during xml writing. |
|
| 57 | + * |
|
| 58 | + * Use the $writer argument to write its own xml serialization. |
|
| 59 | + * |
|
| 60 | + * An important note: do _not_ create a parent element. Any element |
|
| 61 | + * implementing XmlSerializable should only ever write what's considered |
|
| 62 | + * its 'inner xml'. |
|
| 63 | + * |
|
| 64 | + * The parent of the current element is responsible for writing a |
|
| 65 | + * containing element. |
|
| 66 | + * |
|
| 67 | + * This allows serializers to be re-used for different element names. |
|
| 68 | + * |
|
| 69 | + * If you are opening new elements, you must also close them again. |
|
| 70 | + */ |
|
| 71 | + public function xmlSerialize(Xml\Writer $writer) |
|
| 72 | + { |
|
| 73 | + $writer->write($this->value); |
|
| 74 | + } |
|
| 75 | 75 | |
| 76 | - /** |
|
| 77 | - * The deserialize method is called during xml parsing. |
|
| 78 | - * |
|
| 79 | - * This method is called statically, this is because in theory this method |
|
| 80 | - * may be used as a type of constructor, or factory method. |
|
| 81 | - * |
|
| 82 | - * Often you want to return an instance of the current class, but you are |
|
| 83 | - * free to return other data as well. |
|
| 84 | - * |
|
| 85 | - * Important note 2: You are responsible for advancing the reader to the |
|
| 86 | - * next element. Not doing anything will result in a never-ending loop. |
|
| 87 | - * |
|
| 88 | - * If you just want to skip parsing for this element altogether, you can |
|
| 89 | - * just call $reader->next(); |
|
| 90 | - * |
|
| 91 | - * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
| 92 | - * the next element. |
|
| 93 | - * |
|
| 94 | - * @return mixed |
|
| 95 | - */ |
|
| 96 | - public static function xmlDeserialize(Xml\Reader $reader) |
|
| 97 | - { |
|
| 98 | - return Deserializer\keyValue($reader); |
|
| 99 | - } |
|
| 76 | + /** |
|
| 77 | + * The deserialize method is called during xml parsing. |
|
| 78 | + * |
|
| 79 | + * This method is called statically, this is because in theory this method |
|
| 80 | + * may be used as a type of constructor, or factory method. |
|
| 81 | + * |
|
| 82 | + * Often you want to return an instance of the current class, but you are |
|
| 83 | + * free to return other data as well. |
|
| 84 | + * |
|
| 85 | + * Important note 2: You are responsible for advancing the reader to the |
|
| 86 | + * next element. Not doing anything will result in a never-ending loop. |
|
| 87 | + * |
|
| 88 | + * If you just want to skip parsing for this element altogether, you can |
|
| 89 | + * just call $reader->next(); |
|
| 90 | + * |
|
| 91 | + * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
| 92 | + * the next element. |
|
| 93 | + * |
|
| 94 | + * @return mixed |
|
| 95 | + */ |
|
| 96 | + public static function xmlDeserialize(Xml\Reader $reader) |
|
| 97 | + { |
|
| 98 | + return Deserializer\keyValue($reader); |
|
| 99 | + } |
|
| 100 | 100 | } |
@@ -21,39 +21,39 @@ |
||
| 21 | 21 | */ |
| 22 | 22 | class Cdata implements Xml\XmlSerializable |
| 23 | 23 | { |
| 24 | - /** |
|
| 25 | - * CDATA element value. |
|
| 26 | - * |
|
| 27 | - * @var string |
|
| 28 | - */ |
|
| 29 | - protected $value; |
|
| 24 | + /** |
|
| 25 | + * CDATA element value. |
|
| 26 | + * |
|
| 27 | + * @var string |
|
| 28 | + */ |
|
| 29 | + protected $value; |
|
| 30 | 30 | |
| 31 | - /** |
|
| 32 | - * Constructor. |
|
| 33 | - */ |
|
| 34 | - public function __construct(string $value) |
|
| 35 | - { |
|
| 36 | - $this->value = $value; |
|
| 37 | - } |
|
| 31 | + /** |
|
| 32 | + * Constructor. |
|
| 33 | + */ |
|
| 34 | + public function __construct(string $value) |
|
| 35 | + { |
|
| 36 | + $this->value = $value; |
|
| 37 | + } |
|
| 38 | 38 | |
| 39 | - /** |
|
| 40 | - * The xmlSerialize method is called during xml writing. |
|
| 41 | - * |
|
| 42 | - * Use the $writer argument to write its own xml serialization. |
|
| 43 | - * |
|
| 44 | - * An important note: do _not_ create a parent element. Any element |
|
| 45 | - * implementing XmlSerializable should only ever write what's considered |
|
| 46 | - * its 'inner xml'. |
|
| 47 | - * |
|
| 48 | - * The parent of the current element is responsible for writing a |
|
| 49 | - * containing element. |
|
| 50 | - * |
|
| 51 | - * This allows serializers to be re-used for different element names. |
|
| 52 | - * |
|
| 53 | - * If you are opening new elements, you must also close them again. |
|
| 54 | - */ |
|
| 55 | - public function xmlSerialize(Xml\Writer $writer) |
|
| 56 | - { |
|
| 57 | - $writer->writeCData($this->value); |
|
| 58 | - } |
|
| 39 | + /** |
|
| 40 | + * The xmlSerialize method is called during xml writing. |
|
| 41 | + * |
|
| 42 | + * Use the $writer argument to write its own xml serialization. |
|
| 43 | + * |
|
| 44 | + * An important note: do _not_ create a parent element. Any element |
|
| 45 | + * implementing XmlSerializable should only ever write what's considered |
|
| 46 | + * its 'inner xml'. |
|
| 47 | + * |
|
| 48 | + * The parent of the current element is responsible for writing a |
|
| 49 | + * containing element. |
|
| 50 | + * |
|
| 51 | + * This allows serializers to be re-used for different element names. |
|
| 52 | + * |
|
| 53 | + * If you are opening new elements, you must also close them again. |
|
| 54 | + */ |
|
| 55 | + public function xmlSerialize(Xml\Writer $writer) |
|
| 56 | + { |
|
| 57 | + $writer->writeCData($this->value); |
|
| 58 | + } |
|
| 59 | 59 | } |
@@ -19,66 +19,66 @@ |
||
| 19 | 19 | */ |
| 20 | 20 | class Base implements Xml\Element |
| 21 | 21 | { |
| 22 | - /** |
|
| 23 | - * PHP value to serialize. |
|
| 24 | - * |
|
| 25 | - * @var mixed |
|
| 26 | - */ |
|
| 27 | - protected $value; |
|
| 22 | + /** |
|
| 23 | + * PHP value to serialize. |
|
| 24 | + * |
|
| 25 | + * @var mixed |
|
| 26 | + */ |
|
| 27 | + protected $value; |
|
| 28 | 28 | |
| 29 | - /** |
|
| 30 | - * Constructor. |
|
| 31 | - */ |
|
| 32 | - public function __construct($value = null) |
|
| 33 | - { |
|
| 34 | - $this->value = $value; |
|
| 35 | - } |
|
| 29 | + /** |
|
| 30 | + * Constructor. |
|
| 31 | + */ |
|
| 32 | + public function __construct($value = null) |
|
| 33 | + { |
|
| 34 | + $this->value = $value; |
|
| 35 | + } |
|
| 36 | 36 | |
| 37 | - /** |
|
| 38 | - * The xmlSerialize method is called during xml writing. |
|
| 39 | - * |
|
| 40 | - * Use the $writer argument to write its own xml serialization. |
|
| 41 | - * |
|
| 42 | - * An important note: do _not_ create a parent element. Any element |
|
| 43 | - * implementing XmlSerializable should only ever write what's considered |
|
| 44 | - * its 'inner xml'. |
|
| 45 | - * |
|
| 46 | - * The parent of the current element is responsible for writing a |
|
| 47 | - * containing element. |
|
| 48 | - * |
|
| 49 | - * This allows serializers to be re-used for different element names. |
|
| 50 | - * |
|
| 51 | - * If you are opening new elements, you must also close them again. |
|
| 52 | - */ |
|
| 53 | - public function xmlSerialize(Xml\Writer $writer) |
|
| 54 | - { |
|
| 55 | - $writer->write($this->value); |
|
| 56 | - } |
|
| 37 | + /** |
|
| 38 | + * The xmlSerialize method is called during xml writing. |
|
| 39 | + * |
|
| 40 | + * Use the $writer argument to write its own xml serialization. |
|
| 41 | + * |
|
| 42 | + * An important note: do _not_ create a parent element. Any element |
|
| 43 | + * implementing XmlSerializable should only ever write what's considered |
|
| 44 | + * its 'inner xml'. |
|
| 45 | + * |
|
| 46 | + * The parent of the current element is responsible for writing a |
|
| 47 | + * containing element. |
|
| 48 | + * |
|
| 49 | + * This allows serializers to be re-used for different element names. |
|
| 50 | + * |
|
| 51 | + * If you are opening new elements, you must also close them again. |
|
| 52 | + */ |
|
| 53 | + public function xmlSerialize(Xml\Writer $writer) |
|
| 54 | + { |
|
| 55 | + $writer->write($this->value); |
|
| 56 | + } |
|
| 57 | 57 | |
| 58 | - /** |
|
| 59 | - * The deserialize method is called during xml parsing. |
|
| 60 | - * |
|
| 61 | - * This method is called statically, this is because in theory this method |
|
| 62 | - * may be used as a type of constructor, or factory method. |
|
| 63 | - * |
|
| 64 | - * Often you want to return an instance of the current class, but you are |
|
| 65 | - * free to return other data as well. |
|
| 66 | - * |
|
| 67 | - * Important note 2: You are responsible for advancing the reader to the |
|
| 68 | - * next element. Not doing anything will result in a never-ending loop. |
|
| 69 | - * |
|
| 70 | - * If you just want to skip parsing for this element altogether, you can |
|
| 71 | - * just call $reader->next(); |
|
| 72 | - * |
|
| 73 | - * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
| 74 | - * the next element. |
|
| 75 | - * |
|
| 76 | - * @return mixed |
|
| 77 | - */ |
|
| 78 | - public static function xmlDeserialize(Xml\Reader $reader) |
|
| 79 | - { |
|
| 80 | - $subTree = $reader->parseInnerTree(); |
|
| 58 | + /** |
|
| 59 | + * The deserialize method is called during xml parsing. |
|
| 60 | + * |
|
| 61 | + * This method is called statically, this is because in theory this method |
|
| 62 | + * may be used as a type of constructor, or factory method. |
|
| 63 | + * |
|
| 64 | + * Often you want to return an instance of the current class, but you are |
|
| 65 | + * free to return other data as well. |
|
| 66 | + * |
|
| 67 | + * Important note 2: You are responsible for advancing the reader to the |
|
| 68 | + * next element. Not doing anything will result in a never-ending loop. |
|
| 69 | + * |
|
| 70 | + * If you just want to skip parsing for this element altogether, you can |
|
| 71 | + * just call $reader->next(); |
|
| 72 | + * |
|
| 73 | + * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
| 74 | + * the next element. |
|
| 75 | + * |
|
| 76 | + * @return mixed |
|
| 77 | + */ |
|
| 78 | + public static function xmlDeserialize(Xml\Reader $reader) |
|
| 79 | + { |
|
| 80 | + $subTree = $reader->parseInnerTree(); |
|
| 81 | 81 | |
| 82 | - return $subTree; |
|
| 83 | - } |
|
| 82 | + return $subTree; |
|
| 83 | + } |
|
| 84 | 84 | } |
@@ -18,32 +18,32 @@ |
||
| 18 | 18 | */ |
| 19 | 19 | class LibXMLException extends ParseException |
| 20 | 20 | { |
| 21 | - /** |
|
| 22 | - * The error list. |
|
| 23 | - * |
|
| 24 | - * @var \LibXMLError[] |
|
| 25 | - */ |
|
| 26 | - protected $errors; |
|
| 21 | + /** |
|
| 22 | + * The error list. |
|
| 23 | + * |
|
| 24 | + * @var \LibXMLError[] |
|
| 25 | + */ |
|
| 26 | + protected $errors; |
|
| 27 | 27 | |
| 28 | - /** |
|
| 29 | - * Creates the exception. |
|
| 30 | - * |
|
| 31 | - * You should pass a list of LibXMLError objects in its constructor. |
|
| 32 | - * |
|
| 33 | - * @param LibXMLError[] $errors |
|
| 34 | - * @param Throwable $previousException |
|
| 35 | - */ |
|
| 36 | - public function __construct(array $errors, int $code = 0, Throwable $previousException = null) |
|
| 37 | - { |
|
| 38 | - $this->errors = $errors; |
|
| 39 | - parent::__construct($errors[0]->message.' on line '.$errors[0]->line.', column '.$errors[0]->column, $code, $previousException); |
|
| 40 | - } |
|
| 28 | + /** |
|
| 29 | + * Creates the exception. |
|
| 30 | + * |
|
| 31 | + * You should pass a list of LibXMLError objects in its constructor. |
|
| 32 | + * |
|
| 33 | + * @param LibXMLError[] $errors |
|
| 34 | + * @param Throwable $previousException |
|
| 35 | + */ |
|
| 36 | + public function __construct(array $errors, int $code = 0, Throwable $previousException = null) |
|
| 37 | + { |
|
| 38 | + $this->errors = $errors; |
|
| 39 | + parent::__construct($errors[0]->message.' on line '.$errors[0]->line.', column '.$errors[0]->column, $code, $previousException); |
|
| 40 | + } |
|
| 41 | 41 | |
| 42 | - /** |
|
| 43 | - * Returns the LibXML errors. |
|
| 44 | - */ |
|
| 45 | - public function getErrors(): array |
|
| 46 | - { |
|
| 47 | - return $this->errors; |
|
| 48 | - } |
|
| 42 | + /** |
|
| 43 | + * Returns the LibXML errors. |
|
| 44 | + */ |
|
| 45 | + public function getErrors(): array |
|
| 46 | + { |
|
| 47 | + return $this->errors; |
|
| 48 | + } |
|
| 49 | 49 | } |
@@ -32,226 +32,226 @@ |
||
| 32 | 32 | */ |
| 33 | 33 | class Writer extends XMLWriter |
| 34 | 34 | { |
| 35 | - use ContextStackTrait; |
|
| 35 | + use ContextStackTrait; |
|
| 36 | 36 | |
| 37 | - /** |
|
| 38 | - * Any namespace that the writer is asked to write, will be added here. |
|
| 39 | - * |
|
| 40 | - * Any of these elements will get a new namespace definition *every single |
|
| 41 | - * time* they are used, but this array allows the writer to make sure that |
|
| 42 | - * the prefixes are consistent anyway. |
|
| 43 | - * |
|
| 44 | - * @var array |
|
| 45 | - */ |
|
| 46 | - protected $adhocNamespaces = []; |
|
| 37 | + /** |
|
| 38 | + * Any namespace that the writer is asked to write, will be added here. |
|
| 39 | + * |
|
| 40 | + * Any of these elements will get a new namespace definition *every single |
|
| 41 | + * time* they are used, but this array allows the writer to make sure that |
|
| 42 | + * the prefixes are consistent anyway. |
|
| 43 | + * |
|
| 44 | + * @var array |
|
| 45 | + */ |
|
| 46 | + protected $adhocNamespaces = []; |
|
| 47 | 47 | |
| 48 | - /** |
|
| 49 | - * When the first element is written, this flag is set to true. |
|
| 50 | - * |
|
| 51 | - * This ensures that the namespaces in the namespaces map are only written |
|
| 52 | - * once. |
|
| 53 | - * |
|
| 54 | - * @var bool |
|
| 55 | - */ |
|
| 56 | - protected $namespacesWritten = false; |
|
| 48 | + /** |
|
| 49 | + * When the first element is written, this flag is set to true. |
|
| 50 | + * |
|
| 51 | + * This ensures that the namespaces in the namespaces map are only written |
|
| 52 | + * once. |
|
| 53 | + * |
|
| 54 | + * @var bool |
|
| 55 | + */ |
|
| 56 | + protected $namespacesWritten = false; |
|
| 57 | 57 | |
| 58 | - /** |
|
| 59 | - * Writes a value to the output stream. |
|
| 60 | - * |
|
| 61 | - * The following values are supported: |
|
| 62 | - * 1. Scalar values will be written as-is, as text. |
|
| 63 | - * 2. Null values will be skipped (resulting in a short xml tag). |
|
| 64 | - * 3. If a value is an instance of an Element class, writing will be |
|
| 65 | - * delegated to the object. |
|
| 66 | - * 4. If a value is an array, two formats are supported. |
|
| 67 | - * |
|
| 68 | - * Array format 1: |
|
| 69 | - * [ |
|
| 70 | - * "{namespace}name1" => "..", |
|
| 71 | - * "{namespace}name2" => "..", |
|
| 72 | - * ] |
|
| 73 | - * |
|
| 74 | - * One element will be created for each key in this array. The values of |
|
| 75 | - * this array support any format this method supports (this method is |
|
| 76 | - * called recursively). |
|
| 77 | - * |
|
| 78 | - * Array format 2: |
|
| 79 | - * |
|
| 80 | - * [ |
|
| 81 | - * [ |
|
| 82 | - * "name" => "{namespace}name1" |
|
| 83 | - * "value" => "..", |
|
| 84 | - * "attributes" => [ |
|
| 85 | - * "attr" => "attribute value", |
|
| 86 | - * ] |
|
| 87 | - * ], |
|
| 88 | - * [ |
|
| 89 | - * "name" => "{namespace}name1" |
|
| 90 | - * "value" => "..", |
|
| 91 | - * "attributes" => [ |
|
| 92 | - * "attr" => "attribute value", |
|
| 93 | - * ] |
|
| 94 | - * ] |
|
| 95 | - * ] |
|
| 96 | - * |
|
| 97 | - * @param mixed $value |
|
| 98 | - */ |
|
| 99 | - public function write($value) |
|
| 100 | - { |
|
| 101 | - Serializer\standardSerializer($this, $value); |
|
| 102 | - } |
|
| 58 | + /** |
|
| 59 | + * Writes a value to the output stream. |
|
| 60 | + * |
|
| 61 | + * The following values are supported: |
|
| 62 | + * 1. Scalar values will be written as-is, as text. |
|
| 63 | + * 2. Null values will be skipped (resulting in a short xml tag). |
|
| 64 | + * 3. If a value is an instance of an Element class, writing will be |
|
| 65 | + * delegated to the object. |
|
| 66 | + * 4. If a value is an array, two formats are supported. |
|
| 67 | + * |
|
| 68 | + * Array format 1: |
|
| 69 | + * [ |
|
| 70 | + * "{namespace}name1" => "..", |
|
| 71 | + * "{namespace}name2" => "..", |
|
| 72 | + * ] |
|
| 73 | + * |
|
| 74 | + * One element will be created for each key in this array. The values of |
|
| 75 | + * this array support any format this method supports (this method is |
|
| 76 | + * called recursively). |
|
| 77 | + * |
|
| 78 | + * Array format 2: |
|
| 79 | + * |
|
| 80 | + * [ |
|
| 81 | + * [ |
|
| 82 | + * "name" => "{namespace}name1" |
|
| 83 | + * "value" => "..", |
|
| 84 | + * "attributes" => [ |
|
| 85 | + * "attr" => "attribute value", |
|
| 86 | + * ] |
|
| 87 | + * ], |
|
| 88 | + * [ |
|
| 89 | + * "name" => "{namespace}name1" |
|
| 90 | + * "value" => "..", |
|
| 91 | + * "attributes" => [ |
|
| 92 | + * "attr" => "attribute value", |
|
| 93 | + * ] |
|
| 94 | + * ] |
|
| 95 | + * ] |
|
| 96 | + * |
|
| 97 | + * @param mixed $value |
|
| 98 | + */ |
|
| 99 | + public function write($value) |
|
| 100 | + { |
|
| 101 | + Serializer\standardSerializer($this, $value); |
|
| 102 | + } |
|
| 103 | 103 | |
| 104 | - /** |
|
| 105 | - * Opens a new element. |
|
| 106 | - * |
|
| 107 | - * You can either just use a local elementname, or you can use clark- |
|
| 108 | - * notation to start a new element. |
|
| 109 | - * |
|
| 110 | - * Example: |
|
| 111 | - * |
|
| 112 | - * $writer->startElement('{http://www.w3.org/2005/Atom}entry'); |
|
| 113 | - * |
|
| 114 | - * Would result in something like: |
|
| 115 | - * |
|
| 116 | - * <entry xmlns="http://w3.org/2005/Atom"> |
|
| 117 | - * |
|
| 118 | - * Note: this function doesn't have the string typehint, because PHP's |
|
| 119 | - * XMLWriter::startElement doesn't either. |
|
| 120 | - * |
|
| 121 | - * @param string $name |
|
| 122 | - */ |
|
| 123 | - public function startElement($name): bool |
|
| 124 | - { |
|
| 125 | - if ('{' === $name[0]) { |
|
| 126 | - list($namespace, $localName) = |
|
| 127 | - Service::parseClarkNotation($name); |
|
| 104 | + /** |
|
| 105 | + * Opens a new element. |
|
| 106 | + * |
|
| 107 | + * You can either just use a local elementname, or you can use clark- |
|
| 108 | + * notation to start a new element. |
|
| 109 | + * |
|
| 110 | + * Example: |
|
| 111 | + * |
|
| 112 | + * $writer->startElement('{http://www.w3.org/2005/Atom}entry'); |
|
| 113 | + * |
|
| 114 | + * Would result in something like: |
|
| 115 | + * |
|
| 116 | + * <entry xmlns="http://w3.org/2005/Atom"> |
|
| 117 | + * |
|
| 118 | + * Note: this function doesn't have the string typehint, because PHP's |
|
| 119 | + * XMLWriter::startElement doesn't either. |
|
| 120 | + * |
|
| 121 | + * @param string $name |
|
| 122 | + */ |
|
| 123 | + public function startElement($name): bool |
|
| 124 | + { |
|
| 125 | + if ('{' === $name[0]) { |
|
| 126 | + list($namespace, $localName) = |
|
| 127 | + Service::parseClarkNotation($name); |
|
| 128 | 128 | |
| 129 | - if (array_key_exists($namespace, $this->namespaceMap)) { |
|
| 130 | - $result = $this->startElementNS( |
|
| 131 | - '' === $this->namespaceMap[$namespace] ? null : $this->namespaceMap[$namespace], |
|
| 132 | - $localName, |
|
| 133 | - null |
|
| 134 | - ); |
|
| 135 | - } else { |
|
| 136 | - // An empty namespace means it's the global namespace. This is |
|
| 137 | - // allowed, but it mustn't get a prefix. |
|
| 138 | - if ('' === $namespace || null === $namespace) { |
|
| 139 | - $result = $this->startElement($localName); |
|
| 140 | - $this->writeAttribute('xmlns', ''); |
|
| 141 | - } else { |
|
| 142 | - if (!isset($this->adhocNamespaces[$namespace])) { |
|
| 143 | - $this->adhocNamespaces[$namespace] = 'x'.(count($this->adhocNamespaces) + 1); |
|
| 144 | - } |
|
| 145 | - $result = $this->startElementNS($this->adhocNamespaces[$namespace], $localName, $namespace); |
|
| 146 | - } |
|
| 147 | - } |
|
| 148 | - } else { |
|
| 149 | - $result = parent::startElement($name); |
|
| 150 | - } |
|
| 129 | + if (array_key_exists($namespace, $this->namespaceMap)) { |
|
| 130 | + $result = $this->startElementNS( |
|
| 131 | + '' === $this->namespaceMap[$namespace] ? null : $this->namespaceMap[$namespace], |
|
| 132 | + $localName, |
|
| 133 | + null |
|
| 134 | + ); |
|
| 135 | + } else { |
|
| 136 | + // An empty namespace means it's the global namespace. This is |
|
| 137 | + // allowed, but it mustn't get a prefix. |
|
| 138 | + if ('' === $namespace || null === $namespace) { |
|
| 139 | + $result = $this->startElement($localName); |
|
| 140 | + $this->writeAttribute('xmlns', ''); |
|
| 141 | + } else { |
|
| 142 | + if (!isset($this->adhocNamespaces[$namespace])) { |
|
| 143 | + $this->adhocNamespaces[$namespace] = 'x'.(count($this->adhocNamespaces) + 1); |
|
| 144 | + } |
|
| 145 | + $result = $this->startElementNS($this->adhocNamespaces[$namespace], $localName, $namespace); |
|
| 146 | + } |
|
| 147 | + } |
|
| 148 | + } else { |
|
| 149 | + $result = parent::startElement($name); |
|
| 150 | + } |
|
| 151 | 151 | |
| 152 | - if (!$this->namespacesWritten) { |
|
| 153 | - foreach ($this->namespaceMap as $namespace => $prefix) { |
|
| 154 | - $this->writeAttribute(($prefix ? 'xmlns:'.$prefix : 'xmlns'), $namespace); |
|
| 155 | - } |
|
| 156 | - $this->namespacesWritten = true; |
|
| 157 | - } |
|
| 152 | + if (!$this->namespacesWritten) { |
|
| 153 | + foreach ($this->namespaceMap as $namespace => $prefix) { |
|
| 154 | + $this->writeAttribute(($prefix ? 'xmlns:'.$prefix : 'xmlns'), $namespace); |
|
| 155 | + } |
|
| 156 | + $this->namespacesWritten = true; |
|
| 157 | + } |
|
| 158 | 158 | |
| 159 | - return $result; |
|
| 160 | - } |
|
| 159 | + return $result; |
|
| 160 | + } |
|
| 161 | 161 | |
| 162 | - /** |
|
| 163 | - * Write a full element tag and it's contents. |
|
| 164 | - * |
|
| 165 | - * This method automatically closes the element as well. |
|
| 166 | - * |
|
| 167 | - * The element name may be specified in clark-notation. |
|
| 168 | - * |
|
| 169 | - * Examples: |
|
| 170 | - * |
|
| 171 | - * $writer->writeElement('{http://www.w3.org/2005/Atom}author',null); |
|
| 172 | - * becomes: |
|
| 173 | - * <author xmlns="http://www.w3.org/2005" /> |
|
| 174 | - * |
|
| 175 | - * $writer->writeElement('{http://www.w3.org/2005/Atom}author', [ |
|
| 176 | - * '{http://www.w3.org/2005/Atom}name' => 'Evert Pot', |
|
| 177 | - * ]); |
|
| 178 | - * becomes: |
|
| 179 | - * <author xmlns="http://www.w3.org/2005" /><name>Evert Pot</name></author> |
|
| 180 | - * |
|
| 181 | - * Note: this function doesn't have the string typehint, because PHP's |
|
| 182 | - * XMLWriter::startElement doesn't either. |
|
| 183 | - * |
|
| 184 | - * @param array|string|object|null $content |
|
| 185 | - */ |
|
| 186 | - public function writeElement($name, $content = null): bool |
|
| 187 | - { |
|
| 188 | - $this->startElement($name); |
|
| 189 | - if (!is_null($content)) { |
|
| 190 | - $this->write($content); |
|
| 191 | - } |
|
| 192 | - $this->endElement(); |
|
| 162 | + /** |
|
| 163 | + * Write a full element tag and it's contents. |
|
| 164 | + * |
|
| 165 | + * This method automatically closes the element as well. |
|
| 166 | + * |
|
| 167 | + * The element name may be specified in clark-notation. |
|
| 168 | + * |
|
| 169 | + * Examples: |
|
| 170 | + * |
|
| 171 | + * $writer->writeElement('{http://www.w3.org/2005/Atom}author',null); |
|
| 172 | + * becomes: |
|
| 173 | + * <author xmlns="http://www.w3.org/2005" /> |
|
| 174 | + * |
|
| 175 | + * $writer->writeElement('{http://www.w3.org/2005/Atom}author', [ |
|
| 176 | + * '{http://www.w3.org/2005/Atom}name' => 'Evert Pot', |
|
| 177 | + * ]); |
|
| 178 | + * becomes: |
|
| 179 | + * <author xmlns="http://www.w3.org/2005" /><name>Evert Pot</name></author> |
|
| 180 | + * |
|
| 181 | + * Note: this function doesn't have the string typehint, because PHP's |
|
| 182 | + * XMLWriter::startElement doesn't either. |
|
| 183 | + * |
|
| 184 | + * @param array|string|object|null $content |
|
| 185 | + */ |
|
| 186 | + public function writeElement($name, $content = null): bool |
|
| 187 | + { |
|
| 188 | + $this->startElement($name); |
|
| 189 | + if (!is_null($content)) { |
|
| 190 | + $this->write($content); |
|
| 191 | + } |
|
| 192 | + $this->endElement(); |
|
| 193 | 193 | |
| 194 | - return true; |
|
| 195 | - } |
|
| 194 | + return true; |
|
| 195 | + } |
|
| 196 | 196 | |
| 197 | - /** |
|
| 198 | - * Writes a list of attributes. |
|
| 199 | - * |
|
| 200 | - * Attributes are specified as a key->value array. |
|
| 201 | - * |
|
| 202 | - * The key is an attribute name. If the key is a 'localName', the current |
|
| 203 | - * xml namespace is assumed. If it's a 'clark notation key', this namespace |
|
| 204 | - * will be used instead. |
|
| 205 | - */ |
|
| 206 | - public function writeAttributes(array $attributes) |
|
| 207 | - { |
|
| 208 | - foreach ($attributes as $name => $value) { |
|
| 209 | - $this->writeAttribute($name, $value); |
|
| 210 | - } |
|
| 211 | - } |
|
| 197 | + /** |
|
| 198 | + * Writes a list of attributes. |
|
| 199 | + * |
|
| 200 | + * Attributes are specified as a key->value array. |
|
| 201 | + * |
|
| 202 | + * The key is an attribute name. If the key is a 'localName', the current |
|
| 203 | + * xml namespace is assumed. If it's a 'clark notation key', this namespace |
|
| 204 | + * will be used instead. |
|
| 205 | + */ |
|
| 206 | + public function writeAttributes(array $attributes) |
|
| 207 | + { |
|
| 208 | + foreach ($attributes as $name => $value) { |
|
| 209 | + $this->writeAttribute($name, $value); |
|
| 210 | + } |
|
| 211 | + } |
|
| 212 | 212 | |
| 213 | - /** |
|
| 214 | - * Writes a new attribute. |
|
| 215 | - * |
|
| 216 | - * The name may be specified in clark-notation. |
|
| 217 | - * |
|
| 218 | - * Returns true when successful. |
|
| 219 | - * |
|
| 220 | - * Note: this function doesn't have typehints, because for some reason |
|
| 221 | - * PHP's XMLWriter::writeAttribute doesn't either. |
|
| 222 | - * |
|
| 223 | - * @param string $name |
|
| 224 | - * @param string $value |
|
| 225 | - */ |
|
| 226 | - public function writeAttribute($name, $value): bool |
|
| 227 | - { |
|
| 228 | - if ('{' !== $name[0]) { |
|
| 229 | - return parent::writeAttribute($name, $value); |
|
| 230 | - } |
|
| 213 | + /** |
|
| 214 | + * Writes a new attribute. |
|
| 215 | + * |
|
| 216 | + * The name may be specified in clark-notation. |
|
| 217 | + * |
|
| 218 | + * Returns true when successful. |
|
| 219 | + * |
|
| 220 | + * Note: this function doesn't have typehints, because for some reason |
|
| 221 | + * PHP's XMLWriter::writeAttribute doesn't either. |
|
| 222 | + * |
|
| 223 | + * @param string $name |
|
| 224 | + * @param string $value |
|
| 225 | + */ |
|
| 226 | + public function writeAttribute($name, $value): bool |
|
| 227 | + { |
|
| 228 | + if ('{' !== $name[0]) { |
|
| 229 | + return parent::writeAttribute($name, $value); |
|
| 230 | + } |
|
| 231 | 231 | |
| 232 | - list( |
|
| 233 | - $namespace, |
|
| 234 | - $localName |
|
| 235 | - ) = Service::parseClarkNotation($name); |
|
| 232 | + list( |
|
| 233 | + $namespace, |
|
| 234 | + $localName |
|
| 235 | + ) = Service::parseClarkNotation($name); |
|
| 236 | 236 | |
| 237 | - if (array_key_exists($namespace, $this->namespaceMap)) { |
|
| 238 | - // It's an attribute with a namespace we know |
|
| 239 | - return $this->writeAttribute( |
|
| 240 | - $this->namespaceMap[$namespace].':'.$localName, |
|
| 241 | - $value |
|
| 242 | - ); |
|
| 243 | - } |
|
| 237 | + if (array_key_exists($namespace, $this->namespaceMap)) { |
|
| 238 | + // It's an attribute with a namespace we know |
|
| 239 | + return $this->writeAttribute( |
|
| 240 | + $this->namespaceMap[$namespace].':'.$localName, |
|
| 241 | + $value |
|
| 242 | + ); |
|
| 243 | + } |
|
| 244 | 244 | |
| 245 | - // We don't know the namespace, we must add it in-line |
|
| 246 | - if (!isset($this->adhocNamespaces[$namespace])) { |
|
| 247 | - $this->adhocNamespaces[$namespace] = 'x'.(count($this->adhocNamespaces) + 1); |
|
| 248 | - } |
|
| 245 | + // We don't know the namespace, we must add it in-line |
|
| 246 | + if (!isset($this->adhocNamespaces[$namespace])) { |
|
| 247 | + $this->adhocNamespaces[$namespace] = 'x'.(count($this->adhocNamespaces) + 1); |
|
| 248 | + } |
|
| 249 | 249 | |
| 250 | - return $this->writeAttributeNS( |
|
| 251 | - $this->adhocNamespaces[$namespace], |
|
| 252 | - $localName, |
|
| 253 | - $namespace, |
|
| 254 | - $value |
|
| 255 | - ); |
|
| 256 | - } |
|
| 250 | + return $this->writeAttributeNS( |
|
| 251 | + $this->adhocNamespaces[$namespace], |
|
| 252 | + $localName, |
|
| 253 | + $namespace, |
|
| 254 | + $value |
|
| 255 | + ); |
|
| 256 | + } |
|
| 257 | 257 | } |