Passed
Pull Request — dev (#8)
by Rafael
58:47
created

EvaluationLine::validate()   F

Complexity

Conditions 22
Paths 2801

Size

Total Lines 122
Code Lines 71

Duplication

Lines 0
Ratio 0 %

Importance

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

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