Passed
Push — GENERAL_BUG_REVIEW_240911 ( 3362b2...8cbbee )
by Rafael
49:13
created

Cronjob   F

Complexity

Total Complexity 298

Size/Duplication

Total Lines 1508
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 901
dl 0
loc 1508
rs 1.699
c 0
b 0
f 0
wmc 298

15 Methods

Rating   Name   Duplication   Size   Complexity  
B getTooltipContentArray() 0 35 9
D reprogram_jobs() 0 69 22
A __construct() 0 3 1
F create() 0 191 74
A getLibStatut() 0 3 1
B LibStatut() 0 35 9
F run_jobs() 0 280 49
F getNomUrl() 0 64 20
A delete() 0 27 5
F update() 0 178 80
A createFromClone() 0 43 3
A initAsSpecimen() 0 38 1
F fetchAll() 0 137 17
B fetch() 0 94 4
A info() 0 26 3

How to fix   Complexity   

Complex Class

Complex classes like Cronjob often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Cronjob, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* Copyright (C) 2007-2022  Laurent Destailleur         <[email protected]>
4
 * Copyright (C) 2013       Florian Henry               <[email protected]>
5
 * Copyright (C) 2023-2024	William Mead		        <[email protected]>
6
 * Copyright (C) 2024       Frédéric France             <[email protected]>
7
 * Copyright (C) 2024		MDW							<[email protected]>
8
 * Copyright (C) 2024       Rafael San José             <[email protected]>
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23
24
namespace Dolibarr\Code\Cron\Classes;
25
26
use Dolibarr\Code\Core\Classes\CMailFile;
27
use Dolibarr\Code\Core\Classes\Utils;
28
use Dolibarr\Code\User\Classes\User;
29
use Dolibarr\Core\Base\CommonObject;
30
use Dolibarr\Core\Base\CommonObjectLine;
31
use Dolibarr\Lib\Misc;
32
use DoliDB;
33
34
/**
35
 *  \file       cron/class/cronjob.class.php
36
 *  \ingroup    cron
37
 */
38
39
// Put here all includes required by your class file
40
41
require_once DOL_DOCUMENT_ROOT . "/core/lib/date.lib.php";
42
43
44
/**
45
 *  Cron Job class
46
 */
