[!!!][FEATURE] Migrate Scheduler Cli Controller to Symfony Command 46/51246/5
authorBenni Mack <benni@typo3.org>
Tue, 10 Jan 2017 20:36:40 +0000 (21:36 +0100)
committerOliver Hader <oliver.hader@typo3.org>
Tue, 10 Jan 2017 23:34:40 +0000 (00:34 +0100)
The scheduler CLI controller that is triggered via
"typo3/cli_dispatch.phpsh scheduler" is migrated to a Symfony Command,
which also allows the scheduler to be called via
"typo3/sysext/core/bin/typo3 scheduler:run" with the same arguments.

The PHP class TYPO3\CMS\Scheduler\Controller\SchedulerCliController
has been replaced by TYPO3\CMS\Scheduler\Command\SchedulerCommand.

Resolves: #79263
Releases: master
Change-Id: I3f117a5a4d46cffe303f0209ac256d0011afe979
Reviewed-on: https://review.typo3.org/51246
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
typo3/sysext/backend/Classes/Console/CliRequestHandler.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-79263-SchedulerCLIControllerClassRemoved.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Feature-79263-SchedulerCLIAvailableAsSymfonyCommand.rst [new file with mode: 0644]
typo3/sysext/scheduler/Classes/Command/SchedulerCommand.php [new file with mode: 0644]
typo3/sysext/scheduler/Classes/Controller/SchedulerCliController.php [deleted file]
typo3/sysext/scheduler/Configuration/Commands.php [new file with mode: 0644]
typo3/sysext/scheduler/Documentation/Installation/SchedulerShellScript/Index.rst
typo3/sysext/scheduler/ext_localconf.php

