Passed
Branch develop (aaddda)
by
unknown
27:46
created

Workstation::createFromClone()   F

Complexity

Conditions 22
Paths 13824

Size

Total Lines 83
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 22
eloc 41
nc 13824
nop 2
dl 0
loc 83
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
/* Copyright (C) 2017  Laurent Destailleur <[email protected]>
3
 * Copyright (C) 2020 Gauthier VERDOL <[email protected]>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
 */
18
19
/**
20
 * \file        class/workstation.class.php
21
 * \ingroup     workstation
22
 * \brief       This file is a CRUD class file for Workstation (Create/Read/Update/Delete)
23
 */
24
25
// Put here all includes required by your class file
26
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
27
//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
28
//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
29
30
/**
31
 * Class for Workstation
32
 */
33
class Workstation extends CommonObject
34
{
35
	/**
36
	 * @var string ID of module.
37
	 */
38
	public $module = 'workstation';
39
40
	/**
41
	 * @var string ID to identify managed object.
42
	 */
43
	public $element = 'workstation';
44
45
	/**
46
	 * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
47
	 */
48
	public $table_element = 'workstation_workstation';
49
50
	/**
51
	 * @var int  Does this object support multicompany module ?
52
	 * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table
53
	 */
54
	public $ismultientitymanaged = 0;
55
56
	/**
57
	 * @var int  Does object support extrafields ? 0=No, 1=Yes
58
	 */
59
	public $isextrafieldmanaged = 0;
60
61
	/**
62
	 * @var string String with name of icon for workstation. Must be the part after the 'object_' into object_workstation.png
63
	 */
64
	public $picto = 'mrp';
65
66
67
	const STATUS_DISABLED = 0;
68
	const STATUS_ENABLED = 1;
69
70
71
	/**
72
	 *  'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password')
73
	 *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
74
	 *  'label' the translation key.
75
	 *  'picto' is code of a picto to show before value in forms
76
	 *  'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM)
77
	 *  'position' is the sort order of field.
78
	 *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
79
	 *  '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)
80
	 *  'noteditable' says if field is not editable (1 or 0)
81
	 *  '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.
82
	 *  'index' if we want an index in database.
83
	 *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...).
84
	 *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
85
	 *  '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).
86
	 *  '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: 'maxwidth200', 'wordbreak', 'tdoverflowmax200'
87
	 *  'help' is a string visible as a tooltip on field
88
	 *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
89
	 *  '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.
90
	 *  'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
91
	 *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
92
	 *  'comment' is not used. You can store here any text of your choice. It is not used by application.
93
	 *
94
	 *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
95
	 */
96
97
	// BEGIN MODULEBUILDER PROPERTIES
98
	/**
99
	 * @var array  Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
100
	 */
101
	public $fields=array(
102
		'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"),
103
		'ref' => array('type'=>'varchar(128)', 'picto'=>'mrp', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>1, 'noteditable'=>'0', 'default'=>'', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"),
104
		'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'showoncombobox'=>'1',),
105
		'type' => array('type'=>'select', 'label'=>'Type', 'enabled'=>'1', 'position'=>32, 'default'=>1, 'notnull'=>1, 'visible'=>1, 'arrayofkeyval'=>array('HUMAN'=>'Human', 'MACHINE'=>'Machine', 'BOTH'=>'HumanMachine'),),
106
		'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0,),
107
		'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0,),
108
		'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,),
109
		'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,),
110
		'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',),
111
		'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,),
112
		'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>512, 'notnull'=>-1, 'visible'=>-2,),
113
		'nb_operators_required' => array('type'=>'integer', 'label'=>'NbOperatorsRequired', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,),
114
		'thm_operator_estimated' => array('type'=>'double', 'help'=>'THMEstimatedHelp','label'=>'THMOperatorEstimated', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,),
115
		'thm_machine_estimated' => array('type'=>'double', 'help'=>'THMEstimatedHelp', 'label'=>'THMMachineEstimated', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,),
116
		'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'default'=>1, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Disabled', '1'=>'Enabled'),),
117
	);
118
	public $rowid;
119
	public $ref;
120
	public $label;
121
	public $note_public;
122
	public $note_private;
123
	public $date_creation;
124
	public $tms;
125
	public $fk_user_creat;
126
	public $fk_user_modif;
