mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-10-24 22:25:09 +03:00
Sabre XML v4.1.0
This commit is contained in:
parent
e66f325aa3
commit
dfc9420385
13 changed files with 78 additions and 107 deletions
|
|
@ -212,11 +212,13 @@ function valueObject(Reader $reader, string $className, string $namespace): obje
|
|||
|
||||
$reader->read();
|
||||
do {
|
||||
if (Reader::ELEMENT === $reader->nodeType && $reader->namespaceURI == $namespace) {
|
||||
if (Reader::ELEMENT === $reader->nodeType && $reader->namespaceURI === $namespace) {
|
||||
if (property_exists($valueObject, $reader->localName)) {
|
||||
if (is_array($defaultProperties[$reader->localName])) {
|
||||
// @phpstan-ignore property.dynamicName
|
||||
$valueObject->{$reader->localName}[] = $reader->parseCurrentElement()['value'];
|
||||
} else {
|
||||
// @phpstan-ignore property.dynamicName
|
||||
$valueObject->{$reader->localName} = $reader->parseCurrentElement()['value'];
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -19,19 +19,13 @@ use Sabre\Xml;
|
|||
*/
|
||||
class Base implements Xml\Element
|
||||
{
|
||||
/**
|
||||
* @var mixed PHP value to serialize
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $value PHP value to serialize
|
||||
*/
|
||||
public function __construct($value = null)
|
||||
public function __construct(protected $value = null)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -21,17 +21,15 @@ use Sabre\Xml;
|
|||
*/
|
||||
class Cdata implements Xml\XmlSerializable
|
||||
{
|
||||
/**
|
||||
* CDATA element value.
|
||||
*/
|
||||
protected string $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
public function __construct(
|
||||
/**
|
||||
* CDATA element value.
|
||||
*/
|
||||
protected string $value,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -52,6 +50,6 @@ class Cdata implements Xml\XmlSerializable
|
|||
*/
|
||||
public function xmlSerialize(Xml\Writer $writer): void
|
||||
{
|
||||
$writer->writeCData($this->value);
|
||||
$writer->writeCdata($this->value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,21 +37,17 @@ use Sabre\Xml\Serializer;
|
|||
*/
|
||||
class Elements implements Xml\Element
|
||||
{
|
||||
/**
|
||||
* Value to serialize.
|
||||
*
|
||||
* @var array<int, mixed>
|
||||
*/
|
||||
protected array $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array<int, mixed> $value
|
||||
*/
|
||||
public function __construct(array $value = [])
|
||||
{
|
||||
$this->value = $value;
|
||||
public function __construct(
|
||||
/**
|
||||
* Value to serialize.
|
||||
*/
|
||||
protected array $value = [],
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -37,21 +37,17 @@ use Sabre\Xml\Deserializer;
|
|||
*/
|
||||
class KeyValue implements Xml\Element
|
||||
{
|
||||
/**
|
||||
* Value to serialize.
|
||||
*
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
protected array $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array<string, mixed> $value
|
||||
*/
|
||||
public function __construct(array $value = [])
|
||||
{
|
||||
$this->value = $value;
|
||||
public function __construct(
|
||||
/**
|
||||
* Value to serialize.
|
||||
*/
|
||||
protected array $value = [],
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -26,17 +26,15 @@ use function Sabre\Uri\resolve;
|
|||
*/
|
||||
class Uri implements Xml\Element
|
||||
{
|
||||
/**
|
||||
* Uri element value.
|
||||
*/
|
||||
protected string $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
public function __construct(
|
||||
/**
|
||||
* Uri element value.
|
||||
*/
|
||||
protected string $value,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -24,17 +24,15 @@ use Sabre\Xml\Writer;
|
|||
*/
|
||||
class XmlFragment implements Element
|
||||
{
|
||||
/**
|
||||
* The inner XML value.
|
||||
*/
|
||||
protected string $xml;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(string $xml)
|
||||
{
|
||||
$this->xml = $xml;
|
||||
public function __construct(
|
||||
/**
|
||||
* The inner XML value.
|
||||
*/
|
||||
protected string $xml,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -72,7 +70,7 @@ class XmlFragment implements Element
|
|||
<xml-fragment xmlns="http://sabre.io/ns">{$this->getXml()}</xml-fragment>
|
||||
XML;
|
||||
|
||||
$reader->xml($xml);
|
||||
$reader->XML($xml);
|
||||
|
||||
while ($reader->read()) {
|
||||
if ($reader->depth < 1) {
|
||||
|
|
|
|||
|
|
@ -17,13 +17,6 @@ use LibXMLError;
|
|||
*/
|
||||
class LibXMLException extends ParseException
|
||||
{
|
||||
/**
|
||||
* The error list.
|
||||
*
|
||||
* @var \LibXMLError[]
|
||||
*/
|
||||
protected array $errors;
|
||||
|
||||
/**
|
||||
* Creates the exception.
|
||||
*
|
||||
|
|
@ -31,10 +24,12 @@ class LibXMLException extends ParseException
|
|||
*
|
||||
* @param \LibXMLError[] $errors
|
||||
*/
|
||||
public function __construct(array $errors, int $code = 0, ?\Throwable $previousException = null)
|
||||
public function __construct(/**
|
||||
* The error list.
|
||||
*/
|
||||
protected array $errors, int $code = 0, ?\Throwable $previousException = null)
|
||||
{
|
||||
$this->errors = $errors;
|
||||
parent::__construct($errors[0]->message.' on line '.$errors[0]->line.', column '.$errors[0]->column, $code, $previousException);
|
||||
parent::__construct($this->errors[0]->message.' on line '.$this->errors[0]->line.', column '.$this->errors[0]->column, $code, $previousException);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class Reader extends \XMLReader
|
|||
*/
|
||||
public function getClark(): ?string
|
||||
{
|
||||
if (!$this->localName) {
|
||||
if ('' === $this->localName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ class Reader extends \XMLReader
|
|||
if (!$this->read()) {
|
||||
$errors = libxml_get_errors();
|
||||
libxml_clear_errors();
|
||||
if ($errors) {
|
||||
if (count($errors) > 0) {
|
||||
throw new LibXMLException($errors);
|
||||
}
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ class Reader extends \XMLReader
|
|||
// last line of defense in case errors did occur above
|
||||
$errors = libxml_get_errors();
|
||||
libxml_clear_errors();
|
||||
if ($errors) {
|
||||
if (count($errors) > 0) {
|
||||
throw new LibXMLException($errors);
|
||||
}
|
||||
} finally {
|
||||
|
|
@ -153,7 +153,7 @@ class Reader extends \XMLReader
|
|||
if (!$this->read()) {
|
||||
$errors = libxml_get_errors();
|
||||
libxml_clear_errors();
|
||||
if ($errors) {
|
||||
if (count($errors) > 0) {
|
||||
throw new LibXMLException($errors);
|
||||
}
|
||||
throw new ParseException('This should never happen (famous last words)');
|
||||
|
|
@ -165,7 +165,7 @@ class Reader extends \XMLReader
|
|||
if (!$this->isValid()) {
|
||||
$errors = libxml_get_errors();
|
||||
|
||||
if ($errors) {
|
||||
if (count($errors) > 0) {
|
||||
libxml_clear_errors();
|
||||
throw new LibXMLException($errors);
|
||||
}
|
||||
|
|
@ -199,7 +199,7 @@ class Reader extends \XMLReader
|
|||
}
|
||||
}
|
||||
|
||||
return $elements ?: $text;
|
||||
return count($elements) > 0 ? $elements : $text;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -210,8 +210,8 @@ class Reader extends \XMLReader
|
|||
$result = '';
|
||||
$previousDepth = $this->depth;
|
||||
|
||||
while ($this->read() && $this->depth != $previousDepth) {
|
||||
if (in_array($this->nodeType, [\XMLReader::TEXT, \XMLReader::CDATA, \XMLReader::WHITESPACE])) {
|
||||
while ($this->read() && $this->depth !== $previousDepth) {
|
||||
if (in_array($this->nodeType, [\XMLReader::TEXT, \XMLReader::CDATA, \XMLReader::WHITESPACE], true)) {
|
||||
$result .= $this->value;
|
||||
}
|
||||
}
|
||||
|
|
@ -266,7 +266,7 @@ class Reader extends \XMLReader
|
|||
$attributes = [];
|
||||
|
||||
while ($this->moveToNextAttribute()) {
|
||||
if ($this->namespaceURI) {
|
||||
if ('' !== $this->namespaceURI) {
|
||||
// Ignoring 'xmlns', it doesn't make any sense.
|
||||
if ('http://www.w3.org/2000/xmlns/' === $this->namespaceURI) {
|
||||
continue;
|
||||
|
|
@ -290,10 +290,10 @@ class Reader extends \XMLReader
|
|||
public function getDeserializerForElementName(string $name): callable
|
||||
{
|
||||
if (!array_key_exists($name, $this->elementMap)) {
|
||||
if ('{}' == substr($name, 0, 2) && array_key_exists(substr($name, 2), $this->elementMap)) {
|
||||
if (str_starts_with($name, '{}') && array_key_exists(substr($name, 2), $this->elementMap)) {
|
||||
$name = substr($name, 2);
|
||||
} else {
|
||||
return ['Sabre\\Xml\\Element\\Base', 'xmlDeserialize'];
|
||||
return Element\Base::xmlDeserialize(...);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -302,8 +302,8 @@ class Reader extends \XMLReader
|
|||
return $deserializer;
|
||||
}
|
||||
|
||||
if (is_subclass_of($deserializer, 'Sabre\\Xml\\XmlDeserializable')) {
|
||||
return [$deserializer, 'xmlDeserialize'];
|
||||
if (is_subclass_of($deserializer, XmlDeserializable::class)) {
|
||||
return fn (Reader $reader) => $deserializer::xmlDeserialize($reader);
|
||||
}
|
||||
|
||||
throw new \LogicException('Could not use this type as a deserializer: '.get_debug_type($deserializer).' for element: '.$name);
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ function valueObject(Writer $writer, object $valueObject, string $namespace): vo
|
|||
*
|
||||
* You can even mix the two array syntaxes.
|
||||
*
|
||||
* @param string|int|float|bool|array<int|string, mixed>|object $value
|
||||
* @param string|int|float|bool|array<int|string, mixed>|object|null $value
|
||||
*/
|
||||
function standardSerializer(Writer $writer, $value): void
|
||||
{
|
||||
|
|
@ -133,9 +133,9 @@ function standardSerializer(Writer $writer, $value): void
|
|||
} elseif ($value instanceof XmlSerializable) {
|
||||
// XmlSerializable classes or Element classes.
|
||||
$value->xmlSerialize($writer);
|
||||
} elseif (is_object($value) && isset($writer->classMap[get_class($value)])) {
|
||||
} elseif (is_object($value) && isset($writer->classMap[$value::class])) {
|
||||
// It's an object which class appears in the classmap.
|
||||
$writer->classMap[get_class($value)]($writer, $value);
|
||||
$writer->classMap[$value::class]($writer, $value);
|
||||
} elseif (is_callable($value)) {
|
||||
// A callback
|
||||
$value($writer);
|
||||
|
|
@ -144,8 +144,8 @@ function standardSerializer(Writer $writer, $value): void
|
|||
// describes a 'name' and optionally 'attributes' and 'value'.
|
||||
|
||||
$name = $value['name'];
|
||||
$attributes = isset($value['attributes']) ? $value['attributes'] : [];
|
||||
$value = isset($value['value']) ? $value['value'] : null;
|
||||
$attributes = $value['attributes'] ?? [];
|
||||
$value = $value['value'] ?? null;
|
||||
|
||||
$writer->startElement($name);
|
||||
$writer->writeAttributes($attributes);
|
||||
|
|
@ -157,7 +157,7 @@ function standardSerializer(Writer $writer, $value): void
|
|||
// This item has a numeric index. We just loop through the
|
||||
// array and throw it back in the writer.
|
||||
standardSerializer($writer, $item);
|
||||
} elseif (is_string($name) && is_array($item) && isset($item['attributes'])) {
|
||||
} elseif (is_array($item) && isset($item['attributes'])) {
|
||||
// The key is used for a name, but $item has 'attributes' and
|
||||
// possibly 'value'
|
||||
$writer->startElement($name);
|
||||
|
|
@ -176,7 +176,7 @@ function standardSerializer(Writer $writer, $value): void
|
|||
}
|
||||
}
|
||||
} elseif (is_object($value)) {
|
||||
throw new \InvalidArgumentException('The writer cannot serialize objects of class: '.get_class($value));
|
||||
throw new \InvalidArgumentException('The writer cannot serialize objects of class: '.$value::class);
|
||||
} elseif (!is_null($value)) {
|
||||
throw new \InvalidArgumentException('The writer cannot serialize values of type: '.get_debug_type($value));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class Service
|
|||
}
|
||||
|
||||
// If input is empty, then it's safe to throw an exception
|
||||
if (empty($input)) {
|
||||
if ('' === $input) {
|
||||
throw new ParseException('The input element to parse is empty. Do not attempt to parse');
|
||||
}
|
||||
|
||||
|
|
@ -174,7 +174,7 @@ class Service
|
|||
}
|
||||
|
||||
// If input is empty, then it's safe to throw an exception
|
||||
if (empty($input)) {
|
||||
if ('' === $input) {
|
||||
throw new ParseException('The input element to parse is empty. Do not attempt to parse');
|
||||
}
|
||||
|
||||
|
|
@ -254,14 +254,12 @@ class Service
|
|||
*/
|
||||
public function mapValueObject(string $elementName, string $className): void
|
||||
{
|
||||
list($namespace) = self::parseClarkNotation($elementName);
|
||||
[$namespace] = self::parseClarkNotation($elementName);
|
||||
|
||||
require_once __DIR__ . '/Deserializer/functions.php';
|
||||
$this->elementMap[$elementName] = function (Reader $reader) use ($className, $namespace) {
|
||||
return \Sabre\Xml\Deserializer\valueObject($reader, $className, $namespace);
|
||||
};
|
||||
$this->elementMap[$elementName] = (fn (Reader $reader) => \Sabre\Xml\Deserializer\valueObject($reader, $className, $namespace));
|
||||
require_once __DIR__ . '/Serializer/functions.php';
|
||||
$this->classMap[$className] = function (Writer $writer, $valueObject) use ($namespace) {
|
||||
$this->classMap[$className] = function (Writer $writer, $valueObject) use ($namespace): void {
|
||||
\Sabre\Xml\Serializer\valueObject($writer, $valueObject, $namespace);
|
||||
};
|
||||
$this->valueObjectMap[$className] = $elementName;
|
||||
|
|
@ -280,12 +278,12 @@ class Service
|
|||
*/
|
||||
public function writeValueObject(object $object, ?string $contextUri = null): string
|
||||
{
|
||||
if (!isset($this->valueObjectMap[get_class($object)])) {
|
||||
throw new \InvalidArgumentException('"'.get_class($object).'" is not a registered value object class. Register your class with mapValueObject.');
|
||||
if (!isset($this->valueObjectMap[$object::class])) {
|
||||
throw new \InvalidArgumentException('"'.$object::class.'" is not a registered value object class. Register your class with mapValueObject.');
|
||||
}
|
||||
|
||||
return $this->write(
|
||||
$this->valueObjectMap[get_class($object)],
|
||||
$this->valueObjectMap[$object::class],
|
||||
$object,
|
||||
$contextUri
|
||||
);
|
||||
|
|
@ -306,7 +304,7 @@ class Service
|
|||
static $cache = [];
|
||||
|
||||
if (!isset($cache[$str])) {
|
||||
if (!preg_match('/^{([^}]*)}(.*)$/', $str, $matches)) {
|
||||
if (1 !== preg_match('/^{([^}]*)}(.*)$/', $str, $matches)) {
|
||||
throw new \InvalidArgumentException('\''.$str.'\' is not a valid clark-notation formatted string');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ class Version
|
|||
/**
|
||||
* Full version number.
|
||||
*/
|
||||
public const VERSION = '4.0.6';
|
||||
public const VERSION = '4.1.0';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,11 +123,11 @@ class Writer extends \XMLWriter
|
|||
public function startElement($name): bool
|
||||
{
|
||||
if ('{' === $name[0]) {
|
||||
list($namespace, $localName) =
|
||||
[$namespace, $localName] =
|
||||
Service::parseClarkNotation($name);
|
||||
|
||||
if (array_key_exists($namespace, $this->namespaceMap)) {
|
||||
$result = $this->startElementNS(
|
||||
$result = $this->startElementNs(
|
||||
'' === $this->namespaceMap[$namespace] ? null : $this->namespaceMap[$namespace],
|
||||
$localName,
|
||||
null
|
||||
|
|
@ -139,10 +139,8 @@ class Writer extends \XMLWriter
|
|||
$result = $this->startElement($localName);
|
||||
$this->writeAttribute('xmlns', '');
|
||||
} else {
|
||||
if (!isset($this->adhocNamespaces[$namespace])) {
|
||||
$this->adhocNamespaces[$namespace] = 'x'.(count($this->adhocNamespaces) + 1);
|
||||
}
|
||||
$result = $this->startElementNS($this->adhocNamespaces[$namespace], $localName, $namespace);
|
||||
$this->adhocNamespaces[$namespace] ??= 'x'.(count($this->adhocNamespaces) + 1);
|
||||
$result = $this->startElementNs($this->adhocNamespaces[$namespace], $localName, $namespace);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -151,7 +149,7 @@ class Writer extends \XMLWriter
|
|||
|
||||
if (!$this->namespacesWritten) {
|
||||
foreach ($this->namespaceMap as $namespace => $prefix) {
|
||||
$this->writeAttribute($prefix ? 'xmlns:'.$prefix : 'xmlns', $namespace);
|
||||
$this->writeAttribute(is_string($prefix) && '' !== $prefix ? 'xmlns:'.$prefix : 'xmlns', $namespace);
|
||||
}
|
||||
$this->namespacesWritten = true;
|
||||
}
|
||||
|
|
@ -248,11 +246,9 @@ class Writer extends \XMLWriter
|
|||
}
|
||||
|
||||
// We don't know the namespace, we must add it in-line
|
||||
if (!isset($this->adhocNamespaces[$namespace])) {
|
||||
$this->adhocNamespaces[$namespace] = 'x'.(count($this->adhocNamespaces) + 1);
|
||||
}
|
||||
$this->adhocNamespaces[$namespace] ??= 'x'.(count($this->adhocNamespaces) + 1);
|
||||
|
||||
return $this->writeAttributeNS(
|
||||
return $this->writeAttributeNs(
|
||||
$this->adhocNamespaces[$namespace],
|
||||
$localName,
|
||||
$namespace,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue