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

Skill::createFromClone()   F

Complexity

Conditions 22
Paths 13824

Size

Total Lines 88
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 22
eloc 46
nc 13824
nop 2
dl 0
loc 88
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        htdocs/hrm/class/skill.class.php
32
 * \ingroup     hrm
33
 * \brief       This file is a CRUD class file for Skill (Create/Read/Update/Delete)
34
 */
35
36
/**
37
 * Class for Skill
38
 */
39
class Skill extends CommonObject
40
{
41
    /**
42
     * @var string ID of module.
43
     */
44
    public $module = 'hrm';
45
46
    /**
47
     * @var string ID to identify managed object.
48
     */
49
    public $element = 'skill';
50
51
    /**
52
     * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
53
     */
54
    public $table_element = 'hrm_skill';
55
56
57
    /**
58
     * @var string Name of subtable line
59
     */
60
    public $table_element_line = 'skilldet';
61
62
    /**
63
     * @var string String with name of icon for skill. Must be the part after the 'object_' into object_skill.png
64
     */
65
    public $picto = 'shapes';
66
67
68
    const STATUS_DRAFT = 0;
69
    const STATUS_VALIDATED = 1;
70
    const STATUS_CANCELED = 9;
71
    const DEFAULT_MAX_RANK_PER_SKILL = 3;
72
73
    /**
74
     *  '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')
75
     *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
76
     *  'label' the translation key.
77
     *  'picto' is code of a picto to show before value in forms
78
     *  'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalString("MY_SETUP_PARAM")')
79
     *  'position' is the sort order of field.
80
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
81
     *  '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)
82
     *  'noteditable' says if field is not editable (1 or 0)
83
     *  '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.
84
     *  'index' if we want an index in database.
85
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
86
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
87
     *  '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).
88
     *  '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'
89
     *  'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
90
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
91
     *  '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.
92
     *  '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'
93
     *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
94
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
95
     *
96
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
97
     */
98
99
    // BEGIN MODULEBUILDER PROPERTIES
100
    /**
101
     * @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...
102
     */
103
    public $fields = array(
104
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
105
        'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2,),
106
        'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => 3,),
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:0', '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:0', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
111
        'required_level' => array('type' => 'integer', 'label' => 'requiredLevel', 'enabled' => 1, 'position' => 50, 'notnull' => 1, 'visible' => 0,),
112
        'date_validite' => array('type' => 'integer', 'label' => 'date_validite', 'enabled' => 1, 'position' => 52, 'notnull' => 1, 'visible' => 0,),
113
        'temps_theorique' => array('type' => 'double(24,8)', 'label' => 'temps_theorique', 'enabled' => 1, 'position' => 54, 'notnull' => 1, 'visible' => 0,),
114
        'skill_type' => array('type' => 'integer', 'label' => 'SkillType', 'enabled' => 1, 'position' => 55, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'css' => 'minwidth200', 'arrayofkeyval' => array('0' => 'TypeKnowHow', '1' => 'TypeHowToBe', '9' => 'TypeKnowledge'), 'default' => '0'),
115
        'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 70, 'notnull' => 0, 'visible' => 0,),
116
        'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 71, 'notnull' => 0, 'visible' => 0,),
117
    );
118
    public $rowid;
119
    public $label;
120
    public $description;
121
    public $date_creation;
122
    public $fk_user_creat;
123
    public $fk_user_modif;
124
    public $required_level;
125
    public $date_validite;
126
    public $temps_theorique;
127
    public $skill_type;
128
    // END MODULEBUILDER PROPERTIES
129
130
131
    // If this object has a subtable with lines
132
133
    // /**
134
    //  * @var string    Name of subtable line
135
    //  */
136
    // public $table_element_line = 'hrm_skillline';
137
138
    /**
139
     * @var string    Field with ID of parent key if this object has a parent
140
     */
141
    public $fk_element = 'fk_skill';
142
143
    // /**
144
    //  * @var string    Name of subtable class that manage subtable lines
145
    //  */
146
    // public $class_element_line = 'Skillline';
147
148
    /**
149
     * @var array<string,string[]>  List of child tables. To test if we can delete object.
150
     */
151
    protected $childtables = array(
152
        'hrm_skillrank' => ['name' => 'SkillRank'],
153
        'hrm_evaluationdet' => ['name' => 'EvaluationDet'],
154
    );
155
156
    /**
157
     * @var string[]    List of child tables. To know object to delete on cascade.
158
     *                  If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will
159
     *                  call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
160
     */
161
    protected $childtablesoncascade = array('hrm_skilldet');
162
163
    // /**
164
    //  * @var SkillLine[]     Array of subtable lines
165
    //  */
166
    // public $lines = array();
167
168
169
170
    /**
171
     * Constructor
172
     *
173
     * @param DoliDB $db Database handler
174
     */
175
    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...
176
    {
177
        global $conf, $langs;
178
179
        $this->db = $db;
180
181
        $this->ismultientitymanaged = 0;
182
        $this->isextrafieldmanaged = 1;
183
184
        if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
185
            $this->fields['rowid']['visible'] = 0;
186
        }
187
        if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
188
            $this->fields['entity']['enabled'] = 0;
189
        }
