[FEATURE] Allow symfony commands to be non-schedulable 46/58046/5
authorBenni Mack <benni@typo3.org>
Mon, 27 Aug 2018 11:53:56 +0000 (13:53 +0200)
committerSusanne Moog <susanne.moog@typo3.org>
Mon, 27 Aug 2018 14:02:32 +0000 (16:02 +0200)
When registering a Symfony Command, it is now possible to
define a new option `schedulable` which can explicitly set to false,
in order to have e.g. EXT:scheduler not show some.

This implements the functionality previously only available for
Extbase's CommandControllers.

Resolves: #85991
Releases: master
Change-Id: Ie2d8d3cc71d04263984a928debd257ecb88184e8
Reviewed-on: https://review.typo3.org/58046
Reviewed-by: Mathias Brodala <mbrodala@pagemachine.de>
Tested-by: Mathias Brodala <mbrodala@pagemachine.de>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
typo3/sysext/core/Classes/Console/CommandRegistry.php
typo3/sysext/core/Documentation/Changelog/master/Feature-85991-ExcludeSymfonyCommandsFromScheduler.rst [new file with mode: 0644]
typo3/sysext/extbase/Configuration/Commands.php
typo3/sysext/scheduler/Classes/Task/ExecuteSchedulableCommandAdditionalFieldProvider.php
typo3/sysext/scheduler/Configuration/Commands.php

index 3c57e7d..ff60a15 100644 (file)
@@ -38,6 +38,13 @@ class CommandRegistry implements \IteratorAggregate, SingletonInterface
     protected $commands = [];
 
     /**
+     * Map of command configurations with the command name as key
+     *
+     * @var array[]
+     */
+    protected $commandConfigurations = [];
+
+    /**
      * @param PackageManager $packageManager
      */
     public function __construct(PackageManager $packageManager = null)
@@ -57,6 +64,21 @@ class CommandRegistry implements \IteratorAggregate, SingletonInterface
     }
 
     /**
+     * Get all commands which are allowed for scheduling recurring commands.
+     *
+     * @return \Generator
+     */
+    public function getSchedulableCommands(): \Generator
+    {
+        $this->populateCommandsFromPackages();
+        foreach ($this->commands as $commandName => $command) {
+            if ($this->commandConfigurations[$commandName]['schedulable'] ?? true) {
+                yield $commandName => $command;
+            }
+        }
+    }
+
+    /**
      * @param string $identifier
      * @throws CommandNameAlreadyInUseException
      * @throws UnknownCommandException
@@ -114,6 +136,7 @@ class CommandRegistry implements \IteratorAggregate, SingletonInterface
                             );
                         }
                         $this->commands[$commandName] = GeneralUtility::makeInstance($commandConfig['class'], $commandName);
+                        $this->commandConfigurations[$commandName] = $commandConfig;
                     }
                 }
             }
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-85991-ExcludeSymfonyCommandsFromScheduler.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-85991-ExcludeSymfonyCommandsFromScheduler.rst
new file mode 100644 (file)
index 0000000..1495b7b
--- /dev/null
@@ -0,0 +1,43 @@
+.. include:: ../../Includes.txt
+
+=========================================================
+Feature: #85991 - Exclude Symfony Commands from Scheduler
+=========================================================
+
+See :issue:`85991`
+
+Description
+===========
+
+TYPO3's Scheduler system extension added a feature to call a Symfony / command repeatedly, however
+it is very helpful if an extension author can decide to explicitly define a command to be
+"non-schedulable" like the installation of an extension or the listing of syslog information which
+act as helpers on the command line.
+
+This feature is the equivalent to Extbase's `@cli` annotation for command controllers, and thus
+finishes the Scheduler integration for Symfony commands in TYPO3.
+
+
+Impact
+======
+
+A registered Symfony command can now have a new option :php:`schedulable` which can be set to
+:php:`false` for commands that should only be executed specifically by TYPO3's CLI interface.
+
+The default value is :php:`true` which means that every Symfony command can be used in the Scheduler.
+
+An example file within :file:`EXT:myextension/Configuration/Commands.php` could look like this:
+
+.. code-block:: php
+
+       return [
+           'admins:delete' => [
+               'class' => \ACME\MyExtension\Command\DeleteAllAdministratorsCommand::class,
+               'schedulable' => false,
+           ]
+       ];
+
+The command could still be executed via :bash:`.../typo3 admins:delete` but not be set up as
+Scheduler task in the TYPO3 backend.
+
+.. index:: CLI, ext:scheduler
\ No newline at end of file
index 6020d50..93007af 100644 (file)
@@ -7,10 +7,12 @@
  */
 return [
     '_core_command' => [
-        'class' => \TYPO3\CMS\Extbase\Command\CoreCommand::class
+        'class' => \TYPO3\CMS\Extbase\Command\CoreCommand::class,
+        'schedulable' => false,
     ],
     // Overriding Symfony Help command to use Extbase-specific output
     '_extbase_help' => [
-        'class' => \TYPO3\CMS\Extbase\Command\HelpCommand::class
+        'class' => \TYPO3\CMS\Extbase\Command\HelpCommand::class,
+        'schedulable' => false,
     ]
 ];
index 4eeaa0b..eb63ff7 100644 (file)
@@ -34,18 +34,6 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\TagBuilder;
 class ExecuteSchedulableCommandAdditionalFieldProvider implements AdditionalFieldProviderInterface
 {
     /**
-     * Commands that should not be schedulable, like scheduler:run,
-     * which would start a recursion.
-     *
-     * @var array
-     */
-    protected static $blacklistedCommands = [
-        \TYPO3\CMS\Scheduler\Command\SchedulerCommand::class, // scheduler:run
-        \TYPO3\CMS\Extbase\Command\CoreCommand::class, // _core_command
-        \TYPO3\CMS\Extbase\Command\HelpCommand::class, // _extbase_help
-    ];
-
-    /**
      * @var array|Command[]
      */
     protected $schedulableCommands = [];
@@ -73,10 +61,7 @@ class ExecuteSchedulableCommandAdditionalFieldProvider implements AdditionalFiel
     public function __construct()
     {
         $commandRegistry = GeneralUtility::makeInstance(CommandRegistry::class);
-        foreach ($commandRegistry as $commandIdentifier => $command) {
-            if (in_array(get_class($command), static::$blacklistedCommands, true)) {
-                continue;
-            }
+        foreach ($commandRegistry->getSchedulableCommands() as $commandIdentifier => $command) {
             $this->schedulableCommands[$commandIdentifier] = $command;
         }
 
index 4a3dc36..d6d3aa2 100644 (file)
@@ -7,6 +7,8 @@
  */
 return [
     'scheduler:run' => [
-        'class' => \TYPO3\CMS\Scheduler\Command\SchedulerCommand::class
+        'class' => \TYPO3\CMS\Scheduler\Command\SchedulerCommand::class,
+        // command must not be schedulable, otherwise we'll get an endless recursion
+        'schedulable' => false,
     ]
 ];