diff --git a/extension/Documentation/Manual.rst b/extension/Documentation/Manual.rst index ef458c3c886f22137fbb6e0c21e4c01656de4534..af0ebb186a8143da2a813ff574ca6d2781c0dfaa 100644 --- a/extension/Documentation/Manual.rst +++ b/extension/Documentation/Manual.rst @@ -6553,7 +6553,7 @@ Same as above, but written in the nested notation :: } } -Best practice *recommendation* for using parameter - see `access-column-values`_ +Best practice *recommendation* for using parameter - see `access-column-values`_ :: 10 { sql = SELECT p.id AS _pId, p.name FROM exp_person AS p @@ -6587,6 +6587,78 @@ FormElement) forms: :: rsep = ,  } +.. _`system`: + +SYSTEM +====== + +.. _`autocron`: + +Auto Cron +--------- + +The `autocron` service fires periodically jobs like `send a mail` or `open a webpage`. + +* The frequency can be configured. +* Minimal time distance is 1 minute. +* Per job: if a job's runs and the receives the next trigger, the running job will be completed first. +* Per job: if more than one trigger arrives during a run, only one trigger will be processed. +* If the system misses a run, it will be played as soon as the system is online again. +* Running and processed jobs can easily be monitored. + +Setup +^^^^^ + +Setup a cron entry, typically as the webserver user ('www-data' on debian): :: + + * * * * * /usr/bin/php /var/www/html/typo3conf/ext/qfq/qfq/external/autocron.php + +Create / edit `autocron` jobs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Create a T3 page with a QFQ record. Such page should be access restricted and is only needed to edit `autocron` jobs: :: + + form={{form:S}} + + 10 { + # List of Forms: Do not show this list of forms if there is a form given by SIP. + # Table header. + sql = SELECT CONCAT('{{pageId:T}}&form=cron') as Pagen, 'id', 'Enable', 'Next run','Frequency','Comment','Last run','Status' FROM (SELECT 1) AS fake WHERE '{{form:SE}}'='' + head = <table class='table table-hover qfq-table-50'> + tail = </table> + rbeg = <thead><tr> + rend = </tr></thead> + fbeg = <th> + fend = </th> + + 10 { + # All Cron Jobs + sql = SELECT CONCAT('{{pageId:T}}&form=cron&r=', c.id) AS _Pagee, c.id, + IF(c.status='enable','green','gray') AS _bullet, + IF(c.nextrun=0,"", DATE_FORMAT(c.nextrun, "%d.%m.%y %H:%i:%s")), + c.frequency, + c.comment, + IF(c.lastrun=0,"", DATE_FORMAT(c.lastrun,"%d.%m.%y %H:%i:%s")), + LEFT(c.laststatus,40), + CONCAT('form=cron&r=', c.id) AS _Paged + FROM Cron AS c + ORDER BY c.id + + rbeg = <tr> + rend = </tr> + fbeg = <td> + fend = </td> + } + } + + + + + + + + + .. _help: Help diff --git a/extension/qfq/external/AutoCron.php b/extension/qfq/external/AutoCron.php index ba45453b88cde47a869751ffc3e9640a3483bb86..de8dfaa2f3809d334b28bd8e30e1a7206ef327f4 100644 --- a/extension/qfq/external/AutoCron.php +++ b/extension/qfq/external/AutoCron.php @@ -19,11 +19,6 @@ require_once(__DIR__ . '/../qfq/report/SendMail.php'); class AutoCron { - /** - * @var Database instantiated class - */ - protected $db = null; - /** * @var Store */ @@ -39,6 +34,14 @@ class AutoCron { */ private $phpUnit = false; + /** + * @var Database[] + */ + private $dbArray = array(); + + private $dbIndexQfq = ''; + + public function __construct($phpUnit = false) { $this->phpUnit = $phpUnit; @@ -48,8 +51,12 @@ class AutoCron { // set_error_handler("\\qfq\\ErrorHandler::exception_error_handler"); $this->store = Store::getInstance(); - $this->db = new Database(); - $this->evaluate = new Evaluate($this->store, $this->db); + + $this->dbIndexQfq = $this->store->getVar(SYSTEM_DB_INDEX_QFQ, STORE_SYSTEM); + + $this->dbArray[$this->dbIndexQfq] = new Database($this->dbIndexQfq); + + $this->evaluate = new Evaluate($this->store, $this->dbArray[$this->dbIndexQfq]); } /** @@ -62,7 +69,7 @@ class AutoCron { */ private function checkForOldJobs($ageMaxMinutes) { $sql = "SELECT c.id, ' Started at: ', c.inProgress FROM Cron AS c WHERE DATE_ADD(c.inProgress, INTERVAL $ageMaxMinutes MINUTE)<NOW()"; - $this->db->sql($sql, ROW_EXPECT_0); + $this->dbArray[$this->dbIndexQfq]->sql($sql, ROW_EXPECT_0); } /** @@ -98,7 +105,7 @@ class AutoCron { // Do the calculation with MySQL to stay in the MySQL date/time calculation world. $sql = "SELECT DATE_ADD('" . $job[AUTOCRON_NEXT_RUN] . "', INTERVAL CEILING( ( 1 + TIMESTAMPDIFF($unit, '" . $job[AUTOCRON_NEXT_RUN] . "', NOW() ) ) / $count ) * " . $job[AUTOCRON_FREQUENCY] . ") AS " . AUTOCRON_NEXT_RUN; - $row = $this->db->sql($sql, ROW_EXPECT_1); // frequency, nextRun, unit, count + $row = $this->dbArray[$this->dbIndexQfq]->sql($sql, ROW_EXPECT_1); // frequency, nextRun, unit, count $job[AUTOCRON_NEXT_RUN] = $row[AUTOCRON_NEXT_RUN]; @@ -212,7 +219,7 @@ class AutoCron { // Select pending jobs $sql = "SELECT * FROM Cron AS c WHERE c.status='enable' AND c.nextRun < NOW() AND c.nextRun!=0 AND c.inProgress=0"; - $jobs = $this->db->sql($sql); + $jobs = $this->dbArray[$this->dbIndexQfq]->sql($sql); // Iterate over all AutoCron Jobs foreach ($jobs as $job) { @@ -220,7 +227,7 @@ class AutoCron { $this->store->setStore($job, STORE_PARENT_RECORD, true); // Start progress counter - $this->db->sql("UPDATE Cron SET inProgress=NOW() WHERE id=? LIMIT 1", ROW_REGULAR, [$job[COLUMN_ID]]); + $this->dbArray[$this->dbIndexQfq]->sql("UPDATE Cron SET inProgress=NOW() WHERE id=? LIMIT 1", ROW_REGULAR, [$job[COLUMN_ID]]); switch ($job[AUTOCRON_TYPE]) { case AUTOCRON_TYPE_WEBSITE: @@ -236,7 +243,7 @@ class AutoCron { // Finish Job $job = $this->calcNextRun($job); $sql = "UPDATE Cron SET lastRun=NOW(), lastStatus=?, nextRun=?, inProgress=0 WHERE id=? LIMIT 1"; - $this->db->sql($sql, ROW_REGULAR, [$job[AUTOCRON_LAST_STATUS], $job[AUTOCRON_NEXT_RUN], $job[COLUMN_ID]]); + $this->dbArray[$this->dbIndexQfq]->sql($sql, ROW_REGULAR, [$job[AUTOCRON_LAST_STATUS], $job[AUTOCRON_NEXT_RUN], $job[COLUMN_ID]]); } $this->checkForOldJobs(AUTOCRON_MAX_AGE_MINUTES); diff --git a/extension/qfq/sql/formEditor.sql b/extension/qfq/sql/formEditor.sql index 8d3f6492b35cd49fca52ce11f9b4fd40bcf7923e..6c7f3eb04f5211b97bdc33eca8e4e0d8446fe390 100644 --- a/extension/qfq/sql/formEditor.sql +++ b/extension/qfq/sql/formEditor.sql @@ -422,25 +422,27 @@ VALUES (4, 'cron', 'cron {{SELECT IF("{{r}}" = "0", "(new)", "(Id: {{r}})") }}', 'Cron', ''); # FormElements: CopyForm -INSERT INTO FormElement (formId, name, label, mode, modeSql, type, encode, checkType, ord, parameter, size, note) +INSERT INTO FormElement (formId, name, label, mode, modeSql, type, encode, checkType, ord, parameter, size, note, dynamicUpdate) VALUES - (4, 'status', 'Enabled', 'show', '', 'checkbox', 'specialchar', 'alnumx', 10, '', '', ''), - (4, 'type', 'Type', 'show', '', 'radio', 'specialchar', 'alnumx', 20, 'buttonClass=btn-default', '', ''), - (4, 'nextRun', 'Next run', 'show', '', 'text', 'specialchar', 'alnumx', 30, '', '', - '<p>Cronjob will be started if specified timestamp is over. If timestamp=0: Job will never be started</p>\r\n<p>Every time the jobs runs, this timestamp will be increased automatically by ''frequency`.</p>'), - (4, 'frequency', 'Frequency', 'show', '', 'text', 'specialchar', 'alnumx', 40, '', '', - '<p>Repeat AutoCron-job with the specified interval. If empty: no repeating.</p>\r\n<p>E.g.: "1 DAY", "15 MINUTE'', "6 MONTH" - used directly in SQL-Function "DATE_ADD(<nextrun>, INTERVAL <frequency>)" </p>'), - (4, 'comment', 'Comment', 'show', '', 'text', 'specialchar', 'allbut', 50, '', '', - '<p>Name/Description of cronjob</p>'), - (4, 'sql1', 'Mail', 'show', '', 'text', 'none', 'all', 60, '', '60,4', - 'Query: {{!SELECT ... as sendMailTo...}}<br><b>sendMailTo / sendMailCc / sendMailBcc</b>: Separate multiple by comma.<br><b>sendMailFrom</b><br><b>sendMailSubject</b><br><b>sendMailReplyTo</b>: Optional<br><b>sendMailFlagAutoSubmit</b>: Optional. on|off. Default on - if "on", suppresses OoO answers from receivers.<br><b>sendMailGrId</b>: Optional<br><b>sendMailXId</b>: Optional'), - (4, 'content', 'Content', 'show', '', 'text', 'none', 'all', 70, '', '40,4', - '<p>Website: URL<br>Mail: Static Body or {{SELECT ...}}</p>'), - (4, 'lastRun', 'Last run', 'readonly', '', 'text', 'specialchar', 'alnumx', 80, '', '', ''), - (4, 'lastStatus', 'Laststatus', 'readonly', '', 'text', 'specialchar', 'alnumx', 90, '', '', ''), - (4, 'inProgress', 'Running', 'show', '', 'text', 'specialchar', 'alnumx', 100, '', '', - '<p>Starttime of running job. When job is finished, will be set back to 0. A new job will only be started, if this is 0.</p>\r\n<p> </p>'); - + (4, 'status', 'Enabled', 'show', '', 'checkbox', 'specialchar', 'alnumx', 10, '', '', '', 'no'), + (4, 'type', 'Type', 'show', '', 'radio', 'specialchar', 'alnumx', 20, 'buttonClass=btn-default', '', '', 'yes'), + (4, 'nextRun', 'Next run', 'show', '', 'text', 'specialchar', 'alnumx', 30, + 'extraButtonInfo = Cronjob will be started if specified timestamp is over. If timestamp=0: Job will never be started<br>Every time the jobs runs, this timestamp will be increased automatically by "frequency".', + '', '', 'no'), + (4, 'frequency', 'Frequency', 'show', '', 'text', 'specialchar', 'alnumx', 40, + 'extraButtonInfo = Repeat AutoCron-job with the specified interval. If empty: no repeating.<br>E.g.: "1 DAY", "15 MINUTE'', "6 MONTH" - used directly in SQL-Function "DATE_ADD(<nextrun>, INTERVAL <frequency>)"', + '', '', 'no'), + (4, 'comment', 'Comment', 'show', '', 'text', 'specialchar', 'allbut', 50, '', '', '', 'no'), + (4, 'sql1', 'Mail', 'show', '{{SELECT IF("{{type:FR:alnumx}}"="mail","show","hidden") }}', 'text', 'none', 'all', 60, + 'extraButtonInfo = Query: {{!SELECT ... as sendMailTo...}}<br><b>sendMailTo / sendMailCc / sendMailBcc</b>: Separate multiple by comma.<br><b>sendMailFrom</b><br><b>sendMailSubject</b><br><b>sendMailReplyTo</b>: Optional<br><b>sendMailFlagAutoSubmit</b>: Optional. on|off. Default on - if "on", suppresses OoO answers from receivers.<br><b>sendMailGrId</b>: Optional<br><b>sendMailXId</b>: Optional', + '60,4', '', 'yes'), + (4, 'content', '{{SELECT IF("{{type:FR:alnumx}}"="mail","Mail body","URL") }}', 'show', '', 'text', 'none', 'all', 70, + 'extraButtonInfo = Website: URL<br>Mail: Static Body or {{SELECT ...}}', '40,4', '', 'yes'), + (4, 'lastRun', 'Last run', 'readonly', '', 'text', 'specialchar', 'alnumx', 80, '', '', '', 'no'), + (4, 'lastStatus', 'Laststatus', 'readonly', '', 'text', 'specialchar', 'alnumx', 90, '', '', '', 'no'), + (4, 'inProgress', 'Running', 'show', '', 'text', 'specialchar', 'alnumx', 100, + 'extraButtonInfo = Starttime of running job. When job is finished, will be set back to 0. A new job will only be started, if this is 0.', + '', '', 'no'); CREATE TABLE IF NOT EXISTS `Split` ( `id` INT(11) NOT NULL AUTO_INCREMENT,