190
191
        // Example to show how to set values of fields definition dynamically
192
        /*if ($user->rights->hrm->skill->read) {
193
            $this->fields['myfield']['visible'] = 1;
194
            $this->fields['myfield']['noteditable'] = 0;
195
        }*/
196
197
        // Unset fields that are disabled
198
        foreach ($this->fields as $key => $val) {
199
            if (isset($val['enabled']) && empty($val['enabled'])) {
200
                unset($this->fields[$key]);
201
            }
202
        }
203
204
        // Translate some data of arrayofkeyval
205
        if (is_object($langs)) {
206
            foreach ($this->fields as $key => $val) {
207
                if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
208
                    foreach ($val['arrayofkeyval'] as $key2 => $val2) {
209
                        $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
210
                    }
211
                }
212
            }
213
        }
214
    }
215
216
    /**
217
     * Create object into database
218
     *
219
     * @param  User $user      User that creates
220
     * @param  int  $notrigger 0=launch triggers after, 1=disable triggers
221
     * @return int             Return integer <0 if KO, Id of created object if OK
222
     */
223
    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...
224
    {
225
        global $langs,$conf;
226
227
        $resultcreate = $this->createCommon($user, $notrigger);
228
229
230
        if ($resultcreate > 0) {
231
            // skillDet create
232
            $this->createSkills();
233
        }
234
235
        return $resultcreate;
236
    }
237
238
    /**
239
     * createSkills
240
     *
241
     * @param int   $i      Rank from which we want to create skilldets (level $i to HRM_MAXRANK will be created)
242
     * @return int          Return integer <0 if KO, Id of created object if OK
243
     */
244
    public function createSkills($i = 1)
245
    {
246
        global $conf, $user, $langs;
247
248
        $MaxNumberSkill = getDolGlobalInt('HRM_MAXRANK', self::DEFAULT_MAX_RANK_PER_SKILL);
249
        $defaultSkillDesc = getDolGlobalString('HRM_DEFAULT_SKILL_DESCRIPTION', $langs->trans("NoDescription"));
250
251
        $error = 0;
252
253
        require_once __DIR__ . '/skilldet.class.php';
254
255
        $this->db->begin();
256
257
        // Create level of skills
258
        while ($i <= $MaxNumberSkill) {
259
            $skilldet = new Skilldet($this->db);
260
            $skilldet->description = $defaultSkillDesc . " " . $i;
261
            $skilldet->rankorder = $i;
262
            $skilldet->fk_skill = $this->id;
263
264
            $result =  $skilldet->create($user);
265
            if ($result <= 0) {
266
                $error++;
267
            }
268
            $i++;
269
        }
270
271
        if (!$error) {
272
            $this->db->commit();
273
274
            setEventMessage($langs->trans('SkillCreated'), $i);
275
            return 1;
276
        } else {
277
            $this->db->rollback();
278
            return -1;
279
        }
280
    }