47
class Cronjob extends CommonObject
48
{
49
    const STATUS_DISABLED = 0;
50
    const STATUS_ENABLED = 1;
51
    const STATUS_ARCHIVED = 2;
52
    const MAXIMUM_LENGTH_FOR_LASTOUTPUT_FIELD = 65535;
53
    /**
54
     * @var string ID to identify managed object
55
     */
56
    public $element = 'cronjob';
57
    /**
58
     * @var string Name of table without prefix where object is stored
59
     */
60
    public $table_element = 'cronjob';
61
    /**
62
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
63
     */
64
    public $picto = 'cron';
65
    /**
66
     * @var int Entity
67
     */
68
    public $entity;
69
    /**
70
     * @var string Job type
71
     */
72
    public $jobtype;
73
    /**
74
     * @var string|int     Date for cron job create
75
     */
76
    public $datec = '';
77
    /**
78
     * @var string Cron Job label
79
     */
80
    public $label;
81
    /**
82
     * @var string Job command
83
     */
84
    public $command;
85
    public $classesname;
86
    public $objectname;
87
    public $methodename;
88
    public $params;
89
    public $md5params;
90
    public $module_name;
91
    public $priority;
92
    /**
93
     * @var string|int|null     Date for last job execution
94
     */
95
    public $datelastrun = '';
96
    /**
97
     * @var string|int          Date for next job execution
98
     */
99
    public $datenextrun = '';
100
    /**
101
     * @var string|int          Date for end job execution
102
     */
103
    public $dateend = '';
104
    /**
105
     * @var string|int          Date for first start job execution
106
     */
107
    public $datestart = '';
108
    /**
109
     * @var string|int|null     Date for last result job execution
110
     */
111
    public $datelastresult = '';
112
    /**
113
     * @var string          Last result from end job execution
114
     */
115
    public $lastresult;
116
    /**
117
     * @var string          Last output from end job execution
118
     */
119
    public $lastoutput;
120
    /**
121
     * @var string          Unit frequency of job execution ('60', '86400', 'd', 'm', ...)
122
     */
123
    public $unitfrequency;
124
    /**
125
     * @var int             Frequency of job execution
126
     */
127
    public $frequency;
128
    /**
129
     * @var int             Status
130
     */
131
    public $status;
132
    /**
133
     * @var int             Is job running ?
134
     */
135
    public $processing;
136
    /**
137
     * @var int|null        The job current PID
138
     */
139
    public $pid;
140
    /**
141
     * @var string          Email when an error occurs
142
     */
143
    public $email_alert;
144
    /**
145
     * @var int             User ID of creation
146
     */
147
    public $fk_user_author;
148
    /**
149
     * @var int             User ID of last modification
150
     */
151
    public $fk_user_mod;
152
    /**
153
     * @var int             Number of run job execution
154
     */
155
    public $nbrun;
156
    /**
157
     * @var int             Maximum run job execution
158
     */
159
    public $maxrun;
160
    /**
161
     * @var string          Libname
162
     */
163
    public $libname;
164
    /**
165
     * @var string          A test condition to know if job is visible/qualified
166
     */
167
    public $test;
168
    /**
169
     * @var string          Autodelete
170
     */
171
    public $autodelete;
172
    /**
173
     * @var CommonObjectLine[]          Cronjob
174
     */
175
    public $lines;
176
177
    /**
178
     *  Constructor
179
     *
180
     * @param DoliDB $db Database handler
181
     */
182
    public function __construct(DoliDB $db)
183
    {
184
        $this->db = $db;
185
    }
186
187
    /**
188
     * Load list of cron jobs in a memory array from the database
189
     *
190
     * @param string $sortorder Sort order
191
     * @param string $sortfield Sort field
192
     * @param int $limit Limit page
193
     * @param int $offset Offset ppage
194
     * @param int $status Display active or not (-1=no filter, 0=not active, 1=active, 2=archived)
195
     * @param string|array $filter Filter USF.
196
     * @param int $processing Processing or not (-1=all, 0=not in progress, 1=in progress)
197
     * @return  int                             if KO: <0 || if OK: >0
198
     */
199
    public function fetchAll(string $sortorder = 'DESC', string $sortfield = 't.rowid', int $limit = 0, int $offset = 0, int $status = 1, $filter = '', int $processing = -1)
200
    {
201
        $this->lines = array();
202
203
        $sql = "SELECT";
204
        $sql .= " t.rowid,";
205
        $sql .= " t.entity,";
206
        $sql .= " t.tms,";
207
        $sql .= " t.datec,";
208
        $sql .= " t.jobtype,";
209
        $sql .= " t.label,";
210
        $sql .= " t.command,";
211
        $sql .= " t.classesname,";
212
        $sql .= " t.objectname,";
213
        $sql .= " t.methodename,";
214
        $sql .= " t.params,";
215
        $sql .= " t.md5params,";
216
        $sql .= " t.module_name,";
217
        $sql .= " t.priority,";
218
        $sql .= " t.datelastrun,";
219
        $sql .= " t.datenextrun,";
220
        $sql .= " t.dateend,";
221
        $sql .= " t.datestart,";
222
        $sql .= " t.lastresult,";
223
        $sql .= " t.datelastresult,";
224
        $sql .= " t.lastoutput,";
225
        $sql .= " t.unitfrequency,";
226
        $sql .= " t.frequency,";
227
        $sql .= " t.status,";
228
        $sql .= " t.processing,";
229
        $sql .= " t.pid,";
230
        $sql .= " t.email_alert,";
231
        $sql .= " t.fk_user_author,";
232
        $sql .= " t.fk_user_mod,";
233
        $sql .= " t.note as note_private,";
234
        $sql .= " t.nbrun,";
235
        $sql .= " t.maxrun,";
236
        $sql .= " t.libname,";
237
        $sql .= " t.test";
238
        $sql .= " FROM " . MAIN_DB_PREFIX . "cronjob as t";
239
        $sql .= " WHERE 1 = 1";
240
        if ($processing >= 0) {
241
            $sql .= " AND t.processing = " . (empty($processing) ? '0' : '1');
242
        }
243
        if ($status >= 0 && $status < 2) {
244
            $sql .= " AND t.status = " . (empty($status) ? '0' : '1');
245
        } elseif ($status == 2) {
246
            $sql .= " AND t.status = 2";
247
        }
248
249
        // Manage filter
250
        if (is_array($filter)) {
251
            if (count($filter) > 0) {
252
                foreach ($filter as $key => $value) {
253
                    if ($key == 't.rowid') {
254
                        $sql .= " AND " . $this->db->sanitize($key) . " = " . ((int)$value);
255
                    } else {
256
                        $sql .= " AND " . $this->db->sanitize($key) . " LIKE '%" . $this->db->escape($this->db->escapeforlike($value)) . "%'";
257
                    }
258
                }
259
            }
260
261
            $filter = '';
262
        }
263
264
        // Manage filter
265
        $errormessage = '';
266
        $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
267
        if ($errormessage) {
268
            $this->errors[] = $errormessage;
269
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
270
            return -1;
271
        }
272
273
        $sql .= $this->db->order($sortfield, $sortorder);
274
        if (!empty($limit) && !empty($offset)) {
275
            $sql .= $this->db->plimit($limit + 1, $offset);
276
        }
277
278
        dol_syslog(get_class($this) . "::fetchAll", LOG_DEBUG);
279
        $resql = $this->db->query($sql);
280
        if ($resql) {
281
            $num = $this->db->num_rows($resql);
282
            $i = 0;
283
284
            if ($num) {
285
                while ($i < $num) {
286
                    $obj = $this->db->fetch_object($resql);
287
                    $cronjob_obj = new Cronjob($this->db);
288
289
                    $cronjob_obj->id = $obj->rowid;
290
                    $cronjob_obj->ref = $obj->rowid;
291
                    $cronjob_obj->entity = $obj->entity;
292
                    $cronjob_obj->tms = $this->db->jdate($obj->tms);
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$tms has been deprecated: Use $date_modification ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

292
                    /** @scrutinizer ignore-deprecated */ $cronjob_obj->tms = $this->db->jdate($obj->tms);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
Documentation Bug introduced by
It seems like $this->db->jdate($obj->tms) can also be of type string. However, the property $tms is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
293
                    $cronjob_obj->datec = $this->db->jdate($obj->datec);
294
                    $cronjob_obj->label = $obj->label;
295
                    $cronjob_obj->jobtype = $obj->jobtype;
296
                    $cronjob_obj->command = $obj->command;
297
                    $cronjob_obj->classesname = $obj->classesname;
298
                    $cronjob_obj->objectname = $obj->objectname;
299
                    $cronjob_obj->methodename = $obj->methodename;
300
                    $cronjob_obj->params = $obj->params;
301
                    $cronjob_obj->md5params = $obj->md5params;
302
                    $cronjob_obj->module_name = $obj->module_name;
303
                    $cronjob_obj->priority = $obj->priority;
304
                    $cronjob_obj->datelastrun = $this->db->jdate($obj->datelastrun);
305
                    $cronjob_obj->datenextrun = $this->db->jdate($obj->datenextrun);
306
                    $cronjob_obj->dateend = $this->db->jdate($obj->dateend);
307
                    $cronjob_obj->datestart = $this->db->jdate($obj->datestart);
308
                    $cronjob_obj->lastresult = $obj->lastresult;
309
                    $cronjob_obj->lastoutput = $obj->lastoutput;
310
                    $cronjob_obj->datelastresult = $this->db->jdate($obj->datelastresult);
311
                    $cronjob_obj->unitfrequency = $obj->unitfrequency;
312
                    $cronjob_obj->frequency = $obj->frequency;
313
                    $cronjob_obj->status = $obj->status;
314
                    $cronjob_obj->processing = $obj->processing;
315
                    $cronjob_obj->pid = $obj->pid;
316
                    $cronjob_obj->email_alert = $obj->email_alert;
317
                    $cronjob_obj->fk_user_author = $obj->fk_user_author;
318
                    $cronjob_obj->fk_user_mod = $obj->fk_user_mod;
319
                    $cronjob_obj->note_private = $obj->note_private;
320
                    $cronjob_obj->nbrun = $obj->nbrun;
321
                    $cronjob_obj->maxrun = $obj->maxrun;
322
                    $cronjob_obj->libname = $obj->libname;
323
                    $cronjob_obj->test = $obj->test;
324
325
                    $this->lines[] = $cronjob_obj;
326
327
                    $i++;
328
                }
329
            }
330
            $this->db->free($resql);
331
332
            return 1;
333
        } else {
334
            $this->error = "Error " . $this->db->lasterror();
335
            return -1;
336
        }
337
    }
338
339
    /**
340
     * Delete object in database
341
     *
342
     * @param User $user User that deletes
343
     * @param int $notrigger 0=launch triggers after, 1=disable triggers
344
     * @return  int                 if KO: <0 || if OK: >0
345
     */
346
    public function delete(User $user, int $notrigger = 0)
347
    {
348
        $error = 0;
349
350
        $this->db->begin();
351
352
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "cronjob";
353
        $sql .= " WHERE rowid=" . ((int)$this->id);
354
355
        dol_syslog(get_class($this) . "::delete", LOG_DEBUG);
356
        $resql = $this->db->query($sql);
357
        if (!$resql) {
358
            $error++;
359
            $this->errors[] = "Error " . $this->db->lasterror();
360
        }
361
362
        // Commit or rollback
363
        if ($error) {
364
            foreach ($this->errors as $errmsg) {
365
                dol_syslog(get_class($this) . "::delete " . $errmsg, LOG_ERR);
366
                $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
367
            }
368
            $this->db->rollback();
369
            return -1 * $error;
370
        } else {
371
            $this->db->commit();
372
            return 1;
373
        }
374
    }
375
376
    /**
377
     * Load an object from its id and create a new one in database
378
     *
379
     * @param User $user User making the clone
380
     * @param int $fromid Id of object to clone
381
     * @return  int                 New id of clone
382
     */
383
    public function createFromClone(User $user, int $fromid)
384
    {
385
        global $langs;
386
387
        $error = 0;
388
389
        $object = new Cronjob($this->db);
390
391
        $this->db->begin();
392
393
        // Load source object
394
        $object->fetch($fromid);
395
        $object->id = 0;
396
397
        // Clear fields
398
        $object->status = self::STATUS_DISABLED;
399
        $object->label = $langs->trans("CopyOf") . ' ' . $langs->trans($object->label);
400
        $object->datelastrun = null;
401
        $object->lastresult = '';
402
        $object->datelastresult = null;
403
        $object->lastoutput = '';
404
        $object->nbrun = 0;
405
406
        // Create clone
407
        $object->context['createfromclone'] = 'createfromclone';
408
        $result = $object->create($user);
409
410
        // Other options
411
        if ($result < 0) {
412
            $this->error = $object->error;
413
            $this->errors = $object->errors;
414
            $error++;
415
        }
416
417
        unset($object->context['createfromclone']);
418
419
        // End
420
        if (!$error) {
421
            $this->db->commit();
422
            return $object->id;
423
        } else {
424
            $this->db->rollback();
425
            return -1;
426
        }
427
    }
428
429
    /**
430
     * Load object in memory from the database
431
     *
432
     * @param int $id Id object
433
     * @param string $objectname Object name
434
     * @param string $methodname Method name
435
     * @return  int                         if KO: <0 || if OK: >0
436
     */
437
    public function fetch(int $id, string $objectname = '', string $methodname = '')
438
    {
439
        $sql = "SELECT";
440
        $sql .= " t.rowid,";
441
        $sql .= " t.entity,";
442
        $sql .= " t.tms,";
443
        $sql .= " t.datec,";
444
        $sql .= " t.jobtype,";
445
        $sql .= " t.label,";
446
        $sql .= " t.command,";
447
        $sql .= " t.classesname,";
448
        $sql .= " t.objectname,";
449
        $sql .= " t.methodename,";
450
        $sql .= " t.params,";
451
        $sql .= " t.md5params,";
452
        $sql .= " t.module_name,";
453
        $sql .= " t.priority,";
454
        $sql .= " t.datelastrun,";
455
        $sql .= " t.datenextrun,";
456
        $sql .= " t.dateend,";
457
        $sql .= " t.datestart,";
458
        $sql .= " t.lastresult,";
459
        $sql .= " t.datelastresult,";
460
        $sql .= " t.lastoutput,";
461
        $sql .= " t.unitfrequency,";
462
        $sql .= " t.frequency,";
463
        $sql .= " t.status,";
464
        $sql .= " t.processing,";
465
        $sql .= " t.pid,";
466
        $sql .= " t.email_alert,";
467
        $sql .= " t.fk_user_author,";
468
        $sql .= " t.fk_user_mod,";
469
        $sql .= " t.note as note_private,";
470
        $sql .= " t.nbrun,";
471
        $sql .= " t.maxrun,";
472
        $sql .= " t.libname,";
473
        $sql .= " t.test";
474
        $sql .= " FROM " . MAIN_DB_PREFIX . "cronjob as t";
475
        if ($id > 0) {
476
            $sql .= " WHERE t.rowid = " . ((int)$id);
477
        } else {
478
            $sql .= " WHERE t.entity IN(0, " . getEntity('cron') . ")";
479
            $sql .= " AND t.objectname = '" . $this->db->escape($objectname) . "'";
480
            $sql .= " AND t.methodename = '" . $this->db->escape($methodname) . "'";
481
        }
482
483
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
484
        $resql = $this->db->query($sql);
485
        if ($resql) {
486
            if ($this->db->num_rows($resql)) {
487
                $obj = $this->db->fetch_object($resql);
488
489
                $this->id = $obj->rowid;
490
                $this->ref = $obj->rowid;
491
                $this->entity = $obj->entity;
492
                $this->tms = $this->db->jdate($obj->tms);
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$tms has been deprecated: Use $date_modification ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

492
                /** @scrutinizer ignore-deprecated */ $this->tms = $this->db->jdate($obj->tms);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
Documentation Bug introduced by
It seems like $this->db->jdate($obj->tms) can also be of type string. However, the property $tms is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
493
                $this->datec = $this->db->jdate($obj->datec);
494
                $this->label = $obj->label;
495
                $this->jobtype = $obj->jobtype;
496
                $this->command = $obj->command;
497
                $this->classesname = $obj->classesname;
498
                $this->objectname = $obj->objectname;
499
                $this->methodename = $obj->methodename;
500
                $this->params = $obj->params;
501
                $this->md5params = $obj->md5params;
502
                $this->module_name = $obj->module_name;
503
                $this->priority = $obj->priority;
504
                $this->datelastrun = $this->db->jdate($obj->datelastrun);
505
                $this->datenextrun = $this->db->jdate($obj->datenextrun);
506
                $this->dateend = $this->db->jdate($obj->dateend);
507
                $this->datestart = $this->db->jdate($obj->datestart);
508
                $this->lastresult = (string)$obj->lastresult;
509
                $this->lastoutput = $obj->lastoutput;
510
                $this->datelastresult = $this->db->jdate($obj->datelastresult);
511
                $this->unitfrequency = $obj->unitfrequency;
512
                $this->frequency = $obj->frequency;
513
                $this->status = $obj->status;
514
                $this->processing = $obj->processing;
515
                $this->pid = $obj->pid;
516
                $this->email_alert = $obj->email_alert;
517
                $this->fk_user_author = $obj->fk_user_author;
518
                $this->fk_user_mod = $obj->fk_user_mod;
519
                $this->note_private = $obj->note_private;
520
                $this->nbrun = $obj->nbrun;
521
                $this->maxrun = $obj->maxrun;
522
                $this->libname = $obj->libname;
523
                $this->test = $obj->test;
524
            }
525
            $this->db->free($resql);
526
527
            return 1;
528
        } else {
529
            $this->error = "Error " . $this->db->lasterror();
530
            return -1;
531
        }
532
    }
533
534
    /**
535
     * Create object into database
536
     *
537
     * @param User $user User that creates
538
     * @param int $notrigger 0=launch triggers after, 1=disable triggers
539
     * @return int                  if KO: <0 || if OK: Id of created object
540
     */
541
    public function create(User $user, int $notrigger = 0)
542
    {
543
        global $conf, $langs;
544
        $error = 0;
545
546
        $now = dol_now();
547
548
        // Clean parameters
549
        if (isset($this->label)) {
550
            $this->label = trim($this->label);
551
        }
552
        if (isset($this->jobtype)) {
553
            $this->jobtype = trim($this->jobtype);
554
        }
555
        if (isset($this->command)) {
556
            $this->command = trim($this->command);
557
        }
558
        if (isset($this->classesname)) {
559
            $this->classesname = trim($this->classesname);
560
        }
561
        if (isset($this->objectname)) {
562
            $this->objectname = trim($this->objectname);
563
        }
564
        if (isset($this->methodename)) {
565
            $this->methodename = trim($this->methodename);
566
        }
567
        if (isset($this->params)) {
568
            $this->params = trim($this->params);
569
        }
570
        if (isset($this->md5params)) {
571
            $this->md5params = trim($this->md5params);
572
        }
573
        if (isset($this->module_name)) {
574
            $this->module_name = trim($this->module_name);
575
        }
576
        if (isset($this->priority)) {
577
            $this->priority = trim($this->priority);
578
        }
579
        if (isset($this->lastoutput)) {
580
            $this->lastoutput = trim($this->lastoutput);
581
        }
582
        if (isset($this->lastresult)) {
583
            $this->lastresult = trim($this->lastresult);
584
        }
585
        if (isset($this->unitfrequency)) {
586
            $this->unitfrequency = trim($this->unitfrequency);
587
        }
588
        if (isset($this->frequency)) {
589
            $this->frequency = (int)$this->frequency;
590
        }
591
        if (isset($this->status)) {
592
            $this->status = (int)$this->status;
593
        }
594
        if (isset($this->note_private)) {
595
            $this->note_private = trim($this->note_private);
596
        }
597
        if (isset($this->nbrun)) {
598
            $this->nbrun = (int)$this->nbrun;
599
        }
600
        if (isset($this->maxrun)) {
601
            $this->maxrun = (int)$this->maxrun;
602
        }
603
        if (isset($this->libname)) {
604
            $this->libname = trim($this->libname);
605
        }
606
        if (isset($this->test)) {
607
            $this->test = trim($this->test);
608
        }
609
610
        // Check parameters
611
        // Put here code to add a control on parameters values
612
        if (dol_strlen($this->datenextrun) == 0) {
613
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronDtNextLaunch'));
614
            $error++;
615
        }
616
        if (empty($this->label)) {
617
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronLabel'));
618
            $error++;
619
        }
620
        if ((dol_strlen($this->datestart) != 0) && (dol_strlen($this->dateend) != 0) && ($this->dateend < $this->datestart)) {
621
            $this->errors[] = $langs->trans('CronErrEndDateStartDt');
622
            $error++;
623
        }
624
        if (empty($this->unitfrequency)) {
625
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronFrequency'));
626
            $error++;
627
        }
628
        if (($this->jobtype == 'command') && (empty($this->command))) {
629
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronCommand'));
630
            $error++;
631
        }
632
        if (($this->jobtype == 'method') && (empty($this->classesname))) {
633
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronClass'));
634
            $error++;
635
        }
636
        if (($this->jobtype == 'method' || $this->jobtype == 'function') && (empty($this->methodename))) {
637
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronMethod'));
638
            $error++;
639
        }
640
        if (($this->jobtype == 'method') && (empty($this->objectname))) {
641
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronObject'));
642
            $error++;
643
        }
644
        if (($this->jobtype == 'function') && (empty($this->libname))) {
645
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronLib'));
646
            $error++;
647
        }
648
649
        // Insert request
650
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "cronjob(";
651
        $sql .= "entity,";
652
        $sql .= "datec,";
653
        $sql .= "jobtype,";
654
        $sql .= "label,";
655
        $sql .= "command,";
656
        $sql .= "classesname,";
657
        $sql .= "objectname,";
658
        $sql .= "methodename,";
659
        $sql .= "params,";
660
        $sql .= "md5params,";
661
        $sql .= "module_name,";
662
        $sql .= "priority,";
663
        $sql .= "datelastrun,";
664
        $sql .= "datenextrun,";
665
        $sql .= "dateend,";
666
        $sql .= "datestart,";
667
        $sql .= "lastresult,";
668
        $sql .= "datelastresult,";
669
        $sql .= "lastoutput,";
670
        $sql .= "unitfrequency,";
671
        $sql .= "frequency,";
672
        $sql .= "status,";
673
        $sql .= "fk_user_author,";
674
        $sql .= "fk_user_mod,";
675
        $sql .= "note,";
676
        $sql .= "nbrun,";
677
        $sql .= "maxrun,";
678
        $sql .= "libname,";
679
        $sql .= "test";
680
        $sql .= ") VALUES (";
681
        $sql .= " " . (!isset($this->entity) ? $conf->entity : $this->db->escape($this->entity)) . ",";
682
        $sql .= " '" . $this->db->idate($now) . "',";
683
        $sql .= " " . (!isset($this->jobtype) ? 'NULL' : "'" . $this->db->escape($this->jobtype) . "'") . ",";
684
        $sql .= " " . (!isset($this->label) ? 'NULL' : "'" . $this->db->escape($this->label) . "'") . ",";
685
        $sql .= " " . (!isset($this->command) ? 'NULL' : "'" . $this->db->escape($this->command) . "'") . ",";
686
        $sql .= " " . (!isset($this->classesname) ? 'NULL' : "'" . $this->db->escape($this->classesname) . "'") . ",";
687
        $sql .= " " . (!isset($this->objectname) ? 'NULL' : "'" . $this->db->escape($this->objectname) . "'") . ",";
688
        $sql .= " " . (!isset($this->methodename) ? 'NULL' : "'" . $this->db->escape($this->methodename) . "'") . ",";
689
        $sql .= " " . (!isset($this->params) ? 'NULL' : "'" . $this->db->escape($this->params) . "'") . ",";
690
        $sql .= " " . (!isset($this->md5params) ? 'NULL' : "'" . $this->db->escape($this->md5params) . "'") . ",";
691
        $sql .= " " . (!isset($this->module_name) ? 'NULL' : "'" . $this->db->escape($this->module_name) . "'") . ",";
692
        $sql .= " " . (!isset($this->priority) ? '0' : $this->priority) . ",";
693
        $sql .= " " . (!isset($this->datelastrun) || dol_strlen($this->datelastrun) == 0 ? 'NULL' : "'" . $this->db->idate($this->datelastrun) . "'") . ",";
694
        $sql .= " " . (!isset($this->datenextrun) || dol_strlen($this->datenextrun) == 0 ? 'NULL' : "'" . $this->db->idate($this->datenextrun) . "'") . ",";
695
        $sql .= " " . (!isset($this->dateend) || dol_strlen($this->dateend) == 0 ? 'NULL' : "'" . $this->db->idate($this->dateend) . "'") . ",";
696
        $sql .= " " . (!isset($this->datestart) || dol_strlen($this->datestart) == 0 ? 'NULL' : "'" . $this->db->idate($this->datestart) . "'") . ",";
697
        $sql .= " " . (!isset($this->lastresult) ? 'NULL' : "'" . $this->db->escape($this->lastresult) . "'") . ",";
698
        $sql .= " " . (!isset($this->datelastresult) || dol_strlen($this->datelastresult) == 0 ? 'NULL' : "'" . $this->db->idate($this->datelastresult) . "'") . ",";
699
        $sql .= " " . (!isset($this->lastoutput) ? 'NULL' : "'" . $this->db->escape($this->lastoutput) . "'") . ",";
700
        $sql .= " " . (!isset($this->unitfrequency) ? 'NULL' : "'" . $this->db->escape($this->unitfrequency) . "'") . ",";
701
        $sql .= " " . (!isset($this->frequency) ? '0' : ((int)$this->frequency)) . ",";
702
        $sql .= " " . (!isset($this->status) ? '0' : ((int)$this->status)) . ",";
703
        $sql .= " " . ($user->id ? (int)$user->id : "NULL") . ",";
704
        $sql .= " " . ($user->id ? (int)$user->id : "NULL") . ",";
705
        $sql .= " " . (!isset($this->note_private) ? 'NULL' : "'" . $this->db->escape($this->note_private) . "'") . ",";
706
        $sql .= " " . (!isset($this->nbrun) ? '0' : ((int)$this->nbrun)) . ",";
707
        $sql .= " " . (empty($this->maxrun) ? '0' : ((int)$this->maxrun)) . ",";
708
        $sql .= " " . (!isset($this->libname) ? 'NULL' : "'" . $this->db->escape($this->libname) . "'") . ",";
709
        $sql .= " " . (!isset($this->test) ? 'NULL' : "'" . $this->db->escape($this->test) . "'");
710
        $sql .= ")";
711
712
        $this->db->begin();
713
714
        dol_syslog(get_class($this) . "::create", LOG_DEBUG);
715
        $resql = $this->db->query($sql);
716
        if (!$resql) {
717
            $error++;
718
            $this->errors[] = "Error " . $this->db->lasterror();
719
        }
720
721
        if (!$error) {
722
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "cronjob");
723
        }
724
725
        // Commit or rollback
726
        if ($error) {
727
            $this->db->rollback();
728
            return -1 * $error;
729
        } else {
730
            $this->db->commit();
731
            return $this->id;
732
        }
733
    }
