dolibarr 18.0.6
knowledgerecord.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
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
24// Put here all includes required by your class file
25require_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
33{
37 public $module = 'knowledgemanagement';
38
42 public $element = 'knowledgerecord';
43
47 public $table_element = 'knowledgemanagement_knowledgerecord';
48
53 public $ismultientitymanaged = 1;
54
58 public $isextrafieldmanaged = 1;
59
63 public $picto = 'knowledgemanagement';
64
65
66 const STATUS_DRAFT = 0;
67 const STATUS_VALIDATED = 1;
68 const STATUS_CANCELED = 9;
69
70
98 // BEGIN MODULEBUILDER PROPERTIES
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
136 public $question;
137
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
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
234 public function create(User $user, $notrigger = false)
235 {
236 return $this->createCommon($user, $notrigger);
237 }
238
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
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
360 public function fetchLines()
361 {
362 $this->lines = array();
363
364 $result = $this->fetchLinesCommon();
365 return $result;
366 }
367
368
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
456 public function update(User $user, $notrigger = false)
457 {
458 return $this->updateCommon($user, $notrigger);
459 }
460
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
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
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 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'knowledgerecord/".$this->db->escape($this->newref)."'";
605 $sql .= " WHERE filepath = 'knowledgerecord/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
606 $resql = $this->db->query($sql);
607 if (!$resql) {
608 $error++; $this->error = $this->db->lasterror();
609 }
610
611 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
612 $oldref = dol_sanitizeFileName($this->ref);
613 $newref = dol_sanitizeFileName($num);
614 $dirsource = $conf->knowledgemanagement->dir_output.'/knowledgerecord/'.$oldref;
615 $dirdest = $conf->knowledgemanagement->dir_output.'/knowledgerecord/'.$newref;
616 if (!$error && file_exists($dirsource)) {
617 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
618
619 if (@rename($dirsource, $dirdest)) {
620 dol_syslog("Rename ok");
621 // Rename docs starting with $oldref with $newref
622 $listoffiles = dol_dir_list($conf->knowledgemanagement->dir_output.'/knowledgerecord/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
623 foreach ($listoffiles as $fileentry) {
624 $dirsource = $fileentry['name'];
625 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
626 $dirsource = $fileentry['path'].'/'.$dirsource;
627 $dirdest = $fileentry['path'].'/'.$dirdest;
628 @rename($dirsource, $dirdest);
629 }
630 }
631 }
632 }
633 }
634
635 // Set new ref and current status
636 if (!$error) {
637 $this->ref = $num;
638 $this->status = self::STATUS_VALIDATED;
639 }
640
641 if (!$error) {
642 $this->db->commit();
643 return 1;
644 } else {
645 $this->db->rollback();
646 return -1;
647 }
648 }
649
650
658 public function setDraft($user, $notrigger = 0)
659 {
660 // Protection
661 if ($this->status <= self::STATUS_DRAFT) {
662 return 0;
663 }
664
665 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
666 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
667 {
668 $this->error='Permission denied';
669 return -1;
670 }*/
671
672 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'KNOWLEDGERECORD_UNVALIDATE');
673 }
674
682 public function cancel($user, $notrigger = 0)
683 {
684 // Protection
685 if ($this->status != self::STATUS_VALIDATED) {
686 return 0;
687 }
688
689 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
690 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
691 {
692 $this->error='Permission denied';
693 return -1;
694 }*/
695
696 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'KNOWLEDGERECORD_CANCEL');
697 }
698
706 public function reopen($user, $notrigger = 0)
707 {
708 // Protection
709 if ($this->status != self::STATUS_CANCELED) {
710 return 0;
711 }
712
713 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
714 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
715 {
716 $this->error='Permission denied';
717 return -1;
718 }*/
719
720 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'KNOWLEDGERECORD_REOPEN');
721 }
722
730 public function getTooltipContentArray($params)
731 {
732 global $conf, $langs;
733
734 $langs->loadLangs(['knowledgemanagement', 'languages']);
735
736 $datas = array();
737 $nofetch = !empty($params['nofetch']);
738
739 $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("KnowledgeRecord").'</u>';
740 if (isset($this->statut)) {
741 $datas['picto'] .= ' '.$this->getLibStatut(5);
742 }
743 $datas['label'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
744 $datas['question'] = '<br><b>'.$langs->trans('Question').':</b> '.$this->question;
745 $labellang = ($this->lang ? $langs->trans('Language_'.$this->lang) : '');
746 $datas['lang'] = '<br><b>'.$langs->trans('Language').':</b> ' . picto_from_langcode($this->lang, 'class="paddingrightonly saturatemedium opacitylow"') . $labellang;
747 // show categories for this record only in ajax to not overload lists
748 if (isModEnabled('categorie') && !$nofetch) {
749 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
750 $form = new Form($this->db);
751 $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_KNOWLEDGEMANAGEMENT, 1);
752 }
753
754 return $datas;
755 }
756
767 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
768 {
769 global $conf, $langs, $hookmanager;
770
771 if (!empty($conf->dol_no_mouse_hover)) {
772 $notooltip = 1; // Force disable tooltips
773 }
774
775 $result = '';
776
777 $params = [
778 'id' => $this->id,
779 'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
780 'option' => $option,
781 'nofetch' => 1,
782 ];
783 $classfortooltip = 'classfortooltip';
784 $dataparams = '';
785 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
786 $classfortooltip = 'classforajaxtooltip';
787 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
788 $label = '';
789 } else {
790 $label = implode($this->getTooltipContentArray($params));
791 }
792
793 $url = dol_buildpath('/knowledgemanagement/knowledgerecord_card.php', 1).'?id='.$this->id;
794
795 if ($option != 'nolink') {
796 // Add param to save lastsearch_values or not
797 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
798 if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
799 $add_save_lastsearch_values = 1;
800 }
801 if ($add_save_lastsearch_values) {
802 $url .= '&save_lastsearch_values=1';
803 }
804 }
805
806 $linkclose = '';
807 if (empty($notooltip)) {
808 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
809 $label = $langs->trans("ShowKnowledgeRecord");
810 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
811 }
812 $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
813 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
814 } else {
815 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
816 }
817
818 if ($option == 'nolink') {
819 $linkstart = '<span';
820 } else {
821 $linkstart = '<a href="'.$url.'"';
822 }
823 $linkstart .= $linkclose.'>';
824 if ($option == 'nolink') {
825 $linkend = '</span>';
826 } else {
827 $linkend = '</a>';
828 }
829
830 $result .= $linkstart;
831
832 if (empty($this->showphoto_on_popup)) {
833 if ($withpicto) {
834 $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);
835 }
836 } else {
837 if ($withpicto) {
838 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
839
840 list($class, $module) = explode('@', $this->picto);
841 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
842 $filearray = dol_dir_list($upload_dir, "files");
843 $filename = $filearray[0]['name'];
844 if (!empty($filename)) {
845 $pospoint = strpos($filearray[0]['name'], '.');
846
847 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
848 if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) {
849 $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>';
850 } else {
851 $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>';
852 }
853
854 $result .= '</div>';
855 } else {
856 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
857 }
858 }
859 }
860
861 if ($withpicto != 2) {
862 $result .= $this->ref;
863 }
864
865 $result .= $linkend;
866 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
867
868 global $action, $hookmanager;
869 $hookmanager->initHooks(array('knowledgerecorddao'));
870 $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
871 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
872 if ($reshook > 0) {
873 $result = $hookmanager->resPrint;
874 } else {
875 $result .= $hookmanager->resPrint;
876 }
877
878 return $result;
879 }
880
887 public function getLibStatut($mode = 0)
888 {
889 return $this->LibStatut($this->status, $mode);
890 }
891
892 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
900 public function LibStatut($status, $mode = 0)
901 {
902 // phpcs:enable
903 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
904 global $langs;
905 //$langs->load("knowledgemanagement");
906 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
907 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
908 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Obsolete');
909 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
910 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
911 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Obsolete');
912 }
913
914 $statusType = 'status'.$status;
915 if ($status == self::STATUS_VALIDATED) $statusType = 'status4';
916 if ($status == self::STATUS_CANCELED) {
917 $statusType = 'status6';
918 }
919
920 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
921 }
922
929 public function info($id)
930 {
931 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
932 $sql .= ' fk_user_creat, fk_user_modif';
933 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
934 $sql .= ' WHERE t.rowid = '.((int) $id);
935 $result = $this->db->query($sql);
936 if ($result) {
937 if ($this->db->num_rows($result)) {
938 $obj = $this->db->fetch_object($result);
939 $this->id = $obj->rowid;
940
941 $this->user_creation_id = $obj->fk_user_creat;
942 $this->user_modification_id = $obj->fk_user_modif;
943 $this->date_creation = $this->db->jdate($obj->datec);
944 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
945 }
946
947 $this->db->free($result);
948 } else {
949 dol_print_error($this->db);
950 }
951 }
952
959 public function initAsSpecimen()
960 {
961 $this->question = "ABCD";
962 $this->initAsSpecimenCommon();
963 }
964
970 public function getLinesArray()
971 {
972 $this->lines = array();
973
974 $objectline = new KnowledgeRecordLine($this->db);
975 $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_knowledgerecord = '.((int) $this->id)));
976
977 if (is_numeric($result)) {
978 $this->error = $objectline->error;
979 $this->errors = $objectline->errors;
980 return $result;
981 } else {
982 $this->lines = $result;
983 return $this->lines;
984 }
985 }
986
992 public function getNextNumRef()
993 {
994 global $langs, $conf;
995 $langs->load("knowledgemanagement");
996
997 if (empty($conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON)) {
998 $conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON = 'mod_knowledgerecord_standard';
999 }
1000
1001 if (!empty($conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON)) {
1002 $mybool = false;
1003
1004 $file = $conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON.".php";
1005 $classname = $conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON;
1006
1007 // Include file with class
1008 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1009 foreach ($dirmodels as $reldir) {
1010 $dir = dol_buildpath($reldir."core/modules/knowledgemanagement/");
1011
1012 // Load file with numbering class (if found)
1013 $mybool |= @include_once $dir.$file;
1014 }
1015
1016 if ($mybool === false) {
1017 dol_print_error('', "Failed to include file ".$file);
1018 return '';
1019 }
1020
1021 if (class_exists($classname)) {
1022 $obj = new $classname();
1023 $numref = $obj->getNextValue($this);
1024
1025 if ($numref != '' && $numref != '-1') {
1026 return $numref;
1027 } else {
1028 $this->error = $obj->error;
1029 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1030 return "";
1031 }
1032 } else {
1033 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1034 return "";
1035 }
1036 } else {
1037 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1038 return "";
1039 }
1040 }
1041
1053 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1054 {
1055 global $conf, $langs;
1056
1057 $result = 0;
1058 $includedocgeneration = 0;
1059
1060 $langs->load("knowledgemanagement");
1061
1062 if (!dol_strlen($modele)) {
1063 $modele = 'standard_knowledgerecord';
1064
1065 if (!empty($this->model_pdf)) {
1066 $modele = $this->model_pdf;
1067 } elseif (!empty($conf->global->KNOWLEDGERECORD_ADDON_PDF)) {
1068 $modele = $conf->global->KNOWLEDGERECORD_ADDON_PDF;
1069 }
1070 }
1071
1072 $modelpath = "core/modules/knowledgemanagement/doc/";
1073
1074 if ($includedocgeneration && !empty($modele)) {
1075 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1076 }
1077
1078 return $result;
1079 }
1080
1088 public function doScheduledJob()
1089 {
1090 global $conf, $langs;
1091
1092 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1093
1094 $error = 0;
1095 $this->output = '';
1096 $this->error = '';
1097
1098 dol_syslog(__METHOD__, LOG_DEBUG);
1099
1100 $now = dol_now();
1101
1102 $this->db->begin();
1103
1104 // ...
1105
1106 $this->db->commit();
1107
1108 return $error;
1109 }
1110
1121 public function setCategories($categories)
1122 {
1123 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1124 return parent::setCategoriesCommon($categories, Categorie::TYPE_KNOWLEDGEMANAGEMENT);
1125 }
1126
1134 public function getKanbanView($option = '', $arraydata = null)
1135 {
1136 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1137
1138 $return = '<div class="box-flex-item box-flex-grow-zero">';
1139 $return .= '<div class="info-box info-box-sm">';
1140 $return .= '<span class="info-box-icon bg-infobox-action">';
1141 $return .= img_picto('', $this->picto);
1142 $return .= '</span>';
1143 $return .= '<div class="info-box-content">';
1144 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).'</span>';
1145 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1146 if (property_exists($this, 'lang') && !empty($this->lang)) {
1147 //$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>';
1148 $return .= '<br>'.picto_from_langcode($this->lang, 'class="paddingrightonly saturatemedium opacitylow paddingrightonly"');
1149 }
1150 if (property_exists($this, 'question')) {
1151 $return .= '<span class="info-box-label">'.dolGetFirstLineOfText($this->question).'</span>';
1152 }
1153 if (method_exists($this, 'getLibStatut')) {
1154 $return .= '<br><div class="info-box-status margintoponly">'.$this->getLibStatut(3).'</div>';
1155 }
1156 $return .= '</div>';
1157 $return .= '</div>';
1158 $return .= '</div>';
1159 return $return;
1160 }
1161}
1162
1163
1164require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1165
1170{
1171 // To complete with content of an object KnowledgeRecordLine
1172 // We should have a field rowid, fk_knowledgerecord and position
1173
1177 public $isextrafieldmanaged = 0;
1178
1184 public function __construct(DoliDB $db)
1185 {
1186 $this->db = $db;
1187 }
1188}
$object ref
Definition info.php:78
Parent class of all other business classes (invoices, contracts, proposals, orders,...
deleteLineCommon(User $user, $idline, $notrigger=false)
Delete a line of object in database.
fetchCommon($id, $ref=null, $morewhere='')
Load object in memory from the database.
createCommon(User $user, $notrigger=false)
Create object into database.
deleteCommon(User $user, $notrigger=false, $forcechilddeletion=0)
Delete object in database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
copy_linked_contact($objFrom, $source='internal')
Copy contact from one element to current.
updateCommon(User $user, $notrigger=false)
Update object into database.
fetchLinesCommon($morewhere='')
Load object in memory from the 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.
info($id)
Load the info information in the object.
cancel($user, $notrigger=0)
Set cancel status.
deleteLine(User $user, $idline, $notrigger=false)
Delete a line of object in database.
fetchLines()
Load object lines in memory from the database.
LibStatut($status, $mode=0)
Return the status.
create(User $user, $notrigger=false)
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 optionaly the picto)
createFromClone(User $user, $fromid)
Clone an object into another one.
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.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter=array(), $filtermode='AND')
Load list of objects in memory from the database.
update(User $user, $notrigger=false)
Update object into database.
Class KnowledgeRecordLine.
__construct(DoliDB $db)
Constructor.
Class to manage Dolibarr users.
print $langs trans("Ref").' m m m statut
Definition index.php:152
dol_dir_list($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:62
picto_from_langcode($codelang, $moreatt='', $notitlealt=0)
Return img flag of country for a language code or country code.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
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_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.