dolibarr 20.0.0
knowledgerecord.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
26// Put here all includes required by your class file
27require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
28//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
29//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
30
35{
39 public $module = 'knowledgemanagement';
40
44 public $element = 'knowledgerecord';
45
49 public $table_element = 'knowledgemanagement_knowledgerecord';
50
54 public $picto = 'knowledgemanagement';
55
56
57 const STATUS_DRAFT = 0;
58 const STATUS_VALIDATED = 1;
59 const STATUS_CANCELED = 9;
60
61
89 // BEGIN MODULEBUILDER PROPERTIES
93 public $fields = array(
94 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
95 '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),
96 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'position' => 20, 'index' => 1),
97 'question' => array('type' => 'text', 'label' => 'Question', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'searchall' => 1, 'csslist' => 'tdoverflowmax300 small', 'copytoclipboard' => 1, 'tdcss' => 'titlefieldcreate nowraponall'),
98 'lang' => array('type' => 'varchar(6)', 'label' => 'Language', 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => 1, 'tdcss' => 'titlefieldcreate nowraponall', "csslist" => "minwidth100 maxwidth200"),
99 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2, 'csslist' => 'nowraponall'),
100 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => 2,),
101 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0,),
102 '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',),
103 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
104 'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'position' => 512, 'notnull' => 0, 'visible' => -2,),
105 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
106 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
107 //'url' => array('type'=>'varchar(255)', 'label'=>'URL', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1, 'csslist'=>'tdoverflow200', 'help'=>'UrlForInfoPage'),
108 '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'),
109 'answer' => array('type' => 'html', 'label' => 'Solution', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 3, 'searchall' => 1, 'csslist' => 'tdoverflowmax300', 'copytoclipboard' => 1, 'tdcss' => 'titlefieldcreate nowraponall'),
110 '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'),),
111 );
112 public $rowid;
113 public $ref;
114 public $entity;
115 public $date_creation;
116 public $last_main_doc;
117 public $fk_user_creat;
118 public $fk_user_modif;
119 public $fk_user_valid;
120 public $import_key;
121 public $model_pdf;
122
126 public $question;
127
131 public $answer;
132 public $url;
133 public $status;
134 public $lang;
135 // END MODULEBUILDER PROPERTIES
136
137
138 // If this object has a subtable with lines
139
140 // /**
141 // * @var string Name of subtable line
142 // */
143 // public $table_element_line = 'knowledgemanagement_knowledgerecordline';
144
145 // /**
146 // * @var string Field with ID of parent key if this object has a parent
147 // */
148 // public $fk_element = 'fk_knowledgerecord';
149
150 // /**
151 // * @var string Name of subtable class that manage subtable lines
152 // */
153 // public $class_element_line = 'KnowledgeRecordline';
154
155 // /**
156 // * @var array List of child tables. To test if we can delete object.
157 // */
158 // protected $childtables = array();
159
160 // /**
161 // * @var array List of child tables. To know object to delete on cascade.
162 // * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will
163 // * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
164 // */
165 // protected $childtablesoncascade = array('knowledgemanagement_knowledgerecorddet');
166
167 // /**
168 // * @var KnowledgeRecordLine[] Array of subtable lines
169 // */
170 // public $lines = array();
171
172
173
179 public function __construct(DoliDB $db)
180 {
181 global $langs;
182
183 $this->db = $db;
184
185 $this->ismultientitymanaged = 1;
186 $this->isextrafieldmanaged = 1;
187
188 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
189 $this->fields['rowid']['visible'] = 0;
190 }
191 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
192 $this->fields['entity']['enabled'] = 0;
193 }
194
195 // Unset fields that are disabled
196 foreach ($this->fields as $key => $val) {
197 if (isset($val['enabled']) && empty($val['enabled'])) {
198 unset($this->fields[$key]);
199 }
200 }
201
202 // Translate some data of arrayofkeyval
203 if (is_object($langs)) {
204 foreach ($this->fields as $key => $val) {
205 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
206 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
207 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
208 }
209 }
210 }
211 }
212 }
213
221 public function create(User $user, $notrigger = 0)
222 {
223 return $this->createCommon($user, $notrigger);
224 }
225
233 public function createFromClone(User $user, $fromid)
234 {
235 global $langs, $extrafields;
236 $error = 0;
237
238 dol_syslog(__METHOD__, LOG_DEBUG);
239
240 $object = new self($this->db);
241
242 $this->db->begin();
243
244 // Load source object
245 $result = $object->fetchCommon($fromid);
246 if ($result > 0 && !empty($object->table_element_line)) {
247 $object->fetchLines();
248 }
249
250 // get lines so they will be clone
251 //foreach($this->lines as $line)
252 // $line->fetch_optionals();
253
254 // Reset some properties
255 unset($object->id);
256 unset($object->fk_user_creat);
257 unset($object->import_key);
258
259 // Clear fields
260 if (property_exists($object, 'ref')) {
261 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
262 }
263 if (property_exists($object, 'question')) {
264 $object->question = empty($this->fields['question']['default']) ? $langs->trans("CopyOf")." ".$object->question : $this->fields['question']['default'];
265 }
266 if (property_exists($object, 'status')) {
267 $object->status = self::STATUS_DRAFT;
268 }
269 if (property_exists($object, 'date_creation')) {
270 $object->date_creation = dol_now();
271 }
272 if (property_exists($object, 'date_modification')) {
273 $object->date_modification = null;
274 }
275 // ...
276 // Clear extrafields that are unique
277 if (is_array($object->array_options) && count($object->array_options) > 0) {
278 $extrafields->fetch_name_optionals_label($this->table_element);
279 foreach ($object->array_options as $key => $option) {
280 $shortkey = preg_replace('/options_/', '', $key);
281 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
282 //var_dump($key);
283 //var_dump($clonedObj->array_options[$key]); exit;
284 unset($object->array_options[$key]);
285 }
286 }
287 }
288
289 // Create clone
290 $object->context['createfromclone'] = 'createfromclone';
291 $result = $object->createCommon($user);
292 if ($result < 0) {
293 $error++;
294 $this->error = $object->error;
295 $this->errors = $object->errors;
296 }
297
298 if (!$error) {
299 // copy internal contacts
300 if ($this->copy_linked_contact($object, 'internal') < 0) {
301 $error++;
302 }
303 }
304
305 if (!$error) {
306 // copy external contacts if same company
307 if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
308 if ($this->copy_linked_contact($object, 'external') < 0) {
309 $error++;
310 }
311 }
312 }
313
314 unset($object->context['createfromclone']);
315
316 // End
317 if (!$error) {
318 $this->db->commit();
319 return $object;
320 } else {
321 $this->db->rollback();
322 return -1;
323 }
324 }
325
333 public function fetch($id, $ref = null)
334 {
335 $result = $this->fetchCommon($id, $ref);
336 if ($result > 0 && !empty($this->table_element_line)) {
337 $this->fetchLines();
338 }
339 return $result;
340 }
341
347 public function fetchLines()
348 {
349 $this->lines = array();
350
351 $result = $this->fetchLinesCommon();
352 return $result;
353 }
354
355
367 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
368 {
369 dol_syslog(__METHOD__, LOG_DEBUG);
370
371 $records = array();
372
373 $sql = 'SELECT ';
374 $sql .= $this->getFieldList('t');
375 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
376 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
377 $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
378 } else {
379 $sql .= ' WHERE 1 = 1';
380 }
381
382 // Manage filter
383 if (is_array($filter)) {
384 $sqlwhere = array();
385 if (count($filter) > 0) {
386 foreach ($filter as $key => $value) {
387 if ($key == 't.rowid') {
388 $sqlwhere[] = $this->db->sanitize($key)." = ".((int) $value);
389 } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) {
390 $sqlwhere[] = $this->db->sanitize($key)." = '".$this->db->idate($value)."'";
391 } elseif (strpos($value, '%') === false) {
392 $sqlwhere[] = $this->db->sanitize($key).' IN ('.$this->db->sanitize($this->db->escape($value)).')';
393 } else {
394 $sqlwhere[] = $this->db->sanitize($key)." LIKE '%".$this->db->escape($this->db->escapeforlike($value))."%'";
395 }
396 }
397 }
398 if (count($sqlwhere) > 0) {
399 $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')';
400 }
401
402 $filter = '';
403 }
404
405 // Manage filter
406 $errormessage = '';
407 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
408 if ($errormessage) {
409 $this->errors[] = $errormessage;
410 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
411 return -1;
412 }
413
414 if (!empty($sortfield)) {
415 $sql .= $this->db->order($sortfield, $sortorder);
416 }
417 if (!empty($limit)) {
418 $sql .= $this->db->plimit($limit, $offset);
419 }
420
421 $resql = $this->db->query($sql);
422 if ($resql) {
423 $num = $this->db->num_rows($resql);
424 $i = 0;
425 while ($i < ($limit ? min($limit, $num) : $num)) {
426 $obj = $this->db->fetch_object($resql);
427
428 $record = new self($this->db);
429 $record->setVarsFromFetchObj($obj);
430
431 $records[$record->id] = $record;
432
433 $i++;
434 }
435 $this->db->free($resql);
436
437 return $records;
438 } else {
439 $this->errors[] = 'Error '.$this->db->lasterror();
440 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
441
442 return -1;
443 }
444 }
445
453 public function update(User $user, $notrigger = 0)
454 {
455 return $this->updateCommon($user, $notrigger);
456 }
457
465 public function delete(User $user, $notrigger = 0)
466 {
467 $error = 0;
468 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_knowledgemanagement WHERE fk_knowledgemanagement = ".((int) $this->id);
469 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
470 $resql = $this->db->query($sql);
471 if (!$resql) {
472 $error++;
473 $this->error .= $this->db->lasterror();
474 $errorflag = -1;
475 }
476
477 // Delete all child tables
478 if (!$error) {
479 $elements = array('categorie_knowledgemanagement');
480 foreach ($elements as $table) {
481 if (!$error) {
482 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$table;
483 $sql .= " WHERE fk_knowledgemanagement = ".(int) $this->id;
484
485 $result = $this->db->query($sql);
486 if (!$result) {
487 $error++;
488 $this->errors[] = $this->db->lasterror();
489 }
490 }
491 }
492 }
493
494 return $this->deleteCommon($user, $notrigger);
495 //return $this->deleteCommon($user, $notrigger, 1);
496 }
497
506 public function deleteLine(User $user, $idline, $notrigger = 0)
507 {
508 if ($this->status < 0) {
509 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
510 return -2;
511 }
512
513 return $this->deleteLineCommon($user, $idline, $notrigger);
514 }
515
516
524 public function validate($user, $notrigger = 0)
525 {
526 global $conf, $langs;
527
528 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
529
530 $error = 0;
531
532 // Protection
533 if ($this->status == self::STATUS_VALIDATED) {
534 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
535 return 0;
536 }
537
538 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->hasRight('knowledgemanagement', 'knowledgerecord', 'write'))
539 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgerecord->knowledgerecord_advance->validate))))
540 {
541 $this->error='NotEnoughPermissions';
542 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
543 return -1;
544 }*/
545
546 $now = dol_now();
547
548 $this->db->begin();
549
550 // Define new ref
551 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
552 $num = $this->getNextNumRef();
553 } else {
554 $num = $this->ref;
555 }
556 $this->newref = $num;
557
558 if (!empty($num)) {
559 // Validate
560 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
561 $sql .= " SET ref = '".$this->db->escape($num)."',";
562 $sql .= " status = ".self::STATUS_VALIDATED;
563 if (!empty($this->fields['date_validation'])) {
564 $sql .= ", date_validation = '".$this->db->idate($now)."'";
565 }
566 if (!empty($this->fields['fk_user_valid'])) {
567 $sql .= ", fk_user_valid = ".((int) $user->id);
568 }
569 $sql .= " WHERE rowid = ".((int) $this->id);
570
571 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
572 $resql = $this->db->query($sql);
573 if (!$resql) {
574 dol_print_error($this->db);
575 $this->error = $this->db->lasterror();
576 $error++;
577 }
578
579 if (!$error && !$notrigger) {
580 // Call trigger
581 $result = $this->call_trigger('KNOWLEDGERECORD_VALIDATE', $user);
582 if ($result < 0) {
583 $error++;
584 }
585 // End call triggers
586 }
587 }
588
589 if (!$error) {
590 $this->oldref = $this->ref;
591
592 // Rename directory if dir was a temporary ref
593 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
594 // Now we rename also files into index
595 $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)."'";
596 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'knowledgerecord/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
597 $resql = $this->db->query($sql);
598 if (!$resql) {
599 $error++;
600 $this->error = $this->db->lasterror();
601 }
602 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'knowledgerecord/".$this->db->escape($this->newref)."'";
603 $sql .= " WHERE filepath = 'knowledgerecord/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
604 $resql = $this->db->query($sql);
605 if (!$resql) {
606 $error++;
607 $this->error = $this->db->lasterror();
608 }
609
610 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
611 $oldref = dol_sanitizeFileName($this->ref);
612 $newref = dol_sanitizeFileName($num);
613 $dirsource = $conf->knowledgemanagement->dir_output.'/knowledgerecord/'.$oldref;
614 $dirdest = $conf->knowledgemanagement->dir_output.'/knowledgerecord/'.$newref;
615 if (!$error && file_exists($dirsource)) {
616 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
617
618 if (@rename($dirsource, $dirdest)) {
619 dol_syslog("Rename ok");
620 // Rename docs starting with $oldref with $newref
621 $listoffiles = dol_dir_list($conf->knowledgemanagement->dir_output.'/knowledgerecord/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
622 foreach ($listoffiles as $fileentry) {
623 $dirsource = $fileentry['name'];
624 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
625 $dirsource = $fileentry['path'].'/'.$dirsource;
626 $dirdest = $fileentry['path'].'/'.$dirdest;
627 @rename($dirsource, $dirdest);
628 }
629 }
630 }
631 }
632 }
633
634 // Set new ref and current status
635 if (!$error) {
636 $this->ref = $num;
637 $this->status = self::STATUS_VALIDATED;
638 }
639
640 if (!$error) {
641 $this->db->commit();
642 return 1;
643 } else {
644 $this->db->rollback();
645 return -1;
646 }
647 }
648
649
657 public function setDraft($user, $notrigger = 0)
658 {
659 // Protection
660 if ($this->status <= self::STATUS_DRAFT) {
661 return 0;
662 }
663
664 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
665 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
666 {
667 $this->error='Permission denied';
668 return -1;
669 }*/
670
671 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'KNOWLEDGERECORD_UNVALIDATE');
672 }
673
681 public function cancel($user, $notrigger = 0)
682 {
683 // Protection
684 if ($this->status != self::STATUS_VALIDATED) {
685 return 0;
686 }
687
688 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
689 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
690 {
691 $this->error='Permission denied';
692 return -1;
693 }*/
694
695 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'KNOWLEDGERECORD_CANCEL');
696 }
697
705 public function reopen($user, $notrigger = 0)
706 {
707 // Protection
708 if ($this->status != self::STATUS_CANCELED) {
709 return 0;
710 }
711
712 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
713 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
714 {
715 $this->error='Permission denied';
716 return -1;
717 }*/
718
719 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'KNOWLEDGERECORD_REOPEN');
720 }
721
729 public function getTooltipContentArray($params)
730 {
731 global $conf, $langs;
732
733 $langs->loadLangs(['knowledgemanagement', 'languages']);
734
735 $datas = array();
736 $nofetch = !empty($params['nofetch']);
737
738 $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("KnowledgeRecord").'</u>';
739 if (isset($this->statut)) {
740 $datas['picto'] .= ' '.$this->getLibStatut(5);
741 }
742 $datas['label'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
743 $datas['question'] = '<br><b>'.$langs->trans('Question').':</b> '.$this->question;
744 $labellang = ($this->lang ? $langs->trans('Language_'.$this->lang) : '');
745 $datas['lang'] = '<br><b>'.$langs->trans('Language').':</b> ' . picto_from_langcode($this->lang, 'class="paddingrightonly saturatemedium opacitylow"') . $labellang;
746 // show categories for this record only in ajax to not overload lists
747 if (isModEnabled('category') && !$nofetch) {
748 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
749 $form = new Form($this->db);
750 $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_KNOWLEDGEMANAGEMENT, 1);
751 }
752
753 return $datas;
754 }
755
766 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
767 {
768 global $conf, $langs, $hookmanager;
769
770 if (!empty($conf->dol_no_mouse_hover)) {
771 $notooltip = 1; // Force disable tooltips
772 }
773
774 $result = '';
775
776 $params = [
777 'id' => $this->id,
778 'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
779 'option' => $option,
780 'nofetch' => 1,
781 ];
782 $classfortooltip = 'classfortooltip';
783 $dataparams = '';
784 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
785 $classfortooltip = 'classforajaxtooltip';
786 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
787 $label = '';
788 } else {
789 $label = implode($this->getTooltipContentArray($params));
790 }
791
792 $url = dol_buildpath('/knowledgemanagement/knowledgerecord_card.php', 1).'?id='.$this->id;
793
794 if ($option != 'nolink') {
795 // Add param to save lastsearch_values or not
796 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
797 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
798 $add_save_lastsearch_values = 1;
799 }
800 if ($add_save_lastsearch_values) {
801 $url .= '&save_lastsearch_values=1';
802 }
803 }
804
805 $linkclose = '';
806 if (empty($notooltip)) {
807 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
808 $label = $langs->trans("ShowKnowledgeRecord");
809 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
810 }
811 $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
812 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
813 } else {
814 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
815 }
816
817 if ($option == 'nolink') {
818 $linkstart = '<span';
819 } else {
820 $linkstart = '<a href="'.$url.'"';
821 }
822 $linkstart .= $linkclose.'>';
823 if ($option == 'nolink') {
824 $linkend = '</span>';
825 } else {
826 $linkend = '</a>';
827 }
828
829 $result .= $linkstart;
830
831 if (empty($this->showphoto_on_popup)) {
832 if ($withpicto) {
833 $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);
834 }
835 } else {
836 if ($withpicto) {
837 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
838
839 list($class, $module) = explode('@', $this->picto);
840 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
841 $filearray = dol_dir_list($upload_dir, "files");
842 $filename = $filearray[0]['name'];
843 if (!empty($filename)) {
844 $pospoint = strpos($filearray[0]['name'], '.');
845
846 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
847 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
848 $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>';
849 } else {
850 $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>';
851 }
852
853 $result .= '</div>';
854 } else {
855 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
856 }
857 }
858 }
859
860 if ($withpicto != 2) {
861 $result .= $this->ref;
862 }
863
864 $result .= $linkend;
865 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
866
867 global $action, $hookmanager;
868 $hookmanager->initHooks(array('knowledgerecorddao'));
869 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
870 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
871 if ($reshook > 0) {
872 $result = $hookmanager->resPrint;
873 } else {
874 $result .= $hookmanager->resPrint;
875 }
876
877 return $result;
878 }
879
886 public function getLibStatut($mode = 0)
887 {
888 return $this->LibStatut($this->status, $mode);
889 }
890
891 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
899 public function LibStatut($status, $mode = 0)
900 {
901 // phpcs:enable
902 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
903 global $langs;
904 //$langs->load("knowledgemanagement");
905 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
906 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
907 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Obsolete');
908 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
909 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
910 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Obsolete');
911 }
912
913 $statusType = 'status'.$status;
914 if ($status == self::STATUS_VALIDATED) {
915 $statusType = 'status4';
916 }
917 if ($status == self::STATUS_CANCELED) {
918 $statusType = 'status6';
919 }
920
921 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
922 }
923
930 public function info($id)
931 {
932 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
933 $sql .= ' fk_user_creat, fk_user_modif';
934 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
935 $sql .= ' WHERE t.rowid = '.((int) $id);
936 $result = $this->db->query($sql);
937 if ($result) {
938 if ($this->db->num_rows($result)) {
939 $obj = $this->db->fetch_object($result);
940
941 $this->id = $obj->rowid;
942
943 $this->user_creation_id = $obj->fk_user_creat;
944 $this->user_modification_id = $obj->fk_user_modif;
945 $this->date_creation = $this->db->jdate($obj->datec);
946 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
947 }
948
949 $this->db->free($result);
950 } else {
951 dol_print_error($this->db);
952 }
953 }
954
961 public function initAsSpecimen()
962 {
963 $this->question = "ABCD";
964
965 return $this->initAsSpecimenCommon();
966 }
967
973 public function getLinesArray()
974 {
975 $this->lines = array();
976
977 $objectline = new KnowledgeRecordLine($this->db);
978 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_knowledgerecord:=:'.((int) $this->id).')');
979
980 if (is_numeric($result)) {
981 $this->error = $objectline->error;
982 $this->errors = $objectline->errors;
983 return $result;
984 } else {
985 $this->lines = $result;
986 return $this->lines;
987 }
988 }
989
995 public function getNextNumRef()
996 {
997 global $langs, $conf;
998 $langs->load("knowledgemanagement");
999
1000 if (!getDolGlobalString('KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON')) {
1001 $conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON = 'mod_knowledgerecord_standard';
1002 }
1003
1004 if (getDolGlobalString('KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON')) {
1005 $mybool = false;
1006
1007 $file = getDolGlobalString('KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON') . ".php";
1008 $classname = getDolGlobalString('KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON');
1009
1010 // Include file with class
1011 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1012 foreach ($dirmodels as $reldir) {
1013 $dir = dol_buildpath($reldir."core/modules/knowledgemanagement/");
1014
1015 // Load file with numbering class (if found)
1016 $mybool = ((bool) @include_once $dir.$file) || $mybool;
1017 }
1018
1019 if ($mybool === false) {
1020 dol_print_error(null, "Failed to include file ".$file);
1021 return '';
1022 }
1023
1024 if (class_exists($classname)) {
1025 $obj = new $classname();
1026 $numref = $obj->getNextValue($this);
1027
1028 if ($numref != '' && $numref != '-1') {
1029 return $numref;
1030 } else {
1031 $this->error = $obj->error;
1032 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1033 return "";
1034 }
1035 } else {
1036 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1037 return "";
1038 }
1039 } else {
1040 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1041 return "";
1042 }
1043 }
1044
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("knowledgemanagement");
1064
1065 if (!dol_strlen($modele)) {
1066 $modele = 'standard_knowledgerecord';
1067
1068 if (!empty($this->model_pdf)) {
1069 $modele = $this->model_pdf;
1070 } elseif (getDolGlobalString('KNOWLEDGERECORD_ADDON_PDF')) {
1071 $modele = getDolGlobalString('KNOWLEDGERECORD_ADDON_PDF');
1072 }
1073 }
1074
1075 $modelpath = "core/modules/knowledgemanagement/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
1091 public function doScheduledJob()
1092 {
1093 global $conf, $langs;
1094
1095 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1096
1097 $error = 0;
1098 $this->output = '';
1099 $this->error = '';
1100
1101 dol_syslog(__METHOD__, LOG_DEBUG);
1102
1103 $now = dol_now();
1104
1105 $this->db->begin();
1106
1107 // ...
1108
1109 $this->db->commit();
1110
1111 return $error;
1112 }
1113
1124 public function setCategories($categories)
1125 {
1126 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1127 return parent::setCategoriesCommon($categories, Categorie::TYPE_KNOWLEDGEMANAGEMENT);
1128 }
1129
1137 public function getKanbanView($option = '', $arraydata = null)
1138 {
1139 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1140
1141 $return = '<div class="box-flex-item box-flex-grow-zero">';
1142 $return .= '<div class="info-box info-box-sm">';
1143 $return .= '<span class="info-box-icon bg-infobox-action">';
1144 $return .= img_picto('', $this->picto);
1145 $return .= '</span>';
1146 $return .= '<div class="info-box-content">';
1147 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).'</span>';
1148 if ($selected >= 0) {
1149 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1150 }
1151 if (property_exists($this, 'lang') && !empty($this->lang)) {
1152 //$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>';
1153 $return .= '<br>'.picto_from_langcode($this->lang, 'class="paddingrightonly saturatemedium opacitylow paddingrightonly"');
1154 }
1155 if (property_exists($this, 'question')) {
1156 $return .= '<div class="info-box-label tdoverflowmax150 classfortooltip" title="'.dolPrintHTMLForAttribute($this->question).'">'.dolGetFirstLineOfText($this->question).'</div>';
1157 }
1158 if (method_exists($this, 'getLibStatut')) {
1159 $return .= '<div class="info-box-status">'.$this->getLibStatut(3).'</div>';
1160 }
1161 $return .= '</div>';
1162 $return .= '</div>';
1163 $return .= '</div>';
1164 return $return;
1165 }
1166}
1167
1168
1169require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1170
1175{
1176 // To complete with content of an object KnowledgeRecordLine
1177 // We should have a field rowid, fk_knowledgerecord and position
1178
1184 public function __construct(DoliDB $db)
1185 {
1186 $this->db = $db;
1187
1188 $this->isextrafieldmanaged = 0;
1189 }
1190}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition security.php:636
$object ref
Definition info.php:79
Parent class of all other business classes (invoices, contracts, proposals, orders,...
deleteLineCommon(User $user, $idline, $notrigger=0)
Delete a line of object in database.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
createCommon(User $user, $notrigger=0)
Create object in the database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
updateCommon(User $user, $notrigger=0)
Update object into database.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
copy_linked_contact($objFrom, $source='internal')
Copy contact from one element to current.
fetchLinesCommon($morewhere='', $noextrafields=0)
Load object in memory from the database.
fetchCommon($id, $ref=null, $morewhere='', $noextrafields=0)
Load object in memory from the database.
deleteCommon(User $user, $notrigger=0, $forcechilddeletion=0)
Delete object in database.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class to manage generation of HTML components Only common components must be here.
Class for KnowledgeRecord.
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
fetch($id, $ref=null)
Load object in memory from the database.
validate($user, $notrigger=0)
Validate object.
getNextNumRef()
Returns the reference to the following non used object depending on the active numbering module.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND')
Load list of objects in memory from the database.
info($id)
Load the info information in the object.
cancel($user, $notrigger=0)
Set cancel status.
update(User $user, $notrigger=0)
Update object into database.
fetchLines()
Load object lines in memory from the database.
LibStatut($status, $mode=0)
Return the status.
create(User $user, $notrigger=0)
Create object into database.
getTooltipContentArray($params)
getTooltipContentArray
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
createFromClone(User $user, $fromid)
Clone an object into another one.
deleteLine(User $user, $idline, $notrigger=0)
Delete a line of object in database.
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
setCategories($categories)
Sets object to supplied categories.
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
getLinesArray()
Create an array of lines.
__construct(DoliDB $db)
Constructor.
getLibStatut($mode=0)
Return the label of the status.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
reopen($user, $notrigger=0)
Set back to validated status.
setDraft($user, $notrigger=0)
Set draft status.
Class KnowledgeRecordLine.
__construct(DoliDB $db)
Constructor.
Class to manage Dolibarr users.
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:63
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
picto_from_langcode($codelang, $moreatt='', $notitlealt=0)
Return img flag of country for a language code or country code.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dolGetFirstLineOfText($text, $nboflines=1, $charset='UTF-8')
Return first line of text.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall TAKEPOS_SHOW_SUBPRICE right right right takeposterminal SELECT e e e e e statut
Definition invoice.php:1991