Passed
Push — dev ( f7d146...05f415 )
by Rafael
60:50
created

Target::getNomUrl()   F

Complexity

Conditions 37
Paths > 20000

Size

Total Lines 103
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 37
eloc 67
nc 20736
nop 5
dl 0
loc 103
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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

617
                            /** @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...
618
                        }
619
                    }
620
                }
621
            }
622
        }
623
624
        // Set new ref and current status
625
        if (!$error) {
626
            $this->ref = $num;
627
            $this->status = self::STATUS_VALIDATED;
628
        }
629
630
        if (!$error) {
631
            $this->db->commit();
632
            return 1;
633
        } else {
634
            $this->db->rollback();
635
            return -1;
636
        }
637
    }
638
639
640
    /**
641
     *  Set draft status
642
     *
643
     *  @param  User    $user           Object user that modify
644
     *  @param  int     $notrigger      1=Does not execute triggers, 0=Execute triggers
645
     *  @return int                     Return integer <0 if KO, >0 if OK
646
     */
647
    public function setDraft($user, $notrigger = 0)
648
    {
649
        // Protection
650
        if ($this->status <= self::STATUS_DRAFT) {
651
            return 0;
652
        }
653
654
        return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'TARGET_UNVALIDATE');
655
    }
656
657
    /**
658
     *  Set cancel status
659
     *
660
     *  @param  User    $user           Object user that modify
661
     *  @param  int     $notrigger      1=Does not execute triggers, 0=Execute triggers
662
     *  @return int                     Return integer <0 if KO, 0=Nothing done, >0 if OK
663
     */
664
    public function cancel($user, $notrigger = 0)
665
    {
666
        // Protection
667
        if ($this->status != self::STATUS_VALIDATED) {
668
            return 0;
669
        }
670
671
        return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'TARGET_CANCEL');
672
    }
673
674
    /**
675
     *  Set back to validated status
676
     *
677
     *  @param  User    $user           Object user that modify
678
     *  @param  int     $notrigger      1=Does not execute triggers, 0=Execute triggers
679
     *  @return int                     Return integer <0 if KO, 0=Nothing done, >0 if OK
680
     */
681
    public function reopen($user, $notrigger = 0)
682
    {
683
        // Protection
684
        if ($this->status != self::STATUS_CANCELED) {
685
            return 0;
686
        }
687
688
        return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'TARGET_REOPEN');
689
    }
690
691
    /**
692
     *  Return a link to the object card (with optionally the picto)
693
     *
694
     *  @param  int     $withpicto                  Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
695
     *  @param  string  $option                     On what the link point to ('nolink', ...)
696
     *  @param  int     $notooltip                  1=Disable tooltip
697
     *  @param  string  $morecss                    Add more css on link
698
     *  @param  int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
699
     *  @return string                              String with URL
700
     */
701
    public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
702
    {
703
        global $conf, $langs, $hookmanager;
704
705
        if (!empty($conf->dol_no_mouse_hover)) {
706
            $notooltip = 1; // Force disable tooltips
707
        }
708
709
        $result = '';
710
711
        $label = img_picto('', $this->picto) . ' <u>' . $langs->trans("Target") . '</u>';
712
        if (isset($this->status)) {
713
            $label .= ' ' . $this->getLibStatut(5);
714
        }
715
        $label .= '<br>';
716
        $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
717
718
        $url = dol_buildpath('/webhook/target_card.php', 1) . '?id=' . $this->id;
719
720
        if ($option != 'nolink') {
721
            // Add param to save lastsearch_values or not
722
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
723
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
724
                $add_save_lastsearch_values = 1;
725
            }
726
            if ($url && $add_save_lastsearch_values) {
727
                $url .= '&save_lastsearch_values=1';
728
            }
729
        }
730
731
        $linkclose = '';
732
        if (empty($notooltip)) {
733
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
734
                $label = $langs->trans("ShowTarget");
735
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
736
            }
737
            $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
738
            $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
739
        } else {
740
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
741
        }
742
743
        if ($option == 'nolink' || empty($url)) {
744
            $linkstart = '<span';
745
        } else {
746
            $linkstart = '<a href="' . $url . '"';
747
        }
