Passed
Push — EXTRACT_CLASSES ( 9f3ede...ff35ec )
by Rafael
76:09 queued 20:57
created

SkillRank::getNomUrl()   F

Complexity

Conditions 34
Paths > 20000

Size

Total Lines 103
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Importance

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

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