v5+ 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.
Updater scripts
To register a page updater script create a service and tag it with:
<tag name="wf_cms.page_article_updater" key="__SCRIPT_NAME__" />
For v7.3+ these services can be registered in app/config/common/admin_services.yml
:
services:
App\Bundle\CmsAdminBundle\ArticleUpdater\TestUpdater:
tags:
- name: wf_cms.page_article_updater
key: __SCRIPT_NAME__
Then you can use __SCRIPT_NAME__
as the <script-name>
argument of the wf:cms:page-article:update
command.
The service must implement \Wf\Bundle\CmsBaseAdminBundle\Manager\PageArticleUpdaterInterface
.
v7.3+ Filter articles to update
Since v7.3.5+, the updater script can implement \Wf\Bundle\CmsBaseAdminBundle\Manager\PageArticleQuerierInterface
to filter out the results passed.
Example: Filtering the articles to process based on some condition
<?php
namespace App\Bundle\CmsAdminBundle\ArticleUpdater;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Console\Output\OutputInterface;
use Wf\Bundle\CmsBaseAdminBundle\Manager\PageArticleQuerierInterface;
use Wf\Bundle\CmsBaseAdminBundle\Manager\PageArticleUpdaterInterface;
use Wf\Bundle\CmsBaseBundle\Entity\Page;
class TestUpdater implements PageArticleUpdaterInterface, PageArticleQuerierInterface
{
public function process(Page $page, OutputInterface $output)
{
// do something with the page here
}
public function buildQuery(QueryBuilder $qb)
{
// Filter only articles with even IDs ( just an example :D )
$qb->andWhere(\sprintf('MOD(%s.id, 2) = 0', $qb->getRootAliases()[0]));
}
}
Note: Please use $qb->andWhere
- using where
directly would overwrite the conditions that the base query sets for batching results.