078a5bf58d2bedcfadf82a59f7060c9f14c74d68
[Packages/TYPO3.CMS.git] / typo3 / sysext / linkvalidator / classes / tasks / class.tx_linkvalidator_tasks_validator.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010 - 2011 Michael Miousse (michael.miousse@infoglobe.ca)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25 /**
26 * This class provides Scheduler plugin implementation.
27 *
28 * @author Michael Miousse <michael.miousse@infoglobe.ca>
29 * @package TYPO3
30 * @subpackage linkvalidator
31 */
32 class tx_linkvalidator_tasks_Validator extends tx_scheduler_Task {
33
34 /**
35 * @var integer
36 */
37 protected $sleepTime;
38
39 /**
40 * @var integer
41 */
42 protected $sleepAfterFinish;
43
44 /**
45 * @var integer
46 */
47 protected $countInARun;
48
49 /**
50 * Total number of broken links.
51 *
52 * @var integer
53 */
54 protected $totalBrokenLink = 0;
55
56 /**
57 * Total number of broken links from the last run.
58 *
59 * @var integer
60 */
61 protected $oldTotalBrokenLink = 0;
62
63 /**
64 * Mail template fetched from the given template file.
65 *
66 * @var string
67 */
68 protected $templateMail;
69
70 /**
71 * specific TSconfig for this task.
72 *
73 * @var array
74 */
75 protected $configuration = array();
76
77 /**
78 * Shows if number of result was diferent from the result of the last check or not.
79 *
80 * @var boolean
81 */
82 protected $dif;
83
84 /**
85 * Template to be used for the email.
86 *
87 * @var string
88 */
89 protected $emailTemplateFile;
90
91 /**
92 * Level of pages the task should check.
93 *
94 * @var integer
95 */
96 protected $depth;
97
98 /**
99 * UID of the start page for this task.
100 *
101 * @var integer
102 */
103 protected $page;
104
105 /**
106 * Email address to which an email report is sent.
107 *
108 * @var string
109 */
110 protected $email;
111
112 /**
113 * Only send an email, if new broken links were found.
114 *
115 * @var boolean
116 */
117 protected $emailOnBrokenLinkOnly;
118
119 /**
120 * Get the value of the protected property email.
121 *
122 * @return string Email address to which an email report is sent
123 */
124 public function getEmail() {
125 return $this->email;
126 }
127
128 /**
129 * Set the value of the private property email.
130 *
131 * @param string Email address to which an email report is sent
132 * @return void
133 */
134 public function setEmail($email) {
135 $this->email=$email;
136 }
137
138 /**
139 * Get the value of the protected property emailOnBrokenLinkOnly.
140 *
141 * @return boolean Only send an email, if new broken links were found.
142 */
143 public function getEmailOnBrokenLinkOnly() {
144 return $this->emailOnBrokenLinkOnly;
145 }
146
147 /**
148 * Set the value of the private property emailOnBrokenLinkOnly.
149 *
150 * @param boolean Only send an email, if new broken links were found.
151 * @return void
152 */
153 public function setEmailOnBrokenLinkOnly($emailOnBrokenLinkOnly) {
154 $this->emailOnBrokenLinkOnly = $emailOnBrokenLinkOnly;
155 }
156
157 /**
158 * Get the value of the protected property page.
159 *
160 * @return integer UID of the start page for this task.
161 */
162 public function getPage() {
163 return $this->page;
164 }
165
166 /**
167 * Set the value of the private property page.
168 *
169 * @param integer UID of the start page for this task.
170 * @return void
171 */
172 public function setPage($page) {
173 $this->page =$page;
174 }
175
176 /**
177 * Get the value of the protected property depth.
178 *
179 * @return integer Level of pages the task should check.
180 */
181 public function getDepth() {
182 return $this->depth;
183 }
184
185 /**
186 * Set the value of the private property depth.
187 *
188 * @param integer Level of pages the task should check.
189 * @return void
190 */
191 public function setDepth($depth) {
192 $this->depth = $depth;
193 }
194
195 /**
196 * Get the value of the protected property emailTemplateFile.
197 *
198 * @return string Template to be used for the email.
199 */
200 public function getEmailTemplateFile() {
201 return $this->emailTemplateFile;
202 }
203
204 /**
205 * Set the value of the private property emailTemplateFile.
206 *
207 * @param string Template to be used for the email.
208 * @return void
209 */
210 public function setEmailTemplateFile($emailTemplateFile) {
211 $this->emailTemplateFile = $emailTemplateFile;
212 }
213
214 /**
215 * Get the value of the protected property configuration.
216 *
217 * @return array specific TSconfig for this task.
218 */
219 public function getConfiguration() {
220 return $this->configuration;
221 }
222
223 /**
224 * Set the value of the private property configuration.
225 *
226 * @param array specific TSconfig for this task.
227 * @return void
228 */
229 public function setConfiguration($configuration) {
230 $this->configuration = $configuration;
231 }
232
233
234 /**
235 * Function executed from the Scheduler.
236 *
237 * @return void
238 */
239 public function execute() {
240 $this->setCliArguments();
241 $successfullyExecuted = TRUE;
242 if (!file_exists($file = t3lib_div::getFileAbsFileName($this->emailTemplateFile)) && !empty($this->email)) {
243 throw new Exception(
244 $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/locallang.xml:tasks.error.invalidEmailTemplateFile'),
245 '1295476972'
246 );
247 }
248 $htmlFile = t3lib_div::getURL($file);
249 $this->templateMail = t3lib_parsehtml::getSubpart($htmlFile, '###REPORT_TEMPLATE###');
250
251 // The array to put the content into
252 $html = array();
253 $pageSections = '';
254 $this->dif = FALSE;
255 $pageList = t3lib_div::trimExplode(',', $this->page, 1);
256 if (is_array($pageList)) {
257 foreach ($pageList as $page) {
258 $modTS = t3lib_BEfunc::getModTSconfig($page, 'mod.linkvalidator');
259 $parseObj = t3lib_div::makeInstance('t3lib_TSparser');
260 $parseObj->parse($this->configuration);
261 if(count($parseObj->errors) > 0){
262 $parseErrorMessage = $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/locallang.xml:tasks.error.invalidTSconfig') . '<br />';
263 foreach($parseObj->errors as $errorInfo){
264 $parseErrorMessage .= $errorInfo[0] . '<br />';
265 }
266 throw new Exception(
267 $parseErrorMessage,
268 '1295476989'
269 );
270 }
271 $TSconfig = $parseObj->setup;
272 $modTS = $modTS['properties'];
273 $overrideTs = $TSconfig['mod.']['tx_linkvalidator.'];
274 if (is_array($overrideTs)) {
275 $modTS = t3lib_div::array_merge_recursive_overrule($modTS, $overrideTs);
276 }
277
278 // get the searchFields from TCA
279 foreach ($GLOBALS['TCA'] as $tableName => $table) {
280 if (!empty($table['columns'])) {
281 foreach ($table['columns'] as $columnName => $column) {
282 if ($column['config']['type'] == 'text' || $column['config']['type'] == 'input') {
283 if (!empty($column['config']['softref']) && (stripos($column['config']['softref'], "typolink")
284 !== FALSE || stripos($column['config']['softref'], "url") !== FALSE)) {
285
286 $searchFields[$tableName][] = $columnName;
287 }
288 }
289 }
290 }
291 }
292
293 // get the searchFields from TypoScript
294 foreach ($modTS['searchFields.'] as $table => $fieldList) {
295 $fields = t3lib_div::trimExplode(',', $fieldList);
296 foreach ($fields as $field) {
297 if (is_array($searchFields[$table])) {
298 if (array_search($field, $searchFields[$table]) === FALSE) {
299 $searchFields[$table][] = $field;
300 }
301 }
302 }
303 }
304 $linkTypes = t3lib_div::trimExplode(',', $modTS['linktypes'], 1);
305 if (is_array($linkTypes)) {
306 if (!empty($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['linkvalidator']['checkLinks'])
307 && is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['linkvalidator']['checkLinks'])) {
308 foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['linkvalidator']['checkLinks'] as $type => $value) {
309 if (in_array($type, $linkTypes)) {
310 $array[$type] = 1;
311 }
312 }
313 }
314 }
315 $processor = t3lib_div::makeInstance('tx_linkvalidator_Processor');
316 $pageIds = $processor->extGetTreeList($page, $this->depth, 0, '1=1');
317 $pageIds .= $page;
318 $processor->init($searchFields, $pageIds);
319 if (!empty($this->email)) {
320 $oldLinkCounts = $processor->getLinkCounts($page);
321 $this->oldTotalBrokenLink += $oldLinkCounts['brokenlinkCount'];
322 }
323
324 $processor->getLinkStatistics($array, $modTS['checkhidden']);
325
326 if (!empty($this->email)) {
327 $linkCounts = $processor->getLinkCounts($page);
328 $this->totalBrokenLink += $linkCounts['brokenlinkCount'];
329 $pageSections .= $this->buildMail($page, $pageIds, $linkCounts, $oldLinkCounts);
330 }
331
332 }
333 }
334 if ($this->totalBrokenLink != $this->oldTotalBrokenLink) {
335 $this->dif = TRUE;
336 }
337 if ($this->totalBrokenLink > 0
338 && (!$this->emailOnBrokenLinkOnly || $this->dif)
339 && !empty($this->email)
340 ) {
341 $successfullyExecuted = $this->reportEmail($pageSections, $modTS);
342 }
343 return $successfullyExecuted;
344 }
345
346
347 /**
348 * Build and send warning email when new broken links were found.
349 *
350 * @param string $pageSections: Content of page section
351 * @param string $modTS: TSconfig array
352 * @return bool TRUE if mail was sent, FALSE if or not
353 */
354 protected function reportEmail($pageSections, $modTS) {
355 $content = t3lib_parsehtml::substituteSubpart($this->templateMail, '###PAGE_SECTION###', $pageSections);
356 /** @var array $markerArray */
357 $markerArray = array();
358 /** @var array $validEmailList */
359 $validEmailList = array();
360 /** @var boolean $sendEmail */
361 $sendEmail = TRUE;
362
363 $markerArray['totalBrokenLink'] = $this->totalBrokenLink;
364 $markerArray['totalBrokenLink_old'] = $this->oldTotalBrokenLink;
365 $content = t3lib_parsehtml::substituteMarkerArray($content, $markerArray, '###|###', TRUE, TRUE);
366
367 /** @var t3lib_mail_Message $mail */
368 $mail = t3lib_div::makeInstance('t3lib_mail_Message');
369 if (t3lib_div::validEmail($modTS['mail.']['fromemail'])) {
370 $mail->setFrom(array($modTS['mail.']['fromemail'] => $modTS['mail.']['fromname']));
371 } else {
372 throw new Exception(
373 $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/locallang.xml:tasks.error.invalidFromEmail'),
374 '1295476760'
375 );
376 }
377 if(t3lib_div::validEmail($modTS['mail.']['replytoemail'])) {
378 $mail->setReplyTo(array($modTS['mail.']['replytoemail'] => $modTS['mail.']['replytoname']));
379 }
380
381 if(!empty($modTS['mail.']['subject'])) {
382 $mail->setSubject($modTS['mail.']['subject']);
383 } else {
384 throw new Exception(
385 $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/locallang.xml:tasks.error.noSubject'),
386 '1295476808'
387 );
388 }
389 if (!empty($this->email)) {
390 $emailList = t3lib_div::trimExplode(',', $this->email);
391 foreach ($emailList as $emailAdd) {
392 if (!t3lib_div::validEmail($emailAdd)) {
393 throw new Exception(
394 $GLOBALS['LANG']->sL('LLL:EXT:linkvalidator/locallang.xml:tasks.error.invalidToEmail'),
395 '1295476821'
396 );
397 } else {
398 $validEmailList[] = $emailAdd;
399 }
400 }
401 }
402 if (is_array($validEmailList) && !empty($validEmailList)) {
403 $mail->setTo($this->email);
404 } else {
405 $sendEmail = FALSE;
406 }
407
408 if($sendEmail) {
409 $mail->setBody($content,'text/html');
410 $mail->send();
411 }
412
413 return $sendEmail;
414 }
415
416
417 /**
418 * Build the mail content.
419 *
420 * @param int $curPage: id of the current page
421 * @param string $pageList: list of pages id
422 * @param array $markerArray: array of markers
423 * @param array $oldBrokenLink: markerarray with the number of link found
424 * @return string Content of the mail
425 */
426 protected function buildMail($curPage, $pageList, $markerArray, $oldBrokenLink) {
427 $pageSectionHTML = t3lib_parsehtml::getSubpart($this->templateMail, '###PAGE_SECTION###');
428
429 if (is_array($markerArray)) {
430 foreach ($markerArray as $markerKey => $markerValue) {
431 if (empty($oldBrokenLink[$markerKey])) {
432 $oldBrokenLink[$markerKey] = 0;
433 }
434 if ($markerValue != $oldBrokenLink[$markerKey]) {
435 $this->dif = TRUE;
436 }
437 $markerArray[$markerKey . '_old'] = $oldBrokenLink[$markerKey];
438 }
439 }
440 $markerArray['title'] = t3lib_BEfunc::getRecordTitle('pages', t3lib_BEfunc::getRecord('pages', $curPage));
441
442 $content = '';
443 if ($markerArray['brokenlinkCount'] > 0) {
444 $content = t3lib_parsehtml::substituteMarkerArray($pageSectionHTML, $markerArray, '###|###', TRUE, TRUE);
445 }
446 return $content;
447 }
448
449
450 /**
451 * Simulate cli call with setting the required options to the $_SERVER['argv']
452 *
453 * @return void
454 * @access protected
455 */
456 protected function setCliArguments() {
457 $_SERVER['argv'] = array(
458 $_SERVER['argv'][0],
459 'tx_link_scheduler_link',
460 '0',
461 '-ss',
462 '--sleepTime',
463 $this->sleepTime,
464 '--sleepAfterFinish',
465 $this->sleepAfterFinish,
466 '--countInARun',
467 $this->countInARun
468 );
469 }
470 }
471
472 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/linkvalidator/classes/tasks/class.tx_linkvalidator_tasks_validator.php'])) {
473 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/linkvalidator/classes/tasks/class.tx_linkvalidator_tasks_validator.php']);
474 }
475 ?>