Skip to content

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:

xml
<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:

yaml
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
<?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.