Passed
Branch develop (b13600)
by
unknown
108:30
created

KnowledgeRecord::delete()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 30
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 19
c 0
b 0
f 0
nc 4
nop 2
dl 0
loc 30
rs 9.0111
1
<?php
2
/* Copyright (C) 2017  Laurent Destailleur <[email protected]>
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
 */
17
18
/**
19
 * \file        htdocs/knowledgemanagement/class/knowledgerecord.class.php
20
 * \ingroup     knowledgemanagement
21
 * \brief       This file is a CRUD class file for KnowledgeRecord (Create/Read/Update/Delete)
22
 */
23
24
// Put here all includes required by your class file
25
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
26
//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
27
//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
28
29
/**
30
 * Class for KnowledgeRecord
31
 */
32
class KnowledgeRecord extends CommonObject
33
{
34
	/**
35
	 * @var string ID of module.
36
	 */
37
	public $module = 'knowledgemanagement';
38
39
	/**
40
	 * @var string ID to identify managed object.
41
	 */
42
	public $element = 'knowledgerecord';
43
44
	/**
45
	 * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
46
	 */
47
	public $table_element = 'knowledgemanagement_knowledgerecord';
48
49
	/**
50
	 * @var int  Does this object support multicompany module ?
51
	 * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table
52
	 */
53
	public $ismultientitymanaged = 1;
54
55
	/**
56
	 * @var int  Does object support extrafields ? 0=No, 1=Yes
57
	 */
58
	public $isextrafieldmanaged = 1;
59
60
	/**
61
	 * @var string String with name of icon for knowledgerecord. Must be the part after the 'object_' into object_knowledgerecord.png
62
	 */
63
	public $picto = 'knowledgemanagement';
64
65
66
	const STATUS_DRAFT = 0;
67
	const STATUS_VALIDATED = 1;
68
	const STATUS_CANCELED = 9;
69
70
71
	/**
72
	 *  'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:SortField]]]', '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')
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 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
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
	 *  'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value)
94
	 *
95
	 *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
96
	 */
97
98
	// BEGIN MODULEBUILDER PROPERTIES
99
	/**
100
	 * @var array  Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
101
	 */
102
	public $fields=array(
103
		'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"),
104
		'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'default'=>'(PROV)', 'visible'=>5, 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", "csslist"=>"nowraponall", "showoncombobox"=>1),
105
		'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>0, 'notnull'=>1, 'position'=>20, 'index'=>1),
106
		'question' => array('type'=>'text', 'label'=>'Question', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'csslist'=>'tdoverflowmax300', 'copytoclipboard'=>1, 'tdcss'=>'titlefieldcreate nowraponall'),
107
		'lang' => array('type'=>'varchar(6)', 'label'=>'Language', 'enabled'=>'1', 'position'=>40, 'notnull'=>0, 'visible'=>1, 'tdcss'=>'titlefieldcreate nowraponall', "csslist"=>"tdoverflowmax100"),
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
		'last_main_doc' => array('type'=>'varchar(255)', 'label'=>'LastMainDoc', 'enabled'=>'1', 'position'=>600, 'notnull'=>0, 'visible'=>0,),
111
		'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserCreation', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',),
112
		'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,),
113
		'fk_user_valid' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserValidation', 'enabled'=>'1', 'position'=>512, 'notnull'=>0, 'visible'=>-2,),
114
		'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,),
115
		'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,),
116
		//'url' => array('type'=>'varchar(255)', 'label'=>'URL', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1, 'csslist'=>'tdoverflow200', 'help'=>'UrlForInfoPage'),
117
		'fk_c_ticket_category' => array('type'=>'integer:CTicketCategory:ticket/class/cticketcategory.class.php:0:(t.active:=:1):pos', 'label'=>'SuggestedForTicketsInGroup', 'enabled'=>'isModEnabled("ticket")', 'position'=>520, 'notnull'=>0, 'visible'=>-1, 'help'=>'YouCanLinkArticleToATicketCategory', 'csslist'=>'minwidth200 tdoverflowmax250'),
118
		'answer' => array('type'=>'html', 'label'=>'Solution', 'enabled'=>'1', 'position'=>600, 'notnull'=>0, 'visible'=>3, 'searchall'=>1, 'csslist'=>'tdoverflowmax300', 'copytoclipboard'=>1, 'tdcss'=>'titlefieldcreate nowraponall'),
119
		'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'visible'=>5, 'default'=>0, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Validated', '9'=>'Obsolete'),),
120
	);
121
	public $rowid;
122
	public $ref;
123
	public $entity;
124
	public $date_creation;
125
	public $tms;
126
	public $last_main_doc;
127
	public $fk_user_creat;
128
	public $fk_user_modif;
129
	public $fk_user_valid;
130
	public $import_key;
131
	public $model_pdf;
