Skip to content

Commit

Permalink
UI improvements (ezsystems#82)
Browse files Browse the repository at this point in the history
* Let "ezxmltext:convert-to-richtext --content-object .." output non-validating Docbook xml on imports

* Added progress bar to ezxmltext:convert-to-richtext

* Replaced '\n' with PHP_EOL constant
  • Loading branch information
vidarl committed Oct 26, 2018
1 parent b1c9485 commit d111132
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 21 deletions.
90 changes: 75 additions & 15 deletions bundle/Command/ConvertXmlTextToRichTextCommand.php
Expand Up @@ -13,6 +13,7 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Helper\ProgressBar;
use eZ\Publish\Core\FieldType\XmlText\Value;
use eZ\Publish\Core\FieldType\XmlText\Converter\RichText as RichTextConverter;
use eZ\Publish\Core\FieldType\XmlText\Persistence\Legacy\ContentModelGateway as Gateway;
Expand Down Expand Up @@ -61,6 +62,15 @@ class ConvertXmlTextToRichTextCommand extends ContainerAwareCommand
*/
protected $processes = [];

/**
* @var bool
*/
protected $hasProgressBar;

/**
* @var \Symfony\Component\Console\Helper\ProgressBar
*/
protected $progressBar;
/**
* @var int
*/
Expand Down Expand Up @@ -139,10 +149,10 @@ protected function configure()
'export-dir-filter',
null,
InputOption::VALUE_OPTIONAL,
"To be used together with --export-dir option. Specify what kind of problems should be exported:\n
notice: ezxmltext contains problems which the conversion tool was able to fix automatically and likly do not need manual intervention\n
warning: the conversion tool was able to convert the ezxmltext to valid richtext, but data was maybe altered/removed/added in the process. Manual supervision recommended\n
error: the ezxmltext text cannot be converted and manual changes are required.",
'To be used together with --export-dir option. Specify what kind of problems should be exported:' . PHP_EOL .
'notice: ezxmltext contains problems which the conversion tool was able to fix automatically and likly do not need manual intervention' . PHP_EOL .
'warning: the conversion tool was able to convert the ezxmltext to valid richtext, but data was maybe altered/removed/added in the process. Manual supervision recommended' . PHP_EOL .
'error: the ezxmltext text cannot be converted and manual changes are required.',
sprintf('%s,%s', LogLevel::WARNING, LogLevel::ERROR)
)
->addOption(
Expand All @@ -161,9 +171,15 @@ protected function configure()
'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."
'Use this option to ensure that embedded images in a database are tagget correctly so that the editor will detect them as such.' . PHP_EOL .
'This option is needed if you have an existing ezplatform database which was converted with an earlier version of' . PHP_EOL .
'\'ezxmltext:convert-to-richtext\' which did not convert embedded images correctly.'
)
->addOption(
'no-progress',
null,
InputOption::VALUE_NONE,
'Disable the progress bar.'
)
->addOption(
'user',
Expand All @@ -181,17 +197,19 @@ protected function execute(InputInterface $input, OutputInterface $output)
if ($dryRun) {
$output->writeln('Running in dry-run mode. No changes will actually be written to database');
if ($this->exportDir !== '') {
$output->writeln("Note: --export-dir option provided, files will be written to $this->exportDir even in dry-run mode\n");
$output->writeln("Note: --export-dir option provided, files will be written to $this->exportDir even in dry-run mode" . PHP_EOL);
}
}

$this->hasProgressBar = !$input->getOption('no-progress');

$testContentId = $input->getOption('test-content-object');
if ($testContentId !== null && $this->maxConcurrency !== 1) {
throw new RuntimeException('Multi concurrency is not supported together with the --test-content-object option');
}

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

return;
Expand Down Expand Up @@ -381,6 +399,7 @@ protected function fixEmbeddedImages($dryRun, $contentId, OutputInterface $outpu
$count = $this->gateway->getRowCountOfContentObjectAttributes('ezrichtext', $contentId);

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

$offset = 0;
$totalCount = 0;
Expand Down Expand Up @@ -431,10 +450,12 @@ protected function fixEmbeddedImages($dryRun, $contentId, OutputInterface $outpu
);
}
}
$this->progressBarAdvance($offset);
$offset += self::MAX_OBJECTS_PER_CHILD;
} while ($offset + self::MAX_OBJECTS_PER_CHILD <= $count);
$this->progressBarFinish();

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

protected function convertFieldDefinitions($dryRun, $output)
Expand All @@ -459,11 +480,16 @@ protected function updateFieldRow($dryRun, $id, $version, $datatext)

