Passed
Push — main ( 9a81fe...875825 )
by Rafael
41:55
created

Availabilities::create()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* Copyright (C) 2017       Laurent Destailleur     <[email protected]>
4
 * Copyright (C) 2022       Alice Adminson          <[email protected]>
5
 * Copyright (C) 2024       Frédéric France         <[email protected]>
6
 * Copyright (C) 2024		MDW						<[email protected]>
7
 * Copyright (C) 2024       Rafael San José         <[email protected]>
8
 *
9
 * This program is 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 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
/**
24
 * \file        class/availabilities.class.php
25
 * \ingroup     bookcal
26
 * \brief       This file is a CRUD class file for Availabilities (Create/Read/Update/Delete)
27
 */
28
29
namespace DoliModules\BookCal\Model;
30
31
use DoliCore\Base\GenericDocument;
32
use DoliDB;
33
use Translate;
34
use User;
35
36
/**
37
 * Class for Availabilities
38
 */
39
class Availabilities extends GenericDocument
40
{
41
    /**
42
     * @var string ID of module.
43
     */
44
    public $module = 'bookcal';
45
46
    /**
47
     * @var string ID to identify managed object.
48
     */
49
    public $element = 'availabilities';
50
51
    /**
52
     * @var string Name of table without prefix where object is stored. This is also the key used for extrafields
53
     *      management.
54
     */
55
    public $table_element = 'bookcal_availabilities';
56
57
    /**
58
     * @var int  Does this object support multicompany module ?
59
     * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table
60
     */
61
    public $ismultientitymanaged = 0;
62
63
    /**
64
     * @var int  Does object support extrafields ? 0=No, 1=Yes
65
     */
66
    public $isextrafieldmanaged = 1;
67
68
    /**
69
     * @var string String with name of icon for availabilities. Must be a 'fa-xxx' fontawesome code (or
70
     *      'fa-xxx_fa_color_size') or 'availabilities@bookcal' if picto is file 'img/object_availabilities.png'.
71
     */
72
    public $picto = 'fa-calendar-check';
73
74
75
    const STATUS_DRAFT = 0;
76
    const STATUS_VALIDATED = 1;
77
    const STATUS_CANCELED = 9;
78
79
80
    /**
81
     *  'type' field format:
82
     *      'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',
83
     *      'select' (list of values are in 'options'),
84
     *      'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]',
85
     *      'chkbxlst:...',
86
     *      'varchar(x)',
87
     *      'text', 'text:none', 'html',
88
     *      'double(24,8)', 'real', 'price',
89
     *      'date', 'datetime', 'timestamp', 'duration',
90
     *      'boolean', 'checkbox', 'radio', 'array',
91
     *      'mail', 'phone', 'url', 'password', 'ip'
92
     *      Note: Filter must be a Dolibarr Universal Filter syntax string. Example: "(t.ref:like:'SO-%') or
93
     *      (t.date_creation:<:'20160101') or (t.status:!=:0) or (t.nature:is:NULL)"
94
     *  'label' the translation key.
95
     *  'picto' is code of a picto to show before value in forms
96
     *  'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalInt('MY_SETUP_PARAM') or
97
     *  'isModEnabled("multicurrency")' ...)
98
     *  'position' is the sort order of field.
99
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
100
     *  'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view
101
     *  forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and
102
     *  update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative
103
     *  value means field is not shown by default on list but can be selected for viewing)
104
     *  'noteditable' says if field is not editable (1 or 0)
105
     *  'alwayseditable' says if field can be modified also when status is not draft ('1' or '0')
106
     *  'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is
107
     *  editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be
108
     *  set to '(PROVid)' where id is rowid when a new record is created.
109
     *  'index' if we want an index in database.
110
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
111
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
112
     *  'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer
113
     *  or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for
114
     *  percentage)
115
     *  'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update.
116
     *  'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300
117
     *  maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200'
118
     *  'help' and 'helplist' is a 'TranslationString' to use to show a tooltip on field. You can also use
119
     *  'TranslationString:keyfortooltiponlick' for a tooltip on click.
120
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
121
     *  'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set
122
     *  into the definition of $fields into class, but is set dynamically by some part of code.
123
     *  'arrayofkeyval' to set a list of values if type is a list of predefined values. For example:
124
     *  array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar'
125
     *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set
126
     *  to 1.
127
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
128
     *  'validate' is 1 if need to validate with $this->validateField()
129
     *  'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto
130
     *  after value)
131
     *
132
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the
133
     *  constructor.
134
     */
135
136
    // BEGIN MODULEBUILDER PROPERTIES
137
    /**
138
     * @var array<string,array{type:string,label:string,enabled:int<0,2>|string,position:int,notnull:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array<int,string>,comment?:string}>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string,array{type:...ring>,comment?:string}> at position 16 could not be parsed: Expected '}' at position 16, but found 'int'.
Loading history...
139
     *       Array with all fields and their property. Do not use it as a static var. It may be modified by
140
     *       constructor.
141
     */
142
    public $fields = [
143
        'rowid' => ['type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 2, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"],
144
        'label' => ['type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'position' => 20, 'notnull' => 0, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'csslist' => 'tdoverflowmax150', 'cssview' => 'wordbreak', 'help' => "BookcalLabelAvailabilityHelp", 'showoncombobox' => 2, 'validate' => 1,],
145
        'fk_bookcal_calendar' => ['type' => 'integer:Calendar:bookcal/class/calendar.class.php:1', 'label' => 'Calendar', 'enabled' => 1, 'position' => 25, 'notnull' => 1, 'visible' => 1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax100'],
146
        'description' => ['type' => 'text', 'label' => 'Description', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => 3, 'validate' => 1,],
147
        'note_public' => ['type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0, 'cssview' => 'wordbreak', 'validate' => 1,],
148
        'note_private' => ['type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0, 'cssview' => 'wordbreak', 'validate' => 1,],
149
        'date_creation' => ['type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2,],
150
        'tms' => ['type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2,],
151
        'fk_user_creat' => ['type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'picto' => 'user', 'enabled' => 1, 'position' => 510, 'notnull' => 1, 'visible' => -2, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150'],
152
        'fk_user_modif' => ['type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'picto' => 'user', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150'],
153
        'last_main_doc' => ['type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0,],
154
        'import_key' => ['type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,],
155
        'model_pdf' => ['type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,],
156
        'start' => ['type' => 'date', 'label' => 'Start Date', 'enabled' => 1, 'position' => 40, 'notnull' => 1, 'visible' => 1, 'searchall' => 1,],
157
        'end' => ['type' => 'date', 'label' => 'End Date', 'enabled' => 1, 'position' => 45, 'notnull' => 1, 'visible' => 1, 'searchall' => 1,],
158
        'duration' => ['type' => 'integer', 'label' => 'DurationOfRange', 'enabled' => 1, 'position' => 47, 'notnull' => 1, 'visible' => 1, 'default' => '30', 'css' => 'width50 right'],
159
        'startHour' => ['type' => 'integer', 'label' => 'Start Hour', 'enabled' => 1, 'position' => 46, 'notnull' => 1, 'visible' => 1,],
160
        'endHour' => ['type' => 'integer', 'label' => 'End Hour', 'enabled' => 1, 'position' => 46.5, 'notnull' => 1, 'visible' => 1,],
161
        'status' => ['type' => 'integer', 'label' => 'Status', 'enabled' => 1, 'position' => 2000, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'arrayofkeyval' => ['0' => 'Draft', '1' => 'Validated', '9' => 'Closed'], 'default' => '1', 'validate' => 1],
162
    ];
163
    public $rowid;
164
    public $label;
165
    public $description;
166
    public $note_public;
167
    public $note_private;
168
    public $date_creation;
169
    public $fk_user_creat;
170
    public $fk_user_modif;
171
    public $last_main_doc;
172
    public $import_key;
173
    public $model_pdf;
174
    public $status;
175
    public $start;
176
    public $end;
177
    public $duration;
178
    public $startHour;
179
    public $endHour;
180
    public $fk_bookcal_calendar;
181
    // END MODULEBUILDER PROPERTIES
182
183
184
    // If this object has a subtable with lines
185
186
    // /**
187
    //  * @var string    Name of subtable line
188
    //  */
189
    // public $table_element_line = 'bookcal_availabilitiesline';
190
191
    // /**
192
    //  * @var string    Field with ID of parent key if this object has a parent
193
    //  */
194
    // public $fk_element = 'fk_availabilities';
195
196
    // /**
197
    //  * @var string    Name of subtable class that manage subtable lines
198
    //  */
199
    // public $class_element_line = 'Availabilitiesline';
200
201
    // /**
202
    //  * @var array    List of child tables. To test if we can delete object.
203
    //  */
204
    // protected $childtables = array();
205
206
    // /**
207
    //  * @var array    List of child tables. To know object to delete on cascade.
208
    //  *               If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will
209
    //  *               call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
210
    //  */
211
    // protected $childtablesoncascade = array('bookcal_availabilitiesdet');
212
213
    // /**
214
    //  * @var AvailabilitiesLine[]     Array of subtable lines
215
    //  */
216
    // public $lines = array();
217
218
219
    /**
220
     * Constructor
221
     *
222
     * @param DoliDB $db Database handler
223
     */
224
    public function __construct(DoliDB $db)
225
    {
226
        global $conf, $langs;
227
228
        $this->db = $db;
229
230
        if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
231
            $this->fields['rowid']['visible'] = 0;
232
        }
233
        if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) {
234
            $this->fields['entity']['enabled'] = 0;
235
        }
236
237
        // Example to show how to set values of fields definition dynamically
238
        /*if ($user->hasRight('bookcal', 'availabilities', 'read')) {
239
            $this->fields['myfield']['visible'] = 1;
240
            $this->fields['myfield']['noteditable'] = 0;
241
        }*/
242
243
        // Unset fields that are disabled
244
        foreach ($this->fields as $key => $val) {
245
            if (isset($val['enabled']) && empty($val['enabled'])) {
246
                unset($this->fields[$key]);
247
            }
248
        }
249
250
        // Translate some data of arrayofkeyval
251
        if (is_object($langs)) {
252
            foreach ($this->fields as $key => $val) {
253
                if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
254
                    foreach ($val['arrayofkeyval'] as $key2 => $val2) {
255
                        $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
256
                    }
257
                }
258
            }
259
        }
260
    }
261
262
    /**
263
     * Create object into database
264
     *
265
     * @param User $user      User that creates
266
     * @param int  $notrigger 0=launch triggers after, 1=disable triggers
267
     *
268
     * @return int             Return integer <0 if KO, Id of created object if OK
269
     */
270
    public function create(User $user, $notrigger = 0)
271
    {
272
        $resultcreate = $this->createCommon($user, $notrigger);
273
274
        //$resultvalidate = $this->validate($user, $notrigger);
275
276
        return $resultcreate;
277
    }
278
279
    /**
280
     * Clone an object into another one
281
     *
282
     * @param User $user   User that creates
283
     * @param int  $fromid Id of object to clone
284
     *
285
     * @return  mixed               New object created, <0 if KO
286
     */
287
    public function createFromClone(User $user, $fromid)
288
    {
289
        global $langs, $extrafields;
290
        $error = 0;
291
292
        dol_syslog(__METHOD__, LOG_DEBUG);
293
294
        $object = new self($this->db);
295
296
        $this->db->begin();
297
298
        // Load source object
299
        $result = $object->fetchCommon($fromid);
300
        if ($result > 0 && !empty($object->table_element_line)) {
301
            $object->fetchLines();
302
        }
303
304
        // get lines so they will be clone
305
        //foreach($this->lines as $line)
306
        //  $line->fetch_optionals();
307
308
        // Reset some properties
309
        unset($object->id);
310
        unset($object->fk_user_creat);
311
        unset($object->import_key);
312
313
        // Clear fields
314
        if (property_exists($object, 'ref')) {
315
            $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_" . $object->ref : $this->fields['ref']['default'];
316
        }
317
        if (property_exists($object, 'label')) {
318
            $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf") . " " . $object->label : $this->fields['label']['default'];
319
        }
320
        if (property_exists($object, 'status')) {
321
            $object->status = self::STATUS_DRAFT;
322
        }
323
        if (property_exists($object, 'date_creation')) {
324
            $object->date_creation = dol_now();
325
        }
326
        if (property_exists($object, 'date_modification')) {
327
            $object->date_modification = null;
328
        }
329
        // ...
330
        // Clear extrafields that are unique
331
        if (is_array($object->array_options) && count($object->array_options) > 0) {
332
            $extrafields->fetch_name_optionals_label($this->table_element);
333
            foreach ($object->array_options as $key => $option) {
334
                $shortkey = preg_replace('/options_/', '', $key);
335
                if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
336
                    //var_dump($key);
337
                    //var_dump($clonedObj->array_options[$key]); exit;
338
                    unset($object->array_options[$key]);
339
                }
340
            }
341
        }
342
343
        // Create clone
344
        $object->context['createfromclone'] = 'createfromclone';
345
        $result = $object->createCommon($user);
346
        if ($result < 0) {
347
            $error++;
348
            $this->error = $object->error;
349
            $this->errors = $object->errors;
350
        }
351
352
        if (!$error) {
353
            // copy internal contacts
354
            if ($this->copy_linked_contact($object, 'internal') < 0) {
355
                $error++;
356
            }
357
        }
358
359
        if (!$error) {
360
            // copy external contacts if same company
361
            if (!empty($object->socid) && property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
0 ignored issues
show
Bug Best Practice introduced by
The property socid does not exist on DoliModules\BookCal\Model\Availabilities. Did you maybe forget to declare it?
Loading history...
362
                if ($this->copy_linked_contact($object, 'external') < 0) {
363
                    $error++;
364
                }
365
            }
366
        }
367
368
        unset($object->context['createfromclone']);
369
370
        // End
371
        if (!$error) {
372
            $this->db->commit();
373
            return $object;
374
        } else {
375
            $this->db->rollback();
376
            return -1;
377
        }
378
    }
379
380
    /**
381
     * Load object in memory from the database
382
     *
383
     * @param int    $id  Id object
384
     * @param string $ref Ref
385
     *
386
     * @return int         Return integer <0 if KO, 0 if not found, >0 if OK
387
     */
388
    public function fetch($id, $ref = null)
389
    {
390
        $result = $this->fetchCommon($id, $ref);
391
        if ($result > 0 && !empty($this->table_element_line)) {
392
            $this->fetchLines();
393
        }
394
        return $result;
395
    }
396
397
    /**
398
     * Load object lines in memory from the database
399
     *
400
     * @return int         Return integer <0 if KO, 0 if not found, >0 if OK
401
     */
402
    public function fetchLines()
403
    {
404
        $this->lines = [];
405
406
        $result = $this->fetchLinesCommon();
407
        return $result;
408
    }
409
410
411
    /**
412
     * Load list of objects in memory from the database.
413
     *
414
     * @param string $sortorder             Sort Order
415
     * @param string $sortfield             Sort field
416
     * @param int    $limit                 limit
417
     * @param int    $offset                Offset
418
     * @param string $filter                Filter as an Universal Search string.
419
     *                                      Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND
420
     *                                      (client:!=:8) AND (nom:like:'a%')'
421
     * @param string $filtermode            No more used
422
     *
423
     * @return array|int                    int <0 if KO, array of pages if OK
424
     */
425
    public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
426
    {
427
        dol_syslog(__METHOD__, LOG_DEBUG);
428
429
        $records = [];
430
431
        $sql = "SELECT ";
432
        $sql .= $this->getFieldList('t');
433
        $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element . " as t";
434
        if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
435
            $sql .= " WHERE t.entity IN (" . getEntity($this->element) . ")";
436
        } else {
437
            $sql .= " WHERE 1 = 1";
438
        }
439
440
        // Manage filter
441
        $errormessage = '';
442
        $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
443
        if ($errormessage) {
444
            $this->errors[] = $errormessage;
445
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
446
            return -1;
447
        }
448
449
        if (!empty($sortfield)) {
450
            $sql .= $this->db->order($sortfield, $sortorder);
451
        }
452
        if (!empty($limit)) {
453
            $sql .= $this->db->plimit($limit, $offset);
454
        }
455
456
        $resql = $this->db->query($sql);
457
        if ($resql) {
458
            $num = $this->db->num_rows($resql);
459
            $i = 0;
460
            while ($i < ($limit ? min($limit, $num) : $num)) {
461
                $obj = $this->db->fetch_object($resql);
462
463
                $record = new self($this->db);
464
                $record->setVarsFromFetchObj($obj);
465
466
                $records[$record->id] = $record;
467
468
                $i++;
469
            }
470
            $this->db->free($resql);
471
472
            return $records;
473
        } else {
474
            $this->errors[] = 'Error ' . $this->db->lasterror();
475
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
476
477
            return -1;
478
        }
479
    }
480
481
    /**
482
     * Update object into database
483
     *
484
     * @param User $user      User that modifies
485
     * @param int  $notrigger false=launch triggers after, true=disable triggers
486
     *
487
     * @return int              Return integer <0 if KO, >0 if OK
488
     */
489
    public function update(User $user, $notrigger = 0)
490
    {
491
        return $this->updateCommon($user, $notrigger);
492
    }
493
494
    /**
495
     * Delete object in database
496
     *
497
     * @param User $user      User that deletes
498
     * @param int  $notrigger 0=launch triggers after, 1=disable triggers
499
     *
500
     * @return int              Return integer <0 if KO, >0 if OK
501
     */
502
    public function delete(User $user, $notrigger = 0)
503
    {
504
        return $this->deleteCommon($user, $notrigger);
505
        //return $this->deleteCommon($user, $notrigger, 1);
506
    }
507
508
    /**
509
     *  Delete a line of object in database
510
     *
511
     * @param User $user      User that delete
512
     * @param int  $idline    Id of line to delete
513
     * @param int  $notrigger 0=launch triggers after, 1=disable triggers
514
     *
515
     * @return int                 >0 if OK, <0 if KO
516
     */
517
    public function deleteLine(User $user, $idline, $notrigger = 0)
518
    {
519
        if ($this->status < 0) {
520
            $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
521
            return -2;
522
        }
523
524
        return $this->deleteLineCommon($user, $idline, $notrigger);
525
    }
526
527
528
    /**
529
     *  Validate object
530
     *
531
     * @param User $user      User making status change
532
     * @param int  $notrigger 1=Does not execute triggers, 0= execute triggers
533
     *
534
     * @return     int                     Return integer <=0 if OK, 0=Nothing done, >0 if KO
535
     */
536
    public function validate($user, $notrigger = 0)
537
    {
538
        global $conf, $langs;
539
540
        require_once BASE_PATH . '/../Dolibarr/Lib/Files.php';
541
542
        $error = 0;
543
544
        // Protection
545
        if ($this->status == self::STATUS_VALIDATED) {
546
            dol_syslog(get_class($this) . "::validate action abandoned: already validated", LOG_WARNING);
547
            return 0;
548
        }
549
550
        $now = dol_now();
551
552
        $this->db->begin();
553
554
        // Define new ref
555
        if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
556
            $num = $this->getNextNumRef();
557
        } else {
558
            $num = $this->ref;
559
        }
560
        $this->newref = $num;
561
562
        if (!empty($num)) {
563
            // Validate
564
            $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
565
            $sql .= " SET label = '" . $this->db->escape($num) . "',";
566
            $sql .= " status = " . self::STATUS_VALIDATED;
567
            if (!empty($this->fields['date_validation'])) {
568
                $sql .= ", date_validation = '" . $this->db->idate($now) . "'";
569
            }
570
            if (!empty($this->fields['fk_user_valid'])) {
571
                $sql .= ", fk_user_valid = " . ((int) $user->id);
572
            }
573
            $sql .= " WHERE rowid = " . ((int) $this->id);
574
575
            dol_syslog(get_class($this) . "::validate()", LOG_DEBUG);
576
            $resql = $this->db->query($sql);
577
            if (!$resql) {
578
                dol_print_error($this->db);
579
                $this->error = $this->db->lasterror();
580
                $error++;
581
            }
582
583
            if (!$error && !$notrigger) {
584
                // Call trigger
585
                $result = $this->call_trigger('AVAILABILITIES_VALIDATE', $user);
586
                if ($result < 0) {
587
                    $error++;
588
                }
589
                // End call triggers
590
            }
591
        }
592
593
        if (!$error) {
594
            $this->oldref = $this->ref;
595
596
            // Rename directory if dir was a temporary ref
597
            if (preg_match('/^[\(]?PROV/i', $this->ref)) {
598
                // Now we rename also files into index
599
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filename = CONCAT('" . $this->db->escape($this->newref) . "', SUBSTR(filename, " . (strlen($this->ref) + 1) . ")), filepath = 'availabilities/" . $this->db->escape($this->newref) . "'";
600
                $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'availabilities/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
601
                $resql = $this->db->query($sql);
602
                if (!$resql) {
603
                    $error++;
604
                    $this->error = $this->db->lasterror();
605
                }
606
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'availabilities/" . $this->db->escape($this->newref) . "'";
607
                $sql .= " WHERE filepath = 'availabilities/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
608
                $resql = $this->db->query($sql);
609
                if (!$resql) {
610
                    $error++;
611
                    $this->error = $this->db->lasterror();
612
                }
613
614
                // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
615
                $oldref = dol_sanitizeFileName($this->ref);
616
                $newref = dol_sanitizeFileName($num);
617
                $dirsource = $conf->bookcal->dir_output . '/availabilities/' . $oldref;
618
                $dirdest = $conf->bookcal->dir_output . '/availabilities/' . $newref;
619
                if (!$error && file_exists($dirsource)) {
620
                    dol_syslog(get_class($this) . "::validate() rename dir " . $dirsource . " into " . $dirdest);
621
622
                    if (@rename($dirsource, $dirdest)) {
623
                        dol_syslog("Rename ok");
624
                        // Rename docs starting with $oldref with $newref
625
                        $listoffiles = dol_dir_list($conf->bookcal->dir_output . '/availabilities/' . $newref, 'files', 1, '^' . preg_quote($oldref, '/'));
626
                        foreach ($listoffiles as $fileentry) {
627
                            $dirsource = $fileentry['name'];
628
                            $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
629
                            $dirsource = $fileentry['path'] . '/' . $dirsource;
630
                            $dirdest = $fileentry['path'] . '/' . $dirdest;
631
                            @rename($dirsource, $dirdest);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rename(). 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

631
                            /** @scrutinizer ignore-unhandled */ @rename($dirsource, $dirdest);

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...
632
                        }
633
                    }
634
                }
635
            }
636
        }
637
638
        // Set new ref and current status
639
        if (!$error) {
640
            $this->ref = $num;
641
            $this->status = self::STATUS_VALIDATED;
642
        }
643
644
        if (!$error) {
645
            $this->db->commit();
646
            return 1;
647
        } else {
648
            $this->db->rollback();
649
            return -1;
650
        }
651
    }
652
653
654
    /**
655
     *  Set draft status
656
     *
657
     * @param User $user      Object user that modify
658
     * @param int  $notrigger 1=Does not execute triggers, 0=Execute triggers
659
     *
660
     * @return int                     Return integer <0 if KO, >0 if OK
661
     */
662
    public function setDraft($user, $notrigger = 0)
663
    {
664
        // Protection
665
        if ($this->status <= self::STATUS_DRAFT) {
666
            return 0;
667
        }
668
669
        return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'AVAILABILITIES_UNVALIDATE');
670
    }
671
672
    /**
673
     *  Set cancel status
674
     *
675
     * @param User $user      Object user that modify
676
     * @param int  $notrigger 1=Does not execute triggers, 0=Execute triggers
677
     *
678
     * @return int                     Return integer <0 if KO, 0=Nothing done, >0 if OK
679
     */
680
    public function cancel($user, $notrigger = 0)
681
    {
682
        // Protection
683
        if ($this->status != self::STATUS_VALIDATED) {
684
            return 0;
685
        }
686
687
        return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'AVAILABILITIES_CANCEL');
688
    }
689
690
    /**
691
     *  Set back to validated status
692
     *
693
     * @param User $user      Object user that modify
694
     * @param int  $notrigger 1=Does not execute triggers, 0=Execute triggers
695
     *
696
     * @return int                     Return integer <0 if KO, 0=Nothing done, >0 if OK
697
     */
698
    public function reopen($user, $notrigger = 0)
699
    {
700
        // Protection
701
        if ($this->status != self::STATUS_CANCELED) {
702
            return 0;
703
        }
704
705
        return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'AVAILABILITIES_REOPEN');
706
    }
707
708
    /**
709
     *  Return a link to the object card (with optionally the picto)
710
     *
711
     * @param int    $withpicto             Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
712
     * @param string $option                On what the link point to ('nolink', ...)
713
     * @param int    $notooltip             1=Disable tooltip
714
     * @param string $morecss               Add more css on link
715
     * @param int    $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save
716
     *                                      lastsearch_values whenclicking
717
     *
718
     * @return string                              String with URL
719
     */
720
    public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
721
    {
722
        global $conf, $langs, $hookmanager;
723
724
        if (!empty($conf->dol_no_mouse_hover)) {
725
            $notooltip = 1; // Force disable tooltips
726
        }
727
728
        $result = '';
729
730
        $label = img_picto('', $this->picto) . ' <u>' . $langs->trans("Availabilities") . '</u>';
731
        if (isset($this->status)) {
732
            $label .= ' ' . $this->getLibStatut(5);
733
        }
734
        $label .= '<br>';
735
        $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
736
737
        $url = dol_buildpath('/bookcal/availabilities_card.php', 1) . '?id=' . $this->id;
738
739
        if ($option != 'nolink') {
740
            // Add param to save lastsearch_values or not
741
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
742
            if ($save_lastsearch_value == -1 && isset($_SERVER['PHP_SELF']) && preg_match('/list\.php/', $_SERVER['PHP_SELF'])) {
743
                $add_save_lastsearch_values = 1;
744
            }
745
            if ($url && $add_save_lastsearch_values) {
746
                $url .= '&save_lastsearch_values=1';
747
            }
748
        }
749
750
        $linkclose = '';
751
        if (empty($notooltip)) {
752
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
753
                $label = $langs->trans("ShowAvailabilities");
754
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
755
            }
756
            $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
757
            $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
758
        } else {
759
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
760
        }
761
762
        if ($option == 'nolink' || empty($url)) {
763
            $linkstart = '<span';
764
        } else {
765
            $linkstart = '<a href="' . $url . '"';
766
        }
767
        $linkstart .= $linkclose . '>';
768
        if ($option == 'nolink' || empty($url)) {
769
            $linkend = '</span>';
770
        } else {
771
            $linkend = '</a>';
772
        }
773
774
        $result .= $linkstart;
775
776
        if (empty($this->showphoto_on_popup)) {
777
            if ($withpicto) {
778
                $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
779
            }
780
        } else {
781
            if ($withpicto) {
782
                require_once BASE_PATH . '/../Dolibarr/Lib/Files.php';
783
784
                [$class, $module] = explode('@', $this->picto);
785
                $upload_dir = $conf->$module->multidir_output[$conf->entity] . "/$class/" . dol_sanitizeFileName($this->ref);
786
                $filearray = dol_dir_list($upload_dir, "files");
787
                $filename = $filearray[0]['name'];
788
                if (!empty($filename)) {
789
                    $pospoint = strpos($filearray[0]['name'], '.');
790
791
                    $pathtophoto = $class . '/' . $this->ref . '/thumbs/' . substr($filename, 0, $pospoint) . '_mini' . substr($filename, $pospoint);
792
                    if (!getDolGlobalString(strtoupper($module . '_' . $class) . '_FORMATLISTPHOTOSASUSERS')) {
793
                        $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo' . $module . '" alt="No photo" border="0" src="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $module . '&entity=' . $conf->entity . '&file=' . urlencode($pathtophoto) . '"></div></div>';
794
                    } else {
795
                        $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $module . '&entity=' . $conf->entity . '&file=' . urlencode($pathtophoto) . '"></div>';
796
                    }
797
798
                    $result .= '</div>';
799
                } else {
800
                    $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
801
                }
802
            }
803
        }
804
805
        if ($withpicto != 2) {
806
            $result .= $this->ref;
807
        }
808
809
        $result .= $linkend;
810
        //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
811
812
        global $action, $hookmanager;
813
        $hookmanager->initHooks(['availabilitiesdao']);
814
        $parameters = ['id' => $this->id, 'getnomurl' => &$result];
815
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
816
        if ($reshook > 0) {
817
            $result = $hookmanager->resPrint;
818
        } else {
819
            $result .= $hookmanager->resPrint;
820
        }
821
822
        return $result;
823
    }
824
825
    /**
826
     *  Return a thumb for kanban views
827
     *
828
     * @param string $option    Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
829
     * @param array  $arraydata Array of data
830
     *
831
     * @return     string                              HTML Code for Kanban thumb.
832
     */
833
    public function getKanbanView($option = '', $arraydata = null)
834
    {
835
        global $conf, $langs;
836
837
        $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
838
839
        $return = '<div class="box-flex-item box-flex-grow-zero">';
840
        $return .= '<div class="info-box info-box-sm">';
841
        $return .= '<span class="info-box-icon bg-infobox-action">';
842
        $return .= img_picto('', $this->picto);
843
        $return .= '</span>';
844
        $return .= '<div class="info-box-content">';
845
        $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref) . '</span>';
846
        if ($selected >= 0) {
847
            $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
848
        }
849
        if (property_exists($this, 'label')) {
850
            $return .= ' <div class="inline-block opacitymedium valignmiddle tdoverflowmax100">' . $this->label . '</div>';
851
        }
852
        if (property_exists($this, 'amount')) {
853
            $return .= '<br>';
854
            $return .= '<span class="info-box-label amount">' . price($this->amount, 0, $langs, 1, -1, -1, $conf->currency) . '</span>';
855
        }
856
        if (method_exists($this, 'getLibStatut')) {
857
            $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
858
        }
859
        $return .= '</div>';
860
        $return .= '</div>';
861
        $return .= '</div>';
862
863
        return $return;
864
    }
865
866
    /**
867
     *  Return the label of the status
868
     *
869
     * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short
870
     *                  label + Picto, 6=Long label + Picto
871
     *
872
     * @return string                 Label of status
873
     */
874
    public function getLabelStatus($mode = 0)
875
    {
876
        return $this->LibStatut($this->status, $mode);
877
    }
878
879
    /**
880
     *  Return the label of the status
881
     *
882
     * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short
883
     *                  label + Picto, 6=Long label + Picto
884
     *
885
     * @return string                 Label of status
886
     */
887
    public function getLibStatut($mode = 0)
888
    {
889
        return $this->LibStatut($this->status, $mode);
890
    }
891
892
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
893
894
    /**
895
     *  Return the status
896
     *
897
     * @param int $status Id status
898
     * @param int $mode   0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short
899
     *                    label + Picto, 6=Long label + Picto
900
     *
901
     * @return string                 Label of status
902
     */
903
    public function LibStatut($status, $mode = 0)
904
    {
905
        // phpcs:enable
906
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
907
            global $langs;
908
            //$langs->load("agenda");
909
            $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
910
            $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
911
            $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
912
            $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
913
            $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
914
            $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
915
        }
916
917
        $statusType = 'status' . $status;
918
        if ($status == self::STATUS_VALIDATED) {
919
            $statusType = 'status4';
920
        }
921
        if ($status == self::STATUS_CANCELED) {
922
            $statusType = 'status6';
923
        }
924
925
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
926
    }
927
928
    /**
929
     *  Load the info information in the object
930
     *
931
     * @param int $id Id of object
932
     *
933
     * @return void
934
     */
935
    public function info($id)
936
    {
937
        $sql = "SELECT rowid,";
938
        $sql .= " date_creation as datec, tms as datem,";
939
        $sql .= " fk_user_creat, fk_user_modif";
940
        $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element . " as t";
941
        $sql .= " WHERE t.rowid = " . ((int) $id);
942
943
        $result = $this->db->query($sql);
944
        if ($result) {
945
            if ($this->db->num_rows($result)) {
946
                $obj = $this->db->fetch_object($result);
947
948
                $this->id = $obj->rowid;
949
950
                $this->user_creation_id = $obj->fk_user_creat;
951
                $this->user_modification_id = $obj->fk_user_modif;
952
                $this->date_creation = $this->db->jdate($obj->datec);
953
                $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
954
            }
955
956
            $this->db->free($result);
957
        } else {
958
            dol_print_error($this->db);
959
        }
960
    }
961
962
    /**
963
     * Initialise object with example values
964
     * Id must be 0 if object instance is a specimen
965
     *
966
     * @return int
967
     */
968
    public function initAsSpecimen()
969
    {
970
        // Set here init that are not commonf fields
971
        // $this->property1 = ...
972
        // $this->property2 = ...
973
974
        return $this->initAsSpecimenCommon();
975
    }
976
977
    /**
978
     *  Create an array of lines
979
     *
980
     * @return array|int       array of lines if OK, <0 if KO
981
     */
982
    public function getLinesArray()
983
    {
984
        $this->lines = [];
985
986
        $objectline = new AvailabilitiesLine($this->db);
987
        $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_availabilities:=:' . ((int) $this->id) . ')');
988
989
        if (is_numeric($result)) {
990
            $this->error = $objectline->error;
991
            $this->errors = $objectline->errors;
992
            return $result;
993
        } else {
994
            $this->lines = $result;
995
            return $this->lines;
996
        }
997
    }
998
999
    /**
1000
     *  Returns the reference to the following non used object depending on the active numbering module.
1001
     *
1002
     * @return string              Object free reference
1003
     */
1004
    public function getNextNumRef()
1005
    {
1006
        global $langs, $conf;
1007
        $langs->load("agenda");
1008
1009
        if (!getDolGlobalString('BOOKCAL_AVAILABILITIES_ADDON')) {
1010
            $conf->global->BOOKCAL_AVAILABILITIES_ADDON = 'mod_availabilities_standard';
1011
        }
1012
1013
        if (getDolGlobalString('BOOKCAL_AVAILABILITIES_ADDON')) {
1014
            $mybool = false;
1015
1016
            $file = getDolGlobalString('BOOKCAL_AVAILABILITIES_ADDON') . ".php";
1017
            $classname = getDolGlobalString('BOOKCAL_AVAILABILITIES_ADDON');
1018
1019
            // Include file with class
1020
            $dirmodels = array_merge(['/'], (array) $conf->modules_parts['models']);
1021
            foreach ($dirmodels as $reldir) {
1022
                $dir = dol_buildpath($reldir . "core/modules/bookcal/");
1023
1024
                // Load file with numbering class (if found)
1025
                $mybool |= @include_once $dir . $file;
1026
            }
1027
1028
            if ($mybool === false) {
1029
                dol_print_error(null, "Failed to include file " . $file);
1030
                return '';
1031
            }
1032
1033
            if (class_exists($classname)) {
1034
                $obj = new $classname();
1035
                $numref = $obj->getNextValue($this);
1036
1037
                if ($numref != '' && $numref != '-1') {
1038
                    return $numref;
1039
                } else {
1040
                    $this->error = $obj->error;
1041
                    //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1042
                    return "";
1043
                }
1044
            } else {
1045
                print $langs->trans("Error") . " " . $langs->trans("ClassNotFound") . ' ' . $classname;
1046
                return "";
1047
            }
1048
        } else {
1049
            print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1050
            return "";
1051
        }
1052
    }
1053
1054
    /**
1055
     *  Create a document onto disk according to template module.
1056
     *
1057
     * @param string     $modele      Force template to use ('' to not force)
1058
     * @param Translate  $outputlangs object lang a utiliser pour traduction
1059
     * @param int        $hidedetails Hide details of lines
1060
     * @param int        $hidedesc    Hide description
1061
     * @param int        $hideref     Hide ref
1062
     * @param null|array $moreparams  Array to provide more information
1063
     *
1064
     * @return     int                         0 if KO, 1 if OK
1065
     */
1066
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1067
    {
1068
        global $conf, $langs;
1069
1070
        $result = 0;
1071
        $includedocgeneration = 0;
1072
1073
        $langs->load("agenda");
1074
1075
        if (!dol_strlen($modele)) {
1076
            $modele = 'standard_availabilities';
1077
1078
            if (!empty($this->model_pdf)) {
1079
                $modele = $this->model_pdf;
1080
            } elseif (getDolGlobalString('AVAILABILITIES_ADDON_PDF')) {
1081
                $modele = getDolGlobalString('AVAILABILITIES_ADDON_PDF');
1082
            }
1083
        }
1084
1085
        $modelpath = "core/modules/bookcal/doc/";
1086
1087
        if ($includedocgeneration && !empty($modele)) {
1088
            $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1089
        }
1090
1091
        return $result;
1092
    }
1093
1094
    /**
1095
     * Action executed by scheduler
1096
     * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters'
1097
     * Use public function doScheduledJob($param1, $param2, ...) to get parameters
1098
     *
1099
     * @return  int         0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
1100
     */
1101
    public function doScheduledJob()
1102
    {
1103
        global $conf, $langs;
1104
1105
        //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1106
1107
        $error = 0;
1108
        $this->output = '';
1109
        $this->error = '';
1110
1111
        dol_syslog(__METHOD__, LOG_DEBUG);
1112
1113
        $now = dol_now();
1114
1115
        $this->db->begin();
1116
1117
        // ...
1118
1119
        $this->db->commit();
1120
1121
        return $error;
1122
    }
1123
}
1124