132
133
	/**
134
	 * @var string question asked
135
	 */
136
	public $question;
137
138
	/**
139
	 * @var string answer to question
140
	 */
141
	public $answer;
142
	public $url;
143
	public $status;
144
	public $lang;
145
	// END MODULEBUILDER PROPERTIES
146
147
148
	// If this object has a subtable with lines
149
150
	// /**
151
	//  * @var string    Name of subtable line
152
	//  */
153
	// public $table_element_line = 'knowledgemanagement_knowledgerecordline';
154
155
	// /**
156
	//  * @var string    Field with ID of parent key if this object has a parent
157
	//  */
158
	// public $fk_element = 'fk_knowledgerecord';
159
160
	// /**
161
	//  * @var string    Name of subtable class that manage subtable lines
162
	//  */
163
	// public $class_element_line = 'KnowledgeRecordline';
164
165
	// /**
166
	//  * @var array	List of child tables. To test if we can delete object.
167
	//  */
168
	// protected $childtables = array();
169
170
	// /**
171
	//  * @var array    List of child tables. To know object to delete on cascade.
172
	//  *               If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will
173
	//  *               call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
174
	//  */
175
	// protected $childtablesoncascade = array('knowledgemanagement_knowledgerecorddet');
176
177
	// /**
178
	//  * @var KnowledgeRecordLine[]     Array of subtable lines
179
	//  */
180
	// public $lines = array();
181
182
183
184
	/**
185
	 * Constructor
186
	 *
187
	 * @param DoliDb $db Database handler
188
	 */
189
	public function __construct(DoliDB $db)
190
	{
191
		global $conf, $langs;
192
193
		$this->db = $db;
194
195
		if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) {
196
			$this->fields['rowid']['visible'] = 0;
197
		}
198
		if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
199
			$this->fields['entity']['enabled'] = 0;
200
		}
201
202
		// Example to show how to set values of fields definition dynamically
203
		/*if ($user->hasRight('knowledgemanagement', 'knowledgerecord', 'read')) {
204
			$this->fields['myfield']['visible'] = 1;
205
			$this->fields['myfield']['noteditable'] = 0;
206
		}*/
207
208
		// Unset fields that are disabled
209
		foreach ($this->fields as $key => $val) {
210
			if (isset($val['enabled']) && empty($val['enabled'])) {
211
				unset($this->fields[$key]);
212
			}
213
		}
214
215
		// Translate some data of arrayofkeyval
216
		if (is_object($langs)) {
217
			foreach ($this->fields as $key => $val) {
218
				if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
219
					foreach ($val['arrayofkeyval'] as $key2 => $val2) {
220
						$this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
221
					}
222
				}
223
			}
224
		}
225
	}
226
227
	/**
228
	 * Create object into database
229
	 *
230
	 * @param  User $user      User that creates
231
	 * @param  bool $notrigger false=launch triggers after, true=disable triggers
232
	 * @return int             <0 if KO, Id of created object if OK
233
	 */
234
	public function create(User $user, $notrigger = false)
235
	{
236
		return $this->createCommon($user, $notrigger);
237
	}
238
239
	/**
240
	 * Clone an object into another one
241
	 *
242
	 * @param  	User 	$user      	User that creates
243
	 * @param  	int 	$fromid     Id of object to clone
244
	 * @return 	mixed 				New object created, <0 if KO
245
	 */
246
	public function createFromClone(User $user, $fromid)
247
	{
248
		global $langs, $extrafields;
249
		$error = 0;
250
251
		dol_syslog(__METHOD__, LOG_DEBUG);
252
253
		$object = new self($this->db);
254
255
		$this->db->begin();
256
257
		// Load source object
258
		$result = $object->fetchCommon($fromid);
259
		if ($result > 0 && !empty($object->table_element_line)) {
260
			$object->fetchLines();
261
		}
262
263
		// get lines so they will be clone
264
		//foreach($this->lines as $line)
265
		//	$line->fetch_optionals();
266
267
		// Reset some properties
268
		unset($object->id);
269
		unset($object->fk_user_creat);
270
		unset($object->import_key);
271
272
		// Clear fields
273
		if (property_exists($object, 'ref')) {
274
			$object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
275
		}
276
		if (property_exists($object, 'question')) {
277
			$object->question = empty($this->fields['question']['default']) ? $langs->trans("CopyOf")." ".$object->question : $this->fields['question']['default'];
278
		}
279
		if (property_exists($object, 'status')) {
280
			$object->status = self::STATUS_DRAFT;
281
		}
282
		if (property_exists($object, 'date_creation')) {
283
			$object->date_creation = dol_now();
284
		}
285
		if (property_exists($object, 'date_modification')) {
286
			$object->date_modification = null;
287
		}
288
		// ...
289
		// Clear extrafields that are unique
290
		if (is_array($object->array_options) && count($object->array_options) > 0) {
291
			$extrafields->fetch_name_optionals_label($this->table_element);
292
			foreach ($object->array_options as $key => $option) {
293
				$shortkey = preg_replace('/options_/', '', $key);
294
				if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
295
					//var_dump($key);
296
					//var_dump($clonedObj->array_options[$key]); exit;
297
					unset($object->array_options[$key]);
298
				}
299
			}
300
		}