734
735
    /**
736
     * Initialise object with example values
737
     * Id must be 0 if object instance is a specimen
738
     *
739
     * @return int
740
     */
741
    public function initAsSpecimen()
742
    {
743
        $this->id = 0;
744
        $this->ref = '';
745
        $this->entity = 0;
746
        $this->date_modification = dol_now();
747
        $this->datec = '';
748
        $this->label = '';
749
        $this->jobtype = '';
750
        $this->command = '';
751
        $this->classesname = '';
752
        $this->objectname = '';
753
        $this->methodename = '';
754
        $this->params = '';
755
        $this->md5params = '';
756
        $this->module_name = '';
757
        $this->priority = '';
758
        $this->datelastrun = '';
759
        $this->datenextrun = '';
760
        $this->dateend = '';
761
        $this->datestart = '';
762
        $this->datelastresult = '';
763
        $this->lastoutput = '';
764
        $this->lastresult = '';
765
        $this->unitfrequency = '86400';
766
        $this->frequency = 0;
767
        $this->status = 0;
768
        $this->processing = 0;
769
        $this->pid = null;
770
        $this->email_alert = '';
771
        $this->fk_user_author = 0;
772
        $this->fk_user_mod = 0;
773
        $this->note_private = '';
774
        $this->nbrun = 0;
775
        $this->maxrun = 100;
776
        $this->libname = '';
777
778
        return 1;
779
    }
780
781
    /**
782
     * Return a link to the object card (with optionally the picto)
783
     *
784
     * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
785
     * @param string $option On what the link point to ('nolink', ...)
786
     * @param int $notooltip 1=Disable tooltip
787
     * @param string $morecss Add more css on link
788
     * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
789
     * @return  string                              String with URL
790
     */
791
    public function getNomUrl(int $withpicto = 0, string $option = '', int $notooltip = 0, string $morecss = '', int $save_lastsearch_value = -1)
792
    {
793
        global $conf, $langs;
794
795
        if (!empty($conf->dol_no_mouse_hover)) {
796
            $notooltip = 1; // Force disable tooltips
797
        }
798
799
        $result = '';
800
801
        $params = [
802
            'id' => $this->id,
803
            'objecttype' => $this->element,
804
        ];
805
        $classfortooltip = 'classfortooltip';
806
        $dataparams = '';
807
        if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
808
            $classfortooltip = 'classforajaxtooltip';
809
            $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"';
810
            $label = '';
811
        } else {
812
            $label = implode($this->getTooltipContentArray($params));
813
        }
814
815
        $url = constant('BASE_URL') . '/cron/card.php?id=' . $this->id;
816
817
        if ($option != 'nolink') {
818
            // Add param to save lastsearch_values or not
819
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
820
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
821
                $add_save_lastsearch_values = 1;
822
            }
823
            if ($add_save_lastsearch_values) {
824
                $url .= '&save_lastsearch_values=1';
825
            }
826
        }
827
828
        $linkclose = '';
829
        if (empty($notooltip)) {
830
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
831
                $label = $langs->trans("ShowCronJob");
832
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
833
            }
834
            $linkclose .= ($label ? ' title="' . dol_escape_htmltag($label, 1) . '"' : ' title="tocomplete"');
835
            $linkclose .= $dataparams . ' class="' . $classfortooltip . ($morecss ? ' ' . $morecss : '') . '"';
836
        } else {
837
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
838
        }
839
840
        $linkstart = '<a href="' . $url . '"';
841
        $linkstart .= $linkclose . '>';
842
        $linkend = '</a>';
843
844
        $result .= $linkstart;
845
        if ($withpicto) {
846
            $result .= img_object(($notooltip ? '' : $label), ($this->picto ?: 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
847
        }
848
        if ($withpicto != 2) {
849
            $result .= $this->ref;
850
        }
851
        $result .= $linkend;
852
        //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
853
854
        return $result;
855
    }
856
857
    /**
858
     * getTooltipContentArray
859
     *
860
     * @param array $params params to construct tooltip data
861
     * @return  array
862
     * @since v18
863
     */
864
    public function getTooltipContentArray($params)
865
    {
866
        global $langs;
867
868
        $langs->load('cron');
869
        $datas = [];
870
871
        $datas['picto'] = img_picto('', 'object_' . $this->picto) . ' <u>' . $langs->trans("CronTask") . '</u>';
872
        if (isset($this->status)) {
873
            $datas['picto'] .= ' ' . $this->getLibStatut(5);
874
        }
875
        $datas['ref'] = '<br><b>' . $langs->trans('Ref') . ':</b> ' . dol_escape_htmltag($this->ref);
876
        $datas['label'] = '<br><b>' . $langs->trans('Title') . ':</b> ' . $langs->trans($this->label);
877
        if ($this->label != $langs->trans($this->label)) {
878
            $datas['label'] .= ' <span class="opacitymedium">(' . $this->label . ')</span>';
879
        }
880
        if (!empty($this->params)) {
881
            $datas['params'] = '<br><b>' . $langs->trans('Parameters') . ':</b> ' . dol_escape_htmltag($this->params);
882
        }
883
        $datas['space'] = '<br>';
884
885
        if (!empty($this->datestart) && $this->datestart >= dol_now()) {
886
            $datas['crondtstart'] = '<br><b>' . $langs->trans('CronDtStart') . ':</b> ' . dol_print_date($this->datestart, 'dayhour', 'tzuserrel');
887
        }
888
        if (!empty($this->dateend)) {
889
            $datas['crondtend'] = '<br><b>' . $langs->trans('CronDtEnd') . ':</b> ' . dol_print_date($this->dateend, 'dayhour', 'tzuserrel');
890
        }
891
        if (!empty($this->datelastrun)) {
892
            $datas['cronlastlaunch'] = '<br><b>' . $langs->trans('CronDtLastLaunch') . ':</b> ' . dol_print_date($this->datelastrun, 'dayhour', 'tzuserrel');
893
        }
894
        if (!empty($this->datenextrun)) {
895
            $datas['crondtnextlaunch'] = '<br><b>' . $langs->trans('CronDtNextLaunch') . ':</b> ' . dol_print_date($this->datenextrun, 'dayhour', 'tzuserrel');
896
        }
897
898
        return $datas;
899
    }
900
901
    /**
902
     * Return label of status of user (active, inactive)
903
     *
904
     * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
905
     * @return  string                  Label of status
906
     */
907
    public function getLibStatut(int $mode = 0)
908
    {
909
        return $this->LibStatut($this->status, $mode, $this->processing, $this->lastresult);
910
    }
911
912
    /**
913
     * Return label of a giver status
914
     *
915
     * @param int $status Id status
916
     * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
917
     * @param int $processing 0=Not running, 1=Running
918
     * @param string $lastResult Value of last result (''=no error, error otherwise)
919
     * @return  string                      Label of status
920
     */
921
    public function LibStatut(int $status, int $mode = 0, int $processing = 0, string $lastResult = '')
922
    {
923
        // phpcs:enable
924
        $this->labelStatus = array(); // Force reset o array because label depends on other fields
925
        $this->labelStatusShort = array();
926
927
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
928
            global $langs;
929
            $langs->load('users');
930
931
            $moreText = '';
932
            if ($processing) {
933
                $moreText = ' (' . $langs->trans("Running") . ')';
934
            } elseif ($lastResult) {
935
                $moreText .= ' (' . $langs->trans("Error") . ')';
936
            }
937
938
            $this->labelStatus[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv('Disabled') . $moreText;
939
            $this->labelStatus[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv('Scheduled') . $moreText;
940
            $this->labelStatusShort[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv('Disabled');
941
            $this->labelStatusShort[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv('Scheduled');
942
        }
943
944
        $statusType = 'status4';
945
        if ($status == 1 && $processing) {
946
            $statusType = 'status1';
947
        }
948
        if ($status == 0) {
949
            $statusType = 'status5';
950
        }
951
        if ($this->lastresult) {
952
            $statusType = 'status8';
953
        }
954
955
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
956
    }
957
958
959
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
960
961
    /**
962
     * Load object information
963
     *
964
     * @param int $id ID
965
     * @return  int             if KO: <0 || if OK: >0
966
     */
967
    public function info(int $id)
968
    {
969
        $sql = "SELECT";
970
        $sql .= " f.rowid, f.datec, f.tms, f.fk_user_mod, f.fk_user_author";
971
        $sql .= " FROM " . MAIN_DB_PREFIX . "cronjob as f";
972
        $sql .= " WHERE f.rowid = " . ((int)$id);
973
974
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
975
        $resql = $this->db->query($sql);
976
        if ($resql) {
977
            if ($this->db->num_rows($resql)) {
978
                $obj = $this->db->fetch_object($resql);
979
980
                $this->id = $obj->rowid;
981
982
                $this->user_modification_id = $obj->fk_user_mod;
983
                $this->user_creation_id = $obj->fk_user_author;
984
                $this->date_creation = $this->db->jdate($obj->datec);
985
                $this->date_modification = $this->db->jdate($obj->tms);
986
            }
987
            $this->db->free($resql);
988
989
            return 1;
990
        } else {
991
            $this->error = "Error " . $this->db->lasterror();
992
            return -1;
993
        }
994
    }
995
996
997
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
998
999
    /**
1000
     * Run a job.
1001
     * Once job is finished, status and nb of run is updated.
1002
     * This function does not plan the next run. This is done by function ->reprogram_jobs
1003
     *
1004
     * @param string $userlogin User login
1005
     * @return  int                         if KO: <0 || if OK: >0
1006
     */
1007
    public function run_jobs(string $userlogin)
1008
    {
1009
        // phpcs:enable
1010
        global $langs, $conf, $hookmanager;
1011
1012
        $hookmanager->initHooks(array('cron'));
1013
1014
        $now = dol_now();
1015
        $error = 0;
1016
1017
        $langs->load('cron');
1018
1019
        if (empty($userlogin)) {
1020
            $this->error = "User login is mandatory";
1021
            dol_syslog(get_class($this) . "::run_jobs " . $this->error, LOG_ERR);
1022
            return -1;
1023
        }
1024
1025
        // Force the environment of running to the environment declared for job, so jobs launched from command line will run into correct environment
1026
        // When job is ran from GUI, the environment should already be same, except if job has entity 0 (visible into all environments)
1027
        if ($conf->entity != $this->entity && $this->entity > 0) {
1028
            dol_syslog("We try to run a job in entity " . $this->entity . " when we are in entity " . $conf->entity, LOG_WARNING);
1029
        }
1030
        $savcurrententity = $conf->entity;
1031
        $conf->setEntityValues($this->db, $this->entity);
1032
        dol_syslog(get_class($this) . "::run_jobs entity for running job is " . $conf->entity);
1033
1034
        $user = new User($this->db);
1035
        $result = $user->fetch('', $userlogin);
1036
        if ($result < 0) {
1037
            $this->error = "User Error:" . $user->error;
1038
            dol_syslog(get_class($this) . "::run_jobs " . $this->error, LOG_ERR);
1039
            $conf->setEntityValues($this->db, $savcurrententity);
1040
            return -1;
1041
        } else {
1042
            if (empty($user->id)) {
1043
                $this->error = "User login: " . $userlogin . " does not exist";
1044
                dol_syslog(get_class($this) . "::run_jobs " . $this->error, LOG_ERR);
1045
                $conf->setEntityValues($this->db, $savcurrententity);
1046
                return -1;
1047
            }
1048
        }
1049
1050
        dol_syslog(get_class($this) . "::run_jobs jobtype=" . $this->jobtype . " userlogin=" . $userlogin, LOG_DEBUG);
1051
1052
        // Increase limit of time. Works only if we are not in safe mode
1053
        $ExecTimeLimit = 600;
1054
        if (!empty($ExecTimeLimit)) {
1055
            $err = error_reporting();
1056
            error_reporting(0); // Disable all errors
1057
            //error_reporting(E_ALL);
1058
            @set_time_limit($ExecTimeLimit); // Need more than 240 on Windows 7/64
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for set_time_limit(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1058
            /** @scrutinizer ignore-unhandled */ @set_time_limit($ExecTimeLimit); // Need more than 240 on Windows 7/64

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1059
            error_reporting($err);
1060
        }
1061
        $MemoryLimit = 0;
1062
        if (!empty($MemoryLimit)) {
1063
            @ini_set('memory_limit', $MemoryLimit);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ini_set(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1063
            /** @scrutinizer ignore-unhandled */ @ini_set('memory_limit', $MemoryLimit);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1064
        }
1065
1066
        // Update last run date start (to track running jobs)
1067
        $this->datelastrun = $now;
1068
        $this->datelastresult = null;
1069
        $this->lastoutput = '';
1070
        $this->lastresult = '';
1071
        $this->processing = 1; // To know job was started
1072
        $this->pid = function_exists('getmypid') ? getmypid() : null; // Avoid dol_getmypid to get null if the function is not available
1073
        $this->nbrun = $this->nbrun + 1;
1074
        $result = $this->update($user); // This include begin/commit
1075
        if ($result < 0) {
1076
            dol_syslog(get_class($this) . "::run_jobs " . $this->error, LOG_ERR);
1077
            $conf->setEntityValues($this->db, $savcurrententity);
1078
            return -1;
1079
        }
1080
1081
        // Run a method
1082
        if ($this->jobtype == 'method') {
1083
1084
            // Deny to launch a method from a deactivated module
1085
            if (!empty($this->entity) && !empty($this->module_name) && !isModEnabled(strtolower($this->module_name))) {
1086
                $this->error = $langs->transnoentitiesnoconv('CronModuleNotEnabledInThisEntity', $this->methodename, $this->objectname);
1087
                dol_syslog(get_class($this) . "::run_jobs " . $this->error, LOG_ERR);
1088
                $this->lastoutput = $this->error;
1089
                $this->lastresult = '-1';
1090
                $error++;
1091
            }
1092
1093
            /*
1094
            // load classes
1095
            if (!$error) {
1096
                $ret = dol_include_once($this->classesname);
1097
                if ($ret === false || (!class_exists($this->objectname))) {
1098
                    if ($ret === false) {
1099
                        $this->error = $langs->transnoentitiesnoconv('CronCannotLoadClass', $this->classesname, $this->objectname);
1100
                    } else {
1101
                        $this->error = $langs->transnoentitiesnoconv('CronCannotLoadObject', $this->classesname, $this->objectname);
1102
                    }
1103
                    dol_syslog(get_class($this) . "::run_jobs " . $this->error, LOG_ERR);
1104
                    $this->lastoutput = $this->error;
1105
                    $this->lastresult = '-1';
1106
                    $error++;
1107
                }
1108
            }
1109
1110
            // test if method exists
1111
            if (!$error) {
1112
                if (!method_exists($this->objectname, $this->methodename)) {
1113
                    $this->error = $langs->transnoentitiesnoconv('CronMethodDoesNotExists', $this->objectname, $this->methodename);
1114
                    dol_syslog(get_class($this) . "::run_jobs " . $this->error, LOG_ERR);
1115
                    $this->lastoutput = $this->error;
1116
                    $this->lastresult = '-1';
1117
                    $error++;
1118
                }
1119
                if (in_array(strtolower(trim($this->methodename)), array('executecli'))) {
1120
                    $this->error = $langs->transnoentitiesnoconv('CronMethodNotAllowed', $this->methodename, $this->objectname);
1121
                    dol_syslog(get_class($this) . "::run_jobs " . $this->error, LOG_ERR);
1122
                    $this->lastoutput = $this->error;
1123
                    $this->lastresult = '-1';
1124
                    $error++;
1125
                }
1126
            }
1127
            */
1128
1129
            // Load langs
1130
            if (!$error) {
1131
                $result = $langs->load($this->module_name);
1132
                $result = $langs->load($this->module_name . '@' . $this->module_name, 0, 0, '', 0, 1);
1133
1134
                if ($result < 0) {  // If technical error
1135
                    dol_syslog(get_class($this) . "::run_jobs Cannot load module lang file - " . $langs->error, LOG_ERR);
1136
                    $this->error = $langs->error;
1137
                    $this->lastoutput = $this->error;
1138
                    $this->lastresult = '-1';
1139
                    $error++;
1140
                }
1141
            }
1142
1143
            if (!$error) {
1144
                dol_syslog(get_class($this) . "::run_jobs START " . $this->objectname . "->" . $this->methodename . "(" . $this->params . "); (Note: Log for cron jobs may be into a different log file)", LOG_DEBUG);
1145
1146
                // Create Object for the called module
1147
                $nameofclass = (string)$this->objectname;
1148
                $object = Misc::getCodeLibClass($this->objectname, $this->db);
1149
                // $object = new $nameofclass($this->db);
1150
                if ($this->entity > 0) {
1151
                    $object->entity = $this->entity; // We work on a dedicated entity
1152
                }
1153
1154
                $params_arr = array();
1155
                if (!empty($this->params) || $this->params === '0') {
1156
                    $params_arr = array_map('trim', explode(",", $this->params));
1157
                }
1158
1159
                if (!is_array($params_arr)) {
1160
                    $result = call_user_func(array($object, $this->methodename), $this->params);
1161
                } else {
1162
                    $result = call_user_func_array(array($object, $this->methodename), $params_arr);
1163
                }
1164
                $errmsg = '';
1165
                if ($result === false || (!is_bool($result) && $result != 0)) {
1166
                    $langs->load("errors");
1167
1168
                    if (!is_array($object->errors) || !in_array($object->error, $object->errors)) {
1169
                        $errmsg .= $object->error;
1170
                    }
1171
                    if (is_array($object->errors) && count($object->errors)) {
1172
                        $errmsg .= (($errmsg ? ', ' : '') . implode(', ', $object->errors));
1173
                    }
1174
                    if (empty($errmsg)) {
1175
                        $errmsg = $langs->trans('ErrorUnknown');
1176
                    }
1177
1178
                    dol_syslog(get_class($this) . "::run_jobs END result=" . $result . " error=" . $errmsg, LOG_ERR);
1179
1180
                    $this->error = $errmsg;
1181
                    $this->lastoutput = dol_substr((empty($object->output) ? "" : $object->output . "\n") . $errmsg, 0, $this::MAXIMUM_LENGTH_FOR_LASTOUTPUT_FIELD, 'UTF-8', 1);
1182
                    $this->lastresult = is_numeric($result) ? var_export($result, true) : '-1';
1183
                    $error++;
1184
                } else {
1185
                    dol_syslog(get_class($this) . "::run_jobs END");
1186
                    $this->lastoutput = dol_substr((empty($object->output) ? "" : $object->output . "\n"), 0, $this::MAXIMUM_LENGTH_FOR_LASTOUTPUT_FIELD, 'UTF-8', 1);
1187
                    $this->lastresult = var_export($result, true);
1188
                }
1189
            }
1190
        }
1191
1192
        if ($this->jobtype == 'function') {
1193
            //load lib
1194
            $libpath = '/' . strtolower($this->module_name) . '/lib/' . $this->libname;
1195
            $ret = dol_include_once($libpath);
1196
            if ($ret === false) {
1197
                $this->error = $langs->trans('CronCannotLoadLib') . ': ' . $libpath;
1198
                dol_syslog(get_class($this) . "::run_jobs " . $this->error, LOG_ERR);
1199
                $conf->setEntityValues($this->db, $savcurrententity);
1200
                return -1;
1201
            }
1202
1203
            // Load langs
1204
            $result = $langs->load($this->module_name);
1205
            $result = $langs->load($this->module_name . '@' . $this->module_name); // If this->module_name was an existing language file, this will make nothing
1206
            if ($result < 0) {  // If technical error
1207
                dol_syslog(get_class($this) . "::run_jobs Cannot load module langs" . $langs->error, LOG_ERR);
1208
                $conf->setEntityValues($this->db, $savcurrententity);
1209
                return -1;
1210
            }
1211
1212
            dol_syslog(get_class($this) . "::run_jobs " . $this->libname . "::" . $this->methodename . "(" . $this->params . ");", LOG_DEBUG);
1213
            $params_arr = explode(", ", $this->params);
1214
            if (!is_array($params_arr)) {
1215
                $result = call_user_func($this->methodename, $this->params);
1216
            } else {
1217
                $result = call_user_func_array($this->methodename, $params_arr);
1218
            }
1219
1220
            if ($result === false || (!is_bool($result) && $result != 0)) {
1221
                $langs->load("errors");
1222
                dol_syslog(get_class($this) . "::run_jobs result=" . $result, LOG_ERR);
1223
                $this->error = $langs->trans('ErrorUnknown');
1224
                $this->lastoutput = $this->error;
1225
                $this->lastresult = is_numeric($result) ? var_export($result, true) : '-1';
1226
                $error++;
1227
            } else {
1228
                $this->lastoutput = var_export($result, true);
1229
                $this->lastresult = var_export($result, true); // Return code
1230
            }
1231
        }
1232
1233
        // Run a command line
1234
        if ($this->jobtype == 'command') {
1235
            global $dolibarr_cron_allow_cli;
1236
1237
            if (empty($dolibarr_cron_allow_cli)) {
1238
                $langs->load("errors");
1239
                $this->error = $langs->trans("FailedToExecutCommandJob");
1240
                $this->lastoutput = '';
1241
                $this->lastresult = $langs->trans("ErrorParameterMustBeEnabledToAllwoThisFeature", 'dolibarr_cron_allow_cli');
1242
            } else {
1243
                $outputdir = $conf->cron->dir_temp;
1244
                if (empty($outputdir)) {
1245
                    $outputdir = $conf->cronjob->dir_temp;
1246
                }
1247
1248
                if (!empty($outputdir)) {
1249
                    dol_mkdir($outputdir);
1250
                    $outputfile = $outputdir . '/cronjob.' . $userlogin . '.out'; // File used with popen method
1251
1252
                    // Execute a CLI
1253
                    include_once DOL_DOCUMENT_ROOT . '/core/class/utils.class.php';
1254
                    $utils = new Utils($this->db);
1255
                    $arrayresult = $utils->executeCLI($this->command, $outputfile);
1256
1257
                    $this->error = $arrayresult['error'];
1258
                    $this->lastoutput = $arrayresult['output'];
1259
                    $this->lastresult = $arrayresult['result'];
1260
                }
1261
            }
1262
        }
1263
1264
        dol_syslog(get_class($this) . "::run_jobs now we update job to track it is finished (with success or error)");
1265
1266
        $this->datelastresult = dol_now();
1267
        $this->processing = 0;
1268
        $this->pid = null;
1269
        $result = $this->update($user); // This include begin/commit
1270
        if ($result < 0) {
1271
            dol_syslog(get_class($this) . "::run_jobs " . $this->error, LOG_ERR);
1272
            $conf->setEntityValues($this->db, $savcurrententity);
1273
            return -1;
1274
        }
1275
1276
        $conf->setEntityValues($this->db, $savcurrententity);
1277
1278
        if ($error && !empty($this->email_alert)) {
1279
            $subject = $langs->trans("ErrorInBatch", $this->label);
1280
            $msg = $langs->trans("ErrorInBatch", $this->label);
1281
            $from = getDolGlobalString('MAIN_MAIL_EMAIL_FROM');
1282
            $cmailfile = new CMailFile($subject, $this->email_alert, $from, $msg);
1283
            $result = $cmailfile->sendfile();   // Do not test result
1284
        }
1285
1286
        return $error ? -1 : 1;
1287
    }
1288
1289
    /**
1290
     * Update object into database
1291
     *
1292
     * @param User|null $user User that modifies
1293
     * @param int $notrigger 0=launch triggers after, 1=disable triggers
1294
     * @return  int                     if KO: <0 || if OK: >0
1295
     */
1296
    public function update(User $user = null, int $notrigger = 0)
1297
    {
1298
        global $conf, $langs;
1299
1300
        $langs->load('cron');
1301
1302
        $error = 0;
1303
1304
        // Clean parameters
1305
        if (isset($this->label)) {
1306
            $this->label = trim($this->label);
1307
        }
1308
        if (isset($this->jobtype)) {
1309
            $this->jobtype = trim($this->jobtype);
1310
        }
1311
        if (isset($this->command)) {
1312
            $this->command = trim($this->command);
1313
        }
1314
        if (isset($this->classesname)) {
1315
            $this->classesname = trim($this->classesname);
1316
        }
1317
        if (isset($this->objectname)) {
1318
            $this->objectname = trim($this->objectname);
1319
        }
1320
        if (isset($this->methodename)) {
1321
            $this->methodename = trim($this->methodename);
1322
        }
1323
        if (isset($this->params)) {
1324
            $this->params = trim($this->params);
1325
        }
1326
        if (isset($this->md5params)) {
1327
            $this->md5params = trim($this->md5params);
1328
        }
1329
        if (isset($this->module_name)) {
1330
            $this->module_name = trim($this->module_name);
1331
        }
1332
        if (isset($this->priority)) {
1333
            $this->priority = trim($this->priority);
1334
        }
1335
        if (isset($this->lastoutput)) {
1336
            $this->lastoutput = trim($this->lastoutput);
1337
        }
1338
        if (isset($this->lastresult)) {
1339
            $this->lastresult = trim($this->lastresult);
1340
        }
1341
        if (isset($this->unitfrequency)) {
1342
            $this->unitfrequency = trim($this->unitfrequency);
1343
        }
1344
        if (isset($this->frequency)) {
1345
            $this->frequency = (int)$this->frequency;
1346
        }
1347
        if (isset($this->status)) {
1348
            $this->status = (int)$this->status;
1349
        }
1350
        if (isset($this->note_private)) {
1351
            $this->note_private = trim($this->note_private);
1352
        }
1353
        if (isset($this->nbrun)) {
1354
            $this->nbrun = (is_numeric($this->nbrun)) ? (int)trim((string)$this->nbrun) : 0;
1355
        }
1356
        if (isset($this->libname)) {
1357
            $this->libname = trim($this->libname);
1358
        }
1359
        if (isset($this->test)) {
1360
            $this->test = trim($this->test);
1361
        }
1362
1363
        if (empty($this->maxrun)) {
1364
            $this->maxrun = 0;
1365
        }
1366
        if (empty($this->processing)) {
1367
            $this->processing = 0;
1368
        }
1369
        if (empty($this->pid)) {
1370
            $this->pid = null;
1371
        }
1372
        if (empty($this->email_alert)) {
1373
            $this->email_alert = '';
1374
        }
1375
        if (empty($this->datenextrun)) {
1376
            $this->datenextrun = dol_now();
1377
        }
1378
1379
        // Check parameters
1380
        // Put here code to add a control on parameters values
1381
        if (dol_strlen($this->datenextrun) == 0 && $this->status == self::STATUS_ENABLED) {
1382
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronDtNextLaunch'));
1383
            $error++;
1384
        }
1385
        if ((dol_strlen($this->datestart) != 0) && (dol_strlen($this->dateend) != 0) && ($this->dateend < $this->datestart)) {
1386
            $this->errors[] = $langs->trans('CronErrEndDateStartDt');
1387
            $error++;
1388
        }
1389
        if (empty($this->label)) {
1390
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronLabel'));
1391
            $error++;
1392
        }
1393
        if (empty($this->unitfrequency)) {
1394
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronFrequency'));
1395
            $error++;
1396
        }
1397
        if (($this->jobtype == 'command') && (empty($this->command))) {
1398
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronCommand'));
1399
            $error++;
1400
        }
1401
        if (($this->jobtype == 'method') && (empty($this->classesname))) {
1402
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronClass'));
1403
            $error++;
1404
        }
1405
        if (($this->jobtype == 'method' || $this->jobtype == 'function') && (empty($this->methodename))) {
1406
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronMethod'));
1407
            $error++;
1408
        }
1409
        if (($this->jobtype == 'method') && (empty($this->objectname))) {
1410
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronObject'));
1411
            $error++;
1412
        }
1413
1414
        if (($this->jobtype == 'function') && (empty($this->libname))) {
1415
            $this->errors[] = $langs->trans('CronFieldMandatory', $langs->transnoentitiesnoconv('CronLib'));
1416
            $error++;
1417
        }
1418
1419
1420
        // Update request
1421
        $sql = "UPDATE " . MAIN_DB_PREFIX . "cronjob SET";
1422
        $sql .= " entity=" . (isset($this->entity) ? ((int)$this->entity) : $conf->entity) . ",";
1423
        $sql .= " label=" . (isset($this->label) ? "'" . $this->db->escape($this->label) . "'" : "null") . ",";
1424
        $sql .= " jobtype=" . (isset($this->jobtype) ? "'" . $this->db->escape($this->jobtype) . "'" : "null") . ",";
1425
        $sql .= " command=" . (isset($this->command) ? "'" . $this->db->escape($this->command) . "'" : "null") . ",";
1426
        $sql .= " classesname=" . (isset($this->classesname) ? "'" . $this->db->escape($this->classesname) . "'" : "null") . ",";
1427
        $sql .= " objectname=" . (isset($this->objectname) ? "'" . $this->db->escape($this->objectname) . "'" : "null") . ",";
1428
        $sql .= " methodename=" . (isset($this->methodename) ? "'" . $this->db->escape($this->methodename) . "'" : "null") . ",";
1429
        $sql .= " params=" . (isset($this->params) ? "'" . $this->db->escape($this->params) . "'" : "null") . ",";
1430
        $sql .= " md5params=" . (isset($this->md5params) ? "'" . $this->db->escape($this->md5params) . "'" : "null") . ",";
1431
        $sql .= " module_name=" . (isset($this->module_name) ? "'" . $this->db->escape($this->module_name) . "'" : "null") . ",";
1432
        $sql .= " priority=" . (isset($this->priority) ? ((int)$this->priority) : "null") . ",";
1433
        $sql .= " datelastrun=" . (dol_strlen($this->datelastrun) != 0 ? "'" . $this->db->idate($this->datelastrun) . "'" : 'null') . ",";
1434
        $sql .= " datenextrun=" . (dol_strlen($this->datenextrun) != 0 ? "'" . $this->db->idate($this->datenextrun) . "'" : 'null') . ",";
1435
        $sql .= " dateend=" . (dol_strlen($this->dateend) != 0 ? "'" . $this->db->idate($this->dateend) . "'" : 'null') . ",";
1436
        $sql .= " datestart=" . (dol_strlen($this->datestart) != 0 ? "'" . $this->db->idate($this->datestart) . "'" : 'null') . ",";
1437
        $sql .= " datelastresult=" . (dol_strlen($this->datelastresult) != 0 ? "'" . $this->db->idate($this->datelastresult) . "'" : 'null') . ",";
1438
        $sql .= " lastresult=" . (isset($this->lastresult) ? "'" . $this->db->escape($this->lastresult) . "'" : "null") . ",";
1439
        $sql .= " lastoutput=" . (isset($this->lastoutput) ? "'" . $this->db->escape($this->lastoutput) . "'" : "null") . ",";
1440
        $sql .= " unitfrequency=" . (isset($this->unitfrequency) ? "'" . $this->db->escape($this->unitfrequency) . "'" : "null") . ",";
1441
        $sql .= " frequency=" . (isset($this->frequency) ? ((int)$this->frequency) : "null") . ",";
1442
        $sql .= " status=" . (isset($this->status) ? ((int)$this->status) : "null") . ",";
1443
        $sql .= " processing=" . ((isset($this->processing) && $this->processing > 0) ? $this->processing : "0") . ",";
1444
        $sql .= " pid=" . (isset($this->pid) ? ((int)$this->pid) : "null") . ",";
1445
        $sql .= " email_alert = " . (isset($this->email_alert) ? "'" . $this->db->escape($this->email_alert) . "'" : "null") . ",";
1446
        $sql .= " fk_user_mod = " . ((int)$user->id) . ",";
1447
        $sql .= " note=" . (isset($this->note_private) ? "'" . $this->db->escape($this->note_private) . "'" : "null") . ",";
1448
        $sql .= " nbrun=" . ((isset($this->nbrun) && $this->nbrun > 0) ? $this->nbrun : "null") . ",";
1449
        $sql .= " maxrun=" . ((isset($this->maxrun) && $this->maxrun > 0) ? $this->maxrun : "0") . ",";
1450
        $sql .= " libname=" . (isset($this->libname) ? "'" . $this->db->escape($this->libname) . "'" : "null") . ",";
1451
        $sql .= " test=" . (isset($this->test) ? "'" . $this->db->escape($this->test) . "'" : "null");
1452
        $sql .= " WHERE rowid=" . ((int)$this->id);
1453
1454
        $this->db->begin();
1455
1456
        dol_syslog(get_class($this) . "::update", LOG_DEBUG);
1457
        $resql = $this->db->query($sql);
1458
        if (!$resql) {
1459
            $error++;
1460
            $this->errors[] = "Error " . $this->db->lasterror();
1461
        }
1462
1463
        // Commit or rollback
1464
        if ($error) {
1465
            foreach ($this->errors as $errmsg) {
1466
                dol_syslog(get_class($this) . "::update " . $errmsg, LOG_ERR);
1467
                $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
1468
            }
1469
            $this->db->rollback();
1470
            return -1 * $error;
1471
        } else {
1472
            $this->db->commit();
1473
            return 1;
1474
        }
1475
    }
1476
1477
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1478
1479
    /**
1480
     * Reprogram a job
1481
     *
1482
     * @param string $userlogin User login
1483
     * @param integer $now Date returned by dol_now()
1484
     * @return  int                         if KO: <0 || if OK: >0
1485
     */
1486
    public function reprogram_jobs(string $userlogin, int $now)
1487
    {
1488
        // phpcs:enable
1489
        dol_syslog(get_class($this) . "::reprogram_jobs userlogin:$userlogin", LOG_DEBUG);
1490
1491
        $user = new User($this->db);
1492
        $result = $user->fetch('', $userlogin);
1493
        if ($result < 0) {
1494
            $this->error = "User Error : " . $user->error;
1495
            dol_syslog(get_class($this) . "::reprogram_jobs " . $this->error, LOG_ERR);
1496
            return -1;
1497
        } else {
1498
            if (empty($user->id)) {
1499
                $this->error = " User user login:" . $userlogin . " do not exists";
1500
                dol_syslog(get_class($this) . "::reprogram_jobs " . $this->error, LOG_ERR);
1501
                return -1;
1502
            }
1503
        }
1504
1505
        dol_syslog(get_class($this) . "::reprogram_jobs datenextrun=" . $this->datenextrun . " " . dol_print_date($this->datenextrun, 'dayhourrfc') . " frequency=" . $this->frequency . " unitfrequency=" . $this->unitfrequency, LOG_DEBUG);
1506
1507
        if (empty($this->datenextrun)) {
1508
            if (empty($this->datestart)) {
1509
                if (!is_numeric($this->frequency) || (int)$this->unitfrequency == 2678400) {
1510
                    $this->datenextrun = dol_time_plus_duree($now, $this->frequency, 'm');
1511
                } else {
1512
                    $this->datenextrun = $now + ($this->frequency * (int)$this->unitfrequency);
1513
                }
1514
            } else {
1515
                if (!is_numeric($this->frequency) || (int)$this->unitfrequency == 2678400) {
1516
                    $this->datenextrun = dol_time_plus_duree($this->datestart, $this->frequency, 'm');
1517
                } else {
1518
                    $this->datenextrun = $this->datestart + ($this->frequency * (int)$this->unitfrequency);
1519
                }
1520
            }
1521
        }
1522
1523
        if ($this->datenextrun < $now && $this->frequency > 0 && !empty($this->unitfrequency)) {
1524
            // Loop until date is after future
1525
            while ($this->datenextrun < $now) {
1526
                if (!is_numeric($this->unitfrequency) || (int)$this->unitfrequency == 2678400 || (int)$this->unitfrequency <= 0) {
1527
                    $this->datenextrun = dol_time_plus_duree($this->datenextrun, $this->frequency, 'm');
1528
                } else {
1529
                    $this->datenextrun += ($this->frequency * (int)$this->unitfrequency);
1530
                }
1531
            }
1532
        } else {
1533
            dol_syslog(get_class($this) . "::reprogram_jobs datenextrun is already in future, we do not change it");
1534
        }
1535
1536
1537
        // Archive job
1538
        if ($this->autodelete == 2) {
1539
            if (
1540
                ($this->maxrun > 0 && ($this->nbrun >= $this->maxrun))
1541
                || ($this->dateend && ($this->datenextrun > $this->dateend))
1542
            ) {
1543
                $this->status = self::STATUS_ARCHIVED;
1544
                dol_syslog(get_class($this) . "::reprogram_jobs Job will be set to archived", LOG_ERR);
1545
            }
1546
        }
1547
1548
        $result = $this->update($user);
1549
        if ($result < 0) {
1550
            dol_syslog(get_class($this) . "::reprogram_jobs " . $this->error, LOG_ERR);
1551
            return -1;
1552
        }
1553
1554
        return 1;
1555
    }
1556
}
1557