748
        $linkstart .= $linkclose . '>';
749
        if ($option == 'nolink' || empty($url)) {
750
            $linkend = '</span>';
751
        } else {
752
            $linkend = '</a>';
753
        }
754
755
        $result .= $linkstart;
756
757
        if (empty($this->showphoto_on_popup)) {
758
            if ($withpicto) {
759
                $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);
760
            }
761
        } else {
762
            if ($withpicto) {
763
                require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
764
765
                list($class, $module) = explode('@', $this->picto);
766
                $upload_dir = $conf->$module->multidir_output[$conf->entity] . "/$class/" . dol_sanitizeFileName($this->ref);
767
                $filearray = dol_dir_list($upload_dir, "files");
768
                $filename = $filearray[0]['name'];
769
                if (!empty($filename)) {
770
                    $pospoint = strpos($filearray[0]['name'], '.');
771
772
                    $pathtophoto = $class . '/' . $this->ref . '/thumbs/' . substr($filename, 0, $pospoint) . '_mini' . substr($filename, $pospoint);
773
                    if (!getDolGlobalString(strtoupper($module . '_' . $class) . '_FORMATLISTPHOTOSASUSERS')) {
774
                        $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo' . $module . '" alt="No photo" border="0" src="' . constant('BASE_URL') . '/viewimage.php?modulepart=' . $module . '&entity=' . $conf->entity . '&file=' . urlencode($pathtophoto) . '"></div></div>';
775
                    } else {
776
                        $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="' . constant('BASE_URL') . '/viewimage.php?modulepart=' . $module . '&entity=' . $conf->entity . '&file=' . urlencode($pathtophoto) . '"></div>';
777
                    }
778
779
                    $result .= '</div>';
780
                } else {
781
                    $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);
782
                }
783
            }
784
        }
785
786
        if ($withpicto != 2) {
787
            $result .= $this->ref;
788
        }
789
790
        $result .= $linkend;
791
        //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
792
793
        global $action, $hookmanager;
794
        $hookmanager->initHooks(array('targetdao'));
795
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
796
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
797
        if ($reshook > 0) {
798
            $result = $hookmanager->resPrint;
799
        } else {
800
            $result .= $hookmanager->resPrint;
801
        }
802
803
        return $result;
804
    }
805
806
    /**
807
     *  Return the label of the status
808
     *
809
     *  @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
810
     *  @return string                 Label of status
811
     */
812
    public function getLabelStatus($mode = 0)
813
    {
814
        return $this->LibStatut($this->status, $mode);
815
    }
816
817
    /**
818
     *  Return the label of the status
819
     *
820
     *  @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
821
     *  @return string                 Label of status
822
     */
823
    public function getLibStatut($mode = 0)
824
    {
825
        return $this->LibStatut($this->status, $mode);
826
    }
827
828
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
829
    /**
830
     *  Return the status
831
     *
832
     *  @param  int     $status        Id status
833
     *  @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
834
     *  @return string                 Label of status
835
     */
836
    public function LibStatut($status, $mode = 0)
837
    {
838
		// phpcs:enable
839
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
840
            global $langs;
841
842
            $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
843
            $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
844
            $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
845
            $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
846
            $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
847
            $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
848
        }
849
850
        $statusType = 'status' . $status;
851
        if ($status == self::STATUS_VALIDATED) {
852
            $statusType = 'status4';
853
        }
854
        if ($status == self::STATUS_CANCELED) {
855
            $statusType = 'status6';
856
        }
857
858
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
859
    }
860
861
    /**
862
     *  Load the info information in the object
863
     *
864
     *  @param  int     $id       Id of object
865
     *  @return void
866
     */
867
    public function info($id)
868
    {
869
        $sql = "SELECT rowid, date_creation as datec, tms as datem,";
870
        $sql .= " fk_user_creat, fk_user_modif";
871
        $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element . " as t";
872
        $sql .= " WHERE t.rowid = " . ((int) $id);
873
874
        $result = $this->db->query($sql);
875
        if ($result) {
876
            if ($this->db->num_rows($result)) {
877
                $obj = $this->db->fetch_object($result);
878
879
                $this->id = $obj->rowid;
880
881
                $this->user_creation_id = $obj->fk_user_creat;
882
                $this->user_modification_id = $obj->fk_user_modif;
883
                $this->date_creation     = $this->db->jdate($obj->datec);
884
                $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
885
            }
886
887
            $this->db->free($result);
888
        } else {
889
            dol_print_error($this->db);
890
        }
891
    }