301
302
		// Create clone
303
		$object->context['createfromclone'] = 'createfromclone';
304
		$result = $object->createCommon($user);
305
		if ($result < 0) {
306
			$error++;
307
			$this->error = $object->error;
308
			$this->errors = $object->errors;
309
		}
310
311
		if (!$error) {
312
			// copy internal contacts
313
			if ($this->copy_linked_contact($object, 'internal') < 0) {
314
				$error++;
315
			}
316
		}
317
318
		if (!$error) {
319
			// copy external contacts if same company
320
			if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
321
				if ($this->copy_linked_contact($object, 'external') < 0) {
322
					$error++;
323
				}
324
			}
325
		}
326
327
		unset($object->context['createfromclone']);
328
329
		// End
330
		if (!$error) {
331
			$this->db->commit();
332
			return $object;
333
		} else {
334
			$this->db->rollback();
335
			return -1;
336
		}
337
	}
338
339
	/**
340
	 * Load object in memory from the database
341
	 *
342
	 * @param int    $id   Id object
343
	 * @param string $ref  Ref
344
	 * @return int         <0 if KO, 0 if not found, >0 if OK
345
	 */
346
	public function fetch($id, $ref = null)
347
	{
348
		$result = $this->fetchCommon($id, $ref);
349
		if ($result > 0 && !empty($this->table_element_line)) {
350
			$this->fetchLines();
351
		}
352
		return $result;
353
	}
354
355
	/**
356
	 * Load object lines in memory from the database
357
	 *
358
	 * @return int         <0 if KO, 0 if not found, >0 if OK
359
	 */
360
	public function fetchLines()
361
	{
362
		$this->lines = array();
363
364
		$result = $this->fetchLinesCommon();
365
		return $result;
366
	}
367
368
369
	/**
370
	 * Load list of objects in memory from the database.
371
	 *
372
	 * @param  string      $sortorder    Sort Order
373
	 * @param  string      $sortfield    Sort field
374
	 * @param  int         $limit        limit
375
	 * @param  int         $offset       Offset
376
	 * @param  array       $filter       Filter array. Example array('field'=>'valueforlike', 'customurl'=>...)
377
	 * @param  string      $filtermode   Filter mode (AND or OR)
378
	 * @return array|int                 int <0 if KO, array of pages if OK
379
	 */
380
	public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
381
	{
382
		global $conf;
383
384
		dol_syslog(__METHOD__, LOG_DEBUG);
385
386
		$records = array();
387
388
		$sql = 'SELECT ';
389
		$sql .= $this->getFieldList('t');
390
		$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
391
		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
392
			$sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
393
		} else {
394
			$sql .= ' WHERE 1 = 1';
395
		}
396
		// Manage filter
397
		$sqlwhere = array();
398
		if (count($filter) > 0) {
399
			foreach ($filter as $key => $value) {
400
				if ($key == 't.rowid') {
401
					$sqlwhere[] = $key." = ".((int) $value);
402
				} elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) {
403
					$sqlwhere[] = $key." = '".$this->db->idate($value)."'";
404
				} elseif ($key == 'customsql') {
405
					$sqlwhere[] = $value;
406
				} elseif (strpos($value, '%') === false) {
407
					$sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')';
408
				} else {
409
					$sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'";
410
				}
411
			}
412
		}
413
		if (count($sqlwhere) > 0) {
414
			$sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')';
415
		}
416
417
		if (!empty($sortfield)) {
418
			$sql .= $this->db->order($sortfield, $sortorder);
419
		}
420
		if (!empty($limit)) {
421
			$sql .= $this->db->plimit($limit, $offset);
422
		}
423
424
		$resql = $this->db->query($sql);
425
		if ($resql) {
426
			$num = $this->db->num_rows($resql);
427
			$i = 0;
428
			while ($i < ($limit ? min($limit, $num) : $num)) {
429
				$obj = $this->db->fetch_object($resql);
430
431
				$record = new self($this->db);
432
				$record->setVarsFromFetchObj($obj);
433
434
				$records[$record->id] = $record;
435
436
				$i++;
437
			}
438
			$this->db->free($resql);
439
440
			return $records;
441
		} else {
442
			$this->errors[] = 'Error '.$this->db->lasterror();
443
			dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
444
445
			return -1;
446
		}
447
	}