127
	public $import_key;
128
	public $status;
129
	public $nb_operators_required;
130
	public $thm_operator_estimated;
131
	public $thm_machine_estimated;
132
	// END MODULEBUILDER PROPERTIES
133
134
135
	// If this object has a subtable with lines
136
137
	/**
138
	 * @var int    Name of subtable line
139
	 */
140
	//public $table_element_line = 'workstation_workstationline';
141
142
	/**
143
	 * @var int    Field with ID of parent key if this object has a parent
144
	 */
145
	//public $fk_element = 'fk_workstation';
146
147
	/**
148
	 * @var int    Name of subtable class that manage subtable lines
149
	 */
150
	//public $class_element_line = 'Workstationline';
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('workstation_workstationdet');
163
164
	/**
165
	 * @var WorkstationLine[]     Array of subtable lines
166
	 */
167
	//public $lines = array();
168
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
		dol_include_once('/workstation/class/workstationusergroup.class.php');
181
		dol_include_once('/workstation/class/workstationresource.class.php');
182
183
		$this->db = $db;
184
185
		$this->fields['ref']['default'] = $this->getNextNumRef();
186
187
		if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0;
188
		if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0;
189
190
		// Example to show how to set values of fields definition dynamically
191
		/*if ($user->rights->workstation->workstation->read) {
192
			$this->fields['myfield']['visible'] = 1;
193
			$this->fields['myfield']['noteditable'] = 0;
194
		}*/
195
196
		// Unset fields that are disabled
197
		foreach ($this->fields as $key => $val)
198
		{
199
			if (isset($val['enabled']) && empty($val['enabled']))
200
			{
201
				unset($this->fields[$key]);
202
			}
203
		}
204
205
		// Translate some data of arrayofkeyval
206
		if (is_object($langs))
207
		{
208
			foreach ($this->fields as $key => $val)
209
			{
210
				if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval']))
211
				{
212
					foreach ($val['arrayofkeyval'] as $key2 => $val2)
213
					{
214
						$this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
215
					}
216
				}
217
			}
218
		}
219
	}
220
221
	/**
222
	 * Create object into database
223
	 *
224
	 * @param  User $user      User that creates
225
	 * @param  bool $notrigger false=launch triggers after, true=disable triggers
226
	 * @return int             <0 if KO, Id of created object if OK
227
	 */
228
	public function create(User $user, $notrigger = false)
229
	{
230
		global $db;
231
232
		$id = $this->createCommon($user, $notrigger);
233
234
		// Usergroups
235
		$groups = GETPOST('groups');
236
		if (empty($groups)) $groups = $this->usergroups; // createFromClone
237
		if (!empty($groups)) {
238
			foreach ($groups as $id_group) {
239
				$ws_usergroup = new WorkstationUserGroup($db);
240
				$ws_usergroup->fk_workstation = $id;
0 ignored issues
show
Bug introduced by
The property fk_workstation does not seem to exist on WorkstationUserGroup.
Loading history...
241
				$ws_usergroup->fk_usergroup = $id_group;
0 ignored issues
show
Bug introduced by
The property fk_usergroup does not seem to exist on WorkstationUserGroup.
Loading history...
242
				$ws_usergroup->createCommon($user);
243
				$this->usergroups[] = $id_group;
244
			}
245
		}
246
247
		// Resources
248
		$resources = GETPOST('resources');
249
		if (empty($resources)) $resources = $this->resources; // createFromClone
250
		if (!empty($resources)) {
251
			foreach ($resources as $id_resource) {
252
				$ws_resource = new WorkstationResource($db);
253
				$ws_resource->fk_workstation = $id;
0 ignored issues
show
Bug introduced by
The property fk_workstation does not seem to exist on WorkstationResource.
Loading history...
254
				$ws_resource->fk_resource = $id_resource;
0 ignored issues
show
Bug introduced by
The property fk_resource does not seem to exist on WorkstationResource.
Loading history...
255
				$ws_resource->createCommon($user);
256
				$this->resources[] = $id_resource;
257
			}
258
		}
259
260
		return $id;
261
	}
262
263
	/**
264
	 * Clone an object into another one
265
	 *
266
	 * @param  	User 	$user      	User that creates
267
	 * @param  	int 	$fromid     Id of object to clone
268
	 * @return 	mixed 				New object created, <0 if KO
269
	 */
