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