index 2e21379..f8ca83c 100644 (file)
@@ -65,7 +65,7 @@ class CliRequestHandler implements RequestHandlerInterface
             $this->boot();
 
             if (is_callable($commandLineScript)) {
-                call_user_func($commandLineScript);
+                call_user_func($commandLineScript, $input, $output);
             } else {
                 // include the CLI script
                 include($commandLineScript);
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-79263-SchedulerCLIControllerClassRemoved.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-79263-SchedulerCLIControllerClassRemoved.rst
new file mode 100644 (file)
index 0000000..4319307
--- /dev/null
@@ -0,0 +1,36 @@
+.. include:: ../../Includes.txt
+
+=========================================================
+Breaking: #79263 - Scheduler CLI Controller class removed
+=========================================================
+
+See :issue:`79263`
+
+Description
+===========
+
+The PHP class `TYPO3\CMS\Scheduler\Controller\SchedulerCliController` has been removed from the system extension "scheduler"
+due to the migration to a native Symfony Command.
+
+
+Impact
+======
+
+Instantiating the mentioned PHP class will result in a fatal PHP error.
+
+
+Affected Installations
+======================
+
+Any installation with a custom extension using this PHP class directly.
+
+Please note that this does not affect any calls via CLI to trigger the scheduler via `typo3/cli_dispatch.phpsh scheduler` directly. This
+still works as before.
+
+
+Migration
+=========
+
+Remove any direct calls to the PHP class and use the provided APIs via CLI instead.
+
+.. index:: CLI
\ No newline at end of file
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-79263-SchedulerCLIAvailableAsSymfonyCommand.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-79263-SchedulerCLIAvailableAsSymfonyCommand.rst
new file mode 100644 (file)
index 0000000..e29543a
--- /dev/null
@@ -0,0 +1,20 @@
+.. include:: ../../Includes.txt
+
+============================================================
+Feature: #79263 - Scheduler CLI available as Symfony Command
+============================================================
+
+See :issue:`79263`
+
+Description
+===========
+
+Calling the scheduler to process a task is now callable via CLI through `typo3/cli_dispatch.phpsh scheduler` and
+`typo3/sysext/core/bin/typo3 scheduler:run`.
+
+The following aliases for the scheduler options are now available:
+* `--task=13` or `--task 13` as synonym to `-i 13` to run a specific task
+* `--force` as synonym to `-f` to force to run a specific task in combination with `--task` or `-i` 
+* `--stop` as synonym to `-s` to stop a specific task in combination with `--task` or `-i`
+
+.. index:: CLI
\ No newline at end of file
diff --git a/typo3/sysext/scheduler/Classes/Command/SchedulerCommand.php b/typo3/sysext/scheduler/Classes/Command/SchedulerCommand.php
new file mode 100644 (file)
index 0000000..585088b
--- /dev/null
@@ -0,0 +1,162 @@
+<?php
+namespace TYPO3\CMS\Scheduler\Command;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Scheduler\Scheduler;
+use TYPO3\CMS\Scheduler\Task\AbstractTask;
+
+/**
+ * CLI command for the 'scheduler' extension which executes
+ */
+class SchedulerCommand extends Command
+{
+    /**
+     * @var bool
+     */
+    protected $hasTask = true;
+
+    /**
+     * @var Scheduler
+     */
+    protected $scheduler;
+
+    /**
+     * Configure the command by defining the name, options and arguments
+     */
+    public function configure()
+    {
+        $this
+            ->setDescription('Start the TYPO3 Scheduler from the command line.')
+            ->setHelp('If no parameter is given, the scheduler executes any tasks that are overdue to run.
+Call it like this: typo3/cli_dispatch.phpsh scheduler --task=13 -f')
+            ->addOption(
+                'task',
+                'i',
+                InputOption::VALUE_REQUIRED,
+                'UID of a specific task'
+            )
+            ->addOption(
+                'force',
+                'f',
+                InputOption::VALUE_NONE,
+                'Force execution of the task which is passed with -i option'
+            )
+            ->addOption(
+                'stop',
+                's',
+                InputOption::VALUE_NONE,
+                'Stop the task which is passed with -i option'
+            );
+    }
+
+    /**
+     * Execute scheduler tasks
+     *
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @return void
+     */
+    public function execute(InputInterface $input, OutputInterface $output)
+    {
+        // Make sure the _cli_ user is loaded
+        Bootstrap::getInstance()->initializeBackendAuthentication();
+
+        $this->scheduler = GeneralUtility::makeInstance(Scheduler::class);
+
+        if ((int)$input->getOption('task') > 0) {
+            $taskUid = (int)$input->getOption('task');
+            $stopTask = (bool)($input->hasOption('stop') && $input->getOption('stop'));
+            $force = (bool)($input->hasOption('force') && $input->getOption('force'));
+            $task = $this->getTask($taskUid, $stopTask || $force);
+
+            if ($this->scheduler->isValidTaskObject($task)) {
+                if ($stopTask) {
+                    $this->stopTask($task);
+                } else {
+                    $this->scheduler->executeTask($task);
+                }
+            }
+            // Record the run in the system registry
+            $this->scheduler->recordLastRun('cli-by-id');
+        } else {
+            $this->loopTasks();
+        }
+    }
+
+    /**
+     * Stop task
+     *
+     * @param AbstractTask $task
+     */
+    protected function stopTask($task)
+    {
+        if ($this->scheduler->isValidTaskObject($task)) {
+            $task->unmarkAllExecutions();
+        }
+    }
+
+    /**
+     * Return task a task for a given UID
+     *
+     * @param int $taskUid
+     * @param bool $force fetch the task regardless if it is queued for execution
+     * @return AbstractTask
+     */
+    protected function getTask(int $taskUid, bool $force)
+    {
+        if ($force) {
+            $task = $this->scheduler->fetchTask($taskUid);
+        } else {
+            $whereClause = 'uid = ' . (int)$taskUid . ' AND nextexecution != 0 AND nextexecution <= ' . $GLOBALS['EXEC_TIME'];
+            list($task) = $this->scheduler->fetchTasksWithCondition($whereClause);
+        }
+
+        return $task;
+    }
+
+    /**
+     * Execute tasks in loop that are ready to execute
+     */
+    protected function loopTasks()
+    {
+        do {
+            // Try getting the next task and execute it
+            // If there are no more tasks to execute, an exception is thrown by \TYPO3\CMS\Scheduler\Scheduler::fetchTask()
+            try {
+                $task = $this->scheduler->fetchTask();
+                try {
+                    $this->scheduler->executeTask($task);
+                } catch (\Exception $e) {
+                    // We ignore any exception that may have been thrown during execution,
+                    // as this is a background process.
+                    // The exception message has been recorded to the database anyway
+                    continue;
+                }
+            } catch (\OutOfBoundsException $e) {
+                $this->hasTask = false;
+            } catch (\UnexpectedValueException $e) {
+                continue;
+            }
+        } while ($this->hasTask);
+        // Record the run in the system registry
+        $this->scheduler->recordLastRun();
+    }
+}
diff --git a/typo3/sysext/scheduler/Classes/Controller/SchedulerCliController.php b/typo3/sysext/scheduler/Classes/Controller/SchedulerCliController.php
deleted file mode 100644 (file)
index dfd5ca5..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-<?php
-namespace TYPO3\CMS\Scheduler\Controller;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * CLI controller for the 'scheduler' extension.
- */
-class SchedulerCliController
-{
-    /**
-     * @var \TYPO3\CMS\Core\Controller\CommandLineController
-     */
-    protected $cli;
-
-    /**
-     * @var bool
-     */
-    protected $hasTask = true;
-
-    /**
-     * @var \TYPO3\CMS\Scheduler\Scheduler
-     */
-    protected $scheduler;
-
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        $this->cli = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Controller\CommandLineController::class);
-        $this->scheduler = GeneralUtility::makeInstance(\TYPO3\CMS\Scheduler\Scheduler::class);
-
-        // Empty options array here because Scheduler uses "-s" as argument too
-        $this->cli->cli_options = [];
-        $this->cli->cli_options[] = ['-h', 'Show this output'];
-        $this->cli->cli_options[] = ['--help', 'Same as -h'];
-        $this->cli->cli_options[] = ['-s', 'Stop the task which is passed with -i option'];
-        $this->cli->cli_options[] = ['-i', 'UID of an task'];
-        $this->cli->cli_options[] = ['-f', 'Force execution of the task which is passed with -i option'];
-
-        // Setting help texts:
-        $this->cli->cli_help['name'] = 'scheduler -- Start the TYPO3 Scheduler from the command line';
-        $this->cli->cli_help['synopsis'] = '###OPTIONS###';
-        $this->cli->cli_help['description'] = 'This command line starts any task';
-        $this->cli->cli_help['examples'] = 'typo3/cli_dispatch.phpsh scheduler';
-        unset($this->cli->cli_help['author']);
-    }
-
-    /**
-     * Check cli is help
-     *
-     * @return bool
-     */
-    protected function isHelp()
-    {
-        return ($this->cli->cli_isArg('--help') && $this->cli->cli_isArg('--help') > 0)
-            || ($this->cli->cli_isArg('-h') && $this->cli->cli_isArg('-h') > 0);
-    }
-
-    /**
-     * Execute scheduler tasks
-     */
-    public function run()
-    {
-        if ($this->isHelp()) {
-            $this->cli->cli_help();
-            return;
-        }
-
-        if ($this->cli->cli_isArg('-i') && $this->cli->cli_isArg('-i') > 0) {
-            /** @var $task \TYPO3\CMS\Scheduler\Task\AbstractTask */
-            $task = $this->getTask();
-            if ($this->scheduler->isValidTaskObject($task)) {
-                if ($this->cli->cli_isArg('-s')) {
-                    $this->stopTask($task);
-                } else {
-                    $this->scheduler->executeTask($task);
-                }
-
-                // Record the run in the system registry
-                $this->scheduler->recordLastRun('cli-by-id');
-            }
-            return;
-        }
-        $this->loopTasks();
-    }
-
-    /**
-     * Stop task
-     *
-     * @param \TYPO3\CMS\Scheduler\Task\AbstractTask $task
-     */
-    protected function stopTask($task)
-    {
-        if ($this->scheduler->isValidTaskObject($task)) {
-            $task->unmarkAllExecutions();
-        }
-    }
-
-    /**
-     * Return task
-     *
-     * @return \TYPO3\CMS\Scheduler\Task\AbstractTask
-     */
-    protected function getTask()
-    {
-        $taskId = (int)$this->cli->cli_argValue('-i');
-
-        if ($this->cli->cli_isArg('-f') || $this->cli->cli_isArg('-s')) {
-            $task = $this->scheduler->fetchTask($taskId);
-        } else {
-            $whereClause = 'uid = ' . $taskId . ' AND nextexecution != 0 AND nextexecution <= ' . $GLOBALS['EXEC_TIME'];
-            list($task) = $this->scheduler->fetchTasksWithCondition($whereClause);
-        }
-
-        return $task;
-    }
-
-    /**
-     * Execute tasks in loop
-     */
-    protected function loopTasks()
-    {
-        do {
-            // Try getting the next task and execute it
-            // If there are no more tasks to execute, an exception is thrown by \TYPO3\CMS\Scheduler\Scheduler::fetchTask()
-            try {
-                /** @var $task \TYPO3\CMS\Scheduler\Task\AbstractTask */
-                $task = $this->scheduler->fetchTask();
-                try {
-                    $this->scheduler->executeTask($task);
-                } catch (\Exception $e) {
-                    // We ignore any exception that may have been thrown during execution,
-                    // as this is a background process.
-                    // The exception message has been recorded to the database anyway
-                    continue;
-                }
-            } catch (\OutOfBoundsException $e) {
-                $this->hasTask = false;
-            } catch (\UnexpectedValueException $e) {
-                continue;
-            }
-        } while ($this->hasTask);
-        // Record the run in the system registry
-        $this->scheduler->recordLastRun();
-    }
-}
diff --git a/typo3/sysext/scheduler/Configuration/Commands.php b/typo3/sysext/scheduler/Configuration/Commands.php
new file mode 100644 (file)
index 0000000..4a3dc36
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Commands to be executed by typo3, where the key of the array
+ * is the name of the command (to be called as the first argument after typo3).
+ * Required parameter is the "class" of the command which needs to be a subclass
+ * of Symfony/Console/Command.
+ */
+return [
+    'scheduler:run' => [
+        'class' => \TYPO3\CMS\Scheduler\Command\SchedulerCommand::class
+    ]
+];
index 158cbc7..7449236 100644 (file)
@@ -21,15 +21,6 @@ to match your system):
 
    /usr/local/bin/php /home/bob/www/typo3/cli_dispatch.phpsh scheduler
 
