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

EvaluationLine   F

Complexity

Total Complexity 143

Size/Duplication

Total Lines 955
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 376
dl 0
loc 955
rs 2
c 0
b 0
f 0
wmc 143

21 Methods

Rating   Name   Duplication   Size   Complexity  
A fetch() 0 7 3
A cancel() 0 15 2
B fetchAll() 0 55 9
A fetchLines() 0 6 1
F validate() 0 122 22
F getNomUrl() 0 103 34
A getLibStatut() 0 3 1
B getNextNumRef() 0 47 9
A getLinesArray() 0 13 2
A update() 0 3 1
F createFromClone() 0 88 22
A initAsSpecimen() 0 7 1
A reopen() 0 15 2
A LibStatut() 0 21 4
A deleteLine() 0 8 2
A setDraft() 0 15 2
A delete() 0 8 2
A info() 0 22 4
A generateDocument() 0 26 6
C __construct() 0 35 13
A create() 0 5 1

How to fix   Complexity   

Complex Class

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

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

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

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\CommonObjectLine;
29
30
/**
31
 * \file        class/evaluationdet.class.php
32
 * \ingroup     hrm
33
 * \brief       This file is a CRUD class file for Evaluationdet (Create/Read/Update/Delete)
34
 */
35
36
// Put here all includes required by your class file
37
require_once constant('DOL_DOCUMENT_ROOT') . '/hrm/class/skillrank.class.php';
38
39
40
/**
41
 * Class for EvaluationLine
42
 */
43
class EvaluationLine extends CommonObjectLine
44
{
45
    /**
46
     * @var string ID of module.
47
     */
48
    public $module = 'hrm';
49
50
    /**
51
     * @var string ID to identify managed object.
52
     */
53
    public $element = 'evaluationdet';
54
55
    /**
56
     * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
57
     */
58
    public $table_element = 'hrm_evaluationdet';
59
60
    /**
61
     * @see CommonObjectLine
62
     */
63
    public $parent_element = 'hrm_evaluation';
64
65
    /**
66
     * @see CommonObjectLine
67
     */
68
    public $fk_parent_attribute = 'fk_evaluation';
69
70
    /**
71
     * @var string String with name of icon for evaluationdet. Must be the part after the 'object_' into object_evaluationdet.png
72
     */
73
    public $picto = 'evaluationdet@hrm';
74
75
76
    const STATUS_DRAFT = 0;
77
    const STATUS_VALIDATED = 1;
78
    const STATUS_CANCELED = 9;
79
80
81
    /**
82
     *  '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')
83
     *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
84
     *  'label' the translation key.
85
     *  'picto' is code of a picto to show before value in forms
86
     *  'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalString("MY_SETUP_PARAM")')
87
     *  'position' is the sort order of field.
88
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
89
     *  '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)
90
     *  'noteditable' says if field is not editable (1 or 0)
91
     *  '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.
92
     *  'index' if we want an index in database.
93
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
94
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
95
     *  '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).
96
     *  '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'
97
     *  'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
98
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
99
     *  '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.
100
     *  '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'
101
     *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
102
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
103
     *
104
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
105
     */
106
107
    // BEGIN MODULEBUILDER PROPERTIES
108
    /**
109
     * @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...
110
     */
111
    public $fields = array(
112
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
113
        'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2,),
114
        'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2,),
115
        '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',),
116
        'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
117
        'fk_skill' => array('type' => 'integer:Skill:hrm/class/skill.class.php:1', 'label' => 'Skill', 'enabled' => 1, 'position' => 3, 'notnull' => 1, 'visible' => 1, 'index' => 1,),
118
        'fk_evaluation' => array('type' => 'integer:Evaluation:hrm/class/evaluation.class.php:1', 'label' => 'Evaluation', 'enabled' => 1, 'position' => 3, 'notnull' => 1, 'visible' => 1, 'index' => 1,),
119
        'rankorder' => array('type' => 'integer', 'label' => 'Rank', 'enabled' => 1, 'position' => 4, 'notnull' => 1, 'visible' => 1,),
120
        'required_rank' => array('type' => 'integer', 'label' => 'requiredRank', 'enabled' => 1, 'position' => 5, 'notnull' => 1, 'visible' => 1,),
121
        'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
122
    );
123
    public $rowid;
124
    public $date_creation;
125
    public $fk_user_creat;
126
    public $fk_user_modif;
127
    public $fk_skill;
128
    public $fk_evaluation;