892
893
    /**
894
     * Initialise object with example values
895
     * Id must be 0 if object instance is a specimen
896
     *
897
     * @return int
898
     */
899
    public function initAsSpecimen()
900
    {
901
        $this->url = "https://thisisunurl";
902
        $this->trigger_codes = "ThisIsATestCode";
903
904
        return $this->initAsSpecimenCommon();
905
    }
906
907
    /**
908
     *  Returns the reference to the following non used object depending on the active numbering module.
909
     *
910
     *  @return string              Object free reference
911
     */
912
    public function getNextNumRef()
913
    {
914
        global $langs, $conf;
915
916
        $mybool = false;
917
918
        $classname = getDolGlobalString('WEBHOOK_TARGET_ADDON', 'mod_target_standard');
919
        $file = $classname . ".php";
920
921
        // Include file with class
922
        $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
923
        foreach ($dirmodels as $reldir) {
924
            $dir = dol_buildpath($reldir . "core/modules/webhook/");
925
926
            // Load file with numbering class (if found)
927
            $mybool = ((bool) @include_once $dir . $file) || $mybool;
928
        }
929
930
        if ($mybool === false) {
931
            dol_print_error(null, "Failed to include file " . $file);
932
            return '';
933
        }
934
935
        if (class_exists($classname)) {
936
            $obj = new $classname();
937
            $numref = $obj->getNextValue($this);
938
939
            if ($numref != '' && $numref != '-1') {
940
                return $numref;
941
            } else {
942
                $this->error = $obj->error;
943
                //dol_print_error($this->db,get_only_class($this)."::getNextNumRef ".$obj->error);
944
                return "";
945
            }
946
        } else {
947
            print $langs->trans("Error") . " " . $langs->trans("ClassNotFound") . ' ' . $classname;
948
            return "";
949
        }
950
    }
951
952
    /**
953
     *  Create a document onto disk according to template module.
954
     *
955
     *  @param      string      $modele         Force template to use ('' to not force)
956
     *  @param      Translate   $outputlangs    object lang a utiliser pour traduction
957
     *  @param      int         $hidedetails    Hide details of lines
958
     *  @param      int         $hidedesc       Hide description
959
     *  @param      int         $hideref        Hide ref
960
     *  @param      null|array  $moreparams     Array to provide more information
961
     *  @return     int                         0 if KO, 1 if OK
962
     */
963
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
964
    {
965
        $result = 0;
966
        $includedocgeneration = 0;
967
968
        if (!dol_strlen($modele)) {
969
            $modele = 'standard_target';
970
971
            if (!empty($this->model_pdf)) {
972
                $modele = $this->model_pdf;
973
            } elseif (getDolGlobalString('TARGET_ADDON_PDF')) {
974
                $modele = getDolGlobalString('TARGET_ADDON_PDF');
975
            }
976
        }
977
978
        $modelpath = "core/modules/webhook/doc/";
979
980
        if ($includedocgeneration && !empty($modele)) {
981
            $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
982
        }
983
984
        return $result;
985
    }
986
987
    /**
988
     * Action executed by scheduler
989
     * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters'
990
     * Use public function doScheduledJob($param1, $param2, ...) to get parameters
991
     *
992
     * @return  int         0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
993
     */
994
    public function doScheduledJob()
995
    {
996
        //global $conf, $langs;
997
998
        //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
999
1000
        $error = 0;
1001
        $this->output = '';
1002
        $this->error = '';
1003
1004
        dol_syslog(__METHOD__, LOG_DEBUG);
1005
1006
        //$now = dol_now();
1007
1008
        $this->db->begin();
1009
1010
        // ...
1011
1012
        $this->db->commit();
1013
1014
        return $error;
1015
    }
1016
}
1017