Read expression node (#5920)
authorOlaf Braun <olaf_schmitz_1@t-online.de>
Fri, 24 May 2024 13:35:41 +0000 (15:35 +0200)
committerGitHub <noreply@github.com>
Fri, 24 May 2024 13:35:41 +0000 (15:35 +0200)
* Add selection for the `type` attribute of `expression`
Read the `expression` node in `cronjob.xml`

* Improve the phrasing

---------

Co-authored-by: Alexander Ebert <ebert@woltlab.com>
wcfsetup/install/files/lib/system/devtools/pip/TXmlGuiPackageInstallationPlugin.class.php
wcfsetup/install/files/lib/system/package/plugin/CronjobPackageInstallationPlugin.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 4ff5c75d4c9b616478d86992df1a84b813d36393..e5e5fce49b9f9b14f5bad5d5f540ec8321b80ca4 100644 (file)
@@ -600,7 +600,7 @@ XML;
                 $statement = WCF::getDB()->prepareStatement($sqlData['sql']);
                 $statement->execute($sqlData['parameters']);
 
-                $existingRow = $statement->fetchArray();
+                $existingRow = $statement->fetchArray() ?: [];
             }
         }
 
index ac2d7013b89fd811093385710193186dbc2cbd77..883ecefb950336ffefc04004acc8c542020a5b47 100644 (file)
@@ -14,7 +14,9 @@ use wcf\system\devtools\pip\TXmlGuiPackageInstallationPlugin;
 use wcf\system\form\builder\container\IFormContainer;
 use wcf\system\form\builder\field\BooleanFormField;
 use wcf\system\form\builder\field\ClassNameFormField;
+use wcf\system\form\builder\field\dependency\ValueFormFieldDependency;
 use wcf\system\form\builder\field\option\OptionFormField;
+use wcf\system\form\builder\field\SingleSelectionFormField;
 use wcf\system\form\builder\field\TextFormField;
 use wcf\system\form\builder\field\validation\FormFieldValidationError;
 use wcf\system\form\builder\field\validation\FormFieldValidator;
@@ -261,6 +263,28 @@ class CronjobPackageInstallationPlugin extends AbstractXMLPackageInstallationPlu
                 ->implementedInterface(ICronjob::class)
                 ->required(),
 
+            SingleSelectionFormField::create('expressionType')
+                ->label('wcf.acp.cronjob.expressionType')
+                ->required()
+                ->options([
+                    '' => 'wcf.acp.cronjob.expressionType.default',
+                    'random' => 'wcf.acp.cronjob.expressionType.random',
+                ]),
+            SingleSelectionFormField::create('expression')
+                ->label('wcf.acp.cronjob.expressionRandom')
+                ->required()
+                ->options([
+                    '@hourly' => '@hourly',
+                    '@daily' => '@daily',
+                    '@weekly' => '@weekly',
+                    '@monthly' => '@monthly',
+                ])
+                ->addDependency(
+                    (new ValueFormFieldDependency())
+                        ->fieldId('expressionType')
+                        ->values(['random'])
+                ),
+
             OptionFormField::create()
                 ->description('wcf.acp.pip.cronjob.options.description'),
 
@@ -290,13 +314,18 @@ class CronjobPackageInstallationPlugin extends AbstractXMLPackageInstallationPlu
                     ->label('wcf.acp.cronjob.' . $timeProperty)
                     ->description("wcf.acp.cronjob.{$timeProperty}.description")
                     ->required()
+                    ->addDependency(
+                        (new ValueFormFieldDependency())
+                            ->fieldId('expressionType')
+                            ->values([''])
+                    )
                     ->addValidator(new FormFieldValidator(
                         'format',
                         static function (TextFormField $formField) use ($timeProperty, $fieldFactory) {
                             $position = match ($timeProperty) {
                                 'startMinute' => CronExpression::MINUTE,
                                 'startHour' => CronExpression::HOUR,
-                                'startDom' => CronExpression::MONTH,
+                                'startDom' => CronExpression::DAY,
                                 'startMonth' => CronExpression::MONTH,
                                 'startDow' => CronExpression::WEEKDAY,
                             };
@@ -311,7 +340,7 @@ class CronjobPackageInstallationPlugin extends AbstractXMLPackageInstallationPlu
                             }
                         }
                     )),
-                'options'
+                'expression'
             );
         }
     }
@@ -327,13 +356,39 @@ class CronjobPackageInstallationPlugin extends AbstractXMLPackageInstallationPlu
             'cronjobName' => $element->getAttribute('name'),
             'description' => [],
             'packageID' => $this->installation->getPackage()->packageID,
-            'startDom' => $element->getElementsByTagName('startdom')->item(0)->nodeValue,
-            'startDow' => $element->getElementsByTagName('startdow')->item(0)->nodeValue,
-            'startHour' => $element->getElementsByTagName('starthour')->item(0)->nodeValue,
-            'startMinute' => $element->getElementsByTagName('startminute')->item(0)->nodeValue,
-            'startMonth' => $element->getElementsByTagName('startmonth')->item(0)->nodeValue,
         ];
 
