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

Position   F

Complexity

Total Complexity 157

Size/Duplication

Total Lines 1079
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 420
dl 0
loc 1079
rs 2
c 1
b 0
f 0
wmc 157

25 Methods

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

How to fix   Complexity   

Complex Class

Complex classes like Position 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 Position, 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\CommonObject;
29
30
/**
31
 * \file        class/position.class.php
32
 * \ingroup     hrm
33
 * \brief       This file is a CRUD class file for Position (Create/Read/Update/Delete)
34
 */
35
36
// Put here all includes required by your class file
37
38
/**
39
 * Class for Position
40
 */
41
class Position extends CommonObject
42
{
43
    /**
44
     * @var string ID of module.
45
     */
46
    public $module = 'hrm';
47
48
    /**
49
     * @var string ID to identify managed object.
50
     */
51
    public $element = 'position';
52
53
    /**
54
     * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
55
     */
56
    public $table_element = 'hrm_job_user';
57
58
    /**
59
     * @var string String with name of icon for position. Must be the part after the 'object_' into object_position.png
60
     */
61
    public $picto = 'user-cog';
62
63
64
    const STATUS_DRAFT = 0;
65
    const STATUS_VALIDATED = 1;
66
    const STATUS_CANCELED = 9;
67
68
69
    /**
70
     *  'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', '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')
71
     *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
72
     *  'label' the translation key.
73
     *  'picto' is code of a picto to show before value in forms
74
     *  'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalString("MY_SETUP_PARAM")')
75
     *  'position' is the sort order of field.
76
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
77
     *  'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
78
     *  'noteditable' says if field is not editable (1 or 0)
79
     *  'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
80
     *  'index' if we want an index in database.
81
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
82
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
83
     *  'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
84
     *  'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200'
85
     *  'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
86
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
87
     *  'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
88
     *  'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar'
89
     *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
90
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
91
     *
92
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
93
     */
94
95
    // BEGIN MODULEBUILDER PROPERTIES
96
    /**
97
     * @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...
98
     */
99
    public $fields = array(
100
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 2, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
101
        //'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"),
102
        'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2,),
103
        'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2,),
104
        'fk_contrat' => array('type' => 'integer:Contrat:contrat/class/contrat.class.php', 'label' => 'fk_contrat', 'enabled' => 'isModEnabled("contract")', 'position' => 50, 'notnull' => 0, 'visible' => 0,),
105
        'fk_user' => array('type' => 'integer:User:user/class/user.class.php:0:(t.statut:=:1)', 'label' => 'Employee', 'enabled' => 1, 'position' => 55, 'notnull' => 1, 'visible' => 1, 'default' => '0', 'picto' => 'user', 'css' => 'maxwidth300 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150'),
106
        'fk_job' => array('type' => 'integer:Job:/hrm/class/job.class.php', 'label' => 'JobProfile', 'enabled' => 1, 'position' => 56, 'notnull' => 1, 'visible' => 1, 'picto' => 'jobprofile', 'css' => 'maxwidth300 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150'),
107
        'date_start' => array('type' => 'date', 'label' => 'DateStart', 'enabled' => 1, 'position' => 101, 'notnull' => 1, 'visible' => 1,),
108
        'date_end' => array('type' => 'date', 'label' => 'DateEnd', 'enabled' => 1, 'position' => 102, 'notnull' => 0, 'visible' => 1,),
109
        'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'position' => 120, 'notnull' => 0, 'visible' => 3,),
110
        'abort_comment' => array('type' => 'varchar(255)', 'label' => 'AbandonmentComment', 'enabled' => 'getDolGlobalInt("HRM_JOB_POSITON_ENDING_COMMENT")', 'position' => 502, 'notnull' => 0, 'visible' => 1,),
111
        'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 151, 'notnull' => 0, 'visible' => 0,),
112
        'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 152, 'notnull' => 0, 'visible' => 0,),
113
        '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',),
114
        'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
115
    );
116
    public $rowid;
117
    public $ref;
118
    public $description;
119
    public $date_creation;
120
    public $fk_contrat;
121
    public $fk_user;
122
    public $fk_job;
123
    public $date_start;
124
    public $date_end;
125
    public $abort_comment;
126
    public $note_public;
127
    public $note_private;
128
    public $fk_user_creat;
129
    public $fk_user_modif;
130
131
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_job_userline';
141
142
    // /**
143
    //  * @var string    Field with ID of parent key if this object has a parent
144
    //  */
145
    // public $fk_element = 'fk_position';
146
147
    // /**
148
    //  * @var string    Name of subtable class that manage subtable lines
149
    //  */
150
    // public $class_element_line = 'Positionline';
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_job_userdet');
163
164
    // /**
165
    //  * @var PositionLine[]     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 = 0;
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->position->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
        //$resultvalidate = $this->validate($user, $notrigger);
228
229
        return $resultcreate;
230
    }
231
232
    /**
233
     * Clone an object into another one
234
     *
235
     * @param User $user User that creates
236
     * @param int $fromid Id of object to clone
237
     * @return    mixed                New object created, <0 if KO
238
     */
239
    public function createFromClone(User $user, $fromid)
240
    {
241
        global $langs, $extrafields;
242
        $error = 0;
243
244
        dol_syslog(__METHOD__, LOG_DEBUG);
245
246
        $object = new self($this->db);
247
248
        $this->db->begin();
249
250
        // Load source object
251
        $result = $object->fetchCommon($fromid);
252
        if ($result > 0 && !empty($object->table_element_line)) {
253
            $object->fetchLines();
254
        }
255
256
        // get lines so they will be clone
257
        //foreach($this->lines as $line)
258
        //  $line->fetch_optionals();
259
260
        // Reset some properties
261
        unset($object->id);
262
        unset($object->fk_user_creat);
263
        unset($object->import_key);
264
265
        // Clear fields
266
        if (property_exists($object, 'ref')) {
267
            $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_" . $object->ref : $this->fields['ref']['default'];
268
        }
269
        if (property_exists($object, 'label')) {
270
            $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf") . " " . $object->label : $this->fields['label']['default'];
271
        }
272
        if (property_exists($object, 'status')) {
273
            $object->status = self::STATUS_DRAFT;
274
        }
275
        if (property_exists($object, 'date_creation')) {
276
            $object->date_creation = dol_now();
277
        }
278
        if (property_exists($object, 'date_modification')) {
279
            $object->date_modification = null;
280
        }
281
        // ...
282
        // Clear extrafields that are unique
283
        if (is_array($object->array_options) && count($object->array_options) > 0) {
284
            $extrafields->fetch_name_optionals_label($this->table_element);
285
            foreach ($object->array_options as $key => $option) {
286
                $shortkey = preg_replace('/options_/', '', $key);
287
                if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
288
                    //var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
289
                    unset($object->array_options[$key]);
290
                }
291
            }
292
        }
293
294
        // Create clone
295
        $object->context['createfromclone'] = 'createfromclone';
296
        $result = $object->createCommon($user);
297
        if ($result < 0) {
298
            $error++;
299
            $this->setErrorsFromObject($object);
300
        }
301
302
        if (!$error) {
303
            // copy internal contacts
304
            if ($this->copy_linked_contact($object, 'internal') < 0) {
305
                $error++;
306
            }
307
        }
308
309
        if (!$error) {
310
            // copy external contacts if same company
311
            if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
312
                if ($this->copy_linked_contact($object, 'external') < 0) {
313
                    $error++;
314
                }
315
            }
316
        }
317
318
        unset($object->context['createfromclone']);
319
320
        // End
321
        if (!$error) {
322
            $this->db->commit();
323
            return $object;
324
        } else {
325
            $this->db->rollback();
326
            return -1;
327
        }
328
    }
329
330
    /**
331
     * Load object in memory from the database
332
     *
333
     * @param int $id Id object
334
     * @param string $ref Ref
335
     * @return int         Return integer <0 if KO, 0 if not found, >0 if OK
336
     */
337
    public function fetch($id, $ref = null)
338
    {
339
        $result = $this->fetchCommon($id, $ref);
340
        if ($result > 0 && !empty($this->table_element_line)) {
341
            $this->fetchLines();
342
        }
343
        return $result;
344
    }
345
346
    /**
347
     * Load object lines in memory from the database
348
     *
349
     * @return int         Return integer <0 if KO, 0 if not found, >0 if OK
350
     */
351
    public function fetchLines()
352
    {
353
        $this->lines = array();
354
355
        $result = $this->fetchLinesCommon();
356
        return $result;
357
    }
358
359
360
    /**
361
     * Load list of objects in memory from the database.
362
     *
363
     * @param   string      $sortorder      Sort Order
364
     * @param   string      $sortfield      Sort field
365
     * @param   int         $limit          limit
366
     * @param   int         $offset         Offset
367
     * @param   string      $filter         Filter as an Universal Search string.
368
     *                                      Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')'
369
     * @param   string      $filtermode     No more used
370
     * @return  array|int                   int <0 if KO, array of pages if OK
371
     */
372
    public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
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
        return $this->deleteCommon($user, $notrigger);
450
        //return $this->deleteCommon($user, $notrigger, 1);
451
    }
452
453
    /**
454
     *  Delete a line of object in database
455
     *
456
     * @param User  $user       User that delete
457
     * @param int   $idline     Id of line to delete
458
     * @param int   $notrigger  0=launch triggers after, 1=disable triggers
459
     * @return int              Return >0 if OK, <0 if KO
460
     */
461
    public function deleteLine(User $user, $idline, $notrigger = 0)
462
    {
463
        if ($this->status < 0) {
464
            $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
465
            return -2;
466
        }
467
468
        return $this->deleteLineCommon($user, $idline, $notrigger);
469
    }
470
471
472
    /**
473
     *    Validate object
474
     *
475
     * @param User $user User making status change
476
     * @param int $notrigger 1=Does not execute triggers, 0= execute triggers
477
     * @return    int                        Return integer <=0 if OK, 0=Nothing done, >0 if KO
478
     */
479
    public function validate($user, $notrigger = 0)
480
    {
481
        global $conf, $langs;
482
483
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
484
485
        $error = 0;
486
487
        // Protection
488
        if ($this->status == self::STATUS_VALIDATED) {
489
            dol_syslog(get_class($this) . "::validate action abandoned: already validated", LOG_WARNING);
490
            return 0;
491
        }
492
493
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->position->write))
494
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->position->position_advance->validate))))
495
         {
496
         $this->error='NotEnoughPermissions';
497
         dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
498
         return -1;
499
         }*/
500
501
        $now = dol_now();
502
503
        $this->db->begin();
504
505
        // Define new ref
506
        if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
507
            $num = $this->getNextNumRef();
508
        } else {
509
            $num = $this->ref;
510
        }
511
        $this->newref = $num;
512
513
        if (!empty($num)) {
514
            // Validate
515
            $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
516
            $sql .= " SET ref = '" . $this->db->escape($num) . "',";
517
            $sql .= " status = " . self::STATUS_VALIDATED;
518
            if (!empty($this->fields['date_validation'])) {
519
                $sql .= ", date_validation = '" . $this->db->idate($now) . "'";
520
            }
521
            if (!empty($this->fields['fk_user_valid'])) {
522
                $sql .= ", fk_user_valid = " . ((int) $user->id);
523
            }
524
            $sql .= " WHERE rowid = " . ((int) $this->id);
525
526
            dol_syslog(get_class($this) . "::validate()", LOG_DEBUG);
527
            $resql = $this->db->query($sql);
528
            if (!$resql) {
529
                dol_print_error($this->db);
530
                $this->error = $this->db->lasterror();
531
                $error++;
532
            }
533
534
            if (!$error && !$notrigger) {
535
                // Call trigger
536
                $result = $this->call_trigger('HRM_POSITION_VALIDATE', $user);
537
                if ($result < 0) {
538
                    $error++;
539
                }
540
                // End call triggers
541
            }
542
        }
543
544
        if (!$error) {
545
            $this->oldref = $this->ref;
546
547
            // Rename directory if dir was a temporary ref
548
            if (preg_match('/^[\(]?PROV/i', $this->ref)) {
549
                // Now we rename also files into index
550
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filename = CONCAT('" . $this->db->escape($this->newref) . "', SUBSTR(filename, " . (strlen($this->ref) + 1) . ")), filepath = 'position/" . $this->db->escape($this->newref) . "'";
551
                $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'position/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
552
                $resql = $this->db->query($sql);
553
                if (!$resql) {
554
                    $error++;
555
                    $this->error = $this->db->lasterror();
556
                }
557
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'position/" . $this->db->escape($this->newref) . "'";
558
                $sql .= " WHERE filepath = 'position/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
559
                $resql = $this->db->query($sql);
560
                if (!$resql) {
561
                    $error++;
562
                    $this->error = $this->db->lasterror();
563
                }
564
565
                // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
566
                $oldref = dol_sanitizeFileName($this->ref);
567
                $newref = dol_sanitizeFileName($num);
568
                $dirsource = $conf->hrm->dir_output . '/position/' . $oldref;
569
                $dirdest = $conf->hrm->dir_output . '/position/' . $newref;
570
                if (!$error && file_exists($dirsource)) {
571
                    dol_syslog(get_class($this) . "::validate() rename dir " . $dirsource . " into " . $dirdest);
572
573
                    if (@rename($dirsource, $dirdest)) {
574
                        dol_syslog("Rename ok");
575
                        // Rename docs starting with $oldref with $newref
576
                        $listoffiles = dol_dir_list($conf->hrm->dir_output . '/position/' . $newref, 'files', 1, '^' . preg_quote($oldref, '/'));
577
                        foreach ($listoffiles as $fileentry) {
578
                            $dirsource = $fileentry['name'];
579
                            $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
580
                            $dirsource = $fileentry['path'] . '/' . $dirsource;
581
                            $dirdest = $fileentry['path'] . '/' . $dirdest;
582
                            @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

582
                            /** @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...
583
                        }
584
                    }
585
                }
586
            }
587
        }
588
589
        // Set new ref and current status
590
        if (!$error) {
591
            $this->ref = $num;
592
            $this->status = self::STATUS_VALIDATED;
593
        }
594
595
        if (!$error) {
596
            $this->db->commit();
597
            return 1;
598
        } else {
599
            $this->db->rollback();
600
            return -1;
601
        }
602
    }
603
604
605
    /**
606
     *    Set draft status
607
     *
608
     * @param User $user Object user that modify
609
     * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
610
     * @return    int                        Return integer <0 if KO, >0 if OK
611
     */
612
    public function setDraft($user, $notrigger = 0)
613
    {
614
        // Protection
615
        if ($this->status <= self::STATUS_DRAFT) {
616
            return 0;
617
        }
618
619
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->write))
620
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->hrm_advance->validate))))
621
         {
622
         $this->error='Permission denied';
623
         return -1;
624
         }*/
625
626
        return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'POSITION_UNVALIDATE');
627
    }
628
629
    /**
630
     *    Set cancel status
631
     *
632
     * @param User $user Object user that modify
633
     * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
634
     * @return    int                        Return integer <0 if KO, 0=Nothing done, >0 if OK
635
     */
636
    public function cancel($user, $notrigger = 0)
637
    {
638
        // Protection
639
        if ($this->status != self::STATUS_VALIDATED) {
640
            return 0;
641
        }
642
643
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->write))
644
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->hrm_advance->validate))))
645
         {
646
         $this->error='Permission denied';
647
         return -1;
648
         }*/
649
650
        return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'POSITION_CANCEL');
651
    }
652
653
    /**
654
     *    Set back to validated status
655
     *
656
     * @param User $user Object user that modify
657
     * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
658
     * @return    int                        Return integer <0 if KO, 0=Nothing done, >0 if OK
659
     */
660
    public function reopen($user, $notrigger = 0)
661
    {
662
        // Protection
663
        if ($this->status != self::STATUS_CANCELED) {
664
            return 0;
665
        }
666
667
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->write))
668
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->hrm_advance->validate))))
669
         {
670
         $this->error='Permission denied';
671
         return -1;
672
         }*/
673
674
        return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'POSITION_REOPEN');
675
    }
676
677
    /**
678
     *  Return a link to the object card (with optionally the picto)
679
     *
680
     * @param   int         $withpicto              Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
681
     * @param   string      $option                 On what the link point to ('nolink', ...)
682
     * @param   int         $notooltip              1=Disable tooltip
683
     * @param   string      $morecss                Add more css on link
684
     * @param   int         $save_lastsearch_value  -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
685
     * @return  string                              String with URL
686
     */
687
    public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
688
    {
689
        global $conf, $langs, $hookmanager;
690
691
        if (!empty($conf->dol_no_mouse_hover)) {
692
            $notooltip = 1; // Force disable tooltips
693
        }
694
695
        $result = '';
696
697
        $label = img_picto('', $this->picto) . ' <u>' . $langs->trans("Position") . '</u>';
698
        if (isset($this->status)) {
699
            $label .= ' ' . $this->getLibStatut(5);
700
        }
701
        $label .= '<br>';
702
        $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
703
704
        $url = dol_buildpath('/hrm/position_card.php', 1) . '?id=' . $this->id;
705
706
        if ($option != 'nolink') {
707
            // Add param to save lastsearch_values or not
708
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
709
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
710
                $add_save_lastsearch_values = 1;
711
            }
712
            if ($add_save_lastsearch_values) {
713
                $url .= '&save_lastsearch_values=1';
714
            }
715
        }
716
717
        $linkclose = '';
718
        if (empty($notooltip)) {
719
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
720
                $label = $langs->trans("ShowPosition");
721
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
722
            }
723
            $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
724
            $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
725
        } else {
726
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
727
        }
728
729
        if ($option == 'nolink') {
730
            $linkstart = '<span';
731
        } else {
732
            $linkstart = '<a href="' . $url . '"';
733
        }
734
        $linkstart .= $linkclose . '>';
735
        if ($option == 'nolink') {
736
            $linkend = '</span>';
737
        } else {
738
            $linkend = '</a>';
739
        }
740
741
        $result .= $linkstart;
742
743
        if (empty($this->showphoto_on_popup)) {
744
            if ($withpicto) {
745
                $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);
746
            }
747
        } else {
748
            if ($withpicto) {
749
                require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
750
751
                list($class, $module) = explode('@', $this->picto);
752
                $upload_dir = $conf->$module->multidir_output[$conf->entity] . "/$class/" . dol_sanitizeFileName($this->ref);
753
                $filearray = dol_dir_list($upload_dir, "files");
754
                $filename = $filearray[0]['name'];
755
                if (!empty($filename)) {
756
                    $pospoint = strpos($filearray[0]['name'], '.');
757
758
                    $pathtophoto = $class . '/' . $this->ref . '/thumbs/' . substr($filename, 0, $pospoint) . '_mini' . substr($filename, $pospoint);
759
                    if (!getDolGlobalString(strtoupper($module . '_' . $class) . '_FORMATLISTPHOTOSASUSERS')) {
760
                        $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>';
761
                    } else {
762
                        $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>';
763
                    }
764
765
                    $result .= '</div>';
766
                } else {
767
                    $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);
768
                }
769
            }
770
        }
771
772
        if ($withpicto != 2) {
773
            $result .= $this->ref;
774
        }
775
776
        $result .= $linkend;
777
        //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
778
779
        global $action, $hookmanager;
780
        $hookmanager->initHooks(array('positiondao'));
781
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
782
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
783
        if ($reshook > 0) {
784
            $result = $hookmanager->resPrint;
785
        } else {
786
            $result .= $hookmanager->resPrint;
787
        }
788
789
        return $result;
790
    }
791
792
    /**
793
     *  Return the label of the status
794
     *
795
     * @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
796
     * @return    string                   Label of status
797
     */
798
    public function getLibStatut($mode = 0)
799
    {
800
        return $this->LibStatut($this->status, $mode);
801
    }
802
803
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
804
805
    /**
806
     *  Return the status
807
     *
808
     * @param int $status Id status
809
     * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
810
     * @return string                   Label of status
811
     */
812
    public function LibStatut($status, $mode = 0)
813
    {
814
		// phpcs:enable
815
        if (is_null($status)) {
816
            return '';
817
        }
818
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
     * Return HTML string to put an input field into a page
841
     * Code very similar with showInputField of extra fields
842
     *
843
     * @param ?array{type:string,label:string,enabled:int|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}   $val    Array of properties for field to show
844
     * @param  string       $key           Key of attribute
845
     * @param  string       $value         Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value)
846
     * @param  string       $moreparam     To add more parameters on html input tag
847
     * @param  string       $keysuffix     Prefix string to add into name and id of field (can be used to avoid duplicate names)
848
     * @param  string       $keyprefix     Suffix string to add into name and id of field (can be used to avoid duplicate names)
849
     * @param  string|int   $morecss       Value for css to define style/length of field. May also be a numeric.
850
     * @param  int<0,1>     $nonewbutton   Do not show new button
851
     * @return string
852
     */
853
    public function showInputField($val, $key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = 0, $nonewbutton = 0)
854
    {
855
        global $langs;
856
857
        if ($key == 'fk_user') {
858
            $vacantId = $keyprefix . $key . 'vacant' . $keysuffix;
859
860
            $out = parent::showInputField($val, $key, $value, $moreparam, $keysuffix, $keyprefix, $morecss);
861
            $out .= '<label class="nowrap position-fk-user classfortooltip" title="' . dol_escape_js($langs->trans('VacantCheckboxHelper')) . '"><input type="checkbox" id="' . $vacantId . '" name="' . $vacantId . '">&nbsp;' . $langs->trans("Vacant") . '</label>'; ?>
862
            <script type="text/javascript">
863
                $(document).ready(function () {
864
                    var checkbox = $('#<?php print $vacantId; ?>');
865
                    var searchfkuser = $('#<?php print $keyprefix . $key . $keysuffix; ?>');
866
                    checkbox.click(function () {
867
                        if (checkbox.prop('checked')) {
868
                            searchfkuser.val(0).trigger('change');
869
                            searchfkuser.prop('disabled', 1);
870
                        } else {
871
                            searchfkuser.prop('disabled', 0);
872
                        }
873
                    });
874
                });
875
            </script>
876
            <?php
877
        } else {
878
            $out = parent::showInputField($val, $key, $value, $moreparam, $keysuffix, $keyprefix, $morecss);
879
        }
880
881
        return $out;
882
    }
883
884
    /**
885
     * Return HTML string to show a field into a page
886
     * Code very similar with showOutputField of extra fields
887
     *
888
     * @param  array   $val            Array of properties of field to show
889
     * @param  string  $key            Key of attribute
890
     * @param  string  $value          Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value)
891
     * @param  string  $moreparam      To add more parameters on html input tag
892
     * @param  string  $keysuffix      Prefix string to add into name and id of field (can be used to avoid duplicate names)
893
     * @param  string  $keyprefix      Suffix string to add into name and id of field (can be used to avoid duplicate names)
894
     * @param  mixed   $morecss        Value for css to define size. May also be a numeric.
895
     * @return string
896
     */
897
    public function showOutputField($val, $key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = '')
898
    {
899
        global $langs;
900
901
        if ($key == 'fk_user' && $this->fk_user == 0) {
902
            return $langs->trans("VacantPosition");
903
        }
904
        return parent::showOutputField($val, $key, $value, $moreparam, $keysuffix, $keyprefix, $morecss);
905
    }
906
907
908
    /**
909
     *    Load the info information in the object
910
     *
911
     * @param int $id Id of object
912
     * @return    void
913
     */
914
    public function info($id)
915
    {
916
        $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
917
        $sql .= ' fk_user_creat, fk_user_modif';
918
        $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
919
        $sql .= ' WHERE t.rowid = ' . ((int) $id);
920
        $result = $this->db->query($sql);
921
        if ($result) {
922
            if ($this->db->num_rows($result)) {
923
                $obj = $this->db->fetch_object($result);
924
925
                $this->id = $obj->rowid;
926
927
                $this->user_creation_id = $obj->fk_user_creat;
928
                $this->user_modification_id = $obj->fk_user_modif;
929
                $this->date_creation     = $this->db->jdate($obj->datec);
930
                $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
931
            }
932
933
            $this->db->free($result);
934
        } else {
935
            dol_print_error($this->db);
936
        }
937
    }
938
939
    /**
940
     * Initialise object with example values
941
     * Id must be 0 if object instance is a specimen
942
     *
943
     * @return int
944
     */
945
    public function initAsSpecimen()
946
    {
947
        // Set here init that are not commonf fields
948
        // $this->property1 = ...
949
        // $this->property2 = ...
950
951
        return $this->initAsSpecimenCommon();
952
    }
953
954
    /**
955
     *    Create an array of lines
956
     *
957
     * @return array|int        array of lines if OK, <0 if KO
958
     */
959
    public function getLinesArray()
960
    {
961
        $this->lines = array();
962
963
        $objectline = new PositionLine($this->db);
964
        $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_position:=:' . ((int) $this->id) . ')');
965
966
        if (is_numeric($result)) {
967
            $this->setErrorsFromObject($objectline);
968
            return $result;
969
        } else {
970
            $this->lines = $result;
971
            return $this->lines;
972
        }
973
    }
974
975
    /**
976
     *  Returns the reference to the following non used object depending on the active numbering module.
977
     *
978
     * @return string            Object free reference
979
     */
980
    public function getNextNumRef()
981
    {
982
        global $langs, $conf;
983
        $langs->load("hrm");
984
985
        if (!getDolGlobalString('hrm_POSITION_ADDON')) {
986
            $conf->global->hrm_POSITION_ADDON = 'mod_position_standard';
987
        }
988
989
        if (getDolGlobalString('hrm_POSITION_ADDON')) {
990
            $mybool = false;
991
992
            $file = getDolGlobalString('hrm_POSITION_ADDON') . ".php";
993
            $classname = getDolGlobalString('hrm_POSITION_ADDON');
994
995
            // Include file with class
996
            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
997
            foreach ($dirmodels as $reldir) {
998
                $dir = dol_buildpath($reldir . "core/modules/hrm/");
999
1000
                // Load file with numbering class (if found)
1001
                $mybool = ((bool) @include_once $dir . $file) || $mybool;
1002
            }
1003
1004
            if ($mybool === false) {
1005
                dol_print_error(null, "Failed to include file " . $file);
1006
                return '';
1007
            }
1008
1009
            if (class_exists($classname)) {
1010
                $obj = new $classname();
1011
                $numref = $obj->getNextValue($this);
1012
1013
                if ($numref != '' && $numref != '-1') {
1014
                    return $numref;
1015
                } else {
1016
                    $this->error = $obj->error;
1017
                    //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1018
                    return "";
1019
                }
1020
            } else {
1021
                print $langs->trans("Error") . " " . $langs->trans("ClassNotFound") . ' ' . $classname;
1022
                return "";
1023
            }
1024
        } else {
1025
            print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1026
            return "";
1027
        }
1028
    }
