Task Interface Error Fix
August 7, 2025 ยท AI Conversations
ConcreteCoreCommandTaskRunnerCommandTaskRunner::__construct(): Argument #1 ($task) must be of type ConcreteCoreCommandTaskTaskInterface, ConcretePackageShoppingFeedManagerCommandGenerateMerchantFeedCommand given
means you're passing a `Symfony Command` (i.e., `GenerateMerchantFeedCommand`) where Concrete CMS expects a `ConcreteCoreCommandTaskTaskInterface`.
—
### ๐ What's the problem?
Concrete CMS distinguishes between:
– **Console Commands**: extend `SymfonyComponentConsoleCommandCommand`
– **Tasks**: implement `ConcreteCoreCommandTaskTaskInterface`
You're trying to run a Symfony-style command in a **Task Controller**, which expects a **Concrete CMS Task** (`TaskInterface`) โ **not a Symfony command**.
—
### โ Solution Options
#### Option 1: Create a separate Task class that wraps the command
If you want this to be used via the **Task Scheduler**, you must create a class that implements `TaskInterface`.
**Example**:
// src/Command/Task/GenerateMerchantFeedTask.php
namespace ConcretePackageShoppingFeedManagerCommandTask;
use ConcreteCoreCommandTaskTaskInterface;
use ConcreteCoreCommandTaskTaskResult;
use ConcreteCoreCommandTaskTaskResultResult;
use ConcreteCoreCommandTaskTaskResultTaskResultInterface;
use ConcreteCoreCommandTaskInputInputInterface;
use ConcreteCoreDatabaseConnectionConnection;
use ConcretePackageShoppingFeedManagerControllerMerchantFeed;
class GenerateMerchantFeedTask implements TaskInterface
{
protected $db;
protected $merchantFeed;
public function __construct(Connection $db, MerchantFeed $merchantFeed)
{
$this->db = $db;
$this->merchantFeed = $merchantFeed;
}
public function getName(): string
{
return t('Generate Merchant Feed Task');
}
public function getDescription(): string
{
return t('Generates feeds using task scheduler.');
}
public function execute(InputInterface $input): TaskResultInterface
{
$feeds = $this->db->fetchAll("SELECT feedSlug FROM shoppingfeedconfiguration");
$success = 0;
$fail = 0;
foreach ($feeds as $feed) {
try {
$res = $this->merchantFeed->generateXml($feed['feedSlug']);
if ($res->getStatusCode() === 200) {
$success++;
} else {
$fail++;
}
} catch (Exception $e) {
$fail++;
}
}
return new TaskResult(Result::create(), t('Completed: %s success, %s failed.', $success, $fail));
}
}
Then update your Task Controller like so:
use ConcretePackageShoppingFeedManagerCommandTaskGenerateMerchantFeedTask;
public function getTaskRunner(TaskInterface $task, InputInterface $input): TaskRunnerInterface
{
$db = Core::make(Connection::class);
$merchantFeed = Core::make(MerchantFeed::class);
$taskInstance = new GenerateMerchantFeedTask($db, $merchantFeed);
return new CommandTaskRunner($taskInstance);
}
—
#### Option 2: Use the Symfony Command *only* for CLI, and create a minimal task wrapper for scheduler
Keep the current `GenerateMerchantFeedCommand` as is, but treat it strictly for command-line use. Then, implement the logic in the task class separately (as shown above), or call the command via Symfony's `Application` class inside the task class if needed.
—
### โ Summary
You cannot pass a `Symfony Command` directly to `CommandTaskRunner`. Instead, create a Concrete CMS `TaskInterface` class that encapsulates the logic and works with the scheduler system. You can still share logic between your Symfony command and the task class if needed.
Let me know if you want help restructuring it to share logic between both.