270
	public function createFromClone(User $user, $fromid)
271
	{
272
		global $langs, $extrafields;
273
		$error = 0;
274
275
		dol_syslog(__METHOD__, LOG_DEBUG);
276
277
		$object = new self($this->db);
278
279
		$this->db->begin();
280
281
		// Load source object
282
		$result = $object->fetch($fromid);
283
		if ($result > 0 && !empty($object->table_element_line)) $object->fetchLines();
284
285
		// get lines so they will be clone
286
		//foreach($this->lines as $line)
287
		//	$line->fetch_optionals();
288
289
		// Reset some properties
290
		unset($object->id);
291
		unset($object->fk_user_creat);
292
		unset($object->import_key);
293
294
		// Clear fields
295
		if (property_exists($object, 'ref')) $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
296
		if (property_exists($object, 'label')) $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
297
		if (property_exists($object, 'status')) { $object->status = self::STATUS_DISABLED; }
298
		if (property_exists($object, 'date_creation')) { $object->date_creation = dol_now(); }
299
		if (property_exists($object, 'date_modification')) { $object->date_modification = null; }
300
		// ...
301
		// Clear extrafields that are unique
302
		if (is_array($object->array_options) && count($object->array_options) > 0)
303
		{
304
			$extrafields->fetch_name_optionals_label($this->table_element);
305
			foreach ($object->array_options as $key => $option)
306
			{
307
				$shortkey = preg_replace('/options_/', '', $key);
308
				if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey]))
309
				{
310
					//var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
311
					unset($object->array_options[$key]);
312
				}
313
			}
314
		}
315
316
		// Create clone
317
		$object->context['createfromclone'] = 'createfromclone';
318
		$result = $object->create($user);
319
		if ($result < 0) {
320
			$error++;
321
			$this->error = $object->error;
322
			$this->errors = $object->errors;
323
		}
324
325
		if (!$error)
326
		{
327
			// copy internal contacts
328
			if ($this->copy_linked_contact($object, 'internal') < 0)
329
			{
330
				$error++;
331
			}
332
		}
333
334
		if (!$error)
335
		{
336
			// copy external contacts if same company
337
			if (property_exists($this, 'socid') && $this->socid == $object->socid)
338
			{
339
				if ($this->copy_linked_contact($object, 'external') < 0)
340
					$error++;
341
			}
342
		}
343
344
		unset($object->context['createfromclone']);
345
346
		// End
347
		if (!$error) {
348
			$this->db->commit();
349
			return $object;
350
		} else {
351
			$this->db->rollback();
352
			return -1;
353
		}
354
	}
355
356
	/**
357
	 * Load object in memory from the database
358
	 *
359
	 * @param int    $id   Id object
360
	 * @param string $ref  Ref
361
	 * @return int         <0 if KO, 0 if not found, >0 if OK
362
	 */
363
	public function fetch($id, $ref = null)
364
	{
365
		$result = $this->fetchCommon($id, $ref);
366
367
		$this->usergroups = WorkstationUserGroup::getAllGroupsOfWorkstation($this->id);
368
		$this->resources = WorkstationResource::getAllResourcesOfWorkstation($this->id);
369
370
		if ($result > 0 && !empty($this->table_element_line)) $this->fetchLines();
371
		return $result;
372
	}
373
374
	/**
375
	 * Load object lines in memory from the database
376
	 *
377
	 * @return int         <0 if KO, 0 if not found, >0 if OK
378
	 */
379
	public function fetchLines()
380
	{
381
		$this->lines = array();
382
383
		$result = $this->fetchLinesCommon();
384
		return $result;
385
	}
386
387
388
	/**
389
	 * Load list of objects in memory from the database.
390
	 *
391
	 * @param  string      $sortorder    Sort Order
392
	 * @param  string      $sortfield    Sort field
393
	 * @param  int         $limit        limit
394
	 * @param  int         $offset       Offset
395
	 * @param  array       $filter       Filter array. Example array('field'=>'valueforlike', 'customurl'=>...)
396
	 * @param  string      $filtermode   Filter mode (AND or OR)
397
	 * @return array|int                 int <0 if KO, array of pages if OK
398
	 */
399
	public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
400
	{
401
		global $conf;
402
403
		dol_syslog(__METHOD__, LOG_DEBUG);
404
405
		$records = array();
406
407
		$sql = 'SELECT ';
408
		$sql .= $this->getFieldList();
409
		$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
410
		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')';
411
		else $sql .= ' WHERE 1 = 1';
412
		// Manage filter
413
		$sqlwhere = array();
414
		if (count($filter) > 0) {
415
			foreach ($filter as $key => $value) {
416
				if ($key == 't.rowid') {
417
					$sqlwhere[] = $key.'='.$value;
418
				} elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) {
419
					$sqlwhere[] = $key.' = \''.$this->db->idate($value).'\'';
420
				} elseif ($key == 'customsql') {
421
					$sqlwhere[] = $value;
422
				} elseif (strpos($value, '%') === false) {
423
					$sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')';
424
				} else {
425
					$sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\'';
426
				}
427
			}
428
		}
429
		if (count($sqlwhere) > 0) {
430
			$sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')';
431
		}
432
433
		if (!empty($sortfield)) {
434
			$sql .= $this->db->order($sortfield, $sortorder);
435
		}
436
		if (!empty($limit)) {
437
			$sql .= ' '.$this->db->plimit($limit, $offset);
438
		}
439
440
		$resql = $this->db->query($sql);
441
		if ($resql) {
442
			$num = $this->db->num_rows($resql);
443
			$i = 0;
444
			while ($i < ($limit ? min($limit, $num) : $num))
445
			{
446
				$obj = $this->db->fetch_object($resql);
447
448
				$record = new self($this->db);
449
				$record->setVarsFromFetchObj($obj);
450
451
				$records[$record->id] = $record;
452
453
				$i++;
454
			}
455
			$this->db->free($resql);
456
457
			return $records;
458
		} else {
459
			$this->errors[] = 'Error '.$this->db->lasterror();
460
			dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
461
462
			return -1;
463
		}
464
	}
465
466
	/**
467
	 * Update object into database
468
	 *
469
	 * @param  User $user      User that modifies
470
	 * @param  bool $notrigger false=launch triggers after, true=disable triggers
471
	 * @return int             <0 if KO, >0 if OK
472
	 */
473
	public function update(User $user, $notrigger = false)
474
	{
475
476
		// Usergroups
477
		$groups = GETPOST('groups');
478
		WorkstationUserGroup::deleteAllGroupsOfWorkstation($this->id);
479
		$this->usergroups=array();
480
481
		foreach ($groups as $id_group) {
482
			$ws_usergroup = new WorkstationUserGroup($this->db);
483
			$ws_usergroup->fk_workstation = $this->id;
0 ignored issues
show
Bug introduced by
The property fk_workstation does not seem to exist on WorkstationUserGroup.
Loading history...
484
			$ws_usergroup->fk_usergroup = $id_group;
0 ignored issues
show
Bug introduced by
The property fk_usergroup does not seem to exist on WorkstationUserGroup.
Loading history...
485
			$ws_usergroup->createCommon($user);
486
			$this->usergroups[] = $id_group;
487
		}
488
489
		// Resources
490
		$resources = GETPOST('resources');
491
		WorkstationResource::deleteAllResourcesOfWorkstation($this->id);
492
		$this->resources=array();
493
		if (!empty($resources)) {
494
			foreach ($resources as $id_resource) {
495
				$ws_resource = new WorkstationResource($this->db);
496
				$ws_resource->fk_workstation = $this->id;
0 ignored issues
show
Bug introduced by
The property fk_workstation does not seem to exist on WorkstationResource.
Loading history...
497
				$ws_resource->fk_resource = $id_resource;
0 ignored issues
show
Bug introduced by
The property fk_resource does not seem to exist on WorkstationResource.
Loading history...
498
				$ws_resource->createCommon($user);
499
				$this->resources[] = $id_resource;
500
			}
501
		}
502
503
		return $this->updateCommon($user, $notrigger);
504
	}
505
506
	/**
507
	 * Delete object in database
508
	 *
509
	 * @param User $user       User that deletes
510
	 * @param bool $notrigger  false=launch triggers after, true=disable triggers
511
	 * @return int             <0 if KO, >0 if OK
512
	 */
513
	public function delete(User $user, $notrigger = false)
514
	{
515
		return $this->deleteCommon($user, $notrigger);
516
		//return $this->deleteCommon($user, $notrigger, 1);
517
	}
518
519
	/**
520
	 *  Delete a line of object in database
521
	 *
522
	 *	@param  User	$user       User that delete
523
	 *  @param	int		$idline		Id of line to delete
524
	 *  @param 	bool 	$notrigger  false=launch triggers after, true=disable triggers
525
	 *  @return int         		>0 if OK, <0 if KO
526
	 */
527
	public function deleteLine(User $user, $idline, $notrigger = false)
528
	{
529
		if ($this->status < 0)
530
		{
531
			$this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
532
			return -2;
533
		}
534
535
		return $this->deleteLineCommon($user, $idline, $notrigger);
536
	}
537
538
539
	/**
540
	 *	Validate object
541
	 *
542
	 *	@param		User	$user     		User making status change
543
	 *  @param		int		$notrigger		1=Does not execute triggers, 0= execute triggers
544
	 *	@return  	int						<=0 if OK, 0=Nothing done, >0 if KO
545
	 */
546
	public function validate($user, $notrigger = 0)
547
	{
548
		global $conf, $langs;
549
550
		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
551
552
		$error = 0;
553
554
		// Protection
555
		if ($this->status == self::STATUS_VALIDATED)
0 ignored issues
show
Bug introduced by
The constant Workstation::STATUS_VALIDATED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
556
		{
557
			dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING);
558
			return 0;
559
		}
560
561
		/*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation->write))
562
		 || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation->workstation_advance->validate))))
563
		 {
564
		 $this->error='NotEnoughPermissions';
565
		 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
566
		 return -1;
567
		 }*/
568
569
		$now = dol_now();
570
571
		$this->db->begin();
572
573
		// Define new ref
574
		if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life
575
		{
576
			$num = $this->getNextNumRef();
577
		} else {
578
			$num = $this->ref;
579
		}
580
		$this->newref = $num;
581
582
		if (!empty($num)) {
583
			// Validate
584
			$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
585
			$sql .= " SET ref = '".$this->db->escape($num)."',";
586
			$sql .= " status = ".self::STATUS_VALIDATED;
587
			if (!empty($this->fields['date_validation'])) $sql .= ", date_validation = '".$this->db->idate($now)."'";
588
			if (!empty($this->fields['fk_user_valid'])) $sql .= ", fk_user_valid = ".$user->id;
589
			$sql .= " WHERE rowid = ".$this->id;
590
591
			dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
592
			$resql = $this->db->query($sql);
593
			if (!$resql)
594
			{
595
				dol_print_error($this->db);
596
				$this->error = $this->db->lasterror();
597
				$error++;
598
			}
599
600
			if (!$error && !$notrigger)
601
			{
602
				// Call trigger
603
				$result = $this->call_trigger('WORKSTATION_VALIDATE', $user);
604
				if ($result < 0) $error++;
605
				// End call triggers
606
			}
607
		}
608
609
		if (!$error)
610
		{
611
			$this->oldref = $this->ref;
612
613
			// Rename directory if dir was a temporary ref
614
			if (preg_match('/^[\(]?PROV/i', $this->ref))
615
			{
616
				// Now we rename also files into index
617
				$sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'workstation/".$this->db->escape($this->newref)."'";
618
				$sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'workstation/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
619
				$resql = $this->db->query($sql);
620
				if (!$resql) { $error++; $this->error = $this->db->lasterror(); }
621
622
				// We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
623
				$oldref = dol_sanitizeFileName($this->ref);
624
				$newref = dol_sanitizeFileName($num);
625
				$dirsource = $conf->workstation->dir_output.'/workstation/'.$oldref;
626
				$dirdest = $conf->workstation->dir_output.'/workstation/'.$newref;
627
				if (!$error && file_exists($dirsource))
628
				{
629
					dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
630
631
					if (@rename($dirsource, $dirdest))
632
					{
633
						dol_syslog("Rename ok");
634
						// Rename docs starting with $oldref with $newref
635
						$listoffiles = dol_dir_list($conf->workstation->dir_output.'/workstation/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
636
						foreach ($listoffiles as $fileentry)
637
						{
638
							$dirsource = $fileentry['name'];
639
							$dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
640
							$dirsource = $fileentry['path'].'/'.$dirsource;
641
							$dirdest = $fileentry['path'].'/'.$dirdest;
642
							@rename($dirsource, $dirdest);
643
						}
644
					}
645
				}
646
			}
647
		}
648
649
		// Set new ref and current status
650
		if (!$error)
651
		{
652
			$this->ref = $num;
653
			$this->status = self::STATUS_VALIDATED;
654
		}
655
656
		if (!$error)
657
		{
658
			$this->db->commit();
659
			return 1;
660
		} else {
661
			$this->db->rollback();
662
			return -1;
663
		}
664
	}
665
666
667
	/**
668
	 *	Set draft status
669
	 *
670
	 *	@param	int	$status			New status to set
671
	 *  @param	int		$notrigger		1=Does not execute triggers, 0=Execute triggers
672
	 *	@return	int						<0 if KO, >0 if OK
673
	 */
674
	public function setStatus($status, $notrigger = 0)
675
	{
676
		global $user;
677
678
		$this->status = $status;
679
680
		if (empty($status)) return $this->setDisabled($user, $notrigger);
681
		else return $this->setEnabled($user, $notrigger);
682
	}
683
684
685
	/**
686
	 *	Set draft status
687
	 *
688
	 *	@param	User	$user			Object user that modify
689
	 *  @param	int		$notrigger		1=Does not execute triggers, 0=Execute triggers
690
	 *	@return	int						<0 if KO, >0 if OK
691
	 */
692
	public function setEnabled($user, $notrigger = 0)
693
	{
694
		return $this->setStatusCommon($user, self::STATUS_ENABLED, $notrigger, 'WORKSTATION_ENABLED');
695
	}
696
697
698
	/**
699
	 *	Set draft status
700
	 *
701
	 *	@param	User	$user			Object user that modify
702
	 *  @param	int		$notrigger		1=Does not execute triggers, 0=Execute triggers
703
	 *	@return	int						<0 if KO, >0 if OK
704
	 */
705
	public function setDisabled($user, $notrigger = 0)
706
	{
707
		return $this->setStatusCommon($user, self::STATUS_DISABLED, $notrigger, 'WORKSTATION_DISABLED');
708
	}
709
710
	/**
711
	 *  Return a link to the object card (with optionaly the picto)
712
	 *
713
	 *  @param  int     $withpicto                  Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
714
	 *  @param  string  $option                     On what the link point to ('nolink', ...)
715
	 *  @param  int     $notooltip                  1=Disable tooltip
716
	 *  @param  string  $morecss                    Add more css on link
717
	 *  @param  int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
718
	 *  @return	string                              String with URL
719
	 */
720
	public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
721
	{
722
		global $conf, $langs, $hookmanager;
723
724
		if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
725
726
		$result = '';
727
728
		$label = img_picto('', $this->picto).' <u>'.$langs->trans("Workstation").'</u>';
729
		$label .= '<br>';
730
		$label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
731
		if (isset($this->status)) {
732
			$label .= '<br><b>'.$langs->trans("Status").":</b> ".$this->getLibStatut(5);
733
		}
734
735
		$url = dol_buildpath('/workstation/workstation_card.php', 1).'?id='.$this->id;
736
737
		if ($option != 'nolink')
738
		{
739
			// Add param to save lastsearch_values or not
740
			$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
741
			if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1;
742
			if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1';
743
		}
744
745
		$linkclose = '';
746
		if (empty($notooltip))
747
		{
748
			if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
749
			{
750
				$label = $langs->trans("ShowWorkstation");
751
				$linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
752
			}
753
			$linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
754
			$linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
755
		} else $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
756
757
		$linkstart = '<a href="'.$url.'"';
758
		$linkstart .= $linkclose.'>';
759
		$linkend = '</a>';
760
761
		$result .= $linkstart;
762
763
		if (empty($this->showphoto_on_popup)) {
764
			if ($withpicto) $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'mrp'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
765
		} else {
766
			if ($withpicto) {
767
				require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
768
769
				list($class, $module) = explode('@', $this->picto);
770
				$upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
771
				$filearray = dol_dir_list($upload_dir, "files");
772
				$filename = $filearray[0]['name'];
773
				if (!empty($filename)) {
774
					$pospoint = strpos($filearray[0]['name'], '.');
775
776
					$pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
777
					if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) {
778
						$result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo'.$module.'" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div></div>';
779
					} else {
780
						$result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div>';
781
					}
782
783
					$result .= '</div>';
784
				} else {
785
					$result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'mrp'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
786
				}
787
			}
788
		}
789
790
		if ($withpicto != 2) $result .= $this->ref;
791
792
		$result .= $linkend;
793
		//if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
794
795
		global $action, $hookmanager;
796
		$hookmanager->initHooks(array('workstationdao'));
797
		$parameters = array('id'=>$this->id, 'getnomurl'=>$result);
798
		$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
799
		if ($reshook > 0) $result = $hookmanager->resPrint;
800
		else $result .= $hookmanager->resPrint;
801
802
		return $result;
803
	}
804
805
	/**
806
	 *  Return the label of the status
807
	 *
808
	 *  @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
809
	 *  @return	string 			       Label of status
810
	 */
811
	public function getLibStatut($mode = 0)
812
	{
813
		return $this->LibStatut($this->status, $mode);
814
	}
815
816
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
817
	/**
818
	 *  Return the status
819
	 *
820
	 *  @param	int		$status        Id status
821
	 *  @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
822
	 *  @return string 			       Label of status
823
	 */
824
	public function LibStatut($status, $mode = 0)
825
	{
826
		// phpcs:enable
827
		if (empty($this->labelStatus) || empty($this->labelStatusShort))
0 ignored issues
show
Bug introduced by
The property labelStatusShort does not exist on Workstation. Did you mean labelStatus?
Loading history...
828
		{
829
			global $langs;
830
			//$langs->load("workstation@workstation");
831
			$this->labelStatus[self::STATUS_DISABLED] = $langs->trans('Disabled');
832
			$this->labelStatus[self::STATUS_ENABLED] = $langs->trans('Enabled');
833
		}
834
835
		$statusType = 'status'.$status;
836
		//if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
837
		//if ($status == self::STATUS_CANCELED) $statusType = 'status6';
838
839
		return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
840
	}
841
842
	/**
843
	 *	Load the info information in the object
844
	 *
845
	 *	@param  int		$id       Id of object
846
	 *	@return	void
847
	 */
848
	public function info($id)
849
	{
850
		$sql = 'SELECT rowid, date_creation as datec, tms as datem,';
851
		$sql .= ' fk_user_creat, fk_user_modif';
852
		$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
853
		$sql .= ' WHERE t.rowid = '.$id;
854
		$result = $this->db->query($sql);
855
		if ($result)
856
		{
857
			if ($this->db->num_rows($result))
858
			{
859
				$obj = $this->db->fetch_object($result);
860
				$this->id = $obj->rowid;
861
				if ($obj->fk_user_author)
862
				{
863
					$cuser = new User($this->db);
864
					$cuser->fetch($obj->fk_user_author);
865
					$this->user_creation = $cuser;
866
				}
867
868
				if ($obj->fk_user_valid)
869
				{
870
					$vuser = new User($this->db);
871
					$vuser->fetch($obj->fk_user_valid);
872
					$this->user_validation = $vuser;
873
				}
874
875
				if ($obj->fk_user_cloture)
876
				{
877
					$cluser = new User($this->db);
878
					$cluser->fetch($obj->fk_user_cloture);
879
					$this->user_cloture = $cluser;
880
				}
881
882
				$this->date_creation     = $this->db->jdate($obj->datec);
883
				$this->date_modification = $this->db->jdate($obj->datem);
884
				$this->date_validation   = $this->db->jdate($obj->datev);
885
			}
886
887
			$this->db->free($result);
888
		} else {
889
			dol_print_error($this->db);
890
		}
891
	}
892
893
	/**
894
	 * Initialise object with example values
895
	 * Id must be 0 if object instance is a specimen
896
	 *
897
	 * @return void
898
	 */
899
	public function initAsSpecimen()
900
	{
901
		$this->initAsSpecimenCommon();
902
	}
903
904
	/**
905
	 * 	Create an array of lines
906
	 *
907
	 * 	@return array|int		array of lines if OK, <0 if KO
908
	 */
909
	public function getLinesArray()
910
	{
911
		$this->lines = array();
912
913
		$objectline = new WorkstationLine($this->db);
0 ignored issues
show
Bug introduced by
The type WorkstationLine was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
914
		$result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_workstation = '.$this->id));
915
916
		if (is_numeric($result))
917
		{
918
			$this->error = $this->error;
919
			$this->errors = $this->errors;
920
			return $result;
921
		} else {
922
			$this->lines = $result;
923
			return $this->lines;
924
		}
925
	}
926
927
	/**
928
	 *  Returns the reference to the following non used object depending on the active numbering module.
929
	 *
930
	 *  @return string      		Object free reference
931
	 */
932
	public function getNextNumRef()
933
	{
934
		global $langs, $conf;
935
		$langs->load("workstation@workstation");
936
937
		if (empty($conf->global->WORKSTATION_WORKSTATION_ADDON)) {
938
			$conf->global->WORKSTATION_WORKSTATION_ADDON = 'mod_workstation_standard';
939
		}
940
941
		if (!empty($conf->global->WORKSTATION_WORKSTATION_ADDON))
942
		{
943
			$mybool = false;
944
945
			$file = $conf->global->WORKSTATION_WORKSTATION_ADDON.".php";
946
			$classname = $conf->global->WORKSTATION_WORKSTATION_ADDON;
947
948
			// Include file with class
949
			$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
950
			foreach ($dirmodels as $reldir)
951
			{
952
				$dir = dol_buildpath($reldir."core/modules/workstation/");
953
954
				// Load file with numbering class (if found)
955
				$mybool |= @include_once $dir.$file;
956
			}
957
958
			if ($mybool === false)
959
			{
960
				dol_print_error('', "Failed to include file ".$file);
961
				return '';
962
			}
963
964
			if (class_exists($classname)) {
965
				$obj = new $classname();
966
				$numref = $obj->getNextValue($this);
967
968
				if ($numref != '' && $numref != '-1')
969
				{
970
					return $numref;
971
				} else {
972
					$this->error = $obj->error;
973
					//dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
974
					return "";
975
				}
976
			} else {
977
				print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
978
				return "";
979
			}
980
		} else {
981
			print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
982
			return "";
983
		}
984
	}
985
986
	/**
987
	 *  Create a document onto disk according to template module.
988
	 *
989
	 *  @param	    string		$modele			Force template to use ('' to not force)
990
	 *  @param		Translate	$outputlangs	objet lang a utiliser pour traduction
991
	 *  @param      int			$hidedetails    Hide details of lines
992
	 *  @param      int			$hidedesc       Hide description
993
	 *  @param      int			$hideref        Hide ref
994
	 *  @param      null|array  $moreparams     Array to provide more information
995
	 *  @return     int         				0 if KO, 1 if OK
996
	 */
997
	public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
998
	{
999
		global $conf, $langs;
1000
1001
		$result = 0;
1002
		$includedocgeneration = 0;
1003
1004
		$langs->load("workstation@workstation");
1005
1006
		if (!dol_strlen($modele)) {
1007
			$modele = 'standard_workstation';
1008
1009
			if ($this->model_pdf) {
1010
				$modele = $this->model_pdf;
1011
			} elseif (!empty($conf->global->WORKSTATION_ADDON_PDF)) {
1012
				$modele = $conf->global->WORKSTATION_ADDON_PDF;
1013
			}
1014
		}
1015
1016
		$modelpath = "core/modules/workstation/doc/";
1017
1018
		if ($includedocgeneration) {
1019
			$result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1020
		}
1021
1022
		return $result;
1023
	}
1024
1025
	/**
1026
	 * Action executed by scheduler
1027
	 * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters'
1028
	 * Use public function doScheduledJob($param1, $param2, ...) to get parameters
1029
	 *
1030
	 * @return	int			0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
1031
	 */
1032
	public function doScheduledJob()
1033
	{
1034
		global $conf, $langs;
1035
1036
		//$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1037
1038
		$error = 0;
1039
		$this->output = '';
1040
		$this->error = '';
1041
1042
		dol_syslog(__METHOD__, LOG_DEBUG);
1043
1044
		$now = dol_now();
1045
1046
		$this->db->begin();
1047
1048
		// ...
1049
1050
		$this->db->commit();
1051
1052
		return $error;
1053
	}
1054
}
1055