dolibarr  19.0.0-dev
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
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 
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 
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 
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 
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 
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 
724  public function getTooltipContentArray($params)
725  {
726  global $conf, $langs;
727 
728  $langs->loadLangs(['knowledgemanagement', 'languages']);
729 
730  $datas = array();
731  $nofetch = !empty($params['nofetch']);
732 
733  $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("KnowledgeRecord").'</u>';
734  if (isset($this->statut)) {
735  $datas['picto'] .= ' '.$this->getLibStatut(5);
736  }
737  $datas['label'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
738  $datas['question'] = '<br><b>'.$langs->trans('Question').':</b> '.$this->question;
739  $labellang = ($this->lang ? $langs->trans('Language_'.$this->lang) : '');
740  $datas['lang'] = '<br><b>'.$langs->trans('Language').':</b> ' . picto_from_langcode($this->lang, 'class="paddingrightonly saturatemedium opacitylow"') . $labellang;
741  // show categories for this record only in ajax to not overload lists
742  if (isModEnabled('categorie') && !$nofetch) {
743  require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
744  $form = new Form($this->db);
745  $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_KNOWLEDGEMANAGEMENT, 1);
746  }
747 
748  return $datas;
749  }
750 
761  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
762  {
763  global $conf, $langs, $hookmanager;
764 
765  if (!empty($conf->dol_no_mouse_hover)) {
766  $notooltip = 1; // Force disable tooltips
767  }
768 
769  $result = '';
770 
771  $params = [
772  'id' => $this->id,
773  'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
774  'option' => $option,
775  'nofetch' => 1,
776  ];
777  $classfortooltip = 'classfortooltip';
778  $dataparams = '';
779  if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
780  $classfortooltip = 'classforajaxtooltip';
781  $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
782  $label = '';
783  } else {
784  $label = implode($this->getTooltipContentArray($params));
785  }
786 
787  $url = dol_buildpath('/knowledgemanagement/knowledgerecord_card.php', 1).'?id='.$this->id;
788 
789  if ($option != 'nolink') {
790  // Add param to save lastsearch_values or not
791  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
792  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
793  $add_save_lastsearch_values = 1;
794  }
795  if ($add_save_lastsearch_values) {
796  $url .= '&save_lastsearch_values=1';
797  }
798  }
799 
800  $linkclose = '';
801  if (empty($notooltip)) {
802  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
803  $label = $langs->trans("ShowKnowledgeRecord");
804  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
805  }
806  $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
807  $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
808  } else {
809  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
810  }
811 
812  if ($option == 'nolink') {
813  $linkstart = '<span';
814  } else {
815  $linkstart = '<a href="'.$url.'"';
816  }
817  $linkstart .= $linkclose.'>';
818  if ($option == 'nolink') {
819  $linkend = '</span>';
820  } else {
821  $linkend = '</a>';
822  }
823 
824  $result .= $linkstart;
825 
826  if (empty($this->showphoto_on_popup)) {
827  if ($withpicto) {
828  $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);
829  }
830  } else {
831  if ($withpicto) {
832  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
833 
834  list($class, $module) = explode('@', $this->picto);
835  $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
836  $filearray = dol_dir_list($upload_dir, "files");
837  $filename = $filearray[0]['name'];
838  if (!empty($filename)) {
839  $pospoint = strpos($filearray[0]['name'], '.');
840 
841  $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
842  if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
843  $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>';
844  } else {
845  $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>';
846  }
847 
848  $result .= '</div>';
849  } else {
850  $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);
851  }
852  }
853  }
854 
855  if ($withpicto != 2) {
856  $result .= $this->ref;
857  }
858 
859  $result .= $linkend;
860  //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
861 
862  global $action, $hookmanager;
863  $hookmanager->initHooks(array('knowledgerecorddao'));
864  $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
865  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
866  if ($reshook > 0) {
867  $result = $hookmanager->resPrint;
868  } else {
869  $result .= $hookmanager->resPrint;
870  }
871 
872  return $result;
873  }
874 
881  public function getLibStatut($mode = 0)
882  {
883  return $this->LibStatut($this->status, $mode);
884  }
885 
886  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
894  public function LibStatut($status, $mode = 0)
895  {
896  // phpcs:enable
897  if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
898  global $langs;
899  //$langs->load("knowledgemanagement");
900  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
901  $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
902  $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Obsolete');
903  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
904  $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
905  $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Obsolete');
906  }
907 
908  $statusType = 'status'.$status;
909  if ($status == self::STATUS_VALIDATED) $statusType = 'status4';
910  if ($status == self::STATUS_CANCELED) {
911  $statusType = 'status6';
912  }
913 
914  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
915  }
916 
923  public function info($id)
924  {
925  $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
926  $sql .= ' fk_user_creat, fk_user_modif';
927  $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
928  $sql .= ' WHERE t.rowid = '.((int) $id);
929  $result = $this->db->query($sql);
930  if ($result) {
931  if ($this->db->num_rows($result)) {
932  $obj = $this->db->fetch_object($result);
933  $this->id = $obj->rowid;
934 
935  $this->user_creation_id = $obj->fk_user_creat;
936  $this->user_modification_id = $obj->fk_user_modif;
937  $this->date_creation = $this->db->jdate($obj->datec);
938  $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
939  }
940 
941  $this->db->free($result);
942  } else {
943  dol_print_error($this->db);
944  }
945  }
946 
953  public function initAsSpecimen()
954  {
955  $this->question = "ABCD";
956  $this->initAsSpecimenCommon();
957  }
958 
964  public function getLinesArray()
965  {
966  $this->lines = array();
967 
968  $objectline = new KnowledgeRecordLine($this->db);
969  $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_knowledgerecord = '.((int) $this->id)));
970 
971  if (is_numeric($result)) {
972  $this->error = $objectline->error;
973  $this->errors = $objectline->errors;
974  return $result;
975  } else {
976  $this->lines = $result;
977  return $this->lines;
978  }
979  }
980 
986  public function getNextNumRef()
987  {
988  global $langs, $conf;
989  $langs->load("knowledgemanagement");
990 
991  if (empty($conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON)) {
992  $conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON = 'mod_knowledgerecord_standard';
993  }
994 
995  if (!empty($conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON)) {
996  $mybool = false;
997 
998  $file = $conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON.".php";
999  $classname = $conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON;
1000 
1001  // Include file with class
1002  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1003  foreach ($dirmodels as $reldir) {
1004  $dir = dol_buildpath($reldir."core/modules/knowledgemanagement/");
1005 
1006  // Load file with numbering class (if found)
1007  $mybool |= @include_once $dir.$file;
1008  }
1009 
1010  if ($mybool === false) {
1011  dol_print_error('', "Failed to include file ".$file);
1012  return '';
1013  }
1014 
1015  if (class_exists($classname)) {
1016  $obj = new $classname();
1017  $numref = $obj->getNextValue($this);
1018 
1019  if ($numref != '' && $numref != '-1') {
1020  return $numref;
1021  } else {
1022  $this->error = $obj->error;
1023  //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1024  return "";
1025  }
1026  } else {
1027  print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1028  return "";
1029  }
1030  } else {
1031  print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1032  return "";
1033  }
1034  }
1035 
1047  public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1048  {
1049  global $conf, $langs;
1050 
1051  $result = 0;
1052  $includedocgeneration = 0;
1053 
1054  $langs->load("knowledgemanagement");
1055 
1056  if (!dol_strlen($modele)) {
1057  $modele = 'standard_knowledgerecord';
1058 
1059  if (!empty($this->model_pdf)) {
1060  $modele = $this->model_pdf;
1061  } elseif (!empty($conf->global->KNOWLEDGERECORD_ADDON_PDF)) {
1062  $modele = $conf->global->KNOWLEDGERECORD_ADDON_PDF;
1063  }
1064  }
1065 
1066  $modelpath = "core/modules/knowledgemanagement/doc/";
1067 
1068  if ($includedocgeneration && !empty($modele)) {
1069  $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1070  }
1071 
1072  return $result;
1073  }
1074 
1082  public function doScheduledJob()
1083  {
1084  global $conf, $langs;
1085 
1086  //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1087 
1088  $error = 0;
1089  $this->output = '';
1090  $this->error = '';
1091 
1092  dol_syslog(__METHOD__, LOG_DEBUG);
1093 
1094  $now = dol_now();
1095 
1096  $this->db->begin();
1097 
1098  // ...
1099 
1100  $this->db->commit();
1101 
1102  return $error;
1103  }
1104 
1115  public function setCategories($categories)
1116  {
1117  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1118  return parent::setCategoriesCommon($categories, Categorie::TYPE_KNOWLEDGEMANAGEMENT);
1119  }
1120 
1128  public function getKanbanView($option = '', $arraydata = null)
1129  {
1130  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1131 
1132  $return = '<div class="box-flex-item box-flex-grow-zero">';
1133  $return .= '<div class="info-box info-box-sm">';
1134  $return .= '<span class="info-box-icon bg-infobox-action">';
1135  $return .= img_picto('', $this->picto);
1136  $return .= '</span>';
1137  $return .= '<div class="info-box-content">';
1138  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).'</span>';
1139  $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1140  if (property_exists($this, 'lang') && !empty($this->lang)) {
1141  //$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>';
1142  $return .= '<br>'.picto_from_langcode($this->lang, 'class="paddingrightonly saturatemedium opacitylow paddingrightonly"');
1143  }
1144  if (property_exists($this, 'question')) {
1145  $return .= '<span class="info-box-label">'.dolGetFirstLineOfText($this->question).'</span>';
1146  }
1147  if (method_exists($this, 'getLibStatut')) {
1148  $return .= '<br><div class="info-box-status margintoponly">'.$this->getLibStatut(3).'</div>';
1149  }
1150  $return .= '</div>';
1151  $return .= '</div>';
1152  $return .= '</div>';
1153  return $return;
1154  }
1155 }
1156 
1157 
1158 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1159 
1164 {
1165  // To complete with content of an object KnowledgeRecordLine
1166  // We should have a field rowid, fk_knowledgerecord and position
1167 
1171  public $isextrafieldmanaged = 0;
1172 
1178  public function __construct(DoliDB $db)
1179  {
1180  $this->db = $db;
1181  }
1182 }
$object ref
Definition: info.php:78
Parent class of all other business classes (invoices, contracts, proposals, orders,...
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
deleteLineCommon(User $user, $idline, $notrigger=false)
Delete a line of object in database.
getFieldList($alias='')
Function to concat keys of fields.
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.
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.
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.
Definition: user.class.php:48
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
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)
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
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.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.