129
    public $fk_rank;
130
    public $required_rank;
131
    public $import_key;
132
    // END MODULEBUILDER PROPERTIES
133
134
135
    // If this object has a subtable with lines
136
137
    // /**
138
    //  * @var string    Name of subtable line
139
    //  */
140
    // public $table_element_line = 'hrm_evaluationline';
141
142
    // /**
143
    //  * @var string    Field with ID of parent key if this object has a parent
144
    //  */
145
    // public $fk_element = 'fk_evaluationdet';
146
147
    // /**
148
    //  * @var string    Name of subtable class that manage subtable lines
149
    //  */
150
    // public $class_element_line = 'EvaluationLine';
151
152
    // /**
153
    //  * @var array    List of child tables. To test if we can delete object.
154
    //  */
155
    // protected $childtables = array();
156
157
    // /**
158
    //  * @var array    List of child tables. To know object to delete on cascade.
159
    //  *               If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will
160
    //  *               call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
161
    //  */
162
    // protected $childtablesoncascade = array('hrm_evaluationdetdet');
163
164
    // /**
165
    //  * @var EvaluationLine[]     Array of subtable lines
166
    //  */
167
    // public $lines = array();
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->evaluationdet->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
        $resultcreate = $this->createCommon($user, $notrigger);
226
227
        return $resultcreate;
228
    }
229
230
    /**
231
     * Clone an object into another one
232
     *
233
     * @param   User    $user       User that creates
234
     * @param   int     $fromid     Id of object to clone
235
     * @return  mixed               New object created, <0 if KO
236
     */
237
    public function createFromClone(User $user, $fromid)
238
    {
239
        global $langs, $extrafields;
240
        $error = 0;
241
242
        dol_syslog(__METHOD__, LOG_DEBUG);
243
244
        $object = new self($this->db);
245
246
        $this->db->begin();
247
248
        // Load source object
249
        $result = $object->fetchCommon($fromid);
250
        if ($result > 0 && !empty($object->table_element_line)) {
251
            $object->fetchLines();
252
        }
253
254
        // get lines so they will be clone
255
        //foreach($this->lines as $line)
256
        //  $line->fetch_optionals();
257
258
        // Reset some properties
259
        unset($object->id);
260
        unset($object->fk_user_creat);
261
        unset($object->import_key);
262
263
        // Clear fields
264
        if (property_exists($object, 'ref')) {
265
            $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_" . $object->ref : $this->fields['ref']['default'];
266
        }
267
        if (property_exists($object, 'label')) {
268
            $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf") . " " . $object->label : $this->fields['label']['default'];
269
        }
270
        if (property_exists($object, 'status')) {
271
            $object->status = self::STATUS_DRAFT;
272
        }
273
        if (property_exists($object, 'date_creation')) {
274
            $object->date_creation = dol_now();
275
        }
276
        if (property_exists($object, 'date_modification')) {
277
            $object->date_modification = null;
278
        }
279
        // ...
280
        // Clear extrafields that are unique
281
        if (is_array($object->array_options) && count($object->array_options) > 0) {
282
            $extrafields->fetch_name_optionals_label($this->table_element);
283
            foreach ($object->array_options as $key => $option) {
284
                $shortkey = preg_replace('/options_/', '', $key);
285
                if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
286
                    //var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
287
                    unset($object->array_options[$key]);
288
                }
289
            }
290
        }
291
292
        // Create clone
293
        $object->context['createfromclone'] = 'createfromclone';
294
        $result = $object->createCommon($user);
295
        if ($result < 0) {
296
            $error++;
297
            $this->setErrorsFromObject($object);
298
        }
299
300
        if (!$error) {
301
            // copy internal contacts
302
            if ($this->copy_linked_contact($object, 'internal') < 0) {
303
                $error++;
304
            }
305
        }
306
307
        if (!$error) {
308
            // copy external contacts if same company
309
            if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
310
                if ($this->copy_linked_contact($object, 'external') < 0) {
311
                    $error++;
312
                }
313
            }
314
        }
315
316
        unset($object->context['createfromclone']);
317
318
        // End
319
        if (!$error) {
320
            $this->db->commit();
321
            return $object;
322
        } else {
323
            $this->db->rollback();
324
            return -1;
325
        }
326
    }
327
328
    /**
329
     * Load object in memory from the database
330
     *
331
     * @param int    $id   Id object
332
     * @param string $ref  Ref
333
     * @return int         Return integer <0 if KO, 0 if not found, >0 if OK
334
     */
