Skip to content

Commit

Permalink
EZP-28718: Embedded images should be handled as images instead of pla…
Browse files Browse the repository at this point in the history
…in embed object after migrating from XmlText to RichText (#39)

* Adding "ezxhtml:class="ez-embed-type-image" attribute to embedded images

* Ensured consistent naming of variables
  • Loading branch information
vidarl authored and andrerom committed Jun 4, 2018
1 parent 2bfe72b commit ccd8455
Show file tree
Hide file tree
Showing 22 changed files with 714 additions and 67 deletions.
225 changes: 180 additions & 45 deletions bundle/Command/ConvertXmlTextToRichTextCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PDO;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -27,12 +28,18 @@ class ConvertXmlTextToRichTextCommand extends ContainerAwareCommand
*/
private $logger;

public function __construct(Connection $dbal, LoggerInterface $logger = null)
/**
* @var RichTextConverter
*/
private $converter;

public function __construct(Connection $dbal, RichTextConverter $converter, LoggerInterface $logger)
{
parent::__construct();

$this->dbal = $dbal;
$this->logger = $logger;
$this->converter = $converter;
}

protected function configure()
Expand Down Expand Up @@ -64,25 +71,132 @@ protected function configure()
null,
InputOption::VALUE_OPTIONAL,
'Test if converting object with the given id succeeds'
)
->addOption(
'image-content-types',
null,
InputOption::VALUE_OPTIONAL,
'Comma separated list of content type identifiers which are considered as images when converting embedded tags. Default value is image'
)
->addOption(
'fix-embedded-images-only',
null,
InputOption::VALUE_NONE,
"Use this option to ensure that embedded images in a database are tagget correctly so that the editor will detect them as such.\n
This option is needed if you have an existing ezplatform database which was converted with an earlier version of\n
'ezxmltext:convert-to-richtext' which did not convert embedded images correctly."
);
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$this->loginAsAdmin();
$dryRun = false;
if ($input->getOption('dry-run')) {
$output->writeln("Running in dry-run mode. No changes will actually be written to database\n");
$dryRun = true;
}

$testContentObjectId = $input->getOption('test-content-object');
$testContentId = $input->getOption('test-content-object');

if ($testContentObjectId === null) {
if ($input->getOption('image-content-types')) {
$contentTypeIdentifiers = explode(',', $input->getOption('image-content-types'));
} else {
$contentTypeIdentifiers = ['image'];
}
$contentTypeIds = $this->getContentTypeIds($contentTypeIdentifiers);
if (count($contentTypeIds) !== count($contentTypeIdentifiers)) {
throw new RuntimeException('Unable to lookup all content type identifiers, found : ' . implode(',', $contentTypeIds));
}
$this->converter->setImageContentTypes($contentTypeIds);

if ($input->getOption('fix-embedded-images-only')) {
$output->writeln("Fixing embedded images only. No other changes are done to the database\n");
$this->fixEmbeddedImages($dryRun, $testContentId, $output);

return;
}

if ($testContentId === null) {
$this->convertFieldDefinitions($dryRun, $output);
} else {
$dryRun = true;
}
$this->convertFields($dryRun, $testContentObjectId, !$input->getOption('disable-duplicate-id-check'), $output);

$this->convertFields($dryRun, $testContentId, !$input->getOption('disable-duplicate-id-check'), $output);
}

protected function getContentTypeIds($contentTypeIdentifiers)
{
$query = $this->dbal->createQueryBuilder();

$query->select('c.id')
->from('ezcontentclass', 'c')
->where(
$query->expr()->in(
'c.identifier',
':contentTypeIdentifiers'
)
)
->setParameter(':contentTypeIdentifiers', $contentTypeIdentifiers, Connection::PARAM_STR_ARRAY);

$statement = $query->execute();

return $statement->fetchAll(PDO::FETCH_COLUMN);
}

protected function loginAsAdmin()
{
$userService = $this->getContainer()->get('ezpublish.api.service.user');
$repository = $this->getContainer()->get('ezpublish.api.repository');
$permissionResolver = $repository->getPermissionResolver();
$permissionResolver->setCurrentUserReference($userService->loadUserByLogin('admin'));
}

protected function fixEmbeddedImages($dryRun, $contentId, OutputInterface $output)
{
$count = $this->getRowCountOfContentObjectAttributes('ezrichtext', $contentId);

$output->writeln("Found $count field rows to convert.");

$statement = $this->getFieldRows('ezrichtext', $contentId);

$totalCount = 0;
while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
if (empty($row['data_text'])) {
$inputValue = Value::EMPTY_VALUE;
} else {
$inputValue = $row['data_text'];
}

$xmlDoc = $this->createDocument($inputValue);
$count = $this->converter->tagEmbeddedImages($xmlDoc);
if ($count > 0) {
++$totalCount;
}
$converted = $xmlDoc->saveXML();

if ($count === 0) {
$this->logger->info(
"No embedded image(s) in ezrichtext field #{$row['id']} needed to be updated",
[
'original' => $inputValue,
]
);
} else {
$this->updateFieldRow($dryRun, $row['id'], $row['version'], $converted);

$this->logger->info(
"Updated $count embded image(s) in ezrichtext field #{$row['id']}",
[
'original' => $inputValue,
'converted' => $converted,
]
);
}
}

