v3-4 Updating articles
Intro
The process of updating a large number of articles needs some special attention, since it's easy to leak memory from Doctrine's listeners, thus a script that needs to process thousands of articles can increase the memory consumption until it crashes.
To ease writing such scripts, XalokNext comes with the wf:cms:page-article:update
command.
The command can be invoked like this:
./app/admin/console wf:cms:page-article:update --batch-size=100 <script-name>
This command splits the work into batches of articles, each of the batches being processed in a separate process. If the process of updating one batch fails, the most common case is that the batch size was too large and the process was terminated due to exceeding the memory allocated, so the command automatically halves the batch size and tries again, until no runs are permitted.
The command requires a script-name argument, that is the name of a file stored in the app/PageArticleUpdateScripts
. Each of the files contained in this folder must define a class PageArticleUpdateScript
that defines at least a process
method.
For example, given the file app/PageArticleUpdateScripts/update_title.php
:
<?php
class PageArticleUpdateScript
{
public function process($page)
{
$modules = $page->getModules();
foreach ($modules as $module) {
if ($module['moduleId'] == 'wfed/title/page_title') {
$module['html'] = sprintf('<h1 class="title">%s</h1>', $module['data']['content']);
}
}
$page->setModules($modules);
}
}
the command should be invoked:
./app/admin/console wf:cms:page-article:update update_title
BasePageArticleUpdateScript
For some of the standard tasks, you can extend the base class that comes with XalokNext:
class PageArticleUpdateScript extends \Wf\Bundle\CmsBaseAdminBundle\Manager\BasePageArticleUpdateScript
{
public function process($page)
{
//... process the page here
}
}
The base script has methods to manipulate the top level modules (NOT a submodule of a composite). These methods are:
replaceModuleHTML
$this->replaceModuleHTML(
$page,
'wfed/title/page_title',
function($module) {
return sprintf(
'<h1 class="new-title-class">%s</h1>',
$module['data']['content']
);
}
);
replaceModuleId
$this->replaceModuleId(
$page,
'admin/body_text/epigraph',
'admin/body_text/new-epigraph-module'
);
replaceTextModuleContent
$this->replaceTextModuleContent(
$page,
'wfed/title/page_title',
function($module) {
return sprintf(
'Changed content, old content was: %s',
$module['data']['content']
);
}
);
Please note that this doesn't change the HTML to reflect the change, use replaceModuleHTML
for that.
replaceModuleSelectorById
$this->replaceModuleSelectorById(
$page,
'wfed/title/page_title',
'.new-path .to-title-module-container'
);
replaceModuleSelectorBySelector
$this->replaceModuleSelectorBySelector(
$page,
'.old-path .to-title-module-container',
'.new-path .to-title-module-container'
);