-If the "cli\_scheduler" user was not created, this will result in the
-following error:
-
-::
-
-   ERROR: No backend user named "_cli_scheduler" was found! [Database: my_typo3_database]
-
-If the user exists, you should see nothing, as the Scheduler doesn't
-give any visual feedback while running.
 
 .. _options:
 
@@ -43,7 +34,7 @@ To run a specific scheduler task you need to provide the uid of the task:
 
 ::
 
-   /usr/local/bin/php /home/bob/www/typo3/cli_dispatch.phpsh scheduler -8
+   /usr/local/bin/php /home/bob/www/typo3/cli_dispatch.phpsh scheduler --task=8
 
 The example will trigger the task with uid 8.
 
@@ -51,6 +42,6 @@ To run a task even if it is disabled, you need to provide the force option
 
 ::
 
-   /usr/local/bin/php /home/bob/www/typo3/cli_dispatch.phpsh scheduler -8 -f
+   /usr/local/bin/php /home/bob/www/typo3/cli_dispatch.phpsh scheduler --task=8 -f
 
 This will also run the task with uid 8 if it is disabled.
index 31d3f99..50614a0 100644 (file)
@@ -3,9 +3,11 @@ defined('TYPO3_MODE') or die();
 
 // Register the Scheduler as a possible key for CLI calls
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['cliKeys']['scheduler'] = [
-    function () {
-        $schedulerCliController = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Scheduler\Controller\SchedulerCliController::class);
-        $schedulerCliController->run();
+    function ($input, $output) {
+        $app = new \Symfony\Component\Console\Application('TYPO3 Scheduler', TYPO3_version);
+        $app->add(new \TYPO3\CMS\Scheduler\Command\SchedulerCommand('scheduler'));
+        $app->setDefaultCommand('scheduler');
+        $app->run($input, $output);
     }
 ];