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 b1e4a7aaa..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,12 +79,17 @@ public function __construct($version = '2.1', QtiComponent $documentComponent = parent::__construct($version, $documentComponent); } + 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; } @@ -95,7 +101,7 @@ protected function setDomDocument(DOMDocument $domDocument) */ public function getDomDocument() { - return $this->domDocument; + return $this->domDocument->getDom(); } /** @@ -137,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. @@ -260,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; @@ -329,14 +335,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 +351,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..a25889c44 100644 --- a/test/qtismtest/data/storage/xml/XmlDocumentTest.php +++ b/test/qtismtest/data/storage/xml/XmlDocumentTest.php @@ -254,6 +254,35 @@ 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 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 000000000..af85c18c0 Binary files /dev/null and b/test/samples/serialized/xmldocument differ