281
282
    /**
283
     * Clone an object into another one
284
     *
285
     * @param   User    $user       User that creates
286
     * @param   int     $fromid     Id of object to clone
287
     * @return  mixed               New object created, <0 if KO
288
     */
289
    public function createFromClone(User $user, $fromid)
290
    {
291
        global $langs, $extrafields;
292
        $error = 0;
293
294
        dol_syslog(__METHOD__, LOG_DEBUG);
295
296
        $object = new self($this->db);
297
298
        $this->db->begin();
299
300
        // Load source object
301
        $result = $object->fetchCommon($fromid);
302
        if ($result > 0 && !empty($object->table_element_line)) {
303
            $object->fetchLines();
304
        }
305
306
        // get lines so they will be clone
307
        //foreach($this->lines as $line)
308
        //  $line->fetch_optionals();
309
310
        // Reset some properties
311
        unset($object->id);
312
        unset($object->fk_user_creat);
313
        unset($object->import_key);
314
315
        // Clear fields
316
        if (property_exists($object, 'ref')) {
317
            $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_" . $object->ref : $this->fields['ref']['default'];
318
        }
319
        if (property_exists($object, 'label')) {
320
            $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf") . " " . $object->label : $this->fields['label']['default'];
321
        }
322
        if (property_exists($object, 'status')) {
323
            $object->status = self::STATUS_DRAFT;
324
        }
325
        if (property_exists($object, 'date_creation')) {
326
            $object->date_creation = dol_now();
327
        }
328
        if (property_exists($object, 'date_modification')) {
329
            $object->date_modification = null;
330
        }
331
        // ...
332
        // Clear extrafields that are unique
333
        if (is_array($object->array_options) && count($object->array_options) > 0) {
334
            $extrafields->fetch_name_optionals_label($this->table_element);
335
            foreach ($object->array_options as $key => $option) {
336
                $shortkey = preg_replace('/options_/', '', $key);
337
                if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
338
                    //var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
339
                    unset($object->array_options[$key]);
340
                }
341
            }
342
        }
343
344
        // Create clone
345
        $object->context['createfromclone'] = 'createfromclone';
346
        $result = $object->createCommon($user);
347
        if ($result < 0) {
348
            $error++;
349
            $this->setErrorsFromObject($object);
350
        }
351
352
        if (!$error) {
353
            // copy internal contacts
354
            if ($this->copy_linked_contact($object, 'internal') < 0) {
355
                $error++;
356
            }
357
        }
358
359
        if (!$error) {
360
            // copy external contacts if same company
361
            if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
362
                if ($this->copy_linked_contact($object, 'external') < 0) {
363
                    $error++;
364
                }
365
            }
366
        }
367
368
        unset($object->context['createfromclone']);
369
370
        // End
371
        if (!$error) {
372
            $this->db->commit();
373
            return $object;
374
        } else {
375
            $this->db->rollback();
376
            return -1;
377
        }
378
    }
379
380
    /**
381
     * Load object in memory from the database
382
     *
383
     * @param int    $id   Id object
384
     * @param string $ref  Ref
385
     * @return int         Return integer <0 if KO, 0 if not found, >0 if OK
386
     */
387
    public function fetch($id, $ref = null)
388
    {
389
        $result = $this->fetchCommon($id, $ref);
390
        if ($result > 0 && !empty($this->table_element_line)) {
391
            $this->fetchLines();
392
        }
393
        return $result;
394
    }
395
396
    /**
397
     * Load object lines in memory from the database
398
     *
399
     * @return array|int         Return integer <0 if KO, array of skill level found
400
     */
401
    public function fetchLines()
402
    {
403
        $this->lines = array();
404
        require_once __DIR__ . '/skilldet.class.php';
405
        $skilldet = new Skilldet($this->db);
406
        $this->lines = $skilldet->fetchAll('ASC', '', 0, 0, '(fk_skill:=:' . $this->id . ')');
0 ignored issues
show
Documentation Bug introduced by
It seems like $skilldet->fetchAll('ASC...:=:' . $this->id . ')') can also be of type integer. However, the property $lines is declared as type Dolibarr\Core\Base\Commo...rr\Core\Base\stdClass[]. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
407
408
        if (is_array($this->lines)) {
409
            return (count($this->lines) > 0) ? $this->lines : array();
410
        } elseif ($this->lines < 0) {
411
            $this->setErrorsFromObject($skilldet);
412
            return $this->lines;
413
        }
414
        return [];
415
    }
