mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-29 20:19:22 +03:00
Sabre: VObject to v4.5.0 and Xml to v3.0.0
This commit is contained in:
parent
fe20741409
commit
5a9540b9c3
24 changed files with 189 additions and 127 deletions
|
|
@ -456,7 +456,7 @@ HELP
|
|||
*/
|
||||
protected function color($vObj)
|
||||
{
|
||||
fwrite($this->stdout, $this->serializeComponent($vObj));
|
||||
$this->serializeComponent($vObj);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class Component extends Node
|
|||
/**
|
||||
* A list of properties and/or sub-components.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, Component|Property>
|
||||
*/
|
||||
protected $children = [];
|
||||
|
||||
|
|
@ -43,12 +43,12 @@ class Component extends Node
|
|||
* an iCalendar object, this may be something like CALSCALE:GREGORIAN. To
|
||||
* ensure that this does not happen, set $defaults to false.
|
||||
*
|
||||
* @param string $name such as VCALENDAR, VEVENT
|
||||
* @param bool $defaults
|
||||
* @param string|null $name such as VCALENDAR, VEVENT
|
||||
* @param bool $defaults
|
||||
*/
|
||||
public function __construct(Document $root, $name, array $children = [], $defaults = true)
|
||||
{
|
||||
$this->name = strtoupper($name);
|
||||
$this->name = isset($name) ? strtoupper($name) : '';
|
||||
$this->root = $root;
|
||||
|
||||
if ($defaults) {
|
||||
|
|
@ -238,7 +238,7 @@ class Component extends Node
|
|||
return array_filter(
|
||||
$result,
|
||||
function ($child) use ($group) {
|
||||
return $child instanceof Property && strtoupper($child->group) === $group;
|
||||
return $child instanceof Property && (null !== $child->group ? strtoupper($child->group) : '') === $group;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -249,7 +249,7 @@ class Component extends Node
|
|||
$result = [];
|
||||
foreach ($this->children as $childGroup) {
|
||||
foreach ($childGroup as $child) {
|
||||
if ($child instanceof Property && $child->group && strtoupper($child->group) === $group) {
|
||||
if ($child instanceof Property && (null !== $child->group ? strtoupper($child->group) : '') === $group) {
|
||||
$result[] = $child;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,11 +52,12 @@ class Parameter extends Node
|
|||
*/
|
||||
public function __construct(Document $root, $name, $value = null)
|
||||
{
|
||||
$this->name = strtoupper($name);
|
||||
$this->root = $root;
|
||||
if (is_null($name)) {
|
||||
$this->noName = true;
|
||||
$this->name = static::guessParameterNameByValue($value);
|
||||
} else {
|
||||
$this->name = strtoupper($name);
|
||||
}
|
||||
|
||||
// If guessParameterNameByValue() returns an empty string
|
||||
|
|
|
|||
|
|
@ -167,7 +167,11 @@ class MimeDir extends Parser
|
|||
|
||||
while (true) {
|
||||
// Reading until we hit END:
|
||||
$line = $this->readLine();
|
||||
try {
|
||||
$line = $this->readLine();
|
||||
} catch (EofException $oEx) {
|
||||
$line = 'END:'.$this->root->name;
|
||||
}
|
||||
if ('END:' === strtoupper(substr($line, 0, 4))) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -372,12 +376,22 @@ class MimeDir extends Parser
|
|||
$value = $this->unescapeParam($value);
|
||||
|
||||
if (is_null($lastParam)) {
|
||||
if ($this->options & self::OPTION_IGNORE_INVALID_LINES) {
|
||||
// When the property can't be matched and the configuration
|
||||
// option is set to ignore invalid lines, we ignore this line
|
||||
// This can happen when servers provide faulty data as iCloud
|
||||
// frequently does with X-APPLE-STRUCTURED-LOCATION
|
||||
continue;
|
||||
}
|
||||
throw new ParseException('Invalid Mimedir file. Line starting at '.$this->startLine.' did not follow iCalendar/vCard conventions');
|
||||
}
|
||||
if (is_null($property['parameters'][$lastParam])) {
|
||||
$property['parameters'][$lastParam] = $value;
|
||||
} elseif (is_array($property['parameters'][$lastParam])) {
|
||||
$property['parameters'][$lastParam][] = $value;
|
||||
} elseif ($property['parameters'][$lastParam] === $value) {
|
||||
// When the current value of the parameter is the same as the
|
||||
// new one, then we can leave the current parameter as it is.
|
||||
} else {
|
||||
$property['parameters'][$lastParam] = [
|
||||
$property['parameters'][$lastParam],
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ abstract class Property extends Node
|
|||
*
|
||||
* This is only used in vcards
|
||||
*
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
public $group;
|
||||
|
||||
|
|
|
|||
|
|
@ -136,16 +136,18 @@ class Text extends Property
|
|||
}
|
||||
|
||||
foreach ($item as &$subItem) {
|
||||
$subItem = strtr(
|
||||
$subItem,
|
||||
[
|
||||
'\\' => '\\\\',
|
||||
';' => '\;',
|
||||
',' => '\,',
|
||||
"\n" => '\n',
|
||||
"\r" => '',
|
||||
]
|
||||
);
|
||||
if (!is_null($subItem)) {
|
||||
$subItem = strtr(
|
||||
$subItem,
|
||||
[
|
||||
'\\' => '\\\\',
|
||||
';' => '\;',
|
||||
',' => '\,',
|
||||
"\n" => '\n',
|
||||
"\r" => '',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
$item = implode(',', $item);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ use Sabre\VObject\Property;
|
|||
*/
|
||||
class RRuleIterator implements Iterator
|
||||
{
|
||||
/**
|
||||
* Constant denoting the upper limit on how long into the future
|
||||
* we want to iterate. The value is a unix timestamp and currently
|
||||
* corresponds to the datetime 9999-12-31 11:59:59 UTC.
|
||||
*/
|
||||
const dateUpperLimit = 253402300799;
|
||||
|
||||
/**
|
||||
* Creates the Iterator.
|
||||
*
|
||||
|
|
@ -366,6 +373,12 @@ class RRuleIterator implements Iterator
|
|||
|
||||
// Current hour of the day
|
||||
$currentHour = $this->currentDate->format('G');
|
||||
|
||||
if ($this->currentDate->getTimestamp() > self::dateUpperLimit) {
|
||||
$this->currentDate = null;
|
||||
|
||||
return;
|
||||
}
|
||||
} while (
|
||||
($this->byDay && !in_array($currentDay, $recurrenceDays)) ||
|
||||
($this->byHour && !in_array($currentHour, $recurrenceHours)) ||
|
||||
|
|
@ -486,7 +499,7 @@ class RRuleIterator implements Iterator
|
|||
|
||||
// To prevent running this forever (better: until we hit the max date of DateTimeImmutable) we simply
|
||||
// stop at 9999-12-31. Looks like the year 10000 problem is not solved in php ....
|
||||
if ($this->currentDate->getTimestamp() > 253402300799) {
|
||||
if ($this->currentDate->getTimestamp() > self::dateUpperLimit) {
|
||||
$this->currentDate = null;
|
||||
|
||||
return;
|
||||
|
|
@ -589,11 +602,12 @@ class RRuleIterator implements Iterator
|
|||
// loop through all YearDay and Days to check all the combinations
|
||||
foreach ($this->byYearDay as $byYearDay) {
|
||||
$date = clone $this->currentDate;
|
||||
$date = $date->setDate($currentYear, 1, 1);
|
||||
if ($byYearDay > 0) {
|
||||
$date = $date->add(new \DateInterval('P'.$byYearDay.'D'));
|
||||
$date = $date->setDate($currentYear, 1, 1);
|
||||
$date = $date->add(new \DateInterval('P'.($byYearDay - 1).'D'));
|
||||
} else {
|
||||
$date = $date->sub(new \DateInterval('P'.abs($byYearDay).'D'));
|
||||
$date = $date->setDate($currentYear, 12, 31);
|
||||
$date = $date->sub(new \DateInterval('P'.abs($byYearDay + 1).'D'));
|
||||
}
|
||||
|
||||
if ($date > $this->currentDate && in_array($date->format('N'), $dayOffsets)) {
|
||||
|
|
@ -658,6 +672,14 @@ class RRuleIterator implements Iterator
|
|||
(int) $currentMonth,
|
||||
(int) $currentDayOfMonth
|
||||
);
|
||||
|
||||
// To prevent running this forever (better: until we hit the max date of DateTimeImmutable) we simply
|
||||
// stop at 9999-12-31. Looks like the year 10000 problem is not solved in php ....
|
||||
if ($this->currentDate->getTimestamp() > self::dateUpperLimit) {
|
||||
$this->currentDate = null;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we made it here, it means we got a valid occurrence
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ class VCardConverter
|
|||
$newProperty = $output->createProperty('X-ADDRESSBOOKSERVER-KIND', 'GROUP');
|
||||
break;
|
||||
}
|
||||
} elseif ('MEMBER' === $property->name) {
|
||||
$newProperty = $output->createProperty('X-ADDRESSBOOKSERVER-MEMBER', $property->getValue());
|
||||
}
|
||||
} elseif (Document::VCARD40 === $targetVersion) {
|
||||
// These properties were removed in vCard 4.0
|
||||
|
|
@ -173,6 +175,9 @@ class VCardConverter
|
|||
$newProperty = $output->createProperty('KIND', 'GROUP');
|
||||
}
|
||||
break;
|
||||
case 'X-ADDRESSBOOKSERVER-MEMBER':
|
||||
$newProperty = $output->createProperty('MEMBER', $property->getValue());
|
||||
break;
|
||||
case 'X-ANNIVERSARY':
|
||||
$newProperty->name = 'ANNIVERSARY';
|
||||
// If we already have an anniversary property with the same
|
||||
|
|
|
|||
|
|
@ -14,5 +14,5 @@ class Version
|
|||
/**
|
||||
* Full version number.
|
||||
*/
|
||||
const VERSION = '4.4.2';
|
||||
const VERSION = '4.5.0';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ trait ContextStackTrait
|
|||
* Values may also be a callable. In that case the function will be called
|
||||
* directly.
|
||||
*
|
||||
* @var array
|
||||
* @phpstan-var array<string, class-string|callable|object>
|
||||
*/
|
||||
public $elementMap = [];
|
||||
public array $elementMap = [];
|
||||
|
||||
/**
|
||||
* A contextUri pointing to the document being parsed / written.
|
||||
|
|
@ -44,10 +44,8 @@ trait ContextStackTrait
|
|||
* The reader and writer don't use this property, but as it's an extremely
|
||||
* common use-case for parsing XML documents, it's added here as a
|
||||
* convenience.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $contextUri;
|
||||
public ?string $contextUri = null;
|
||||
|
||||
/**
|
||||
* This is a list of namespaces that you want to give default prefixes.
|
||||
|
|
@ -55,9 +53,9 @@ trait ContextStackTrait
|
|||
* You must make sure you create this entire list before starting to write.
|
||||
* They should be registered on the root element.
|
||||
*
|
||||
* @var array
|
||||
* @phpstan-var array<string, class-string|string|null>
|
||||
*/
|
||||
public $namespaceMap = [];
|
||||
public array $namespaceMap = [];
|
||||
|
||||
/**
|
||||
* This is a list of custom serializers for specific classes.
|
||||
|
|
@ -75,16 +73,16 @@ trait ContextStackTrait
|
|||
*
|
||||
* function (Writer $writer, object $value)
|
||||
*
|
||||
* @var array
|
||||
* @phpstan-var array<class-string, callable(Writer, object):mixed>
|
||||
*/
|
||||
public $classMap = [];
|
||||
public array $classMap = [];
|
||||
|
||||
/**
|
||||
* Backups of previous contexts.
|
||||
*
|
||||
* @var array
|
||||
* @var list<mixed>
|
||||
*/
|
||||
protected $contextStack = [];
|
||||
protected array $contextStack = [];
|
||||
|
||||
/**
|
||||
* Create a new "context".
|
||||
|
|
@ -93,7 +91,7 @@ trait ContextStackTrait
|
|||
* namespaceMap. After you're done, you can restore the old data again
|
||||
* with popContext.
|
||||
*/
|
||||
public function pushContext()
|
||||
public function pushContext(): void
|
||||
{
|
||||
$this->contextStack[] = [
|
||||
$this->elementMap,
|
||||
|
|
@ -106,7 +104,7 @@ trait ContextStackTrait
|
|||
/**
|
||||
* Restore the previous "context".
|
||||
*/
|
||||
public function popContext()
|
||||
public function popContext(): void
|
||||
{
|
||||
list(
|
||||
$this->elementMap,
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ use Sabre\Xml\Reader;
|
|||
*
|
||||
* Attributes will be removed from the top-level elements. If elements with
|
||||
* the same name appear twice in the list, only the last one will be kept.
|
||||
*
|
||||
* @phpstan-return array<string, mixed>
|
||||
*/
|
||||
function keyValue(Reader $reader, string $namespace = null): array
|
||||
{
|
||||
|
|
@ -143,6 +145,7 @@ function keyValue(Reader $reader, string $namespace = null): array
|
|||
* ];
|
||||
*
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
function enum(Reader $reader, string $namespace = null): array
|
||||
{
|
||||
|
|
@ -189,9 +192,12 @@ function enum(Reader $reader, string $namespace = null): array
|
|||
* This is primarily used by the mapValueObject function from the Service
|
||||
* class, but it can also easily be used for more specific situations.
|
||||
*
|
||||
* @return object
|
||||
* @template C of object
|
||||
*
|
||||
* @param class-string<C> $className
|
||||
* @phpstan-return C
|
||||
*/
|
||||
function valueObject(Reader $reader, string $className, string $namespace)
|
||||
function valueObject(Reader $reader, string $className, string $namespace): object
|
||||
{
|
||||
$valueObject = new $className();
|
||||
if ($reader->isEmptyElement) {
|
||||
|
|
@ -250,6 +256,8 @@ function valueObject(Reader $reader, string $className, string $namespace)
|
|||
*
|
||||
* $childElementName must either be a a clark-notation element name, or if no
|
||||
* namespace is used, the bare element name.
|
||||
*
|
||||
* @phpstan-return list<mixed>
|
||||
*/
|
||||
function repeatingElements(Reader $reader, string $childElementName): array
|
||||
{
|
||||
|
|
@ -268,7 +276,7 @@ function repeatingElements(Reader $reader, string $childElementName): array
|
|||
}
|
||||
|
||||
/**
|
||||
* This deserializer helps you to deserialize structures which contain mixed content like this:.
|
||||
* This deserializer helps you to deserialize structures which contain mixed content.
|
||||
*
|
||||
* <p>some text <extref>and a inline tag</extref>and even more text</p>
|
||||
*
|
||||
|
|
@ -285,6 +293,8 @@ function repeatingElements(Reader $reader, string $childElementName): array
|
|||
* ]
|
||||
*
|
||||
* In strict XML documents you wont find this kind of markup but in html this is a quite common pattern.
|
||||
*
|
||||
* @return array<mixed>
|
||||
*/
|
||||
function mixedContent(Reader $reader): array
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ class Base implements Xml\Element
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function __construct($value = null)
|
||||
{
|
||||
|
|
@ -50,7 +52,7 @@ class Base implements Xml\Element
|
|||
*
|
||||
* If you are opening new elements, you must also close them again.
|
||||
*/
|
||||
public function xmlSerialize(Xml\Writer $writer)
|
||||
public function xmlSerialize(Xml\Writer $writer): void
|
||||
{
|
||||
$writer->write($this->value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,10 +23,8 @@ class Cdata implements Xml\XmlSerializable
|
|||
{
|
||||
/**
|
||||
* CDATA element value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $value;
|
||||
protected string $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
|
@ -52,7 +50,7 @@ class Cdata implements Xml\XmlSerializable
|
|||
*
|
||||
* If you are opening new elements, you must also close them again.
|
||||
*/
|
||||
public function xmlSerialize(Xml\Writer $writer)
|
||||
public function xmlSerialize(Xml\Writer $writer): void
|
||||
{
|
||||
$writer->writeCData($this->value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,12 +40,14 @@ class Elements implements Xml\Element
|
|||
/**
|
||||
* Value to serialize.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, mixed>
|
||||
*/
|
||||
protected $value;
|
||||
protected array $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array<int, mixed> $value
|
||||
*/
|
||||
public function __construct(array $value = [])
|
||||
{
|
||||
|
|
@ -68,7 +70,7 @@ class Elements implements Xml\Element
|
|||
*
|
||||
* If you are opening new elements, you must also close them again.
|
||||
*/
|
||||
public function xmlSerialize(Xml\Writer $writer)
|
||||
public function xmlSerialize(Xml\Writer $writer): void
|
||||
{
|
||||
Serializer\enum($writer, $this->value);
|
||||
}
|
||||
|
|
@ -91,9 +93,9 @@ class Elements implements Xml\Element
|
|||
* $reader->parseSubTree() will parse the entire sub-tree, and advance to
|
||||
* the next element.
|
||||
*
|
||||
* @return mixed
|
||||
* @return string[]
|
||||
*/
|
||||
public static function xmlDeserialize(Xml\Reader $reader)
|
||||
public static function xmlDeserialize(Xml\Reader $reader): array
|
||||
{
|
||||
return Deserializer\enum($reader);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,12 +40,14 @@ class KeyValue implements Xml\Element
|
|||
/**
|
||||
* Value to serialize.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
protected $value;
|
||||
protected array $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array<string, mixed> $value
|
||||
*/
|
||||
public function __construct(array $value = [])
|
||||
{
|
||||
|
|
@ -68,7 +70,7 @@ class KeyValue implements Xml\Element
|
|||
*
|
||||
* If you are opening new elements, you must also close them again.
|
||||
*/
|
||||
public function xmlSerialize(Xml\Writer $writer)
|
||||
public function xmlSerialize(Xml\Writer $writer): void
|
||||
{
|
||||
$writer->write($this->value);
|
||||
}
|
||||
|
|
@ -91,9 +93,9 @@ class KeyValue implements Xml\Element
|
|||
* $reader->parseInnerTree() will parse the entire sub-tree, and advance to
|
||||
* the next element.
|
||||
*
|
||||
* @return mixed
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function xmlDeserialize(Xml\Reader $reader)
|
||||
public static function xmlDeserialize(Xml\Reader $reader): array
|
||||
{
|
||||
return Deserializer\keyValue($reader);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Sabre\Xml\Element;
|
||||
|
||||
use function Sabre\Uri\resolve;
|
||||
|
||||
use Sabre\Xml;
|
||||
|
||||
/**
|
||||
|
|
@ -26,17 +28,13 @@ class Uri implements Xml\Element
|
|||
{
|
||||
/**
|
||||
* Uri element value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $value;
|
||||
protected string $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function __construct($value)
|
||||
public function __construct(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
|
@ -57,10 +55,10 @@ class Uri implements Xml\Element
|
|||
*
|
||||
* If you are opening new elements, you must also close them again.
|
||||
*/
|
||||
public function xmlSerialize(Xml\Writer $writer)
|
||||
public function xmlSerialize(Xml\Writer $writer): void
|
||||
{
|
||||
$writer->text(
|
||||
\Sabre\Uri\resolve(
|
||||
resolve(
|
||||
$writer->contextUri,
|
||||
$this->value
|
||||
)
|
||||
|
|
@ -84,13 +82,11 @@ class Uri implements Xml\Element
|
|||
*
|
||||
* $reader->parseSubTree() will parse the entire sub-tree, and advance to
|
||||
* the next element.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function xmlDeserialize(Xml\Reader $reader)
|
||||
public static function xmlDeserialize(Xml\Reader $reader): Uri
|
||||
{
|
||||
return new self(
|
||||
\Sabre\Uri\resolve(
|
||||
resolve(
|
||||
(string) $reader->contextUri,
|
||||
$reader->readText()
|
||||
)
|
||||
|
|
|
|||
|
|
@ -26,10 +26,8 @@ class XmlFragment implements Element
|
|||
{
|
||||
/**
|
||||
* The inner XML value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $xml;
|
||||
protected string $xml;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
|
@ -63,7 +61,7 @@ class XmlFragment implements Element
|
|||
*
|
||||
* If you are opening new elements, you must also close them again.
|
||||
*/
|
||||
public function xmlSerialize(Writer $writer)
|
||||
public function xmlSerialize(Writer $writer): void
|
||||
{
|
||||
$reader = new Reader();
|
||||
|
||||
|
|
@ -135,10 +133,8 @@ XML;
|
|||
*
|
||||
* $reader->parseInnerTree() will parse the entire sub-tree, and advance to
|
||||
* the next element.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function xmlDeserialize(Reader $reader)
|
||||
public static function xmlDeserialize(Reader $reader): XmlFragment
|
||||
{
|
||||
$result = new self($reader->readInnerXml());
|
||||
$reader->next();
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class LibXMLException extends ParseException
|
|||
*
|
||||
* @var \LibXMLError[]
|
||||
*/
|
||||
protected $errors;
|
||||
protected array $errors;
|
||||
|
||||
/**
|
||||
* Creates the exception.
|
||||
|
|
@ -31,7 +31,6 @@ class LibXMLException extends ParseException
|
|||
* You should pass a list of LibXMLError objects in its constructor.
|
||||
*
|
||||
* @param LibXMLError[] $errors
|
||||
* @param Throwable $previousException
|
||||
*/
|
||||
public function __construct(array $errors, int $code = 0, Throwable $previousException = null)
|
||||
{
|
||||
|
|
@ -41,6 +40,8 @@ class LibXMLException extends ParseException
|
|||
|
||||
/**
|
||||
* Returns the LibXML errors.
|
||||
*
|
||||
* @return LibXMLError[]
|
||||
*/
|
||||
public function getErrors(): array
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,10 +30,8 @@ class Reader extends XMLReader
|
|||
* Or if no namespace is defined: "{}feed".
|
||||
*
|
||||
* This method returns null if we're not currently on an element.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getClark()
|
||||
public function getClark(): ?string
|
||||
{
|
||||
if (!$this->localName) {
|
||||
return null;
|
||||
|
|
@ -52,6 +50,8 @@ class Reader extends XMLReader
|
|||
*
|
||||
* This function will also disable the standard libxml error handler (which
|
||||
* usually just results in PHP errors), and throw exceptions instead.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function parse(): array
|
||||
{
|
||||
|
|
@ -102,6 +102,10 @@ class Reader extends XMLReader
|
|||
*
|
||||
* If the $elementMap argument is specified, the existing elementMap will
|
||||
* be overridden while parsing the tree, and restored after this process.
|
||||
*
|
||||
* @param array<string, mixed>|null $elementMap
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function parseGetElements(array $elementMap = null): array
|
||||
{
|
||||
|
|
@ -124,7 +128,9 @@ class Reader extends XMLReader
|
|||
* If the $elementMap argument is specified, the existing elementMap will
|
||||
* be overridden while parsing the tree, and restored after this process.
|
||||
*
|
||||
* @return array|string|null
|
||||
* @param array<string, mixed>|null $elementMap
|
||||
*
|
||||
* @return array<string, mixed>|string|null
|
||||
*/
|
||||
public function parseInnerTree(array $elementMap = null)
|
||||
{
|
||||
|
|
@ -193,7 +199,7 @@ class Reader extends XMLReader
|
|||
}
|
||||
}
|
||||
|
||||
return $elements ? $elements : $text;
|
||||
return $elements ?: $text;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -220,6 +226,8 @@ class Reader extends XMLReader
|
|||
* * name - A clark-notation XML element name.
|
||||
* * value - The parsed value.
|
||||
* * attributes - A key-value list of attributes.
|
||||
*
|
||||
* @return array <string, mixed>
|
||||
*/
|
||||
public function parseCurrentElement(): array
|
||||
{
|
||||
|
|
@ -250,6 +258,8 @@ class Reader extends XMLReader
|
|||
* If the attributes are part of the same namespace, they will simply be
|
||||
* short keys. If they are defined on a different namespace, the attribute
|
||||
* name will be returned in clark-notation.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function parseAttributes(): array
|
||||
{
|
||||
|
|
@ -297,9 +307,9 @@ class Reader extends XMLReader
|
|||
}
|
||||
|
||||
$type = gettype($deserializer);
|
||||
if ('string' === $type) {
|
||||
if (is_string($deserializer)) {
|
||||
$type .= ' ('.$deserializer.')';
|
||||
} elseif ('object' === $type) {
|
||||
} elseif (is_object($deserializer)) {
|
||||
$type .= ' ('.get_class($deserializer).')';
|
||||
}
|
||||
throw new \LogicException('Could not use this type as a deserializer: '.$type.' for element: '.$name);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ use Sabre\Xml\XmlSerializable;
|
|||
*
|
||||
* @param string[] $values
|
||||
*/
|
||||
function enum(Writer $writer, array $values)
|
||||
function enum(Writer $writer, array $values): void
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
$writer->writeElement($value);
|
||||
|
|
@ -53,10 +53,8 @@ function enum(Writer $writer, array $values)
|
|||
*
|
||||
* Values that are set to null or an empty array are not serialized. To
|
||||
* serialize empty properties, you must specify them as an empty string.
|
||||
*
|
||||
* @param object $valueObject
|
||||
*/
|
||||
function valueObject(Writer $writer, $valueObject, string $namespace)
|
||||
function valueObject(Writer $writer, object $valueObject, string $namespace): void
|
||||
{
|
||||
foreach (get_object_vars($valueObject) as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
|
|
@ -85,8 +83,10 @@ function valueObject(Writer $writer, $valueObject, string $namespace)
|
|||
* and this could be called like this:
|
||||
*
|
||||
* repeatingElements($writer, $items, '{}item');
|
||||
*
|
||||
* @param array<int,mixed> $items
|
||||
*/
|
||||
function repeatingElements(Writer $writer, array $items, string $childElementName)
|
||||
function repeatingElements(Writer $writer, array $items, string $childElementName): void
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
$writer->writeElement($childElementName, $item);
|
||||
|
|
@ -104,7 +104,7 @@ function repeatingElements(Writer $writer, array $items, string $childElementNam
|
|||
* calls it's xmlSerialize() method.
|
||||
* $value may be a PHP callback/function/closure, in case we call the callback
|
||||
* and give it the Writer as an argument.
|
||||
* $value may be a an object, and if it's in the classMap we automatically call
|
||||
* $value may be an object, and if it's in the classMap we automatically call
|
||||
* the correct serializer for it.
|
||||
* $value may be null, in which case we do nothing.
|
||||
*
|
||||
|
|
@ -148,9 +148,9 @@ function repeatingElements(Writer $writer, array $items, string $childElementNam
|
|||
*
|
||||
* You can even mix the two array syntaxes.
|
||||
*
|
||||
* @param string|int|float|bool|array|object $value
|
||||
* @param string|int|float|bool|array<int|string, mixed>|object $value
|
||||
*/
|
||||
function standardSerializer(Writer $writer, $value)
|
||||
function standardSerializer(Writer $writer, $value): void
|
||||
{
|
||||
if (is_scalar($value)) {
|
||||
// String, integer, float, boolean
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ class Service
|
|||
* Values may also be a callable. In that case the function will be called
|
||||
* directly.
|
||||
*
|
||||
* @var array
|
||||
* @phpstan-var array<string, class-string|callable|object>
|
||||
*/
|
||||
public $elementMap = [];
|
||||
public array $elementMap = [];
|
||||
|
||||
/**
|
||||
* This is a list of namespaces that you want to give default prefixes.
|
||||
|
|
@ -36,9 +36,9 @@ class Service
|
|||
* You must make sure you create this entire list before starting to write.
|
||||
* They should be registered on the root element.
|
||||
*
|
||||
* @var array
|
||||
* @phpstan-var array<string, class-string|string|null>
|
||||
*/
|
||||
public $namespaceMap = [];
|
||||
public array $namespaceMap = [];
|
||||
|
||||
/**
|
||||
* This is a list of custom serializers for specific classes.
|
||||
|
|
@ -56,16 +56,14 @@ class Service
|
|||
*
|
||||
* function (Writer $writer, object $value)
|
||||
*
|
||||
* @var array
|
||||
* @phpstan-var array<class-string, callable(Writer, object):mixed>
|
||||
*/
|
||||
public $classMap = [];
|
||||
public array $classMap = [];
|
||||
|
||||
/**
|
||||
* A bitmask of the LIBXML_* constants.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $options = 0;
|
||||
public int $options = 0;
|
||||
|
||||
/**
|
||||
* Returns a fresh XML Reader.
|
||||
|
|
@ -107,7 +105,7 @@ class Service
|
|||
*
|
||||
* @throws ParseException
|
||||
*
|
||||
* @return array|object|string
|
||||
* @return array<string, mixed>|object|string
|
||||
*/
|
||||
public function parse($input, string $contextUri = null, string &$rootElementName = null)
|
||||
{
|
||||
|
|
@ -151,7 +149,7 @@ class Service
|
|||
*
|
||||
* @throws ParseException
|
||||
*
|
||||
* @return array|object|string
|
||||
* @return array<string, mixed>|object|string
|
||||
*/
|
||||
public function expect($rootElementName, $input, string $contextUri = null)
|
||||
{
|
||||
|
|
@ -200,11 +198,9 @@ class Service
|
|||
* This allows an implementor to easily create URI's relative to the root
|
||||
* of the domain.
|
||||
*
|
||||
* @param string|array|object|XmlSerializable $value
|
||||
*
|
||||
* @return string
|
||||
* @param string|array<string, mixed>|object|XmlSerializable $value
|
||||
*/
|
||||
public function write(string $rootElementName, $value, string $contextUri = null)
|
||||
public function write(string $rootElementName, $value, string $contextUri = null): string
|
||||
{
|
||||
$w = $this->getWriter();
|
||||
$w->openMemory();
|
||||
|
|
@ -239,8 +235,10 @@ class Service
|
|||
* These can easily be mapped by calling:
|
||||
*
|
||||
* $service->mapValueObject('{http://example.org}author', 'Author');
|
||||
*
|
||||
* @param class-string $className
|
||||
*/
|
||||
public function mapValueObject(string $elementName, string $className)
|
||||
public function mapValueObject(string $elementName, string $className): void
|
||||
{
|
||||
list($namespace) = self::parseClarkNotation($elementName);
|
||||
|
||||
|
|
@ -248,7 +246,7 @@ class Service
|
|||
return \Sabre\Xml\Deserializer\valueObject($reader, $className, $namespace);
|
||||
};
|
||||
$this->classMap[$className] = function (Writer $writer, $valueObject) use ($namespace) {
|
||||
return \Sabre\Xml\Serializer\valueObject($writer, $valueObject, $namespace);
|
||||
\Sabre\Xml\Serializer\valueObject($writer, $valueObject, $namespace);
|
||||
};
|
||||
$this->valueObjectMap[$className] = $elementName;
|
||||
}
|
||||
|
|
@ -262,11 +260,9 @@ class Service
|
|||
* The ValueObject must have been previously registered using
|
||||
* mapValueObject().
|
||||
*
|
||||
* @param object $object
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*@throws \InvalidArgumentException
|
||||
*/
|
||||
public function writeValueObject($object, string $contextUri = null)
|
||||
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.');
|
||||
|
|
@ -286,6 +282,8 @@ class Service
|
|||
* If the string was invalid, it will throw an InvalidArgumentException.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return array{string|null, string}
|
||||
*/
|
||||
public static function parseClarkNotation(string $str): array
|
||||
{
|
||||
|
|
@ -307,6 +305,8 @@ class Service
|
|||
|
||||
/**
|
||||
* A list of classes and which XML elements they map to.
|
||||
*
|
||||
* @var array<class-string, string>
|
||||
*/
|
||||
protected $valueObjectMap = [];
|
||||
protected array $valueObjectMap = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ class Version
|
|||
/**
|
||||
* Full version number.
|
||||
*/
|
||||
const VERSION = '2.2.5';
|
||||
public const VERSION = '3.0.0';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,19 +41,17 @@ class Writer extends XMLWriter
|
|||
* time* they are used, but this array allows the writer to make sure that
|
||||
* the prefixes are consistent anyway.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $adhocNamespaces = [];
|
||||
protected array $adhocNamespaces = [];
|
||||
|
||||
/**
|
||||
* When the first element is written, this flag is set to true.
|
||||
*
|
||||
* This ensures that the namespaces in the namespaces map are only written
|
||||
* once.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $namespacesWritten = false;
|
||||
protected bool $namespacesWritten = false;
|
||||
|
||||
/**
|
||||
* Writes a value to the output stream.
|
||||
|
|
@ -96,16 +94,15 @@ class Writer extends XMLWriter
|
|||
*
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function write($value)
|
||||
public function write($value): void
|
||||
{
|
||||
require_once __DIR__ . '/Serializer/functions.php';
|
||||
Serializer\standardSerializer($this, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new element.
|
||||
*
|
||||
* You can either just use a local elementname, or you can use clark-
|
||||
* You can either just use a local element name, or you can use clark-
|
||||
* notation to start a new element.
|
||||
*
|
||||
* Example:
|
||||
|
|
@ -118,6 +115,7 @@ class Writer extends XMLWriter
|
|||
*
|
||||
* Note: this function doesn't have the string typehint, because PHP's
|
||||
* XMLWriter::startElement doesn't either.
|
||||
* From PHP 8.0 the typehint exists, so it can be added here after PHP 7.4 is dropped.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
|
|
@ -152,7 +150,7 @@ class Writer extends XMLWriter
|
|||
|
||||
if (!$this->namespacesWritten) {
|
||||
foreach ($this->namespaceMap as $namespace => $prefix) {
|
||||
$this->writeAttribute(($prefix ? 'xmlns:'.$prefix : 'xmlns'), $namespace);
|
||||
$this->writeAttribute($prefix ? 'xmlns:'.$prefix : 'xmlns', $namespace);
|
||||
}
|
||||
$this->namespacesWritten = true;
|
||||
}
|
||||
|
|
@ -181,8 +179,10 @@ class Writer extends XMLWriter
|
|||
*
|
||||
* Note: this function doesn't have the string typehint, because PHP's
|
||||
* XMLWriter::startElement doesn't either.
|
||||
* From PHP 8.0 the typehint exists, so it can be added here after PHP 7.4 is dropped.
|
||||
*
|
||||
* @param array|string|object|null $content
|
||||
* @param string $name
|
||||
* @param array<int|string, mixed>|string|object|null $content
|
||||
*/
|
||||
public function writeElement($name, $content = null): bool
|
||||
{
|
||||
|
|
@ -203,8 +203,10 @@ class Writer extends XMLWriter
|
|||
* The key is an attribute name. If the key is a 'localName', the current
|
||||
* xml namespace is assumed. If it's a 'clark notation key', this namespace
|
||||
* will be used instead.
|
||||
*
|
||||
* @param array<string, string> $attributes
|
||||
*/
|
||||
public function writeAttributes(array $attributes)
|
||||
public function writeAttributes(array $attributes): void
|
||||
{
|
||||
foreach ($attributes as $name => $value) {
|
||||
$this->writeAttribute($name, $value);
|
||||
|
|
@ -220,6 +222,7 @@ class Writer extends XMLWriter
|
|||
*
|
||||
* Note: this function doesn't have typehints, because for some reason
|
||||
* PHP's XMLWriter::writeAttribute doesn't either.
|
||||
* From PHP 8.0 the typehint exists, so it can be added here after PHP 7.4 is dropped.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
|
|
|
|||
|
|
@ -30,5 +30,5 @@ interface XmlSerializable
|
|||
*
|
||||
* If you are opening new elements, you must also close them again.
|
||||
*/
|
||||
public function xmlSerialize(Writer $writer);
|
||||
public function xmlSerialize(Writer $writer): void;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue