Passed
Push — EXTRACT_CLASSES ( 9f3ede...ff35ec )
by Rafael
76:09 queued 20:57
created

KnowledgeRecord::validate()   F

Complexity

Conditions 22
Paths 2801

Size

Total Lines 122
Code Lines 71

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 22
eloc 71
nc 2801
nop 2
dl 0
loc 122
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* Copyright (C) 2017       Laurent Destailleur         <[email protected]>
4
 * Copyright (C) 2024       Frédéric France             <[email protected]>
5
 * Copyright (C) 2024		MDW							<[email protected]>
6
 * Copyright (C) 2024       Rafael San José             <[email protected]>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Dolibarr\Code\KnowledgeManagement\Classes;
23
24
use Dolibarr\Core\Base\CommonObject;
25
26
/**
27
 * \file        htdocs/knowledgemanagement/class/knowledgerecord.class.php
28
 * \ingroup     knowledgemanagement
29
 * \brief       This file is a CRUD class file for KnowledgeRecord (Create/Read/Update/Delete)
30
 */
31
32
// Put here all includes required by your class file
33
//require_once constant('DOL_DOCUMENT_ROOT') . '/societe/class/societe.class.php';
34
//require_once constant('DOL_DOCUMENT_ROOT') . '/product/class/product.class.php';
35
36
/**
37
 * Class for KnowledgeRecord
38
 */
39
class KnowledgeRecord extends CommonObject
40
{
41
    /**
42
     * @var string ID of module.
43
     */
44
    public $module = 'knowledgemanagement';
45
46
    /**
47
     * @var string ID to identify managed object.
48
     */
49
    public $element = 'knowledgerecord';
50
51
    /**
52
     * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
53
     */
54
    public $table_element = 'knowledgemanagement_knowledgerecord';
55
56
    /**
57
     * @var string String with name of icon for knowledgerecord. Must be the part after the 'object_' into object_knowledgerecord.png
58
     */
59
    public $picto = 'knowledgemanagement';
60
61
62
    const STATUS_DRAFT = 0;
63
    const STATUS_VALIDATED = 1;
64
    const STATUS_CANCELED = 9;
65
66
67
    /**
68
     *  'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:SortField]]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password')
69
     *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
70
     *  'label' the translation key.
71
     *  'picto' is code of a picto to show before value in forms
72
     *  'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalString("MY_SETUP_PARAM")'
73
     *  'position' is the sort order of field.
74
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
75
     *  'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
76
     *  'noteditable' says if field is not editable (1 or 0)
77
     *  'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
78
     *  'index' if we want an index in database.
79
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
80
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
81
     *  'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
82
     *  'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'maxwidth200', 'wordbreak', 'tdoverflowmax200'
83
     *  'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
84
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
85
     *  'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
86
     *  'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
87
     *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
88
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
89
     *  'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value)
90
     *
91
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
92
     */
93
94
    // BEGIN MODULEBUILDER PROPERTIES
95
    /**
96
     * @var array<string,array{type:string,label:string,enabled:int<0,2>|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array<int,string>,comment?:string}>  Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string,array{type:...ring>,comment?:string}> at position 16 could not be parsed: Expected '}' at position 16, but found 'int'.
Loading history...
97
     */
98
    public $fields = array(
99
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
100
        '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),
101
        'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'position' => 20, 'index' => 1),
102
        'question' => array('type' => 'text', 'label' => 'Question', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'searchall' => 1, 'csslist' => 'tdoverflowmax300 small', 'copytoclipboard' => 1, 'tdcss' => 'titlefieldcreate nowraponall'),
103
        'lang' => array('type' => 'varchar(6)', 'label' => 'Language', 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => 1, 'tdcss' => 'titlefieldcreate nowraponall', "csslist" => "minwidth100 maxwidth200"),
104
        'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2, 'csslist' => 'nowraponall'),
105
        'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => 2,),
106
        'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0,),
107
        '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',),
108
        'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
109
        'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'position' => 512, 'notnull' => 0, 'visible' => -2,),
110
        'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
111
        'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
112
        //'url' => array('type'=>'varchar(255)', 'label'=>'URL', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1, 'csslist'=>'tdoverflow200', 'help'=>'UrlForInfoPage'),
113
        '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'),
114
        'answer' => array('type' => 'html', 'label' => 'Solution', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 3, 'searchall' => 1, 'csslist' => 'tdoverflowmax300', 'copytoclipboard' => 1, 'tdcss' => 'titlefieldcreate nowraponall'),
115
        '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'),),
116
    );
117
    public $rowid;
118
    public $ref;
119
    public $entity;
120
    public $date_creation;
121
    public $last_main_doc;
122
    public $fk_user_creat;
123
    public $fk_user_modif;
124
    public $fk_user_valid;
125
    public $import_key;
126
    public $model_pdf;
127
128
    /**
129
     * @var string question asked
130
     */
131
    public $question;
132
133
    /**
134
     * @var string answer to question
135
     */
136
    public $answer;
137
    public $url;
138
    public $status;
139
    public $lang;
140
    // END MODULEBUILDER PROPERTIES
141
142
143
    // If this object has a subtable with lines
144
145
    // /**
146
    //  * @var string    Name of subtable line
147
    //  */
148
    // public $table_element_line = 'knowledgemanagement_knowledgerecordline';
149
150
    // /**
151
    //  * @var string    Field with ID of parent key if this object has a parent
152
    //  */
153
    // public $fk_element = 'fk_knowledgerecord';
154
155
    // /**
156
    //  * @var string    Name of subtable class that manage subtable lines
157
    //  */
158
    // public $class_element_line = 'KnowledgeRecordline';
159
160
    // /**
161
    //  * @var array    List of child tables. To test if we can delete object.
162
    //  */
163
    // protected $childtables = array();
164
165
    // /**
166
    //  * @var array    List of child tables. To know object to delete on cascade.
167
    //  *               If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will
168
    //  *               call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
169
    //  */
170
    // protected $childtablesoncascade = array('knowledgemanagement_knowledgerecorddet');
171
172
    // /**
173
    //  * @var KnowledgeRecordLine[]     Array of subtable lines
174
    //  */
175
    // public $lines = array();
176
177
178
179
    /**
180
     * Constructor
181
     *
182
     * @param DoliDB $db Database handler
183
     */
184
    public function __construct(DoliDB $db)
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\KnowledgeManagement\Classes\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
185
    {
186
        global $langs;
187
188
        $this->db = $db;
189
190
        $this->ismultientitymanaged = 1;
191
        $this->isextrafieldmanaged = 1;
192
193
        if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
194
            $this->fields['rowid']['visible'] = 0;
195
        }
196
        if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
197
            $this->fields['entity']['enabled'] = 0;
198
        }
199
200
        // Unset fields that are disabled
201
        foreach ($this->fields as $key => $val) {
202
            if (isset($val['enabled']) && empty($val['enabled'])) {
203
                unset($this->fields[$key]);
204
            }
205
        }
206
207
        // Translate some data of arrayofkeyval
208
        if (is_object($langs)) {
209
            foreach ($this->fields as $key => $val) {
210
                if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
211
                    foreach ($val['arrayofkeyval'] as $key2 => $val2) {
212
                        $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
213
                    }
214
                }
215
            }
216
        }
217
    }
218
219
    /**
220
     * Create object into database
221
     *
222
     * @param  User $user      User that creates
223
     * @param  int  $notrigger 0=launch triggers after, 1=disable triggers
224
     * @return int             Return integer <0 if KO, Id of created object if OK
225
     */
226
    public function create(User $user, $notrigger = 0)
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\KnowledgeManagement\Classes\User was not found. Did you mean User? If so, make sure to prefix the type with \.
Loading history...
227
    {
228
        return $this->createCommon($user, $notrigger);
229
    }
230
231
    /**
232
     * Clone an object into another one
233
     *
234
     * @param   User    $user       User that creates
235
     * @param   int     $fromid     Id of object to clone
236
     * @return  mixed               New object created, <0 if KO
237
     */
238
    public function createFromClone(User $user, $fromid)
239
    {
240
        global $langs, $extrafields;
241
        $error = 0;
242
243
        dol_syslog(__METHOD__, LOG_DEBUG);
244
245
        $object = new self($this->db);
246
247
        $this->db->begin();
248
249
        // Load source object
250
        $result = $object->fetchCommon($fromid);
251
        if ($result > 0 && !empty($object->table_element_line)) {
252
            $object->fetchLines();
253
        }
254
255
        // get lines so they will be clone
256
        //foreach($this->lines as $line)
257
        //  $line->fetch_optionals();
258
259
        // Reset some properties
260
        unset($object->id);
261
        unset($object->fk_user_creat);
262
        unset($object->import_key);
263
264
        // Clear fields
265
        if (property_exists($object, 'ref')) {
266
            $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_" . $object->ref : $this->fields['ref']['default'];
267
        }
268
        if (property_exists($object, 'question')) {
269
            $object->question = empty($this->fields['question']['default']) ? $langs->trans("CopyOf") . " " . $object->question : $this->fields['question']['default'];
270
        }
271
        if (property_exists($object, 'status')) {
272
            $object->status = self::STATUS_DRAFT;
273
        }
274
        if (property_exists($object, 'date_creation')) {
275
            $object->date_creation = dol_now();
276
        }
277
        if (property_exists($object, 'date_modification')) {
278
            $object->date_modification = null;
279
        }
280
        // ...
281
        // Clear extrafields that are unique
282
        if (is_array($object->array_options) && count($object->array_options) > 0) {
283
            $extrafields->fetch_name_optionals_label($this->table_element);
284
            foreach ($object->array_options as $key => $option) {
285
                $shortkey = preg_replace('/options_/', '', $key);
286
                if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
287
                    //var_dump($key);
288
                    //var_dump($clonedObj->array_options[$key]); exit;
289
                    unset($object->array_options[$key]);
290
                }
291
            }
292
        }
293
294
        // Create clone
295
        $object->context['createfromclone'] = 'createfromclone';
296
        $result = $object->createCommon($user);
297
        if ($result < 0) {
298
            $error++;
299
            $this->error = $object->error;
300
            $this->errors = $object->errors;
301
        }
302
303
        if (!$error) {
304
            // copy internal contacts
305
            if ($this->copy_linked_contact($object, 'internal') < 0) {
306
                $error++;
307
            }
308
        }
309
310
        if (!$error) {
311
            // copy external contacts if same company
312
            if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
313
                if ($this->copy_linked_contact($object, 'external') < 0) {
314
                    $error++;
315
                }
316
            }
317
        }
318
319
        unset($object->context['createfromclone']);
320
321
        // End
322
        if (!$error) {
323
            $this->db->commit();
324
            return $object;
325
        } else {
326
            $this->db->rollback();
327
            return -1;
328
        }
329
    }
330
331
    /**
332
     * Load object in memory from the database
333
     *
334
     * @param int    $id   Id object
335
     * @param string $ref  Ref
336
     * @return int         Return integer <0 if KO, 0 if not found, >0 if OK
337
     */
338
    public function fetch($id, $ref = null)
339
    {
340
        $result = $this->fetchCommon($id, $ref);
341
        if ($result > 0 && !empty($this->table_element_line)) {
342
            $this->fetchLines();
343
        }
344
        return $result;
345
    }
346
347
    /**
348
     * Load object lines in memory from the database
349
     *
350
     * @return int         Return integer <0 if KO, 0 if not found, >0 if OK
351
     */
352
    public function fetchLines()
353
    {
354
        $this->lines = array();
355
356
        $result = $this->fetchLinesCommon();
357
        return $result;
358
    }
359
360
361
    /**
362
     * Load list of objects in memory from the database.
363
     *
364
     * @param  string           $sortorder      Sort Order
365
     * @param  string           $sortfield      Sort field
366
     * @param  int              $limit          Limit
367
     * @param  int              $offset         Offset
368
     * @param  string|array     $filter         Filter USF.
369
     * @param  string           $filtermode     Filter mode (AND or OR)
370
     * @return array|int                        int <0 if KO, array of pages if OK
371
     */
372
    public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
373
    {
374
        dol_syslog(__METHOD__, LOG_DEBUG);
375
376
        $records = array();
377
378
        $sql = 'SELECT ';
379
        $sql .= $this->getFieldList('t');
380
        $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
381
        if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
382
            $sql .= ' WHERE t.entity IN (' . getEntity($this->element) . ')';
383
        } else {
384
            $sql .= ' WHERE 1 = 1';
385
        }
386
387
        // Manage filter
388
        if (is_array($filter)) {
389
            $sqlwhere = array();
390
            if (count($filter) > 0) {
391
                foreach ($filter as $key => $value) {
392
                    if ($key == 't.rowid') {
393
                        $sqlwhere[] = $this->db->sanitize($key) . " = " . ((int) $value);
394
                    } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) {
395
                        $sqlwhere[] = $this->db->sanitize($key) . " = '" . $this->db->idate($value) . "'";
396
                    } elseif (strpos($value, '%') === false) {
397
                        $sqlwhere[] = $this->db->sanitize($key) . ' IN (' . $this->db->sanitize($this->db->escape($value)) . ')';
398
                    } else {
399
                        $sqlwhere[] = $this->db->sanitize($key) . " LIKE '%" . $this->db->escape($this->db->escapeforlike($value)) . "%'";
400
                    }
401
                }
402
            }
403
            if (count($sqlwhere) > 0) {
404
                $sql .= ' AND (' . implode(' ' . $this->db->escape($filtermode) . ' ', $sqlwhere) . ')';
405
            }
406
407
            $filter = '';
408
        }
409
410
        // Manage filter
411
        $errormessage = '';
412
        $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
413
        if ($errormessage) {
414
            $this->errors[] = $errormessage;
415
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
416
            return -1;
417
        }
418
419
        if (!empty($sortfield)) {
420
            $sql .= $this->db->order($sortfield, $sortorder);
421
        }
422
        if (!empty($limit)) {
423
            $sql .= $this->db->plimit($limit, $offset);
424
        }
425
426
        $resql = $this->db->query($sql);
427
        if ($resql) {
428
            $num = $this->db->num_rows($resql);
429
            $i = 0;
430
            while ($i < ($limit ? min($limit, $num) : $num)) {
431
                $obj = $this->db->fetch_object($resql);
432
433
                $record = new self($this->db);
434
                $record->setVarsFromFetchObj($obj);
435
436
                $records[$record->id] = $record;
437
438
                $i++;
439
            }
440
            $this->db->free($resql);
441
442
            return $records;
443
        } else {
444
            $this->errors[] = 'Error ' . $this->db->lasterror();
445
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
446
447
            return -1;
448
        }
449
    }
450
451
    /**
452
     * Update object into database
453
     *
454
     * @param  User $user      User that modifies
455
     * @param  int  $notrigger 0=launch triggers after, 1=disable triggers
456
     * @return int             Return integer <0 if KO, >0 if OK
457
     */
458
    public function update(User $user, $notrigger = 0)