protected function waitForAvailableProcessSlot(OutputInterface $output)
{
if (count($this->processes) >= $this->maxConcurrency) {
if (!$this->processSlotAvailable()) {
$this->waitForChild($output);
}
}

protected function processSlotAvailable()
{
return count($this->processes) < $this->maxConcurrency;
}

protected function waitForChild(OutputInterface $output)
{
$childEnded = false;
Expand Down Expand Up @@ -623,30 +649,64 @@ protected function convertFields($dryRun, $contentId, $checkDuplicateIds, $check
$this->writeCustomTagLog();
}

protected function progressBarStart(OutputInterface $output, $count)
{
if ($this->hasProgressBar) {
$this->progressBar = new ProgressBar($output, $count);
$this->progressBar->start();
}
}

protected function progressBarAdvance($step)
{
if ($this->hasProgressBar) {
$this->progressBar->advance($step);
}
}

protected function progressBarFinish()
{
if ($this->hasProgressBar) {
$this->progressBar->finish();
}
}

protected function processFields($dryRun, $checkDuplicateIds, $checkIdValues, OutputInterface $output)
{
$count = $this->gateway->getRowCountOfContentObjectAttributes('ezxmltext', null);
$output->writeln("Found $count field rows to convert.");

if ($count < self::MAX_OBJECTS_PER_CHILD * $this->maxConcurrency && $this->maxConcurrency > 1) {
$objectsPerChild = (int) ceil($count / $this->maxConcurrency);
} else {
$objectsPerChild = self::MAX_OBJECTS_PER_CHILD;
}
$offset = 0;
$fork = $this->maxConcurrency > 1;
$this->progressBarStart($output, $count);

do {
$limit = self::MAX_OBJECTS_PER_CHILD;
$limit = $objectsPerChild;
if ($fork) {
$processSlotAvailable = $this->processSlotAvailable();
$this->waitForAvailableProcessSlot($output);
if (!$processSlotAvailable) {
$this->progressBarAdvance($objectsPerChild);
}
$process = $this->createChildProcess($dryRun, $checkDuplicateIds, $checkIdValues, $offset, $limit, $output);
$this->processes[$process->getPid()] = ['offset' => $offset, 'limit' => $limit, 'process' => $process];
} else {
$this->convertFields($dryRun, null, $checkDuplicateIds, $checkIdValues, $offset, $limit);
}
$offset += self::MAX_OBJECTS_PER_CHILD;
} while ($offset + self::MAX_OBJECTS_PER_CHILD <= $count);
$offset += $objectsPerChild;
} while ($offset + $objectsPerChild <= $count);

while (count($this->processes) > 0) {
$this->waitForChild($output);
$this->progressBarAdvance($objectsPerChild);
}
$output->writeln("Converted $count ezxmltext fields to richtext");
$this->progressBarFinish();
$output->writeln(PHP_EOL . 'Converted $count ezxmltext fields to richtext');
}

protected function createDocument($xmlString)
Expand Down
24 changes: 18 additions & 6 deletions bundle/Command/ImportXmlCommand.php
Expand Up @@ -42,6 +42,11 @@ class ImportXmlCommand extends ContainerAwareCommand
*/
private $output;

/**
* @var string|null
*/
private $contentObjectId;

public function __construct(Gateway $gateway, RichTextConverter $converter)
{
parent::__construct();
Expand Down Expand Up @@ -92,13 +97,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
{
$dryRun = false;
if ($input->getOption('dry-run')) {
$output->writeln("Running in dry-run mode. No changes will actually be written to database\n");
$output->writeln('Running in dry-run mode. No changes will actually be written to database' . PHP_EOL);
$dryRun = true;
}

$this->output = $output;

$contentObjectId = $input->getOption('content-object');
$this->contentObjectId = $input->getOption('content-object');

if ($input->getOption('export-dir')) {
$this->exportDir = $input->getOption('export-dir');
Expand All @@ -118,10 +123,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$this->converter->setImageContentTypes($imageContentTypeIds);

$this->importDumps($dryRun, $contentObjectId);
$this->importDumps($dryRun);
}

protected function importDumps($dryRun, $contentObjectId = null)
protected function importDumps($dryRun)
{
foreach (new \DirectoryIterator($this->exportDir) as $dirItem) {
if ($dirItem->isFile() && $dirItem->getExtension() === 'xml') {
Expand All @@ -143,7 +148,7 @@ protected function importDumps($dryRun, $contentObjectId = null)
$language = $fileNameArray[4];
$filename = $this->exportDir . DIRECTORY_SEPARATOR . $dirItem->getFilename();

if ($contentObjectId !== null && $contentObjectId !== $objectId) {
if ($this->contentObjectId !== null && $this->contentObjectId !== $objectId) {
continue;
}

Expand All @@ -155,7 +160,9 @@ protected function importDumps($dryRun, $contentObjectId = null)

protected function validateConversion(DOMDocument $xmlDoc, $filename, $attributeId)
{
$this->converter->convert($xmlDoc, true, true, $attributeId);
$docBookDoc = new DOMDocument();
$docBookDoc->loadXML($this->converter->convert($xmlDoc, true, true, $attributeId));
$docBookDoc->formatOutput = true;
// Looks like XSLT processor is setting formatOutput to true
$xmlDoc->formatOutput = false;
$errors = $this->converter->getErrors();
Expand All @@ -178,6 +185,11 @@ protected function validateConversion(DOMDocument $xmlDoc, $filename, $attribute
}
}
}

if ($this->contentObjectId !== null) {
$this->output->writeln('Docbook result:');
$this->output->writeln($docBookDoc->saveXML());
}
} else {
$result = true;
}
Expand Down

0 comments on commit d111132

Please sign in to comment.