448
449
	/**
450
	 * Update object into database
451
	 *
452
	 * @param  User $user      User that modifies
453
	 * @param  bool $notrigger false=launch triggers after, true=disable triggers
454
	 * @return int             <0 if KO, >0 if OK
455
	 */
456
	public function update(User $user, $notrigger = false)
457
	{
458
		return $this->updateCommon($user, $notrigger);
459
	}
460
461
	/**
462
	 * Delete object in database
463
	 *
464
	 * @param User $user       User that deletes
465
	 * @param bool $notrigger  false=launch triggers after, true=disable triggers
466
	 * @return int             <0 if KO, >0 if OK
467
	 */
468
	public function delete(User $user, $notrigger = false)
469
	{
470
		$error = 0;
471
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_knowledgemanagement WHERE fk_knowledgemanagement = ".((int) $this->id);
472
		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
473
		$resql = $this->db->query($sql);
474
		if (!$resql) {
475
			$error++;
476
			$this->error .= $this->db->lasterror();
477
			$errorflag = -1;
478
		}
479
480
		// Delete all child tables
481
		if (!$error) {
482
			$elements = array('categorie_knowledgemanagement');
483
			foreach ($elements as $table) {
484
				if (!$error) {
485
					$sql = "DELETE FROM ".MAIN_DB_PREFIX.$table;
486
					$sql .= " WHERE fk_knowledgemanagement = ".(int) $this->id;
487
488
					$result = $this->db->query($sql);
489
					if (!$result) {
490
						$error++;
491
						$this->errors[] = $this->db->lasterror();
492
					}
493
				}
494
			}
495
		}
496
497
		return $this->deleteCommon($user, $notrigger);
498
		//return $this->deleteCommon($user, $notrigger, 1);
499
	}
500
501
	/**
502
	 *  Delete a line of object in database
503
	 *
504
	 *	@param  User	$user       User that delete
505
	 *  @param	int		$idline		Id of line to delete
506
	 *  @param 	bool 	$notrigger  false=launch triggers after, true=disable triggers
507
	 *  @return int         		>0 if OK, <0 if KO
508
	 */
509
	public function deleteLine(User $user, $idline, $notrigger = false)
510
	{
511
		if ($this->status < 0) {
512
			$this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
513
			return -2;
514
		}
515
516
		return $this->deleteLineCommon($user, $idline, $notrigger);
517
	}
518
519
520
	/**
521
	 *	Validate object
522
	 *
523
	 *	@param		User	$user     		User making status change
524
	 *  @param		int		$notrigger		1=Does not execute triggers, 0= execute triggers
525
	 *	@return  	int						<=0 if OK, 0=Nothing done, >0 if KO
526
	 */
527
	public function validate($user, $notrigger = 0)
528
	{
529
		global $conf, $langs;
530
531
		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
532
533
		$error = 0;
534
535
		// Protection
536
		if ($this->status == self::STATUS_VALIDATED) {
537
			dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING);
538
			return 0;
539
		}
540
541
		/*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->hasRight('knowledgemanagement', 'knowledgerecord', 'write'))
542
		 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgerecord->knowledgerecord_advance->validate))))
543
		 {
544
		 $this->error='NotEnoughPermissions';
545
		 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
546
		 return -1;
547
		 }*/
548
549
		$now = dol_now();
550
551
		$this->db->begin();
552
553
		// Define new ref
554
		if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
555
			$num = $this->getNextNumRef();
556
		} else {
557
			$num = $this->ref;
558
		}
559
		$this->newref = $num;
560
561
		if (!empty($num)) {
562
			// Validate
563
			$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
564
			$sql .= " SET ref = '".$this->db->escape($num)."',";
565
			$sql .= " status = ".self::STATUS_VALIDATED;
566
			if (!empty($this->fields['date_validation'])) {
567
				$sql .= ", date_validation = '".$this->db->idate($now)."'";
568
			}
569
			if (!empty($this->fields['fk_user_valid'])) {
570
				$sql .= ", fk_user_valid = ".((int) $user->id);
571
			}
572
			$sql .= " WHERE rowid = ".((int) $this->id);
573
574
			dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
575
			$resql = $this->db->query($sql);
576
			if (!$resql) {
577
				dol_print_error($this->db);
578
				$this->error = $this->db->lasterror();
579
				$error++;
580
			}
581
582
			if (!$error && !$notrigger) {
583
				// Call trigger
584
				$result = $this->call_trigger('KNOWLEDGERECORD_VALIDATE', $user);
585
				if ($result < 0) {
586
					$error++;
587
				}
588
				// End call triggers
589
			}
590
		}
591
592
		if (!$error) {
593
			$this->oldref = $this->ref;
594
595
			// Rename directory if dir was a temporary ref
596
			if (preg_match('/^[\(]?PROV/i', $this->ref)) {
597
				// Now we rename also files into index
598
				$sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'knowledgerecord/".$this->db->escape($this->newref)."'";
599
				$sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'knowledgerecord/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
600
				$resql = $this->db->query($sql);
601
				if (!$resql) {
602
					$error++; $this->error = $this->db->lasterror();
603
				}
604
605
				// We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
606
				$oldref = dol_sanitizeFileName($this->ref);
607
				$newref = dol_sanitizeFileName($num);
608
				$dirsource = $conf->knowledgemanagement->dir_output.'/knowledgerecord/'.$oldref;
609
				$dirdest = $conf->knowledgemanagement->dir_output.'/knowledgerecord/'.$newref;
610
				if (!$error && file_exists($dirsource)) {
611
					dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
612
613
					if (@rename($dirsource, $dirdest)) {
614
						dol_syslog("Rename ok");
615
						// Rename docs starting with $oldref with $newref
616
						$listoffiles = dol_dir_list($conf->knowledgemanagement->dir_output.'/knowledgerecord/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
617
						foreach ($listoffiles as $fileentry) {
618
							$dirsource = $fileentry['name'];
619
							$dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
620
							$dirsource = $fileentry['path'].'/'.$dirsource;
621
							$dirdest = $fileentry['path'].'/'.$dirdest;
622
							@rename($dirsource, $dirdest);
623
						}
624
					}
625
				}
626
			}
627
		}
628
629
		// Set new ref and current status
630
		if (!$error) {
631
			$this->ref = $num;
632
			$this->status = self::STATUS_VALIDATED;
633
		}
634
635
		if (!$error) {
636
			$this->db->commit();
637
			return 1;
638
		} else {
639
			$this->db->rollback();
640
			return -1;
641
		}
642
	}
643
644
645
	/**
646
	 *	Set draft status
647
	 *
648
	 *	@param	User	$user			Object user that modify
649
	 *  @param	int		$notrigger		1=Does not execute triggers, 0=Execute triggers
650
	 *	@return	int						<0 if KO, >0 if OK
651
	 */
652
	public function setDraft($user, $notrigger = 0)
653
	{
654
		// Protection
655
		if ($this->status <= self::STATUS_DRAFT) {
656
			return 0;
657
		}
658
659
		/*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
660
		 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
661
		 {
662
		 $this->error='Permission denied';
663
		 return -1;
664
		 }*/
665
666
		return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'KNOWLEDGERECORD_UNVALIDATE');
667
	}
668
669
	/**
670
	 *	Set cancel status
671
	 *
672
	 *	@param	User	$user			Object user that modify
673
	 *  @param	int		$notrigger		1=Does not execute triggers, 0=Execute triggers
674
	 *	@return	int						<0 if KO, 0=Nothing done, >0 if OK
675
	 */
676
	public function cancel($user, $notrigger = 0)
677
	{
678
		// Protection
679
		if ($this->status != self::STATUS_VALIDATED) {
680
			return 0;
681
		}
682
683
		/*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
684
		 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
685
		 {
686
		 $this->error='Permission denied';
687
		 return -1;
688
		 }*/
689
690
		return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'KNOWLEDGERECORD_CANCEL');
691
	}
692
693
	/**
694
	 *	Set back to validated status
695
	 *
696
	 *	@param	User	$user			Object user that modify
697
	 *  @param	int		$notrigger		1=Does not execute triggers, 0=Execute triggers
698
	 *	@return	int						<0 if KO, 0=Nothing done, >0 if OK
699
	 */
700
	public function reopen($user, $notrigger = 0)
701
	{
702
		// Protection
703
		if ($this->status != self::STATUS_CANCELED) {
704
			return 0;
705
		}
706
707
		/*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
708
		 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
709
		 {
710
		 $this->error='Permission denied';
711
		 return -1;
712
		 }*/
713
714
		return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'KNOWLEDGERECORD_REOPEN');
715
	}
716
717
	/**
718
	 * getTooltipContentArray
719
	 *
720
	 * @param array $params ex option, infologin
721
	 * @since v18
722
	 * @return array
723
	 */
724
	public function getTooltipContentArray($params)
725
	{
726
		global $conf, $langs;
727
728
		$langs->loadLangs(['knowledgemanagement', 'languages']);
729
730
		$datas = [];
731
		$nofetch = empty($params['nofetch']) ? false : true;
732
		$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("KnowledgeRecord").'</u>';
733
		if (isset($this->statut)) {
734
			$datas['picto'] .= ' '.$this->getLibStatut(5);
735
		}
736
		$datas['label'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
737
		$datas['question'] = '<br><b>'.$langs->trans('Question').':</b> '.$this->question;
738
		$labellang = ($this->lang ? $langs->trans('Language_'.$this->lang) : '');
739
		$datas['lang'] = '<br><b>'.$langs->trans('Language').':</b> ' . picto_from_langcode($this->lang, 'class="paddingrightonly saturatemedium opacitylow"') . $labellang;
740
		// show categories for this record only in ajax to not overload lists
741
		if (isModEnabled('categorie') && !$nofetch) {
742
			require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
743
			$form = new Form($this->db);
744
			$datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_KNOWLEDGEMANAGEMENT, 1);
745
		}
746
747
		return $datas;
748
	}
749
750
	/**
751
	 *  Return a link to the object card (with optionaly the picto)
752
	 *
753
	 *  @param  int     $withpicto                  Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
754
	 *  @param  string  $option                     On what the link point to ('nolink', ...)
755
	 *  @param  int     $notooltip                  1=Disable tooltip
756
	 *  @param  string  $morecss                    Add more css on link
757
	 *  @param  int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
758
	 *  @return	string                              String with URL
759
	 */
760
	public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
761
	{
762
		global $conf, $langs, $hookmanager;
763
764
		if (!empty($conf->dol_no_mouse_hover)) {
765
			$notooltip = 1; // Force disable tooltips
766
		}
767
768
		$result = '';
769
770
		$params = [
771
			'id' => $this->id,
772
			'objecttype' => $this->element,
773
			'option' => $option,
774
			'nofetch' => 1,
775
		];
776
		$classfortooltip = 'classfortooltip';
777
		$dataparams = '';
778
		if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
779
			$classfortooltip = 'classforajaxtooltip';
780
			$dataparams = ' data-params='.json_encode($params);
781
		}
782
		$label = implode($this->getTooltipContentArray($params));
783
784
		$url = dol_buildpath('/knowledgemanagement/knowledgerecord_card.php', 1).'?id='.$this->id;
785
786
		if ($option != 'nolink') {
787
			// Add param to save lastsearch_values or not
788
			$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
789
			if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
790
				$add_save_lastsearch_values = 1;
791
			}
792
			if ($add_save_lastsearch_values) {
793
				$url .= '&save_lastsearch_values=1';
794
			}
795
		}
796
797
		$linkclose = '';
798
		if (empty($notooltip)) {
799
			if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
800
				$label = $langs->trans("ShowKnowledgeRecord");
801
				$linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
802
			}
803
			$linkclose .= $dataparams.' title="'.dol_escape_htmltag($label, 1).'"';
804
			$linkclose .= ' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
805
		} else {
806
			$linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
807
		}
808
809
		if ($option == 'nolink') {
810
			$linkstart = '<span';
811
		} else {
812
			$linkstart = '<a href="'.$url.'"';
813
		}
814
		$linkstart .= $linkclose.'>';
815
		if ($option == 'nolink') {
816
			$linkend = '</span>';
817
		} else {
818
			$linkend = '</a>';
819
		}
820
821
		$result .= $linkstart;
822
823
		if (empty($this->showphoto_on_popup)) {
824
			if ($withpicto) {
825
				$result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1);
826
			}
827
		} else {
828
			if ($withpicto) {
829
				require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
830
831
				list($class, $module) = explode('@', $this->picto);
832
				$upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
833
				$filearray = dol_dir_list($upload_dir, "files");
834
				$filename = $filearray[0]['name'];
835
				if (!empty($filename)) {
836
					$pospoint = strpos($filearray[0]['name'], '.');
837
838
					$pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
839
					if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) {
840
						$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>';
841
					} else {
842
						$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>';
843
					}
844
845
					$result .= '</div>';
846
				} else {
847
					$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);
848
				}
849
			}
850
		}
851
852
		if ($withpicto != 2) {
853
			$result .= $this->ref;
854
		}
855
856
		$result .= $linkend;
857
		//if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
858
859
		global $action, $hookmanager;
860
		$hookmanager->initHooks(array('knowledgerecorddao'));
861
		$parameters = array('id'=>$this->id, 'getnomurl' => &$result);
862
		$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
863
		if ($reshook > 0) {
864
			$result = $hookmanager->resPrint;
865
		} else {
866
			$result .= $hookmanager->resPrint;
867
		}
868
869
		return $result;
870
	}
871
872
	/**
873
	 *  Return the label of the status
874
	 *
875
	 *  @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
876
	 *  @return	string 			       Label of status
877
	 */
878
	public function getLibStatut($mode = 0)
879
	{
880
		return $this->LibStatut($this->status, $mode);
881
	}
882
883
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
884
	/**
885
	 *  Return the status
886
	 *
887
	 *  @param	int		$status        Id status
888
	 *  @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
889
	 *  @return string 			       Label of status
890
	 */
891
	public function LibStatut($status, $mode = 0)
892
	{
893
		// phpcs:enable
894
		if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
895
			global $langs;
896
			//$langs->load("knowledgemanagement");
897
			$this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
898
			$this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
899
			$this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Obsolete');
900
			$this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
901
			$this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
902
			$this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Obsolete');
903
		}
904
905
		$statusType = 'status'.$status;
906
		if ($status == self::STATUS_VALIDATED) $statusType = 'status4';
907
		if ($status == self::STATUS_CANCELED) {
908
			$statusType = 'status6';
909
		}
910
911
		return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
912
	}
913
914
	/**
915
	 *	Load the info information in the object
916
	 *
917
	 *	@param  int		$id       Id of object
918
	 *	@return	void
919
	 */
920
	public function info($id)
921
	{
922
		$sql = 'SELECT rowid, date_creation as datec, tms as datem,';
923
		$sql .= ' fk_user_creat, fk_user_modif';
924
		$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
925
		$sql .= ' WHERE t.rowid = '.((int) $id);
926
		$result = $this->db->query($sql);
927
		if ($result) {
928
			if ($this->db->num_rows($result)) {
929
				$obj = $this->db->fetch_object($result);
930
				$this->id = $obj->rowid;
931
932
				$this->user_creation_id = $obj->fk_user_creat;
933
				$this->user_modification_id = $obj->fk_user_modif;
934
				$this->date_creation     = $this->db->jdate($obj->datec);
935
				$this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
936
			}
937
938
			$this->db->free($result);
939
		} else {
940
			dol_print_error($this->db);
941
		}
942
	}
943
944
	/**
945
	 * Initialise object with example values
946
	 * Id must be 0 if object instance is a specimen
947
	 *
948
	 * @return void
949
	 */
950
	public function initAsSpecimen()
951
	{
952
		$this->question = "ABCD";
953
		$this->initAsSpecimenCommon();
954
	}
955
956
	/**
957
	 * 	Create an array of lines
958
	 *
959
	 * 	@return array|int		array of lines if OK, <0 if KO
960
	 */
961
	public function getLinesArray()
962
	{
963
		$this->lines = array();
964
965
		$objectline = new KnowledgeRecordLine($this->db);
966
		$result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_knowledgerecord = '.((int) $this->id)));
967
968
		if (is_numeric($result)) {
969
			$this->error = $objectline->error;
970
			$this->errors = $objectline->errors;
971
			return $result;
972
		} else {
973
			$this->lines = $result;
974
			return $this->lines;
975
		}
976
	}
977
978
	/**
979
	 *  Returns the reference to the following non used object depending on the active numbering module.
980
	 *
981
	 *  @return string      		Object free reference
982
	 */
983
	public function getNextNumRef()
984
	{
985
		global $langs, $conf;
986
		$langs->load("knowledgemanagement");
987
988
		if (empty($conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON)) {
989
			$conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON = 'mod_knowledgerecord_standard';
990
		}
991
992
		if (!empty($conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON)) {
993
			$mybool = false;
994
995
			$file = $conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON.".php";
996
			$classname = $conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON;
997
998
			// Include file with class
999
			$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1000
			foreach ($dirmodels as $reldir) {
1001
				$dir = dol_buildpath($reldir."core/modules/knowledgemanagement/");
1002
1003
				// Load file with numbering class (if found)
1004
				$mybool |= @include_once $dir.$file;
1005
			}
1006
1007
			if ($mybool === false) {
1008
				dol_print_error('', "Failed to include file ".$file);
1009
				return '';
1010
			}
1011
1012
			if (class_exists($classname)) {
1013
				$obj = new $classname();
1014
				$numref = $obj->getNextValue($this);
1015
1016
				if ($numref != '' && $numref != '-1') {
1017
					return $numref;
1018
				} else {
1019
					$this->error = $obj->error;
1020
					//dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1021
					return "";
1022
				}
1023
			} else {
1024
				print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1025
				return "";
1026
			}
1027
		} else {
1028
			print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1029
			return "";
1030
		}
1031
	}
1032
1033
	/**
1034
	 *  Create a document onto disk according to template module.
1035
	 *
1036
	 *  @param	    string		$modele			Force template to use ('' to not force)
1037
	 *  @param		Translate	$outputlangs	objet lang a utiliser pour traduction
1038
	 *  @param      int			$hidedetails    Hide details of lines
1039
	 *  @param      int			$hidedesc       Hide description
1040
	 *  @param      int			$hideref        Hide ref
1041
	 *  @param      null|array  $moreparams     Array to provide more information
1042
	 *  @return     int         				0 if KO, 1 if OK
1043
	 */