459
    {
460
        return $this->updateCommon($user, $notrigger);
461
    }
462
463
    /**
464
     * Delete object in database
465
     *
466
     * @param User  $user       User that deletes
467
     * @param int   $notrigger  0=launch triggers after, 1=disable triggers
468
     * @return int              Return integer <0 if KO, >0 if OK
469
     */
470
    public function delete(User $user, $notrigger = 0)
471
    {
472
        $error = 0;
473
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "categorie_knowledgemanagement WHERE fk_knowledgemanagement = " . ((int) $this->id);
474
        dol_syslog(get_class($this) . "::delete", LOG_DEBUG);
475
        $resql = $this->db->query($sql);
476
        if (!$resql) {
477
            $error++;
478
            $this->error .= $this->db->lasterror();
479
            $errorflag = -1;
480
        }
481
482
        // Delete all child tables
483
        if (!$error) {
484
            $elements = array('categorie_knowledgemanagement');
485
            foreach ($elements as $table) {
486
                if (!$error) {
487
                    $sql = "DELETE FROM " . MAIN_DB_PREFIX . $table;
488
                    $sql .= " WHERE fk_knowledgemanagement = " . (int) $this->id;
489
490
                    $result = $this->db->query($sql);
491
                    if (!$result) {
492
                        $error++;
493
                        $this->errors[] = $this->db->lasterror();
494
                    }
495
                }
496
            }
497
        }
498
499
        return $this->deleteCommon($user, $notrigger);
500
        //return $this->deleteCommon($user, $notrigger, 1);
501
    }
502
503
    /**
504
     *  Delete a line of object in database
505
     *
506
     *  @param  User    $user       User that delete
507
     *  @param  int     $idline     Id of line to delete
508
     *  @param  int     $notrigger  0=launch triggers after, 1=disable triggers
509
     *  @return int                 Return >0 if OK, <0 if KO
510
     */
511
    public function deleteLine(User $user, $idline, $notrigger = 0)
512
    {
513
        if ($this->status < 0) {
514
            $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
515
            return -2;
516
        }
517
518
        return $this->deleteLineCommon($user, $idline, $notrigger);
519
    }
520
521
522
    /**
523
     *  Validate object
524
     *
525
     *  @param      User    $user           User making status change
526
     *  @param      int     $notrigger      1=Does not execute triggers, 0= execute triggers
527
     *  @return     int                     Return integer <=0 if OK, 0=Nothing done, >0 if KO
528
     */
529
    public function validate($user, $notrigger = 0)
530
    {
531
        global $conf, $langs;
532
533
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
534
535
        $error = 0;
536
537
        // Protection
538
        if ($this->status == self::STATUS_VALIDATED) {
539
            dol_syslog(get_class($this) . "::validate action abandoned: already validated", LOG_WARNING);
540
            return 0;
541
        }
542
543
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->hasRight('knowledgemanagement', 'knowledgerecord', 'write'))
544
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgerecord->knowledgerecord_advance->validate))))
545
         {
546
         $this->error='NotEnoughPermissions';
547
         dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
548
         return -1;
549
         }*/
550
551
        $now = dol_now();
552
553
        $this->db->begin();
554
555
        // Define new ref
556
        if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
557
            $num = $this->getNextNumRef();
558
        } else {
559
            $num = $this->ref;
560
        }
561
        $this->newref = $num;
562
563
        if (!empty($num)) {
564
            // Validate
565
            $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
566
            $sql .= " SET ref = '" . $this->db->escape($num) . "',";
567
            $sql .= " status = " . self::STATUS_VALIDATED;
568
            if (!empty($this->fields['date_validation'])) {
569
                $sql .= ", date_validation = '" . $this->db->idate($now) . "'";
570
            }
571
            if (!empty($this->fields['fk_user_valid'])) {
572
                $sql .= ", fk_user_valid = " . ((int) $user->id);
573
            }
574
            $sql .= " WHERE rowid = " . ((int) $this->id);
575
576
            dol_syslog(get_class($this) . "::validate()", LOG_DEBUG);
577
            $resql = $this->db->query($sql);
578
            if (!$resql) {
579
                dol_print_error($this->db);
580
                $this->error = $this->db->lasterror();
581
                $error++;
582
            }
583
584
            if (!$error && !$notrigger) {
585
                // Call trigger
586
                $result = $this->call_trigger('KNOWLEDGERECORD_VALIDATE', $user);
587
                if ($result < 0) {
588
                    $error++;
589
                }
590
                // End call triggers
591
            }
592
        }
