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
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  $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 
1164 require_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.
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.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.