$output->writeln("Updated ezembed tags in $totalCount field(s)");
}

protected function convertFieldDefinitions($dryRun, OutputInterface $output)
Expand Down Expand Up @@ -127,9 +241,8 @@ protected function convertFieldDefinitions($dryRun, OutputInterface $output)
$output->writeln("Converted $count ezxmltext field definitions to ezrichtext");
}

protected function convertFields($dryRun, $contentObjectId, $checkDuplicateIds, OutputInterface $output)
protected function getRowCountOfContentObjectAttributes($datatypeString, $contentId)
{
$converter = new RichTextConverter($this->logger);
$query = $this->dbal->createQueryBuilder();
$query->select('count(a.id)')
->from('ezcontentobject_attribute', 'a')
Expand All @@ -139,23 +252,30 @@ protected function convertFields($dryRun, $contentObjectId, $checkDuplicateIds,
':datatypestring'
)
)
->setParameter(':datatypestring', 'ezxmltext');
->setParameter(':datatypestring', $datatypeString);

if ($contentObjectId !== null) {
if ($contentId !== null) {
$query->andWhere(
$query->expr()->eq(
'a.contentobject_id',
':contentobjectid'
':contentid'
)
)
->setParameter(':contentobjectid', $contentObjectId);
->setParameter(':contentid', $contentId);
}

$statement = $query->execute();
$count = (int) $statement->fetchColumn();

$output->writeln("Found $count field rows to convert.");
return (int) $statement->fetchColumn();
}

/**
* @param $datatypeString
* @param $contentId
* @return \Doctrine\DBAL\Driver\Statement|int
*/
protected function getFieldRows($datatypeString, $contentId)
{
$query = $this->dbal->createQueryBuilder();
$query->select('a.*')
->from('ezcontentobject_attribute', 'a')
Expand All @@ -165,18 +285,58 @@ protected function convertFields($dryRun, $contentObjectId, $checkDuplicateIds,
':datatypestring'
)
)
->setParameter(':datatypestring', 'ezxmltext');
->setParameter(':datatypestring', $datatypeString);

if ($contentObjectId !== null) {
if ($contentId !== null) {
$query->andWhere(
$query->expr()->eq(
'a.contentobject_id',
':contentobjectid'
':contentid'
)
)
->setParameter(':contentobjectid', $contentObjectId);
->setParameter(':contentid', $contentId);
}
$statement = $query->execute();

return $query->execute();
}

protected function updateFieldRow($dryRun, $id, $version, $datatext)
{
$updateQuery = $this->dbal->createQueryBuilder();
$updateQuery->update('ezcontentobject_attribute', 'a')
->set('a.data_type_string', ':datatypestring')
->set('a.data_text', ':datatext')
->where(
$updateQuery->expr()->eq(
'a.id',
':id'
)
)
->andWhere(
$updateQuery->expr()->eq(
'a.version',
':version'
)
)
->setParameters([
':datatypestring' => 'ezrichtext',
':datatext' => $datatext,
':id' => $id,
':version' => $version,
]);

if (!$dryRun) {
$updateQuery->execute();
}
}

protected function convertFields($dryRun, $contentId, $checkDuplicateIds, OutputInterface $output)
{
$count = $this->getRowCountOfContentObjectAttributes('ezxmltext', $contentId);

$output->writeln("Found $count field rows to convert.");

$statement = $this->getFieldRows('ezxmltext', $contentId);

while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
if (empty($row['data_text'])) {
Expand All @@ -185,34 +345,9 @@ protected function convertFields($dryRun, $contentObjectId, $checkDuplicateIds,
$inputValue = $row['data_text'];
}

$converted = $converter->convert($this->createDocument($inputValue), $checkDuplicateIds, $row['id']);

$updateQuery = $this->dbal->createQueryBuilder();
$updateQuery->update('ezcontentobject_attribute', 'a')
->set('a.data_type_string', ':datatypestring')
->set('a.data_text', ':datatext')
->where(
$updateQuery->expr()->eq(
'a.id',
':id'
)
)
->andWhere(
$updateQuery->expr()->eq(
'a.version',
':version'
)
)
->setParameters([
':datatypestring' => 'ezrichtext',
':datatext' => $converted,
':id' => $row['id'],
':version' => $row['version'],
]);

if (!$dryRun) {
$updateQuery->execute();
}
$converted = $this->converter->convert($this->createDocument($inputValue), $checkDuplicateIds, $row['id']);

$this->updateFieldRow($dryRun, $row['id'], $row['version'], $converted);

$this->logger->info(
"Converted ezxmltext field #{$row['id']} to richtext",
Expand Down
7 changes: 7 additions & 0 deletions bundle/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ services:
class: EzSystems\EzPlatformXmlTextFieldTypeBundle\Command\ConvertXmlTextToRichTextCommand
arguments:
- "@ezpublish.persistence.connection"
- "@ezxmltext.richtext_converter"
- "@?logger"
tags:
- { name: console.command }

ezxmltext.richtext_converter:
class: eZ\Publish\Core\FieldType\XmlText\Converter\RichText
arguments:
- "@ezpublish.api.repository"
- "@?logger"
Loading

0 comments on commit ccd8455

Please sign in to comment.