593
594
        if (!$error) {
595
            $this->oldref = $this->ref;
596
597
            // Rename directory if dir was a temporary ref
598
            if (preg_match('/^[\(]?PROV/i', $this->ref)) {
599
                // Now we rename also files into index
600
                $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) . "'";
601
                $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'knowledgerecord/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
602
                $resql = $this->db->query($sql);
603
                if (!$resql) {
604
                    $error++;
605
                    $this->error = $this->db->lasterror();
606
                }
607
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'knowledgerecord/" . $this->db->escape($this->newref) . "'";
608
                $sql .= " WHERE filepath = 'knowledgerecord/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
609
                $resql = $this->db->query($sql);
610
                if (!$resql) {
611
                    $error++;
612
                    $this->error = $this->db->lasterror();
613
                }
614
615
                // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
616
                $oldref = dol_sanitizeFileName($this->ref);
617
                $newref = dol_sanitizeFileName($num);
618
                $dirsource = $conf->knowledgemanagement->dir_output . '/knowledgerecord/' . $oldref;
619
                $dirdest = $conf->knowledgemanagement->dir_output . '/knowledgerecord/' . $newref;
620
                if (!$error && file_exists($dirsource)) {
621
                    dol_syslog(get_class($this) . "::validate() rename dir " . $dirsource . " into " . $dirdest);
622
623
                    if (@rename($dirsource, $dirdest)) {
624
                        dol_syslog("Rename ok");
625
                        // Rename docs starting with $oldref with $newref
626
                        $listoffiles = dol_dir_list($conf->knowledgemanagement->dir_output . '/knowledgerecord/' . $newref, 'files', 1, '^' . preg_quote($oldref, '/'));
627
                        foreach ($listoffiles as $fileentry) {
628
                            $dirsource = $fileentry['name'];
629
                            $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
630
                            $dirsource = $fileentry['path'] . '/' . $dirsource;
631
                            $dirdest = $fileentry['path'] . '/' . $dirdest;
632
                            @rename($dirsource, $dirdest);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rename(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

632
                            /** @scrutinizer ignore-unhandled */ @rename($dirsource, $dirdest);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
633
                        }
634
                    }
635
                }
636
            }
637
        }
638
639
        // Set new ref and current status
640
        if (!$error) {
641
            $this->ref = $num;
642
            $this->status = self::STATUS_VALIDATED;
643
        }
644
645
        if (!$error) {
646
            $this->db->commit();
647
            return 1;
648
        } else {
649
            $this->db->rollback();
650
            return -1;
651
        }
652
    }
653
654
655
    /**
656
     *  Set draft status
657
     *
658
     *  @param  User    $user           Object user that modify
659
     *  @param  int     $notrigger      1=Does not execute triggers, 0=Execute triggers
660
     *  @return int                     Return integer <0 if KO, >0 if OK
661
     */
662
    public function setDraft($user, $notrigger = 0)
663
    {
664
        // Protection
665
        if ($this->status <= self::STATUS_DRAFT) {
666
            return 0;
667
        }
668
669
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
670
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
671
         {
672
         $this->error='Permission denied';
673
         return -1;
674
         }*/
675
676
        return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'KNOWLEDGERECORD_UNVALIDATE');
677
    }
678
679
    /**
680
     *  Set cancel status
681
     *
682
     *  @param  User    $user           Object user that modify
683
     *  @param  int     $notrigger      1=Does not execute triggers, 0=Execute triggers
684
     *  @return int                     Return integer <0 if KO, 0=Nothing done, >0 if OK
685
     */
686
    public function cancel($user, $notrigger = 0)
687
    {
688
        // Protection
689
        if ($this->status != self::STATUS_VALIDATED) {
690
            return 0;
691
        }
692
693
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
694
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
695
         {
696
         $this->error='Permission denied';
697
         return -1;
698
         }*/
699
700
        return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'KNOWLEDGERECORD_CANCEL');
701
    }
702
703
    /**
704
     *  Set back to validated status
705
     *
706
     *  @param  User    $user           Object user that modify
707
     *  @param  int     $notrigger      1=Does not execute triggers, 0=Execute triggers
708
     *  @return int                     Return integer <0 if KO, 0=Nothing done, >0 if OK
709
     */
710
    public function reopen($user, $notrigger = 0)
711
    {
712
        // Protection
713
        if ($this->status != self::STATUS_CANCELED) {
714
            return 0;
715
        }
716
717
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->write))
718
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->knowledgemanagement->knowledgemanagement_advance->validate))))
719
         {
720
         $this->error='Permission denied';
721
         return -1;
722
         }*/
723
724
        return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'KNOWLEDGERECORD_REOPEN');
725
    }
726
727
    /**
728
     * getTooltipContentArray
729
     *
730
     * @param array $params ex option, infologin
731
     * @since v18
732
     * @return array
733
     */
734
    public function getTooltipContentArray($params)
735
    {
736
        global $conf, $langs;
737
738
        $langs->loadLangs(['knowledgemanagement', 'languages']);
739
740
        $datas = array();
741
        $nofetch = !empty($params['nofetch']);
742
743
        $datas['picto'] = img_picto('', $this->picto) . ' <u class="paddingrightonly">' . $langs->trans("KnowledgeRecord") . '</u>';
744
        if (isset($this->statut)) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

744
        if (isset(/** @scrutinizer ignore-deprecated */ $this->statut)) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
745
            $datas['picto'] .= ' ' . $this->getLibStatut(5);
746
        }
747
        $datas['label'] = '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
748
        $datas['question'] = '<br><b>' . $langs->trans('Question') . ':</b> ' . $this->question;
749
        $labellang = ($this->lang ? $langs->trans('Language_' . $this->lang) : '');
750
        $datas['lang'] = '<br><b>' . $langs->trans('Language') . ':</b> ' . picto_from_langcode($this->lang, 'class="paddingrightonly saturatemedium opacitylow"') . $labellang;
751
        // show categories for this record only in ajax to not overload lists
752
        if (isModEnabled('category') && !$nofetch) {
753
            require_once constant('DOL_DOCUMENT_ROOT') . '/categories/class/categorie.class.php';
754
            $form = new Form($this->db);
755
            $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_KNOWLEDGEMANAGEMENT, 1);
756
        }
757
758
        return $datas;
759
    }
760
761
    /**
762
     *  Return a link to the object card (with optionally the picto)
763
     *
764
     *  @param  int     $withpicto                  Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
765
     *  @param  string  $option                     On what the link point to ('nolink', ...)
766
     *  @param  int     $notooltip                  1=Disable tooltip
767
     *  @param  string  $morecss                    Add more css on link
768
     *  @param  int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
769
     *  @return string                              String with URL
770
     */
771
    public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
772
    {
773
        global $conf, $langs, $hookmanager;
774
775
        if (!empty($conf->dol_no_mouse_hover)) {
776
            $notooltip = 1; // Force disable tooltips
777
        }
778
779
        $result = '';
780
781
        $params = [
782
            'id' => $this->id,
783
            'objecttype' => $this->element . ($this->module ? '@' . $this->module : ''),
784
            'option' => $option,
785
            'nofetch' => 1,
786
        ];
787
        $classfortooltip = 'classfortooltip';
788
        $dataparams = '';
789
        if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
790
            $classfortooltip = 'classforajaxtooltip';
791
            $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"';
792
            $label = '';
793
        } else {
794
            $label = implode($this->getTooltipContentArray($params));
795
        }
796
797
        $url = dol_buildpath('/knowledgemanagement/knowledgerecord_card.php', 1) . '?id=' . $this->id;
798
799
        if ($option != 'nolink') {
800
            // Add param to save lastsearch_values or not
801
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
802
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
803
                $add_save_lastsearch_values = 1;
804
            }
805
            if ($add_save_lastsearch_values) {
806
                $url .= '&save_lastsearch_values=1';
807
            }
808
        }
809
810
        $linkclose = '';
811
        if (empty($notooltip)) {
812
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
813
                $label = $langs->trans("ShowKnowledgeRecord");
814
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
815
            }
816
            $linkclose .= ($label ? ' title="' . dol_escape_htmltag($label, 1) . '"' : ' title="tocomplete"');
817
            $linkclose .= $dataparams . ' class="' . $classfortooltip . ($morecss ? ' ' . $morecss : '') . '"';
818
        } else {
819
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
820
        }
821
822
        if ($option == 'nolink') {
823
            $linkstart = '<span';
824
        } else {
825
            $linkstart = '<a href="' . $url . '"';
826
        }
827
        $linkstart .= $linkclose . '>';
828
        if ($option == 'nolink') {
829
            $linkend = '</span>';
830
        } else {
831
            $linkend = '</a>';
832
        }
833
834
        $result .= $linkstart;
835
836
        if (empty($this->showphoto_on_popup)) {
837
            if ($withpicto) {
838
                $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);
839
            }
840
        } else {
841
            if ($withpicto) {
842
                require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
843
844
                list($class, $module) = explode('@', $this->picto);
845
                $upload_dir = $conf->$module->multidir_output[$conf->entity] . "/$class/" . dol_sanitizeFileName($this->ref);
846
                $filearray = dol_dir_list($upload_dir, "files");
847
                $filename = $filearray[0]['name'];
848
                if (!empty($filename)) {
849
                    $pospoint = strpos($filearray[0]['name'], '.');
850
851
                    $pathtophoto = $class . '/' . $this->ref . '/thumbs/' . substr($filename, 0, $pospoint) . '_mini' . substr($filename, $pospoint);
852
                    if (!getDolGlobalString(strtoupper($module . '_' . $class) . '_FORMATLISTPHOTOSASUSERS')) {
853
                        $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo' . $module . '" alt="No photo" border="0" src="' . constant('BASE_URL') . '/viewimage.php?modulepart=' . $module . '&entity=' . $conf->entity . '&file=' . urlencode($pathtophoto) . '"></div></div>';
854
                    } else {
855
                        $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="' . constant('BASE_URL') . '/viewimage.php?modulepart=' . $module . '&entity=' . $conf->entity . '&file=' . urlencode($pathtophoto) . '"></div>';
856
                    }
857
858
                    $result .= '</div>';
859
                } else {
860
                    $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
861
                }
862
            }
863
        }
864
865
        if ($withpicto != 2) {
866
            $result .= $this->ref;
867
        }
868
869
        $result .= $linkend;
870
        //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
871
872
        global $action, $hookmanager;
873
        $hookmanager->initHooks(array('knowledgerecorddao'));
874
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
875
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
876
        if ($reshook > 0) {
877
            $result = $hookmanager->resPrint;
878
        } else {
879
            $result .= $hookmanager->resPrint;
880
        }
881
882
        return $result;
883
    }
884
885
    /**
886
     *  Return the label of the status
887
     *
888
     *  @param  int     $mode          0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
889
     *  @return string                 Label of status
890
     */
891
    public function getLibStatut($mode = 0)
892
    {
893
        return $this->LibStatut($this->status, $mode);
894
    }
895
896
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
897
    /**
898
     *  Return the status
899
     *
900
     *  @param  int     $status        Id status
901
     *  @param  int     $mode          0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
902
     *  @return string                 Label of status
903
     */
904
    public function LibStatut($status, $mode = 0)
905
    {
906
		// phpcs:enable
907
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
908
            global $langs;
909
            //$langs->load("knowledgemanagement");
910
            $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
911
            $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
912
            $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Obsolete');
913
            $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
914
            $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
915
            $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Obsolete');
916
        }
917
918
        $statusType = 'status' . $status;
919
        if ($status == self::STATUS_VALIDATED) {
920
            $statusType = 'status4';
921
        }
922
        if ($status == self::STATUS_CANCELED) {
923
            $statusType = 'status6';
924
        }
925
926
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
927
    }
928
929
    /**
930
     *  Load the info information in the object
931
     *
932
     *  @param  int     $id       Id of object
933
     *  @return void
934
     */
935
    public function info($id)
936
    {
937
        $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
938
        $sql .= ' fk_user_creat, fk_user_modif';
939
        $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
940
        $sql .= ' WHERE t.rowid = ' . ((int) $id);
941
        $result = $this->db->query($sql);
942
        if ($result) {
943
            if ($this->db->num_rows($result)) {
944
                $obj = $this->db->fetch_object($result);
945
946
                $this->id = $obj->rowid;
947
948
                $this->user_creation_id = $obj->fk_user_creat;
949
                $this->user_modification_id = $obj->fk_user_modif;
950
                $this->date_creation     = $this->db->jdate($obj->datec);
951
                $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
952
            }
953
954
            $this->db->free($result);
955
        } else {
956
            dol_print_error($this->db);
957
        }
958
    }
959
960
    /**
961
     * Initialise object with example values
962
     * Id must be 0 if object instance is a specimen
963
     *
964
     * @return int
965
     */
966
    public function initAsSpecimen()
967
    {
968
        $this->question = "ABCD";
969
970
        return $this->initAsSpecimenCommon();
971
    }
972
973
    /**
974
     *  Create an array of lines
975
     *
976
     *  @return array|int       array of lines if OK, <0 if KO
977
     */
978
    public function getLinesArray()
979
    {
980
        $this->lines = array();
981
982
        $objectline = new KnowledgeRecordLine($this->db);
983
        $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_knowledgerecord:=:' . ((int) $this->id) . ')');
984
985
        if (is_numeric($result)) {
986
            $this->error = $objectline->error;
987
            $this->errors = $objectline->errors;
988
            return $result;
989
        } else {
990
            $this->lines = $result;
991
            return $this->lines;
992
        }
993
    }
994
995
    /**
996
     *  Returns the reference to the following non used object depending on the active numbering module.
997
     *
998
     *  @return string              Object free reference
999
     */
1000
    public function getNextNumRef()
1001
    {
1002
        global $langs, $conf;
1003
        $langs->load("knowledgemanagement");
1004
1005
        if (!getDolGlobalString('KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON')) {
1006
            $conf->global->KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON = 'mod_knowledgerecord_standard';
1007
        }
1008
1009
        if (getDolGlobalString('KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON')) {
1010
            $mybool = false;
1011
1012
            $file = getDolGlobalString('KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON') . ".php";
1013
            $classname = getDolGlobalString('KNOWLEDGEMANAGEMENT_KNOWLEDGERECORD_ADDON');
1014
1015
            // Include file with class
1016
            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1017
            foreach ($dirmodels as $reldir) {
1018
                $dir = dol_buildpath($reldir . "core/modules/knowledgemanagement/");
1019
1020
                // Load file with numbering class (if found)
1021
                $mybool = ((bool) @include_once $dir . $file) || $mybool;
1022
            }
1023
1024
            if ($mybool === false) {
1025
                dol_print_error(null, "Failed to include file " . $file);
1026
                return '';
1027
            }
1028
1029
            if (class_exists($classname)) {
1030
                $obj = new $classname();
1031
                $numref = $obj->getNextValue($this);
1032
1033
                if ($numref != '' && $numref != '-1') {
1034
                    return $numref;
1035
                } else {
1036
                    $this->error = $obj->error;
1037
                    //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1038
                    return "";
1039
                }
1040
            } else {
1041
                print $langs->trans("Error") . " " . $langs->trans("ClassNotFound") . ' ' . $classname;
1042
                return "";
1043
            }
1044
        } else {
1045
            print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1046
            return "";
1047
        }
1048
    }
1049
1050
    /**
1051
     *  Create a document onto disk according to template module.
1052
     *
1053
     *  @param      string      $modele         Force template to use ('' to not force)
1054
     *  @param      Translate   $outputlangs    object lang a utiliser pour traduction
1055
     *  @param      int         $hidedetails    Hide details of lines
1056
     *  @param      int         $hidedesc       Hide description
1057
     *  @param      int         $hideref        Hide ref
1058
     *  @param      null|array  $moreparams     Array to provide more information
1059
     *  @return     int                         0 if KO, 1 if OK
1060
     */
1061
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1062
    {
1063
        global $conf, $langs;
1064
1065
        $result = 0;
1066
        $includedocgeneration = 0;
1067
1068
        $langs->load("knowledgemanagement");
1069
1070
        if (!dol_strlen($modele)) {
1071
            $modele = 'standard_knowledgerecord';
1072
1073
            if (!empty($this->model_pdf)) {
1074
                $modele = $this->model_pdf;
1075
            } elseif (getDolGlobalString('KNOWLEDGERECORD_ADDON_PDF')) {
1076
                $modele = getDolGlobalString('KNOWLEDGERECORD_ADDON_PDF');
1077
            }
1078
        }
1079
1080
        $modelpath = "core/modules/knowledgemanagement/doc/";
1081
1082
        if ($includedocgeneration && !empty($modele)) {
1083
            $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1084
        }
1085
1086
        return $result;
1087
    }
1088
1089
    /**
1090
     * Action executed by scheduler
1091
     * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters'
1092
     * Use public function doScheduledJob($param1, $param2, ...) to get parameters
1093
     *
1094
     * @return  int         0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
1095
     */
1096
    public function doScheduledJob()
1097
    {
1098
        global $conf, $langs;
1099
1100
        //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1101
1102
        $error = 0;
1103
        $this->output = '';
1104
        $this->error = '';
1105
1106
        dol_syslog(__METHOD__, LOG_DEBUG);
1107
1108
        $now = dol_now();
1109
1110
        $this->db->begin();
1111
1112
        // ...
1113
1114
        $this->db->commit();
1115
1116
        return $error;
1117
    }
1118
1119
    /**
1120
     * Sets object to supplied categories.
1121
     *
1122
     * Deletes object from existing categories not supplied.
1123
     * Adds it to non existing supplied categories.
1124
     * Existing categories are left untouch.
1125
     *
1126
     * @param   int[]|int   $categories     Category or categories IDs
1127
     * @return  int                         Return integer <0 if KO, >0 if OK
1128
     */
1129
    public function setCategories($categories)
1130
    {
1131
        require_once constant('DOL_DOCUMENT_ROOT') . '/categories/class/categorie.class.php';
1132
        return parent::setCategoriesCommon($categories, Categorie::TYPE_KNOWLEDGEMANAGEMENT);
1133
    }
1134
1135
    /**
1136
     *  Return clicable link of object (with eventually picto)
1137
     *
1138
     *  @param      string      $option                 Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
1139
     *  @param      array       $arraydata              Array of data
1140
     *  @return     string                              HTML Code for Kanban thumb.
1141
     */
1142
    public function getKanbanView($option = '', $arraydata = null)
1143
    {
1144
        $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1145
1146
        $return = '<div class="box-flex-item box-flex-grow-zero">';
1147
        $return .= '<div class="info-box info-box-sm">';
1148
        $return .= '<span class="info-box-icon bg-infobox-action">';
1149
        $return .= img_picto('', $this->picto);
1150
        $return .= '</span>';
1151
        $return .= '<div class="info-box-content">';
1152
        $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref) . '</span>';
1153
        if ($selected >= 0) {
1154
            $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
1155
        }
1156
        if (property_exists($this, 'lang') && !empty($this->lang)) {
1157
            //$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>';
1158
            $return .= '<br>' . picto_from_langcode($this->lang, 'class="paddingrightonly saturatemedium opacitylow paddingrightonly"');
1159
        }
1160
        if (property_exists($this, 'question')) {
1161
            $return .= '<div class="info-box-label tdoverflowmax150 classfortooltip" title="' . dolPrintHTMLForAttribute($this->question) . '">' . dolGetFirstLineOfText($this->question) . '</div>';
1162
        }
1163
        if (method_exists($this, 'getLibStatut')) {
1164
            $return .= '<div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
1165
        }
1166
        $return .= '</div>';
1167
        $return .= '</div>';
1168
        $return .= '</div>';
1169
        return $return;
1170
    }
1171
}
1172
1173
1174
use Dolibarr\Core\Base\CommonObjectLine;
1175
1176
/**
1177
 * Class KnowledgeRecordLine. You can also remove this and generate a CRUD class for lines objects.
1178
 */
1179
class KnowledgeRecordLine extends CommonObjectLine
1180
{
1181
    // To complete with content of an object KnowledgeRecordLine
1182
    // We should have a field rowid, fk_knowledgerecord and position
1183
1184
    /**
1185
     * Constructor
1186
     *
1187
     * @param DoliDB $db Database handler
1188
     */
1189
    public function __construct(DoliDB $db)
1190
    {
1191
        $this->db = $db;
1192
1193
        $this->isextrafieldmanaged = 0;
1194
    }
1195
}
1196