335
    public function fetch($id, $ref = null)
336
    {
337
        $result = $this->fetchCommon($id, $ref);
338
        if ($result > 0 && !empty($this->table_element_line)) {
339
            $this->fetchLines();
340
        }
341
        return $result;
342
    }
343
344
    /**
345
     * Load object lines in memory from the database
346
     *
347
     * @return int         Return integer <0 if KO, 0 if not found, >0 if OK
348
     */
349
    public function fetchLines()
350
    {
351
        $this->lines = array();
352
353
        $result = $this->fetchLinesCommon();
354
        return $result;
355
    }
356
357
358
    /**
359
     * Load list of objects in memory from the database.
360
     *
361
     * @param  string       $sortorder      Sort Order
362
     * @param  string       $sortfield      Sort field
363
     * @param  int          $limit          limit
364
     * @param  int          $offset         Offset
365
     * @param  string       $filter         Filter as an Universal Search string.
366
     *                                      Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')'
367
     * @param  string       $filtermode     No more used
368
     * @return array|int                    int <0 if KO, array of pages if OK
369
     */
370
    public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
371
    {
372
        global $conf;
373
374
        dol_syslog(__METHOD__, LOG_DEBUG);
375
376
        $records = array();
377
378
        $sql = 'SELECT ';
379
        $sql .= $this->getFieldList('t');
380
        $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
381
        if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
382
            $sql .= ' WHERE t.entity IN (' . getEntity($this->element) . ')';
383
        } else {
384
            $sql .= ' WHERE 1 = 1';
385
        }
386
387
        // Manage filter
388
        $errormessage = '';
389
        $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
390
        if ($errormessage) {
391
            $this->errors[] = $errormessage;
392
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
393
            return -1;
394
        }
395
396
        if (!empty($sortfield)) {
397
            $sql .= $this->db->order($sortfield, $sortorder);
398
        }
399
        if (!empty($limit)) {
400
            $sql .= ' ' . $this->db->plimit($limit, $offset);
401
        }
402
403
        $resql = $this->db->query($sql);
404
        if ($resql) {
405
            $num = $this->db->num_rows($resql);
406
            $i = 0;
407
            while ($i < ($limit ? min($limit, $num) : $num)) {
408
                $obj = $this->db->fetch_object($resql);
409
410
                $record = new self($this->db);
411
                $record->setVarsFromFetchObj($obj);
412
413
                $records[$record->id] = $record;
414
415
                $i++;
416
            }
417
            $this->db->free($resql);
418
419
            return $records;
420
        } else {
421
            $this->errors[] = 'Error ' . $this->db->lasterror();
422
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
423
424
            return -1;
425
        }
426
    }
427
428
    /**
429
     * Update object into database
430
     *
431
     * @param  User $user      User that modifies
432
     * @param  int  $notrigger 0=launch triggers after, 1=disable triggers
433
     * @return int             Return integer <0 if KO, >0 if OK
434
     */
435
    public function update(User $user, $notrigger = 0)
436
    {
437
        return $this->updateCommon($user, $notrigger);
438
    }
439
440
    /**
441
     * Delete object in database
442
     *
443
     * @param User  $user       User that deletes
444
     * @param int   $notrigger  0=launch triggers after, 1=disable triggers
445
     * @return int              Return integer <0 if KO, >0 if OK
446
     */
447
    public function delete(User $user, $notrigger = 0)
448
    {
449
        if ($this->fk_rank) {
450
            $skillRank = new SkillRank($this->db);
451
            $skillRank->fetch($this->fk_rank);
452
            $skillRank->delete($user, $notrigger);
453
        }
454
        return $this->deleteCommon($user, $notrigger);
455
        //return $this->deleteCommon($user, $notrigger, 1);
456
    }
457
458
    /**
459
     *  Delete a line of object in database
460
     *
461
     *  @param  User    $user       User that delete
462
     *  @param  int     $idline     Id of line to delete
463
     *  @param  int     $notrigger  0=launch triggers after, 1=disable triggers
464
     *  @return int                 >0 if OK, <0 if KO
465
     */
466
    public function deleteLine(User $user, $idline, $notrigger = 0)
467
    {
468
        if ($this->status < 0) {
469
            $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
470
            return -2;
471
        }
472
473
        return $this->deleteLineCommon($user, $idline, $notrigger);
474
    }