416
417
418
    /**
419
     * Load list of objects in memory from the database.
420
     *
421
     * @param  string       $sortorder      Sort Order
422
     * @param  string       $sortfield      Sort field
423
     * @param  int          $limit          limit
424
     * @param  int          $offset         Offset
425
     * @param  string       $filter         Filter as an Universal Search string.
426
     *                                      Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')'
427
     * @param  string       $filtermode     No more used
428
     * @return array|int                    int <0 if KO, array of pages if OK
429
     */
430
    public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
431
    {
432
        dol_syslog(__METHOD__, LOG_DEBUG);
433
434
        $records = array();
435
436
        $sql = 'SELECT ';
437
        $sql .= $this->getFieldList('t');
438
        $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
439
        if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
440
            $sql .= ' WHERE t.entity IN (' . getEntity($this->element) . ')';
441
        } else {
442
            $sql .= ' WHERE 1 = 1';
443
        }
444
445
        // Manage filter
446
        $errormessage = '';
447
        $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
448
        if ($errormessage) {
449
            $this->errors[] = $errormessage;
450
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
451
            return -1;
452
        }
453
454
        if (!empty($sortfield)) {
455
            $sql .= $this->db->order($sortfield, $sortorder);
456
        }
457
        if (!empty($limit)) {
458
            $sql .= ' ' . $this->db->plimit($limit, $offset);
459
        }
460
461
        $resql = $this->db->query($sql);
462
        if ($resql) {
463
            $num = $this->db->num_rows($resql);
464
            $i = 0;
465
            while ($i < ($limit ? min($limit, $num) : $num)) {
466
                $obj = $this->db->fetch_object($resql);
467
468
                $record = new self($this->db);
469
                $record->setVarsFromFetchObj($obj);
470
471
                $records[$record->id] = $record;
472
473
                $i++;
474
            }
475
            $this->db->free($resql);
476
477
            return $records;
478
        } else {
479
            $this->errors[] = 'Error ' . $this->db->lasterror();
480
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
481
482
            return -1;
483
        }
484
    }
485
486
    /**
487
     * Update object into database
488
     *
489
     * @param  User $user      User that modifies
490
     * @param  int  $notrigger 0=launch triggers after, 1=disable triggers
491
     * @return int             Return integer <0 if KO, >0 if OK
492
     */
493
    public function update(User $user, $notrigger = 0)
494
    {
495
        return $this->updateCommon($user, $notrigger);
496
    }
497
498
    /**
499
     * Delete object in database
500
     *
501
     * @param User  $user       User that deletes
502
     * @param int   $notrigger  0=launch triggers after, 1=disable triggers
503
     * @return int              Return integer <0 if KO, >0 if OK
504
     */
505
    public function delete(User $user, $notrigger = 0)
506
    {
507
        return $this->deleteCommon($user, $notrigger);
508
    }
509
510
    /**
511
     *  Delete a line of object in database
512
     *
513
     *  @param  User    $user       User that delete
514
     *  @param  int     $idline     Id of line to delete
515
     *  @param  int     $notrigger  0=launch triggers after, 1=disable triggers
516
     *  @return int                 Return >0 if OK, <0 if KO
517
     */
518
    public function deleteLine(User $user, $idline, $notrigger = 0)
519
    {
520
        if ($this->status < 0) {
521
            $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
522
            return -2;
523
        }
524
525
        return $this->deleteLineCommon($user, $idline, $notrigger);
526
    }
527
528
529
    /**
530
     *  Validate object
531
     *
532
     *  @param      User    $user           User making status change
533
     *  @param      int     $notrigger      1=Does not execute triggers, 0= execute triggers
534
     *  @return     int                     Return integer <=0 if OK, 0=Nothing done, >0 if KO
535
     */
