1<?php
2
3/*
4 * This file is part of the TYPO3 CMS project.
5 *
6 * It is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License, either version 2
8 * of the License, or any later version.
9 *
10 * For the full copyright and license information, please read the
11 * LICENSE.txt file that was distributed with this source code.
12 *
13 * The TYPO3 project - inspiring people to share!
14 */
15
16namespace TYPO3\CMS\Linkvalidator\Task;
17
18use TYPO3\CMS\Backend\Utility\BackendUtility;
19use TYPO3\CMS\Core\Localization\LanguageService;
20use TYPO3\CMS\Core\Messaging\FlashMessage;
21use TYPO3\CMS\Core\Utility\GeneralUtility;
22use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider;
23use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController;
24use TYPO3\CMS\Scheduler\Task\AbstractTask;
25use TYPO3\CMS\Scheduler\Task\Enumeration\Action;
26
27/**
28 * This class provides Scheduler Additional Field plugin implementation
29 * @internal This class is a specific Scheduler task implementation and is not part of the TYPO3's Core API.
30 */
31class ValidatorTaskAdditionalFieldProvider extends AbstractAdditionalFieldProvider
32{
33    /**
34     * Default language file of the extension linkvalidator
35     *
36     * @var string
37     */
38    protected $languageFile = 'LLL:EXT:linkvalidator/Resources/Private/Language/locallang.xlf';
39
40    /**
41     * Render additional information fields within the scheduler backend.
42     *
43     * @param array $taskInfo Array information of task to return
44     * @param ValidatorTask|null $task The task object being edited. Null when adding a task!
45     * @param SchedulerModuleController $schedulerModule Reference to the BE module of the Scheduler
46     * @return array Additional fields
47     * @see AdditionalFieldProviderInterface::getAdditionalFields
48     */
49    public function getAdditionalFields(array &$taskInfo, $task, SchedulerModuleController $schedulerModule)
50    {
51        $additionalFields = [];
52        $currentSchedulerModuleAction = $schedulerModule->getCurrentAction();
53
54        if (empty($taskInfo['configuration'])) {
55            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
56                $taskInfo['configuration'] = $taskInfo['linkvalidator']['configuration'];
57            } elseif ($currentSchedulerModuleAction->equals(Action::EDIT)) {
58                $taskInfo['configuration'] = $task->getConfiguration();
59            } else {
60                $taskInfo['configuration'] = $task->getConfiguration();
61            }
62        }
63
64        if (empty($taskInfo['depth'])) {
65            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
66                $taskInfo['depth'] = $taskInfo['linkvalidator']['depth'];
67            } elseif ($currentSchedulerModuleAction->equals(Action::EDIT)) {
68                $taskInfo['depth'] = $task->getDepth();
69            } else {
70                $taskInfo['depth'] = $task->getDepth();
71            }
72        }
73
74        if (empty($taskInfo['page'])) {
75            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
76                $taskInfo['page'] = $taskInfo['linkvalidator']['page'];
77            } elseif ($currentSchedulerModuleAction->equals(Action::EDIT)) {
78                $taskInfo['page'] = $task->getPage();
79            } else {
80                $taskInfo['page'] = $task->getPage();
81            }
82        }
83        if (empty($taskInfo['email'])) {
84            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
85                $taskInfo['email'] = $taskInfo['linkvalidator']['email'];
86            } elseif ($currentSchedulerModuleAction->equals(Action::EDIT)) {
87                $taskInfo['email'] = $task->getEmail();
88            } else {
89                $taskInfo['email'] = $task->getEmail();
90            }
91        }
92        if (empty($taskInfo['emailOnBrokenLinkOnly'])) {
93            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
94                $taskInfo['emailOnBrokenLinkOnly'] = $taskInfo['linkvalidator']['emailOnBrokenLinkOnly'] ?: 1;
95            } elseif ($currentSchedulerModuleAction->equals(Action::EDIT)) {
96                $taskInfo['emailOnBrokenLinkOnly'] = $task->getEmailOnBrokenLinkOnly();
97            } else {
98                $taskInfo['emailOnBrokenLinkOnly'] = $task->getEmailOnBrokenLinkOnly();
99            }
100        }
101        if (empty($taskInfo['emailTemplateFile'])) {
102            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
103                $taskInfo['emailTemplateFile'] = $taskInfo['linkvalidator']['emailTemplateFile'] ?: 'EXT:linkvalidator/Resources/Private/Templates/mailtemplate.html';
104            } elseif ($currentSchedulerModuleAction->equals(Action::EDIT)) {
105                $taskInfo['emailTemplateFile'] = $task->getEmailTemplateFile();
106            } else {
107                $taskInfo['emailTemplateFile'] = $task->getEmailTemplateFile();
108            }
109        }
110        $fieldId = 'task_page';
111        $fieldCode = '<input type="number" min="0" class="form-control" name="tx_scheduler[linkvalidator][page]" id="'
112            . $fieldId
113            . '" value="'
114            . htmlspecialchars($taskInfo['page'])
115            . '">';
116        $lang = $this->getLanguageService();
117        $label = $lang->sL($this->languageFile . ':tasks.validate.page');
118        $pageTitle = '';
119        if (!empty($taskInfo['page'])) {
120            $pageTitle = $this->getPageTitle((int)$taskInfo['page']);
121        }
122        $additionalFields[$fieldId] = [
123            'browser' => 'page',
124            'pageTitle' => $pageTitle,
125            'code' => $fieldCode,
126            'cshTable' => 'linkvalidator',
127            'cshLabel' => $fieldId,
128            'label' => $label
129        ];
130        // input for depth
131        $fieldId = 'task_depth';
132        $fieldValueArray = [
133            '0' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
134            '1' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
135            '2' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
136            '3' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
137            '4' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
138            '999' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi')
139        ];
140        /** @var array<string, string> $fieldValueArray */
141        $fieldCode = '<select class="form-control" name="tx_scheduler[linkvalidator][depth]" id="' . $fieldId . '">';
142        foreach ($fieldValueArray as $depth => $label) {
143            $fieldCode .= "\t" . '<option value="' . htmlspecialchars($depth) . '"'
144                . (($depth == $taskInfo['depth']) ? ' selected="selected"' : '') . '>'
145                . $label
146                . '</option>';
147        }
148        $fieldCode .= '</select>';
149        $label = $lang->sL($this->languageFile . ':tasks.validate.depth');
150        $additionalFields[$fieldId] = [
151            'code' => $fieldCode,
152            'cshKey' => 'linkvalidator',
153            'cshLabel' => $fieldId,
154            'label' => $label
155        ];
156        $fieldId = 'task_configuration';
157        $fieldCode = '<textarea class="form-control" name="tx_scheduler[linkvalidator][configuration]" id="'
158            . $fieldId
159            . '" >'
160            . htmlspecialchars($taskInfo['configuration'])
161            . '</textarea>';
162        $label = $lang->sL($this->languageFile . ':tasks.validate.conf');
163        $additionalFields[$fieldId] = [
164            'code' => $fieldCode,
165            'cshKey' => 'linkvalidator',
166            'cshLabel' => $fieldId,
167            'label' => $label
168        ];
169        $fieldId = 'task_email';
170        $fieldCode = '<textarea class="form-control" rows="5" cols="50" name="tx_scheduler[linkvalidator][email]" id="'
171            . $fieldId
172            . '">'
173            . htmlspecialchars($taskInfo['email'])
174            . '</textarea>';
175        $label = $lang->sL($this->languageFile . ':tasks.validate.email');
176        $additionalFields[$fieldId] = [
177            'code' => $fieldCode,
178            'cshKey' => 'linkvalidator',
179            'cshLabel' => $fieldId,
180            'label' => $label
181        ];
182        $fieldId = 'task_emailOnBrokenLinkOnly';
183        $fieldCode = '<div class="checkbox"><label>'
184            . '<input type="checkbox" name="tx_scheduler[linkvalidator][emailOnBrokenLinkOnly]" id="' . $fieldId . '" '
185            . (htmlspecialchars($taskInfo['emailOnBrokenLinkOnly']) ? 'checked="checked"' : '')
186            . '></label></div>';
187        $label = $lang->sL($this->languageFile . ':tasks.validate.emailOnBrokenLinkOnly');
188        $additionalFields[$fieldId] = [
189            'code' => $fieldCode,
190            'cshKey' => 'linkvalidator',
191            'cshLabel' => $fieldId,
192            'label' => $label
193        ];
194        $fieldId = 'task_emailTemplateFile';
195        $fieldCode = '<input class="form-control" type="text"  name="tx_scheduler[linkvalidator][emailTemplateFile]" '
196            . 'id="'
197            . $fieldId
198            . '" value="'
199            . htmlspecialchars($taskInfo['emailTemplateFile'])
200            . '">';
201        $label = $lang->sL($this->languageFile . ':tasks.validate.emailTemplateFile');
202        $additionalFields[$fieldId] = [
203            'code' => $fieldCode,
204            'cshKey' => 'linkvalidator',
205            'cshLabel' => $fieldId,
206            'label' => $label
207        ];
208        return $additionalFields;
209    }
210
211    /**
212     * Mark current value as selected by returning the "selected" attribute
213     *
214     * @param array $configurationArray Array of configuration
215     * @param string $currentValue Value of selector object
216     * @return string Html fragment for a selected option or empty
217     */
218    protected function getSelectedState(array $configurationArray, $currentValue)
219    {
220        $selected = '';
221        if (in_array($currentValue, $configurationArray, true)) {
222            $selected = 'selected="selected" ';
223        }
224        return $selected;
225    }
226
227    /**
228     * This method checks any additional data that is relevant to the specific task.
229     * If the task class is not relevant, the method is expected to return TRUE.
230     *
231     * @param array $submittedData Reference to the array containing the data submitted by the user
232     * @param SchedulerModuleController $schedulerModule Reference to the BE module of the Scheduler
233     * @return bool TRUE if validation was ok (or selected class is not relevant), FALSE otherwise
234     */
235    public function validateAdditionalFields(array &$submittedData, SchedulerModuleController $schedulerModule)
236    {
237        $isValid = true;
238        // @todo add validation to validate the $submittedData['configuration']
239        // @todo which is normally a comma separated string
240        $lang = $this->getLanguageService();
241        if (!empty($submittedData['linkvalidator']['email'])) {
242            if (strpos($submittedData['linkvalidator']['email'], ',') !== false) {
243                $emailList = GeneralUtility::trimExplode(',', $submittedData['linkvalidator']['email']);
244            } else {
245                $emailList = GeneralUtility::trimExplode(LF, $submittedData['linkvalidator']['email']);
246            }
247            foreach ($emailList as $emailAdd) {
248                if (!GeneralUtility::validEmail($emailAdd)) {
249                    $isValid = false;
250                    $this->addMessage(
251                        $lang->sL($this->languageFile . ':tasks.validate.invalidEmail'),
252                        FlashMessage::ERROR
253                    );
254                }
255            }
256        }
257
258        $row = BackendUtility::getRecord('pages', (int)$submittedData['linkvalidator']['page'], '*', '', false);
259        if (empty($row)) {
260            $isValid = false;
261            $this->addMessage(
262                $lang->sL($this->languageFile . ':tasks.validate.invalidPage'),
263                FlashMessage::ERROR
264            );
265        }
266        if ($submittedData['linkvalidator']['depth'] < 0) {
267            $isValid = false;
268            $this->addMessage(
269                $lang->sL($this->languageFile . ':tasks.validate.invalidDepth'),
270                FlashMessage::ERROR
271            );
272        }
273        return $isValid;
274    }
275
276    /**
277     * This method is used to save any additional input into the current task object
278     * if the task class matches.
279     *
280     * @param array $submittedData Array containing the data submitted by the user
281     * @param AbstractTask $task Reference to the current task object
282     */
283    public function saveAdditionalFields(array $submittedData, AbstractTask $task)
284    {
285        /** @var ValidatorTask $task */
286        $task->setDepth($submittedData['linkvalidator']['depth']);
287        $task->setPage($submittedData['linkvalidator']['page']);
288        $task->setEmail($submittedData['linkvalidator']['email']);
289        if ($submittedData['linkvalidator']['emailOnBrokenLinkOnly']) {
290            $task->setEmailOnBrokenLinkOnly(1);
291        } else {
292            $task->setEmailOnBrokenLinkOnly(0);
293        }
294        $task->setConfiguration($submittedData['linkvalidator']['configuration']);
295        $task->setEmailTemplateFile($submittedData['linkvalidator']['emailTemplateFile']);
296    }
297
298    /**
299     * Get the title of the selected page
300     *
301     * @param int $pageId
302     * @return string Page title or empty string
303     */
304    private function getPageTitle($pageId)
305    {
306        $page = BackendUtility::getRecord('pages', $pageId, 'title', '', false);
307        if ($page === null) {
308            return '';
309        }
310        return $page['title'];
311    }
312
313    /**
314     * @return LanguageService
315     */
316    protected function getLanguageService()
317    {
318        return $GLOBALS['LANG'];
319    }
320}
321