From 70bb5fe5b9537215027f7c5ec96c26ef2daf3835 Mon Sep 17 00:00:00 2001 From: Sergei Mikhailov Date: Tue, 15 Nov 2022 14:12:42 +0100 Subject: [PATCH 1/3] feat: add support for `XmlDocument` serialization (cherry picked from commit e8adf1f74ae2c8342e4cdf71e5f1f208f236c350) --- qtism/data/storage/xml/XmlDocument.php | 16 +++++++++++++--- .../data/storage/xml/XmlDocumentTest.php | 11 +++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/qtism/data/storage/xml/XmlDocument.php b/qtism/data/storage/xml/XmlDocument.php index b1e4a7aaa..a177a3484 100644 --- a/qtism/data/storage/xml/XmlDocument.php +++ b/qtism/data/storage/xml/XmlDocument.php @@ -78,6 +78,16 @@ public function __construct($version = '2.1', QtiComponent $documentComponent = parent::__construct($version, $documentComponent); } + public function __serialize(): array + { + return ['domDocument' => $this->saveToString(false)]; + } + + public function __unserialize(array $data): void + { + $this->loadFromString($data['domDocument']); + } + /** * Set the DOMDocument object in use. * @@ -329,14 +339,14 @@ public function schemaValidate($filename = '') } $doc = $this->getDomDocument(); - + $oldErrorConfig = libxml_use_internal_errors(true); $valid = $doc->schemaValidate($filename); $libXmlErrors = libxml_get_errors(); libxml_clear_errors(); libxml_use_internal_errors($oldErrorConfig); - + if (!$valid) { $formattedErrors = self::formatLibXmlErrors($libXmlErrors); @@ -345,7 +355,7 @@ public function schemaValidate($filename = '') realpath($filename), $formattedErrors ); - + throw XmlStorageException::createValidationException($msg, $libXmlErrors); } } diff --git a/test/qtismtest/data/storage/xml/XmlDocumentTest.php b/test/qtismtest/data/storage/xml/XmlDocumentTest.php index ed77762c6..375b0ec25 100644 --- a/test/qtismtest/data/storage/xml/XmlDocumentTest.php +++ b/test/qtismtest/data/storage/xml/XmlDocumentTest.php @@ -254,6 +254,17 @@ public function testLoadFromMalformedString() $doc->loadFromString(''); } + public function testSerialization() + { + $doc = new XmlDocument('2.1'); + $doc->loadFromString(''); + + $this->assertEquals( + $doc->saveToString(), + unserialize(serialize($doc))->saveToString() + ); + } + public function testLoadNoVersion() { $doc = new XmlDocument('2.1'); From 40a7e4f76367b079dfc9657e05376bc99d321918 Mon Sep 17 00:00:00 2001 From: Sergei Mikhailov Date: Tue, 15 Nov 2022 14:16:02 +0100 Subject: [PATCH 2/3] feat: make `XmlDocument` stringable (cherry picked from commit 4073afad555290edf6360728a0e72ea17e658d44) --- qtism/data/storage/xml/XmlDocument.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/qtism/data/storage/xml/XmlDocument.php b/qtism/data/storage/xml/XmlDocument.php index a177a3484..3d87712fc 100644 --- a/qtism/data/storage/xml/XmlDocument.php +++ b/qtism/data/storage/xml/XmlDocument.php @@ -80,7 +80,7 @@ public function __construct($version = '2.1', QtiComponent $documentComponent = public function __serialize(): array { - return ['domDocument' => $this->saveToString(false)]; + return ['domDocument' => (string)$this]; } public function __unserialize(array $data): void @@ -88,6 +88,11 @@ public function __unserialize(array $data): void $this->loadFromString($data['domDocument']); } + public function __toString(): string + { + return $this->saveToString(false); + } + /** * Set the DOMDocument object in use. * From d66ca6a1d2749c0e10d320e335ba765e01544b56 Mon Sep 17 00:00:00 2001 From: Sergei Mikhailov Date: Tue, 15 Nov 2022 16:35:21 +0100 Subject: [PATCH 3/3] fix: support older `XmlDocument` serialized data deserialization (cherry picked from commit 33f8ba843cb8833b296362c24afe56d7fee88ad0) --- qtism/common/dom/SerializableDomDocument.php | 19 ++++++++----- qtism/data/storage/xml/XmlDocument.php | 25 ++++++------------ .../data/storage/xml/XmlDocumentTest.php | 18 +++++++++++++ test/samples/serialized/xmldocument | Bin 0 -> 1636 bytes 4 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 test/samples/serialized/xmldocument diff --git a/qtism/common/dom/SerializableDomDocument.php b/qtism/common/dom/SerializableDomDocument.php index a14cc9d5f..3ae55281d 100644 --- a/qtism/common/dom/SerializableDomDocument.php +++ b/qtism/common/dom/SerializableDomDocument.php @@ -23,19 +23,19 @@ namespace qtism\common\dom; +use DOMAttr; +use DOMCDATASection; +use DOMComment; use DOMDocument; +use DOMDocumentFragment; use DOMDocumentType; use DOMElement; -use DOMImplementation; -use DOMDocumentFragment; -use DOMComment; -use DOMCDATASection; -use DOMProcessingInstruction; -use DOMText; -use DOMAttr; use DOMEntityReference; +use DOMImplementation; use DOMNode; use DOMNodeList; +use DOMProcessingInstruction; +use DOMText; use Error; /** @@ -183,4 +183,9 @@ public function __unset(string $name): void { unset($this->dom->$name); } + + public function getDom(): DOMDocument + { + return $this->dom; + } } diff --git a/qtism/data/storage/xml/XmlDocument.php b/qtism/data/storage/xml/XmlDocument.php index 3d87712fc..ed574b6a0 100644 --- a/qtism/data/storage/xml/XmlDocument.php +++ b/qtism/data/storage/xml/XmlDocument.php @@ -30,6 +30,7 @@ use InvalidArgumentException; use LibXMLError; use LogicException; +use qtism\common\dom\SerializableDomDocument; use qtism\common\utils\Url; use qtism\data\content\Flow; use qtism\data\QtiComponent; @@ -59,7 +60,7 @@ class XmlDocument extends QtiDocument * The produced domDocument after a successful call to * XmlDocument::load or XmlDocument::save. * - * @var DOMDocument + * @var SerializableDomDocument */ private $domDocument = null; @@ -78,27 +79,17 @@ public function __construct($version = '2.1', QtiComponent $documentComponent = parent::__construct($version, $documentComponent); } - public function __serialize(): array - { - return ['domDocument' => (string)$this]; - } - - public function __unserialize(array $data): void - { - $this->loadFromString($data['domDocument']); - } - public function __toString(): string { return $this->saveToString(false); } /** - * Set the DOMDocument object in use. + * Set the SerializableDomDocument object in use. * - * @param DOMDocument $domDocument A DOMDocument object. + * @param SerializableDomDocument $domDocument A DOMDocument object. */ - protected function setDomDocument(DOMDocument $domDocument) + protected function setDomDocument(SerializableDomDocument $domDocument) { $this->domDocument = $domDocument; } @@ -110,7 +101,7 @@ protected function setDomDocument(DOMDocument $domDocument) */ public function getDomDocument() { - return $this->domDocument; + return $this->domDocument->getDom(); } /** @@ -152,7 +143,7 @@ public function loadFromString($string, $validate = false) protected function loadImplementation($data, $validate = false, $fromString = false) { try { - $this->setDomDocument(new DOMDocument('1.0', 'UTF-8')); + $this->setDomDocument(new SerializableDomDocument('1.0', 'UTF-8')); $this->getDomDocument()->preserveWhiteSpace = true; // Disable xml warnings and errors and fetch error information as needed. @@ -275,7 +266,7 @@ protected function saveImplementation($uri = '', $formatOutput = true) $assessmentTest = $this->getDocumentComponent(); if (!empty($assessmentTest)) { - $this->setDomDocument(new DOMDocument('1.0', 'UTF-8')); + $this->setDomDocument(new SerializableDomDocument('1.0', 'UTF-8')); if ($formatOutput == true) { $this->getDomDocument()->formatOutput = true; diff --git a/test/qtismtest/data/storage/xml/XmlDocumentTest.php b/test/qtismtest/data/storage/xml/XmlDocumentTest.php index 375b0ec25..a25889c44 100644 --- a/test/qtismtest/data/storage/xml/XmlDocumentTest.php +++ b/test/qtismtest/data/storage/xml/XmlDocumentTest.php @@ -265,6 +265,24 @@ public function testSerialization() ); } + public function testOlderSerializedDataDeserialization() + { + if (PHP_VERSION_ID >= 80100 || PHP_VERSION_ID < 70400) { + $this->markTestSkipped('DOM objects serialization is impossible in PHP 8.1 or higher.'); + } + + $unserializedDoc = unserialize(file_get_contents(self::samplesDir(). 'serialized/xmldocument')); + $this->assertInstanceOf(XmlDocument::class, $unserializedDoc); + + $doc = new XmlDocument('2.1'); + $doc->loadFromString(''); + + $this->assertEquals( + $doc->saveToString(), + $unserializedDoc->saveToString() + ); + } + public function testLoadNoVersion() { $doc = new XmlDocument('2.1'); diff --git a/test/samples/serialized/xmldocument b/test/samples/serialized/xmldocument new file mode 100644 index 0000000000000000000000000000000000000000..af85c18c0e86a8433824c782004aeb548b0ff8a7 GIT binary patch literal 1636 zcmbVN%W~Q<6!p5Fp=B4;59mXzQdl%IO(3C@X5o!&3s6V097#^oVfybmvI8|3($bx6 z?&I8Z&b`cNGNk0e39HhAIhI4p5HC?Sy>a5M z&4{Cr(8$j-dS#v?iQAUfwaU05fP%j9AR2^Z?B~IlU3SoMJ2Dt)iJWLv>C!U_*zw0b z*caAvYdzhUnDv$~fim$hy++-_y})2?5Dh$^C>gxF38Mk@^Y24XRY$OXX3iX6X(PDZ zCoh(X#Liu}116TK9oGG9y?f z`4y`wQLb7z@g70e0c?7=A9y~N