536
    public function validate($user, $notrigger = 0)
537
    {
538
        global $conf;
539
540
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
541
542
        $error = 0;
543
544
        // Protection
545
        if ($this->status == self::STATUS_VALIDATED) {
546
            dol_syslog(get_class($this) . "::validate action abandoned: already validated", LOG_WARNING);
547
            return 0;
548
        }
549
550
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->skill->write))
551
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->skill->skill_advance->validate))))
552
         {
553
         $this->error='NotEnoughPermissions';
554
         dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
555
         return -1;
556
         }*/
557
558
        $now = dol_now();
559
560
        $this->db->begin();
561
562
        // Define new ref
563
        if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
564
            $num = $this->getNextNumRef();
565
        } else {
566
            $num = $this->ref;
567
        }
568
        $this->newref = $num;
569
570
        if (!empty($num)) {
571
            // Validate
572
            $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
573
            $sql .= " SET ref = '" . $this->db->escape($num) . "',";
574
            $sql .= " status = " . self::STATUS_VALIDATED;
575
            if (!empty($this->fields['date_validation'])) {
576
                $sql .= ", date_validation = '" . $this->db->idate($now) . "'";
577
            }
578
            if (!empty($this->fields['fk_user_valid'])) {
579
                $sql .= ", fk_user_valid = " . ((int) $user->id);
580
            }
581
            $sql .= " WHERE rowid = " . ((int) $this->id);
582
583
            dol_syslog(get_class($this) . "::validate()", LOG_DEBUG);
584
            $resql = $this->db->query($sql);
585
            if (!$resql) {
586
                dol_print_error($this->db);
587
                $this->error = $this->db->lasterror();
588
                $error++;
589
            }
590
591
            if (!$error && !$notrigger) {
592
                // Call trigger
593
                $result = $this->call_trigger('HRM_SKILL_VALIDATE', $user);
594
                if ($result < 0) {
595
                    $error++;
596
                }
597
                // End call triggers
598
            }
599
        }
600
601
        if (!$error) {
602
            $this->oldref = $this->ref;
603
604
            // Rename directory if dir was a temporary ref
605
            if (preg_match('/^[\(]?PROV/i', $this->ref)) {
606
                // Now we rename also files into index
607
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filename = CONCAT('" . $this->db->escape($this->newref) . "', SUBSTR(filename, " . (strlen($this->ref) + 1) . ")), filepath = 'skill/" . $this->db->escape($this->newref) . "'";
608
                $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'skill/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
609
                $resql = $this->db->query($sql);
610
                if (!$resql) {
611
                    $error++;
612
                    $this->error = $this->db->lasterror();
613
                }
614
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'skill/" . $this->db->escape($this->newref) . "'";
615
                $sql .= " WHERE filepath = 'skill/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
616
                $resql = $this->db->query($sql);
617
                if (!$resql) {
618
                    $error++;
619
                    $this->error = $this->db->lasterror();
620
                }
621
622
                // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
623
                $oldref = dol_sanitizeFileName($this->ref);
624
                $newref = dol_sanitizeFileName($num);
625
                $dirsource = $conf->hrm->dir_output . '/skill/' . $oldref;
626
                $dirdest = $conf->hrm->dir_output . '/skill/' . $newref;
627
                if (!$error && file_exists($dirsource)) {
628
                    dol_syslog(get_class($this) . "::validate() rename dir " . $dirsource . " into " . $dirdest);
629
630
                    if (@rename($dirsource, $dirdest)) {
631
                        dol_syslog("Rename ok");
632
                        // Rename docs starting with $oldref with $newref
633
                        $listoffiles = dol_dir_list($conf->hrm->dir_output . '/skill/' . $newref, 'files', 1, '^' . preg_quote($oldref, '/'));
634
                        foreach ($listoffiles as $fileentry) {
635
                            $dirsource = $fileentry['name'];
636
                            $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
637
                            $dirsource = $fileentry['path'] . '/' . $dirsource;
638
                            $dirdest = $fileentry['path'] . '/' . $dirdest;
639
                            @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

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