forked from ezsystems/ezplatform-xmltext-fieldtype
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix EZP-29116 : Conversions from ezxmltext to ezrichtext fails if ezx…
…mtext have duplicate xhtml ids (ezsystems#36) * Added warning if ezxmltext includes duplicates ids * Refactoring : Moved XmlTextToRichText conversion to separate converter * Added tests for duplicate ids in ezxmltext to richtext conversion * fixup! Added tests for duplicate ids in ezxmltext to richtext conversion * fixup! Refactoring : Moved XmlTextToRichText conversion to separate converter * fixup! Refactoring : Moved XmlTextToRichText conversion to separate converter * fixup! fixup! Refactoring : Moved XmlTextToRichText conversion to separate converter * fixup! Added tests for duplicate ids in ezxmltext to richtext conversion * Added more ezxmltext->richtext conversion tests
- Loading branch information
Showing
35 changed files
with
695 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
<?php | ||
|
||
/** | ||
* This file is part of the eZ Platform XmlText Field Type package. | ||
* | ||
* @copyright Copyright (C) eZ Systems AS. All rights reserved. | ||
* @license For full copyright and license information view LICENSE file distributed with this source code. | ||
*/ | ||
namespace eZ\Publish\Core\FieldType\XmlText\Converter; | ||
|
||
use eZ\Publish\Core\FieldType\XmlText\Converter; | ||
use DOMDocument; | ||
use DOMXPath; | ||
use Psr\Log\LoggerInterface; | ||
use eZ\Publish\Core\FieldType\RichText\Converter\Aggregate; | ||
use eZ\Publish\Core\FieldType\RichText\Converter\Ezxml\ToRichTextPreNormalize; | ||
use eZ\Publish\Core\FieldType\RichText\Converter\Xslt; | ||
use eZ\Publish\Core\FieldType\RichText\Validator; | ||
|
||
class RichText implements Converter | ||
{ | ||
/** | ||
* @var \eZ\Publish\Core\FieldType\RichText\Converter | ||
*/ | ||
private $converter; | ||
|
||
/** | ||
* @var \eZ\Publish\Core\FieldType\RichText\Validator | ||
*/ | ||
private $validator; | ||
|
||
public function __construct(LoggerInterface $logger = null) | ||
{ | ||
$this->logger = $logger; | ||
|
||
$this->converter = new Aggregate( | ||
array( | ||
new ToRichTextPreNormalize(new Expanding(), new EmbedLinking()), | ||
new Xslt( | ||
'./vendor/ezsystems/ezpublish-kernel/eZ/Publish/Core/FieldType/RichText/Resources/stylesheets/ezxml/docbook/docbook.xsl', | ||
array( | ||
array( | ||
'path' => './vendor/ezsystems/ezpublish-kernel/eZ/Publish/Core/FieldType/RichText/Resources/stylesheets/ezxml/docbook/core.xsl', | ||
'priority' => 99, | ||
), | ||
) | ||
), | ||
) | ||
); | ||
|
||
$this->validator = new Validator( | ||
array( | ||
'./vendor/ezsystems/ezpublish-kernel/eZ/Publish/Core/FieldType/RichText/Resources/schemas/docbook/ezpublish.rng', | ||
'./vendor/ezsystems/ezpublish-kernel/eZ/Publish/Core/FieldType/RichText/Resources/schemas/docbook/docbook.iso.sch.xsl', | ||
) | ||
); | ||
} | ||
|
||
protected function removeComments(DOMDocument $document) | ||
{ | ||
$xpath = new DOMXpath($document); | ||
$nodes = $xpath->query('//comment()'); | ||
|
||
for ($i = 0; $i < $nodes->length; ++$i) { | ||
$nodes->item($i)->parentNode->removeChild($nodes->item($i)); | ||
} | ||
} | ||
|
||
protected function reportNonUniqueIds(DOMDocument $document, $contentObjectAttributeId) | ||
{ | ||
$xpath = new DOMXPath($document); | ||
$ns = $document->documentElement->namespaceURI; | ||
$nodes = $xpath->query("//*[contains(@xml:id, 'duplicated_id_')]"); | ||
foreach ($nodes as $node) { | ||
$id=$node->attributes->getNamedItem('id')->nodeValue; | ||
// id has format "duplicated_id_foo_bar_idm45226413447104" where "foo_bar" is the duplicated id | ||
$duplicatedId = substr($id, strlen('duplicated_id_'), strrpos($id, '_') - strlen('duplicated_id_')); | ||
if ($this->logger !== null) { | ||
$this->logger->warning("Duplicated id in original ezxmltext for contentobject_attribute.id=$contentObjectAttributeId, automatically generated new id : $duplicatedId --> $id"); | ||
} | ||
} | ||
} | ||
|
||
public function convert(DOMDocument $inputDocument, $checkDuplicateIds = false, $contentObjectAttributeId = null) | ||
{ | ||
$this->removeComments($inputDocument); | ||
|
||
$convertedDocument = $this->converter->convert($inputDocument); | ||
if ($checkDuplicateIds) { | ||
$this->reportNonUniqueIds($convertedDocument, $contentObjectAttributeId); | ||
} | ||
|
||
// Needed by some disabled output escaping (eg. legacy ezxml paragraph <line/> elements) | ||
$convertedDocumentNormalized = new DOMDocument(); | ||
$convertedDocumentNormalized->loadXML($convertedDocument->saveXML()); | ||
|
||
$errors = $this->validator->validate($convertedDocument); | ||
|
||
$result = $convertedDocumentNormalized->saveXML(); | ||
|
||
if (!empty($errors) && $this->logger !== null) { | ||
$this->logger->error( | ||
"Validation errors when converting ezxmltext for contentobject_attribute.id=$contentObjectAttributeId", | ||
['result' => $result, 'errors' => $errors, 'xmlString' => $inputDocument->saveXML()] | ||
); | ||
} | ||
|
||
return $result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
<?php | ||
|
||
/** | ||
* This file is part of the eZ Platform XmlText Field Type package. | ||
* | ||
* @copyright Copyright (C) eZ Systems AS. All rights reserved. | ||
* @license For full copyright and license information view LICENSE file distributed with this source code. | ||
*/ | ||
namespace EzSystems\EzPlatformXmlTextFieldType\Tests\FieldType\Converter; | ||
|
||
use eZ\Publish\Core\FieldType\XmlText\Converter\RichText; | ||
use DOMDocument; | ||
use DOMXPath; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
class RichTextTest extends TestCase | ||
{ | ||
/** | ||
* @param string $xml | ||
* @param bool $isPath | ||
* | ||
* @return \DOMDocument | ||
*/ | ||
protected function createDocument($xml, $isPath = true) | ||
{ | ||
$document = new DOMDocument(); | ||
|
||
$document->preserveWhiteSpace = false; | ||
$document->formatOutput = false; | ||
|
||
if ($isPath === true) { | ||
$xml = file_get_contents($xml); | ||
} | ||
|
||
$document->loadXml($xml); | ||
|
||
return $document; | ||
} | ||
|
||
/** | ||
* Provider for conversion test. | ||
* | ||
* @return array | ||
*/ | ||
public function providerForTestConvert() | ||
{ | ||
$map = array(); | ||
|
||
foreach (glob(__DIR__ . '/_fixtures/richtext/input/*.xml') as $inputFilePath) { | ||
$basename = basename($inputFilePath, '.xml'); | ||
$outputFilePath = __DIR__ . "/_fixtures/richtext/output/{$basename}.xml"; | ||
|
||
$map[] = array($inputFilePath, $outputFilePath); | ||
} | ||
|
||
return $map; | ||
} | ||
|
||
protected function normalizeRewrittenIds(DOMDocument $xmlDoc) | ||
{ | ||
$counter = 0; | ||
$xpath = new DOMXPath($xmlDoc); | ||
$nodes = $xpath->query("//*[contains(@xml:id, 'duplicated_id_')]"); | ||
foreach ($nodes as $node) { | ||
$id=$node->attributes->getNamedItem('id')->nodeValue; | ||
$node->attributes->getNamedItem('id')->nodeValue = "duplicated_id_foobar$counter"; | ||
++$counter; | ||
} | ||
} | ||
|
||
/** | ||
* @param string $inputFilePath | ||
* @param string $outputFilePath | ||
* | ||
* @dataProvider providerForTestConvert | ||
*/ | ||
public function testConvert($inputFilePath, $outputFilePath) | ||
{ | ||
$inputDocument = $this->createDocument($inputFilePath); | ||
$richText = new RichText(null); | ||
|
||
$result = $richText->convert($inputDocument, true); | ||
|
||
$convertedDocument = $this->createDocument($result, false); | ||
$expectedDocument = $this->createDocument($outputFilePath); | ||
|
||
// since duplicate ids are rewritten with random values, we need to normalize those | ||
$this->normalizeRewrittenIds($convertedDocument); | ||
|
||
$this->assertEquals( | ||
$expectedDocument, | ||
$convertedDocument | ||
); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
tests/lib/FieldType/Converter/_fixtures/richtext/input/001-title-dupid.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<section xmlns:image="http://ez.no/namespaces/ezpublish3/image/" xmlns:xhtml="http://ez.no/namespaces/ezpublish3/xhtml/" xmlns:custom="http://ez.no/namespaces/ezpublish3/custom/"> | ||
<paragraph xmlns:tmp="http://ez.no/namespaces/ezpublish3/temporary/"> | ||
<ul> | ||
<li> | ||
<paragraph xmlns:tmp="http://ez.no/namespaces/ezpublish3/temporary/"> | ||
<line><link target="_blank" xhtml:id="inv5" url_id="2309">link with id inv5</link></line> | ||
<line> </line> | ||
</paragraph> | ||
</li> | ||
<li> | ||
<paragraph xmlns:tmp="http://ez.no/namespaces/ezpublish3/temporary/"> | ||
<line><link target="_blank" xhtml:id="inv5" url_id="2309">another link with id inv5</link></line> | ||
<line> </line> | ||
</paragraph> | ||
</li> | ||
</ul> | ||
</paragraph> | ||
</section> |
Oops, something went wrong.