+        $expressionItem = $element->getElementsByTagName('expression')->item(0);
+        if ($expressionItem instanceof \DOMElement) {
+            $expression = $expressionItem->nodeValue;
+            $expressionType = $expressionItem->getAttribute('type');
+            $cronExpression = match ($expressionType) {
+                '' => new CronExpression($expression),
+                'random' => $this->getRandomExpression(
+                    $data['cronjobName'],
+                    $expression
+                ),
+            };
+
+            $data['startMinute'] = $cronExpression->getExpression(CronExpression::MINUTE);
+            $data['startHour'] = $cronExpression->getExpression(CronExpression::HOUR);
+            $data['startDom'] = $cronExpression->getExpression(CronExpression::DAY);
+            $data['startMonth'] = $cronExpression->getExpression(CronExpression::MONTH);
+            $data['startDow'] = $cronExpression->getExpression(CronExpression::WEEKDAY);
+            $data['expressionType'] = $expressionType;
+
+            if ($expressionType === 'random') {
+                $data['expression'] = $expression;
+            }
+        } else {
+            // Legacy cronjob definition, pre 6.0
+            $data['startMinute'] = $element->getElementsByTagName('startminute')->item(0)->nodeValue;
+            $data['startHour'] = $element->getElementsByTagName('starthour')->item(0)->nodeValue;
+            $data['startDom'] = $element->getElementsByTagName('startdom')->item(0)->nodeValue;
+            $data['startMonth'] = $element->getElementsByTagName('startmonth')->item(0)->nodeValue;
+            $data['startDow'] = $element->getElementsByTagName('startdow')->item(0)->nodeValue;
+        }
+
         $canBeDisabled = $element->getElementsByTagName('canbedisabled')->item(0);
         if ($canBeDisabled !== null) {
             $data['canBeDisabled'] = $canBeDisabled->nodeValue;
@@ -401,6 +456,9 @@ class CronjobPackageInstallationPlugin extends AbstractXMLPackageInstallationPlu
             foreach ($descriptions as $languageID => $description) {
                 $data['description'][LanguageFactory::getInstance()->getLanguage($languageID)->languageCode] = $description;
             }
+
+            unset($data['expressionType']);
+            unset($data['expression']);
         }
 
         return $data;
@@ -468,14 +526,26 @@ class CronjobPackageInstallationPlugin extends AbstractXMLPackageInstallationPlu
             }
         }
 
+        $expression = $document->createElement(
+            'expression',
+            $formData['expression'] ??
+            \sprintf(
+                '%s %s %s %s %s',
+                $formData['startminute'],
+                $formData['starthour'],
+                $formData['startdom'],
+                $formData['startmonth'],
+                $formData['startdow']
+            )
+        );
+        if ($formData['expressionType'] !== '') {
+            $expression->setAttribute('type', $formData['expressionType']);
+        }
+        $cronjob->appendChild($expression);
+
         $this->appendElementChildren(
             $cronjob,
             [
-                'startminute',
-                'starthour',
-                'startdom',
-                'startmonth',
-                'startdow',
                 'options' => '',
                 'canbeedited' => 1,
                 'canbedisabled' => 1,
index f6baf087898cc5a5f92af7f5ac14e61508c917f4..a45d0ef629c1b43069c9dfee52a82e318fe1c6d3 100644 (file)
                <item name="wcf.acp.cronjob.startMonth.description"><![CDATA[Monate (1 - 12, oder jan - dec), an denen der Cronjob ausgeführt werden soll.]]></item>
                <item name="wcf.acp.cronjob.startMonthShort"><![CDATA[M]]></item>
                <item name="wcf.acp.cronjob.expression"><![CDATA[Definition (m h DoM M DoW)]]></item>
+               <item name="wcf.acp.cronjob.expressionType"><![CDATA[Ausführungszeitpunkt]]></item>
+               <item name="wcf.acp.cronjob.expressionType.default"><![CDATA[Präzise Vorgabe]]></item>
+               <item name="wcf.acp.cronjob.expressionType.random"><![CDATA[Ungefähre Zeitspanne]]></item>
+               <item name="wcf.acp.cronjob.expressionRandom"><![CDATA[Zeitspanne]]></item>
                <item name="wcf.acp.cronjob.description"><![CDATA[Beschreibung]]></item>
                <item name="wcf.acp.cronjob.nextExec"><![CDATA[Nächste Ausführung]]></item>
                <item name="wcf.acp.cronjob.edit"><![CDATA[Cronjob bearbeiten]]></item>
index b12aacc48ba5267ca9d85127264248dffbeb5252..99e1a0a57d4bcde67f7aab3ebcc754779c9a8332 100644 (file)
                <item name="wcf.acp.cronjob.startMonth.description"><![CDATA[Month (1 - 12, or jan - dec), the cronjob should be executed.]]></item>
                <item name="wcf.acp.cronjob.startMonthShort"><![CDATA[M]]></item>
                <item name="wcf.acp.cronjob.expression"><![CDATA[Definition (m h DoM M DoW)]]></item>
+               <item name="wcf.acp.cronjob.expressionType"><![CDATA[Time of Execution]]></item>
+               <item name="wcf.acp.cronjob.expressionType.default"><![CDATA[Precise values]]></item>
+               <item name="wcf.acp.cronjob.expressionType.random"><![CDATA[Approximate time span]]></item>
+               <item name="wcf.acp.cronjob.expressionRandom"><![CDATA[Time Span]]></item>
                <item name="wcf.acp.cronjob.description"><![CDATA[Description]]></item>
                <item name="wcf.acp.cronjob.nextExec"><![CDATA[Next Scheduled Execution]]></item>
                <item name="wcf.acp.cronjob.edit"><![CDATA[Edit Cronjob]]></item>