12 namespace fpoirotte\XRL;
34 \XMLReader::NONE =>
'NONE',
35 \XMLReader::ELEMENT =>
'ELEMENT',
36 \XMLReader::ATTRIBUTE =>
'ATTRIBUTE',
37 \XMLReader::TEXT =>
'TEXT',
38 \XMLReader::CDATA =>
'CDATA',
39 \XMLReader::ENTITY_REF =>
'ENTITY_REF',
40 \XMLReader::ENTITY =>
'ENTITY',
41 \XMLReader::PI =>
'PI',
42 \XMLReader::COMMENT =>
'COMMENT',
43 \XMLReader::DOC =>
'DOC',
44 \XMLReader::DOC_TYPE =>
'DOC_TYPE',
45 \XMLReader::DOC_FRAGMENT =>
'DOC_FRAGMENT',
46 \XMLReader::NOTATION =>
'NOTATION',
47 \XMLReader::WHITESPACE =>
'WHITESPACE',
48 \XMLReader::SIGNIFICANT_WHITESPACE =>
'SIGNIFICANT_WHITESPACE',
49 \XMLReader::END_ELEMENT =>
'END_ELEMENT',
50 \XMLReader::END_ENTITY =>
'END_ENTITY',
51 \XMLReader::XML_DECLARATION =>
'XML_DECLARATION',
76 throw new \InvalidArgumentException(
'Not a boolean');
81 $timezone = new \DateTimeZone(@date_default_timezone_get());
83 throw new \InvalidArgumentException($e->getMessage(), $e->getCode());
88 $this->currentNode = null;
116 if (!is_string($URI)) {
117 throw new \InvalidArgumentException(
'Not a string');
120 if (!is_bool($request)) {
121 throw new \InvalidArgumentException(
'Not a boolean');
124 $this->currentNode = null;
125 $reader = new \XMLReader();
126 $reader->open($URI, null, LIBXML_NONET | LIBXML_NOENT);
127 if ($this->validate) {
128 $schema = dirname(__DIR__) .
129 DIRECTORY_SEPARATOR .
'data' .
131 $schema .= $request ?
'request.rng' :
'response.rng';
132 $reader->setRelaxNGSchema($schema);
149 if ($this->currentNode !== null) {
153 $this->currentNode = new \fpoirotte\XRL\Node($reader, $this->validate,
true);
164 if (!$this->currentNode->emptyNodeExpansionWorked()) {
165 $this->currentNode = null;
192 $type = $node->nodeType;
193 if ($type !== \XMLReader::ELEMENT) {
194 $type = isset(self::$types[$type]) ? self::$types[$type] :
"#$type";
195 throw new \InvalidArgumentException(
196 "Expected an opening $expectedTag tag ".
197 "but got a node of type $type instead"
201 $readTag = $node->name;
202 if ($readTag !== $expectedTag) {
203 throw new \InvalidArgumentException(
204 "Got opening tag for $readTag instead of $expectedTag"
234 $type = $node->nodeType;
235 if ($type !== \XMLReader::END_ELEMENT) {
236 $type = isset(self::$types[$type]) ? self::$types[$type] :
"#$type";
237 throw new \InvalidArgumentException(
238 "Expected a closing $expectedTag tag ".
239 "but got a node of type $type instead"
243 $readTag = $node->name;
244 if ($readTag !== $expectedTag) {
245 throw new \InvalidArgumentException(
246 "Got closing tag for $readTag instead of $expectedTag"
274 $type = $node->nodeType;
275 if ($type !== \XMLReader::TEXT) {
276 $type = isset(self::$types[$type]) ? self::$types[$type] :
"#$type";
277 throw new \InvalidArgumentException(
278 "Expected a text node, but got ".
279 "a node of type $type instead"
283 $value = $node->value;
310 protected static function checkType(array $allowedTypes, $type, $value)
312 if (count($allowedTypes) && !in_array($type, $allowedTypes)) {
313 $allowed = implode(
', ', $allowedTypes);
314 throw new \InvalidArgumentException(
315 "Expected one of: $allowed; got $type"
342 protected function decodeValue(\XMLReader $reader, array $allowedTypes = array())
348 'nil' =>
'\\fpoirotte\\XRL\\Types\\Nil',
349 'i4' =>
'\\fpoirotte\\XRL\\Types\\I4',
350 'i8' =>
'\\fpoirotte\\XRL\\Types\\I8',
351 'int' =>
'\\fpoirotte\\XRL\\Types\\Int',
352 'boolean' =>
'\\fpoirotte\\XRL\\Types\\Boolean',
353 'string' =>
'\\fpoirotte\\XRL\\Types\\String',
354 'double' =>
'\\fpoirotte\\XRL\\Types\\Double',
355 'dateTime.iso8601' =>
'\\fpoirotte\\XRL\\Types\\DateTimeIso8601',
356 'base64' =>
'\\fpoirotte\\XRL\\Types\\Base64',
360 '{http://ws.apache.org/xmlrpc/namespaces/extensions}nil'
361 =>
'\\fpoirotte\\XRL\\Types\\Nil',
362 '{http://ws.apache.org/xmlrpc/namespaces/extensions}i1'
363 =>
'\\fpoirotte\\XRL\\Types\\I1',
364 '{http://ws.apache.org/xmlrpc/namespaces/extensions}i8'
365 =>
'\\fpoirotte\\XRL\\Types\\I8',
366 '{http://ws.apache.org/xmlrpc/namespaces/extensions}i2'
367 =>
'\\fpoirotte\\XRL\\Types\\I2',
368 '{http://ws.apache.org/xmlrpc/namespaces/extensions}biginteger'
369 =>
'\\fpoirotte\\XRL\\Types\\BigInteger',
370 '{http://ws.apache.org/xmlrpc/namespaces/extensions}dateTime'
371 =>
'\\fpoirotte\\XRL\\Types\\DateTime',
374 foreach (
$types as $type => $cls) {
377 }
catch (\InvalidArgumentException $e) {
383 }
catch (\InvalidArgumentException $e) {
386 if ($type !==
'string' && $type !==
'base64') {
392 $value = $cls::read($value, $this->timezone);
393 return self::checkType($allowedTypes, $type, $value);
400 }
catch (\InvalidArgumentException $error) {
404 $value = new \fpoirotte\XRL\Types\Struct(array());
410 }
catch (\InvalidArgumentException $error) {
428 return self::checkType($allowedTypes,
'struct', $value);
435 }
catch (\InvalidArgumentException $error) {
439 $value = new \fpoirotte\XRL\Types\ArrayType(array());
446 }
catch (\InvalidArgumentException $error) {
458 return self::checkType($allowedTypes,
'array', $value);
464 $this->
expectStartTag($reader,
'{http://ws.apache.org/xmlrpc/namespaces/extensions}dom');
465 }
catch (\InvalidArgumentException $error) {
471 $this->currentNode = new \fpoirotte\XRL\Node($reader, $this->validate,
false);
472 return self::checkType(
474 '{http://ws.apache.org/xmlrpc/namespaces/extensions}dom',
482 }
catch (\InvalidArgumentException $e) {
485 $value = new \fpoirotte\XRL\Types\String($value);
486 return self::checkType($allowedTypes,
'string', $value);
492 if (!is_string($URI)) {
493 throw new \InvalidArgumentException(
'A string was expected');
497 $ldel = libxml_disable_entity_loader(
true);
498 $luie = libxml_use_internal_errors(
true);
499 libxml_clear_errors();
510 }
catch (\InvalidArgumentException $emptyParams) {
519 }
catch (\InvalidArgumentException $endOfParams) {
539 }
catch (\InvalidArgumentException $endOfFile) {
543 throw new \InvalidArgumentException(
'Expected end of document');
546 $request = new \fpoirotte\XRL\Request($methodName, $params);
547 libxml_disable_entity_loader($ldel);
548 libxml_clear_errors();
549 libxml_use_internal_errors($luie);
552 libxml_disable_entity_loader($ldel);
553 libxml_clear_errors();
554 libxml_use_internal_errors($luie);
562 if (!is_string($URI)) {
563 throw new \InvalidArgumentException(
'A string was expected');
568 $ldel = libxml_disable_entity_loader(
true);
569 $luie = libxml_use_internal_errors(
true);
570 libxml_clear_errors();
582 }
catch (\InvalidArgumentException $error) {
588 if (!($response instanceof \fpoirotte\XRL\Types\Struct) ||
589 count($response) != 2) {
590 throw new \UnexpectedValueException(
591 'An associative array with exactly '.
592 'two entries was expected'
596 if (!isset($response[
'faultCode'])) {
597 throw new \DomainException(
'The failure lacks a faultCode');
600 if (!isset($response[
'faultString'])) {
601 throw new \DomainException(
'The failure lacks a faultString');
612 }
catch (\InvalidArgumentException $endOfFile) {
616 throw new \InvalidArgumentException(
'Expected end of document');
620 throw new \fpoirotte\XRL\Exception(
621 (
string) $response[
'faultString'],
622 $response[
'faultCode']->
get()
626 libxml_disable_entity_loader($ldel);
627 libxml_clear_errors();
628 libxml_use_internal_errors($luie);
631 libxml_disable_entity_loader($ldel);
632 libxml_clear_errors();
633 libxml_use_internal_errors($luie);
Interface for an XML-RPC decoder.
$validate
Whether the documents should be validated or not.
$timezone
Timezone used to decode date/times.
static read($value,\DateTimeZone $timezone=null)
static $types
Names for the various types of XML nodes in libxml.
An exception that is used to represent XML-RPC errors.
expectEndTag($reader, $expectedTag)
static checkType(array $allowedTypes, $type, $value)
decodeValue(\XMLReader $reader, array $allowedTypes=array())
getReader($URI, $request)
$currentNode
The fpoirotte::XRL::Node currently being processed.
A decoder that can process XML-RPC requests and responses, with optional XML validation.
expectStartTag($reader, $expectedTag)
__construct(\DateTimeZone $timezone=null, $validate=true)