1044
	public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1045
	{
1046
		global $conf, $langs;
1047
1048
		$result = 0;
1049
		$includedocgeneration = 0;
1050
1051
		$langs->load("knowledgemanagement");
1052
1053
		if (!dol_strlen($modele)) {
1054
			$modele = 'standard_knowledgerecord';
1055
1056
			if (!empty($this->model_pdf)) {
1057
				$modele = $this->model_pdf;
1058
			} elseif (!empty($conf->global->KNOWLEDGERECORD_ADDON_PDF)) {
1059
				$modele = $conf->global->KNOWLEDGERECORD_ADDON_PDF;
1060
			}
1061
		}
1062
1063
		$modelpath = "core/modules/knowledgemanagement/doc/";
1064
1065
		if ($includedocgeneration && !empty($modele)) {
1066
			$result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1067
		}
1068
1069
		return $result;
1070
	}
1071
1072
	/**
1073
	 * Action executed by scheduler
1074
	 * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters'
1075
	 * Use public function doScheduledJob($param1, $param2, ...) to get parameters
1076
	 *
1077
	 * @return	int			0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
1078
	 */
1079
	public function doScheduledJob()
1080
	{
1081
		global $conf, $langs;
1082
1083
		//$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1084
1085
		$error = 0;
1086
		$this->output = '';
1087
		$this->error = '';
1088
1089
		dol_syslog(__METHOD__, LOG_DEBUG);
1090
1091
		$now = dol_now();
1092
1093
		$this->db->begin();
1094
1095
		// ...
1096
1097
		$this->db->commit();
1098
1099
		return $error;
1100
	}
1101
1102
	/**
1103
	 * Sets object to supplied categories.
1104
	 *
1105
	 * Deletes object from existing categories not supplied.
1106
	 * Adds it to non existing supplied categories.
1107
	 * Existing categories are left untouch.
1108
	 *
1109
	 * @param 	int[]|int 	$categories 	Category or categories IDs
1110
	 * @return 	int							<0 if KO, >0 if OK
1111
	 */
1112
	public function setCategories($categories)
1113
	{
1114
		require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1115
		return parent::setCategoriesCommon($categories, Categorie::TYPE_KNOWLEDGEMANAGEMENT);
1116
	}
1117
1118
	/**
1119
	 *	Return clicable link of object (with eventually picto)
1120
	 *
1121
	 *	@param      string	    $option                 Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
1122
	 *  @param		array		$arraydata				Array of data
1123
	 *  @return		string								HTML Code for Kanban thumb.
1124
	 */
1125
	public function getKanbanView($option = '', $arraydata = null)
1126
	{
1127
		global $langs, $selected,$arrayofselected;
1128
		$return = '<div class="box-flex-item box-flex-grow-zero">';
1129
		$return .= '<div class="info-box info-box-sm">';
1130
		$return .= '<span class="info-box-icon bg-infobox-action">';
1131
		$return .= img_picto('', $this->picto);
1132
		$return .= '</span>';
1133
		$return .= '<div class="info-box-content">';
1134
		$return .= '<span class="info-box-ref">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).'</span>';
1135
		if (in_array($this->id, $arrayofselected)) {
1136
			$selected = 1;
1137
		}
1138
		$return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1139
		if (property_exists($this, 'question')) {
1140
			$return .= '<br><span class="opacitymedium">'.$langs->trans('Question').'</span> : <span class="info-box-label">'.$this->question.'</span>';
1141
		}
1142
		if (property_exists($this, 'lang') && !empty($this->lang)) {
1143
			$return .= '<br><span class="opacitymedium">'.$langs->trans("Language").'</span> : <span class="info-box-label" title="'.$langs->trans("Language_".$this->lang).'">'.$langs->trans("Language_".$this->lang, '', '', '', '', 12).'</span>';
1144
			$return .=  picto_from_langcode($this->lang, 'class="paddingrightonly saturatemedium opacitylow"');
1145
		}
1146
		if (method_exists($this, 'getLibStatut')) {
1147
			$return .= '<br><div class="info-box-status margintoponly">'.$this->getLibStatut(5).'</div>';
1148
		}
1149
		$return .= '</div>';
1150
		$return .= '</div>';
1151
		$return .= '</div>';
1152
		return $return;
1153
	}
1154
}
1155
1156
1157
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1158
1159
/**
1160
 * Class KnowledgeRecordLine. You can also remove this and generate a CRUD class for lines objects.
1161
 */
1162
class KnowledgeRecordLine extends CommonObjectLine
1163
{
1164
	// To complete with content of an object KnowledgeRecordLine
1165
	// We should have a field rowid, fk_knowledgerecord and position
1166
1167
	/**
1168
	 * @var int  Does object support extrafields ? 0=No, 1=Yes
1169
	 */
1170
	public $isextrafieldmanaged = 0;
1171
1172
	/**
1173
	 * Constructor
1174
	 *
1175
	 * @param DoliDb $db Database handler
1176
	 */
1177
	public function __construct(DoliDB $db)
1178
	{
1179
		$this->db = $db;
1180
	}
1181
}
1182