475
476
477
    /**
478
     *  Validate object
479
     *
480
     *  @param      User    $user           User making status change
481
     *  @param      int     $notrigger      1=Does not execute triggers, 0= execute triggers
482
     *  @return     int                     Return integer <=0 if OK, 0=Nothing done, >0 if KO
483
     */
484
    public function validate($user, $notrigger = 0)
485
    {
486
        global $conf, $langs;
487
488
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
489
490
        $error = 0;
491
492
        // Protection
493
        if ($this->status == self::STATUS_VALIDATED) {
494
            dol_syslog(get_class($this) . "::validate action abandoned: already validated", LOG_WARNING);
495
            return 0;
496
        }
497
498
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->evaluationdet->write))
499
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->evaluationdet->evaluationdet_advance->validate))))
500
         {
501
         $this->error='NotEnoughPermissions';
502
         dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
503
         return -1;
504
         }*/
505
506
        $now = dol_now();
507
508
        $this->db->begin();
509
510
        // Define new ref
511
        if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
512
            $num = $this->getNextNumRef();
513
        } else {
514
            $num = $this->ref;
515
        }
516
        $this->newref = $num;
517
518
        if (!empty($num)) {
519
            // Validate
520
            $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
521
            $sql .= " SET ref = '" . $this->db->escape($num) . "',";
522
            $sql .= " status = " . self::STATUS_VALIDATED;
523
            if (!empty($this->fields['date_validation'])) {
524
                $sql .= ", date_validation = '" . $this->db->idate($now) . "'";
525
            }
526
            if (!empty($this->fields['fk_user_valid'])) {
527
                $sql .= ", fk_user_valid = " . ((int) $user->id);
528
            }
529
            $sql .= " WHERE rowid = " . ((int) $this->id);
530
531
            dol_syslog(get_class($this) . "::validate()", LOG_DEBUG);
532
            $resql = $this->db->query($sql);
533
            if (!$resql) {
534
                dol_print_error($this->db);
535
                $this->error = $this->db->lasterror();
536
                $error++;
537
            }
538
539
            if (!$error && !$notrigger) {
540
                // Call trigger
541
                $result = $this->call_trigger('HRM_EVALUATIONLINE_VALIDATE', $user);
542
                if ($result < 0) {
543
                    $error++;
544
                }
545
                // End call triggers
546
            }
547
        }
548
549
        if (!$error) {
550
            $this->oldref = $this->ref;
551
552
            // Rename directory if dir was a temporary ref
553
            if (preg_match('/^[\(]?PROV/i', $this->ref)) {
554
                // Now we rename also files into index
555
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filename = CONCAT('" . $this->db->escape($this->newref) . "', SUBSTR(filename, " . (strlen($this->ref) + 1) . ")), filepath = 'evaluationline/" . $this->db->escape($this->newref) . "'";
556
                $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'evaluationline/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
557
                $resql = $this->db->query($sql);
558
                if (!$resql) {
559
                    $error++;
560
                    $this->error = $this->db->lasterror();
561
                }
562
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'evaluationline/" . $this->db->escape($this->newref) . "'";
563
                $sql .= " WHERE filepath = 'evaluationline/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
564
                $resql = $this->db->query($sql);
565
                if (!$resql) {
566
                    $error++;
567
                    $this->error = $this->db->lasterror();
568
                }
569
570
                // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
571
                $oldref = dol_sanitizeFileName($this->ref);
572
                $newref = dol_sanitizeFileName($num);
573
                $dirsource = $conf->hrm->dir_output . '/evaluationline/' . $oldref;
574
                $dirdest = $conf->hrm->dir_output . '/evaluationline/' . $newref;
575
                if (!$error && file_exists($dirsource)) {
576
                    dol_syslog(get_class($this) . "::validate() rename dir " . $dirsource . " into " . $dirdest);
577
578
                    if (@rename($dirsource, $dirdest)) {
579
                        dol_syslog("Rename ok");
580
                        // Rename docs starting with $oldref with $newref
581
                        $listoffiles = dol_dir_list($conf->hrm->dir_output . '/evaluationline/' . $newref, 'files', 1, '^' . preg_quote($oldref, '/'));
582
                        foreach ($listoffiles as $fileentry) {
583
                            $dirsource = $fileentry['name'];
584
                            $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
585
                            $dirsource = $fileentry['path'] . '/' . $dirsource;
586
                            $dirdest = $fileentry['path'] . '/' . $dirdest;
587
                            @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

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