1029
1030
    /**
1031
     * getForUser
1032
     *
1033
     * @param int $userid id of user we need to get position list
1034
     * @return array|int of positions of user with for each of them the job fetched into that array
1035
     */
1036
    public function getForUser($userid)
1037
    {
1038
        $TPosition = array();
1039
1040
        $TPosition = $this->fetchAll('ASC', 't.rowid', 0, 0, '(fk_user:=:' . ((int) $userid) . ')');
1041
1042
        return $TPosition;
1043
    }
1044
1045
    /**
1046
     * Create a document onto disk according to template module.
1047
     *
1048
     * @param string $modele Force template to use ('' to not force)
1049
     * @param Translate $outputlangs object lang a utiliser pour traduction
1050
     * @param int $hidedetails Hide details of lines
1051
     * @param int $hidedesc Hide description
1052
     * @param int $hideref Hide ref
1053
     * @param null|array $moreparams Array to provide more information
1054
     * @return     int                        0 if KO, 1 if OK
1055
     */
1056
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1057
    {
1058
        global $conf, $langs;
1059
1060
        $result = 0;
1061
        $includedocgeneration = 0;
1062
1063
        $langs->load("hrm");
1064
1065
        if (!dol_strlen($modele)) {
1066
            $modele = 'standard_position';
1067
1068
            if (!empty($this->model_pdf)) {
1069
                $modele = $this->model_pdf;
1070
            } elseif (getDolGlobalString('POSITION_ADDON_PDF')) {
1071
                $modele = getDolGlobalString('POSITION_ADDON_PDF');
1072
            }
1073
        }
1074
1075
        $modelpath = "core/modules/hrm/doc/";
1076
1077
        if ($includedocgeneration && !empty($modele)) {
1078
            $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1079
        }
1080
1081
        return $result;
1082
    }
1083
1084
    /**
1085
     *  Return clicable link of object (with eventually picto)
1086
     *
1087
     *  @param      string      $option                 Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
1088
     *  @param      array       $arraydata              Array of data
1089
     *  @return     string      HTML Code for Kanban thumb.
1090
     */
1091
    public function getKanbanView($option = '', $arraydata = null)
1092
    {
1093
        global $selected, $langs;
1094
1095
        $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1096
1097
        $return = '<div class="box-flex-item box-flex-grow-zero">';
1098
        $return .= '<div class="info-box info-box-sm">';
1099
        $return .= '<span class="info-box-icon bg-infobox-action">';
1100
        $return .= img_picto('', $this->picto);
1101
        $return .= '</span>';
1102
        $return .= '<div class="info-box-content">';
1103
        $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref) . '</span>';
1104
        $return .= '<input class="fright" id="cb' . $this->id . '" class="flat checkforselect" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
1105
        if (!empty($arraydata['user'])) {
1106
            $return .= '<br><span class="info-box-label ">' . $arraydata['user'] . '</span>';
1107
        }
1108
        if (!empty($arraydata['job'])) {
1109
            //$return .= '<br><span class="info-box-label opacitymedium">'.$langs->trans("JobProfile").'</span> : ';
1110
            $return .= '<br><span class="info-box-label ">' . $arraydata['job'] . '</span>';
1111
        }
1112
        if (property_exists($this, 'date_start') && property_exists($this, 'date_end')) {
1113
            $return .= '<br><div class ="nothing"><span class="info-box-label ">' . dol_print_date($this->db->jdate($this->date_start), 'day') . '</span>';
1114
            $return .= ' - <span class="info-box-label ">' . dol_print_date($this->db->jdate($this->date_end), 'day') . '</span></div>';
1115
        }
1116
        $return .= '</div>';
1117
        $return .= '</div>';
1118
        $return .= '</div>';
1119
        return $return;
1120
    }
1121
}
1122