Task Input and Output

Was this information useful?
Thank you for your feedback.

One of the great features about tasks that sets them apart from previous attempts at solving the command execution problem is the ability for tasks to prompt users for input, and to echo output at various times.

Task Input

Defining Task Input

Getting Task Input can be done by implementing the getInputDefinition method in your task controller. This method must return null or an object of the type Concrete\Core\Command\Task\Input\Definition\Definition. The definition object defines a list of basic inputs for different types of use cases. These input types will display nicely in the Dashboard and work well within the console. Here’s an example of the getInputDefinition method within the ReindexContentController, which powers the “Reindex Content” task.

public function getInputDefinition(): ?Definition
{
    $definition = new Definition();
    $definition->addField(new BooleanField('clear', t('Clear Index'), t('Clear index before reindexing.')));
    $definition->addField(new BooleanField('rebuild', t('Rebuild Index'), t('Rebuild index attributes table by rescanning all keys.')));
    $definition->addField(new Field('after', t('After ID'), t('Reindex objects after a particular ID.')));
    $definition->addField(
        new SelectField(
            'object',
            t('Object to reindex.'),
            t('You must provide what type of object you want to reindex.'),
            [
                'pages' => t('Pages'),
                'files' => t('Files'),
                'users' => t('Users'),
                'express' => t('Express'),
            ],
            true
        )
    );
    return $definition;
}

This should do a decent job at showing off the various Task input fields that are available. We have

  • Concrete\Core\Command\Task\Input\Definition\BooleanField - a simple Yes/No field. Appears as a radio Yes/No field and dashed field in the console. If the user runs this method with --clear specified from the command line it will be akin to selected "Yes" in the Dashboard.
  • Concrete\Core\Command\Task\Input\Definition\Field - a simple text input field.
  • Concrete\Core\Command\Task\Input\Definition\SelectField - a select menu in the Dashboard, and a console option that only excepts a particular set of fields in the console.

Once you provide the input definition, the console arguments and options and the input fields are automatically available to your command. Here’s what the task options look like for Reindex Content in the Dashboard:

and on the console:

Getting Data from Task Input

Showing fields in the Dashboard and on the command line is only half of the problem; we also need to retrieve data for these task options when starting our task. Fortunately, that’s pretty easy to do from within the getTaskRunner command. The getTaskRunner command always has access to the Concrete\Core\Command\Task\Input\Input object, from which you can retrieve fields and their data. Here’s how the Reindex Content task checks the clear, rebuild, and after definition fields.

The --clear option can be checked through the use of $input->hasField()`:

if ($input->hasField('clear')) {
    $batch->add(new ClearPageIndexCommand());
}

Same with the --rebuild command, which is also a BooleanField:

if ($input->hasField('rebuild')) {
    foreach($entities as $entity) {
        $batch->add(new RebuildEntityIndexCommand($entity->getId()));
    }
}

The Field and SelectField objects can be checked with hasField and with getField:

$object = (string) $input->getField('object')->getValue();
$after = null;
if ($input->hasField('after')) {
    $after = $input->getField('after')->getValue();
}

Once you have the value of the specified inputs, you can craft your batches, process or command task runners based on what the administrators have specified.

Task Output

Tasks also do a good job of reporting their activity, provided task logging is enabled. Tasks accomplish this through the of the Concrete\Core\Command\Task\Output\OutputAwareInterface. Any command handler used by a task that implements this interface and its corresponding trait (Concrete\Core\Command\Task\Output\OutputAwareTrait) will be able to echo out various things that occur during the running of a task. Here’s how the rescan file task command reports on how it’s operating:

<?php

namespace Concrete\Core\File\Command;

use Concrete\Core\Command\Task\Output\OutputAwareInterface;
use Concrete\Core\Command\Task\Output\OutputAwareTrait;

class RescanFileTaskCommandHandler extends RescanFileCommandHandler implements OutputAwareInterface
{

    use OutputAwareTrait;

    /**
     * @param RescanFileTaskCommand $command
     */
    public function __invoke(RescanFileCommand $command)
    {
        $this->output->write(t('Rescanning file ID: %s', $command->getFileID()));
        parent::__invoke($command);
    }


}

(The RescanFileTaskCommandHandler differs from the core RescanFileCommandHandler because it reports on its operation within a task context, using $this->output.)

Once you write your task handlers using $this->output, you can rely on their output showing in real-time in the Dashboard, within historical task logs, and on the console if the task is run from the command line.