Passed
Push — EXTRACT_CLASSES ( a2ff75...ae6b5c )
by Rafael
34:15
created

ProductAttribute::updateLine()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 20
nc 8
nop 4
dl 0
loc 32
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
/* Copyright (C) 2016       Marcos García               <[email protected]>
4
 * Copyright (C) 2022       Open-Dsi		            <[email protected]>
5
 * Copyright (C) 2023-2024  Frédéric France             <[email protected]>
6
 * Copyright (C) 2024		MDW							<[email protected]>
7
 * Copyright (C) 2024       Rafael San José             <[email protected]>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
namespace Dolibarr\Code\Variants\Classes;
24
25
use Dolibarr\Core\Base\CommonObject;
26
use DoliDB;
27
28
/**
29
 *  \file       htdocs/variants/class/ProductAttribute.class.php
30
 *  \ingroup    variants
31
 *  \brief      File of the ProductAttribute class
32
 */
33
34
/**
35
 * Class ProductAttribute
36
 * Used to represent a Product attribute
37
 * Examples:
38
 * - Attribute 'color' (of type ProductAttribute) with values 'white', 'blue' or 'red' (each of type ProductAttributeValue).
39
 * - Attribute 'size' (of type ProductAttribute) with values 'S', 'L' or 'XL' (each of type ProductAttributeValue).
40
 */
41
class ProductAttribute extends CommonObject
42
{
43
    /**
44
     * Database handler
45
     * @var DoliDB
46
     */
47
    public $db;
48
49
    /**
50
     * @var string ID of module.
51
     */
52
    public $module = 'variants';
53
54
    /**
55
     * @var string ID to identify managed object.
56
     */
57
    public $element = 'productattribute';
58
59
    /**
60
     * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
61
     */
62
    public $table_element = 'product_attribute';
63
64
    /**
65
     * @var string    Name of sub table line
66
     */
67
    public $table_element_line = 'product_attribute_value';
68
69
    /**
70
     * @var string Field with ID of parent key if this field has a parent or for child tables
71
     */
72
    public $fk_element = 'fk_product_attribute';
73
74
    /**
75
     * @var string String with name of icon for conferenceorbooth. Must be the part after the 'object_' into object_conferenceorbooth.png
76
     */
77
    public $picto = 'product';
78
79
    /**
80
     *  'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', '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')
81
     *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
82
     *  'label' the translation key.
83
     *  'picto' is code of a picto to show before value in forms
84
     *  'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalString("MY_SETUP_PARAM")'
85
     *  'position' is the sort order of field.
86
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
87
     *  '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)
88
     *  'noteditable' says if field is not editable (1 or 0)
89
     *  '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.
90
     *  'index' if we want an index in database.
91
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
92
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
93
     *  '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).
94
     *  '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'
95
     *  'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
96
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
97
     *  '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.
98
     *  'arrayofkeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
99
     *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
100
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
101
     *
102
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
103
     */
104
    /**
105
     * @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...
106
     */
107
    public $fields = array(
108
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
109
        'ref' => array('type' => 'varchar(255)', 'label' => 'Ref', 'visible' => 1, 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'index' => 1, 'searchall' => 1, 'comment' => "Reference of object", 'css' => 'width200'),
110
        'ref_ext' => array('type' => 'varchar(255)', 'label' => 'ExternalRef', 'enabled' => 1, 'visible' => 0, 'position' => 20, 'searchall' => 1),
111
        'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'help' => "", 'showoncombobox' => 1,),
112
        'position' => array('type' => 'integer', 'label' => 'Rank', 'enabled' => 1, 'visible' => 0, 'default' => '0', 'position' => 40, 'notnull' => 1,),
113
    );
114
115
    /**
116
     * @var int rowid
117
     */
118
    public $id;
119
120
    /**
121
     * @var string ref
122
     */
123
    public $ref;
124
125
    /**
126
     * @var string external ref
127
     */
128
    public $ref_ext;
129
130
    /**
131
     * @var string label
132
     */
133
    public $label;
134
135
    /**
136
     * @var int position
137
     * @deprecated
138
     * @see $position
139
     */
140
    public $rang;
141
142
    /**
143
     * @var int position
144
     */
145
    public $position;
146
147
    /**
148
     * @var ProductAttributeValue[]
149
     */
150
    public $lines = array();
151
152
    /**
153
     * @var ProductAttributeValue
154
     */
155
    public $line;
156
157
    /**
158
     * @var int     Number of product that use this attribute
159
     */
160
    public $is_used_by_products;
161
162
163
    /**
164
     * Constructor
165
     *
166
     * @param DoliDB $db Database handler
167
     */
168
    public function __construct(DoliDB $db)
169
    {
170
        global $conf, $langs;
171
172
        $this->db = $db;
173
174
        $this->ismultientitymanaged = 1;
175
        $this->isextrafieldmanaged = 0;
176
        $this->entity = $conf->entity;
177
178
        if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
179
            $this->fields['rowid']['visible'] = 0;
180
        }
181
        if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
182
            $this->fields['entity']['enabled'] = 0;
183
        }
184
185
        // Unset fields that are disabled
186
        foreach ($this->fields as $key => $val) {
187
            if (isset($val['enabled']) && empty($val['enabled'])) {
188
                unset($this->fields[$key]);
189
            }
190
        }
191
192
        // Translate some data of arrayofkeyval
193
        if (is_object($langs)) {
194
            foreach ($this->fields as $key => $val) {
195
                if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
196
                    foreach ($val['arrayofkeyval'] as $key2 => $val2) {
197
                        $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
198
                    }
199
                }
200
            }
201
        }
202
    }
203
204
    /**
205
     * Creates a product attribute
206
     *
207
     * @param   User    $user      Object user
208
     * @param   int     $notrigger Do not execute trigger
209
     * @return                  int Return integer <0 KO, Id of new variant if OK
210
     */
211
    public function create(User $user, $notrigger = 0)
212
    {
213
        global $langs;
214
        $error = 0;
215
216
        // Clean parameters
217
        $this->ref = strtoupper(dol_sanitizeFileName(dol_string_nospecial(trim($this->ref)))); // Ref must be uppercase
218
        $this->label = trim($this->label);
219
        $this->position = $this->position > 0 ? $this->position : 0;
220
221
        // Position to use
222
        if (empty($this->position)) {
223
            $positionmax = $this->getMaxAttributesPosition();
224
            $this->position = $positionmax + 1;
225
        }
226
227
        // Check parameters
228
        if (empty($this->ref)) {
229
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
230
            $error++;
231
        }
232
        if (empty($this->label)) {
233
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label"));
234
            $error++;
235
        }
236
        if ($error) {
237
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
238
            return -1;
239
        }
240
241
        $this->db->begin();
242
243
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . $this->table_element . " (";
244
        $sql .= " ref, ref_ext, label, entity, position";
245
        $sql .= ")";
246
        $sql .= " VALUES (";
247
        $sql .= "  '" . $this->db->escape($this->ref) . "'";
248
        $sql .= ", '" . $this->db->escape($this->ref_ext) . "'";
249
        $sql .= ", '" . $this->db->escape($this->label) . "'";
250
        $sql .= ", " . ((int) $this->entity);
251
        $sql .= ", " . ((int) $this->position);
252
        $sql .= ")";
253
254
        dol_syslog(__METHOD__, LOG_DEBUG);
255
        $resql = $this->db->query($sql);
256
        if (!$resql) {
257
            $this->errors[] = "Error " . $this->db->lasterror();
258
            $error++;
259
        }
260
261
        if (!$error) {
262
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element);
263
        }
264
265
        if (!$error && !$notrigger) {
266
            // Call trigger
267
            $result = $this->call_trigger('PRODUCT_ATTRIBUTE_CREATE', $user);
268
            if ($result < 0) {
269
                $error++;
270
            }
271
            // End call triggers
272
        }
273
274
        if (!$error) {
275
            $this->db->commit();
276
            return $this->id;
277
        } else {
278
            $this->db->rollback();
279
            return -1 * $error;
280
        }
281
    }
282
283
    /**
284
     * Fetches the properties of a product attribute
285
     *
286
     * @param int $id Attribute id
287
     * @return int Return integer <1 KO, >1 OK
288
     */
289
    public function fetch($id)
290
    {
291
        global $langs;
292
        $error = 0;
293
294
        // Clean parameters
295
        $id = $id > 0 ? $id : 0;
296
297
        // Check parameters
298
        if (empty($id)) {
299
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
300
            $error++;
301
        }
302
        if ($error) {
303
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
304
            return -1;
305
        }
306
307
        $sql = "SELECT rowid, ref, ref_ext, label, position";
308
        $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
309
        $sql .= " WHERE rowid = " . ((int) $id);
310
        $sql .= " AND entity IN (" . getEntity('product') . ")";
311
312
        dol_syslog(__METHOD__, LOG_DEBUG);
313
        $resql = $this->db->query($sql);
314
        if (!$resql) {
315
            $this->errors[] = "Error " . $this->db->lasterror();
316
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
317
            return -1;
318
        }
319
320
        $numrows = $this->db->num_rows($resql);
321
        if ($numrows) {
322
            $obj = $this->db->fetch_object($resql);
323
324
            $this->id = $obj->rowid;
325
            $this->ref = $obj->ref;
326
            $this->ref_ext = $obj->ref_ext;
327
            $this->label = $obj->label;
328
            $this->rang = $obj->position; // deprecated
329
            $this->position = $obj->position;
330
        }
331
        $this->db->free($resql);
332
333
        return $numrows;
334
    }
335
336
    /**
337
     * Returns an array with all the ProductAttribute objects of a given entity
338
     *
339
     * @return ProductAttribute[]
340
     */
341
    public function fetchAll()
342
    {
343
        $return = array();
344
345
        $sql = "SELECT rowid, ref, ref_ext, label, position";
346
        $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
347
        $sql .= " WHERE entity IN (" . getEntity('product') . ")";
348
        $sql .= $this->db->order("position", "asc");
349
350
        dol_syslog(__METHOD__, LOG_DEBUG);
351
        $resql = $this->db->query($sql);
352
        if (!$resql) {
353
            $this->errors[] = "Error " . $this->db->lasterror();
354
            dol_print_error($this->db);
355
            return $return;
356
        }
357
358
        while ($obj = $this->db->fetch_object($resql)) {
359
            $tmp = new ProductAttribute($this->db);
360
361
            $tmp->id = $obj->rowid;
362
            $tmp->ref = $obj->ref;
363
            $tmp->ref_ext = $obj->ref_ext;
364
            $tmp->label = $obj->label;
365
            $tmp->rang = $obj->position; // deprecated
366
            $tmp->position = $obj->position;
367
368
            $return[] = $tmp;
369
        }
370
371
        return $return;
372
    }
373
374
    /**
375
     * Updates a product attribute
376
     *
377
     * @param   User            $user           User who updates the attribute
378
     * @param   0|1             $notrigger      1 = Do not execute trigger (0 by default)
0 ignored issues
show
Documentation Bug introduced by
The doc comment 0|1 at position 0 could not be parsed: Unknown type name '0' at position 0 in 0|1.
Loading history...
379
     * @return  int<min,-1>|1                   <0 if KO, 1 if OK
380
     */
381
    public function update(User $user, $notrigger = 0)
382
    {
383
        global $langs;
384
        $error = 0;
385
386
        // Clean parameters
387
        $this->id = $this->id > 0 ? $this->id : 0;
388
        $this->ref = strtoupper(dol_sanitizeFileName(dol_string_nospecial(trim($this->ref)))); // Ref must be uppercase
389
        $this->label = trim($this->label);
390
391
        // Check parameters
392
        if (empty($this->id)) {
393
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
394
            $error++;
395
        }
396
        if (empty($this->ref)) {
397
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
398
            $error++;
399
        }
400
        if (empty($this->label)) {
401
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label"));
402
            $error++;
403
        }
404
        if ($error) {
405
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
406
            return -1;
407
        }
408
409
        $this->db->begin();
410
411
        $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET";
412
413
        $sql .= "  ref = '" . $this->db->escape($this->ref) . "'";
414
        $sql .= ", ref_ext = '" . $this->db->escape($this->ref_ext) . "'";
415
        $sql .= ", label = '" . $this->db->escape($this->label) . "'";
416
        $sql .= ", position = " . ((int) $this->position);
417
418
        $sql .= " WHERE rowid = " . ((int) $this->id);
419
420
        dol_syslog(__METHOD__, LOG_DEBUG);
421
        $resql = $this->db->query($sql);
422
        if (!$resql) {
423
            $this->errors[] = "Error " . $this->db->lasterror();
424
            $error++;
425
        }
426
427
        if (!$error && !$notrigger) {
428
            // Call trigger
429
            $result = $this->call_trigger('PRODUCT_ATTRIBUTE_MODIFY', $user);
430
            if ($result < 0) {
431
                $error++;
432
            }
433
            // End call triggers
434
        }
435
436
        if (!$error) {
437
            $this->db->commit();
438
            return 1;
439
        } else {
440
            $this->db->rollback();
441
            return -1 * $error;
442
        }
443
    }
444
445
    /**
446
     * Deletes a product attribute
447
     *
448
     * @param   User    $user      Object user
449
     * @param   int     $notrigger Do not execute trigger
450
     * @return  int Return integer <0 KO, >0 OK
451
     */
452
    public function delete(User $user, $notrigger = 0)
453
    {
454
        global $langs;
455
        $error = 0;
456
457
        // Clean parameters
458
        $this->id = $this->id > 0 ? $this->id : 0;
459
460
        // Check parameters
461
        if (empty($this->id)) {
462
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
463
            $error++;
464
        }
465
        if ($error) {
466
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
467
            return -1;
468
        }
469
470
        $result = $this->isUsed();
471
        if ($result < 0) {
472
            return -1;
473
        } elseif ($result > 0) {
474
            $this->errors[] = $langs->trans('ErrorAttributeIsUsedIntoProduct');
475
            return -1;
476
        }
477
478
        $this->db->begin();
479
480
        if (!$notrigger) {
481
            // Call trigger
482
            $result = $this->call_trigger('PRODUCT_ATTRIBUTE_DELETE', $user);
483
            if ($result < 0) {
484
                $error++;
485
            }
486
            // End call triggers
487
        }
488
489
        if (!$error) {
490
            // Delete values
491
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . $this->table_element_line;
492
            $sql .= " WHERE " . $this->fk_element . " = " . ((int) $this->id);
493
494
            dol_syslog(__METHOD__ . ' - Delete values', LOG_DEBUG);
495
            $resql = $this->db->query($sql);
496
            if (!$resql) {
497
                $this->errors[] = "Error " . $this->db->lasterror();
498
                $error++;
499
            }
500
        }
501
502
        if (!$error) {
503
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . $this->table_element;
504
            $sql .= " WHERE rowid = " . ((int) $this->id);
505
506
            dol_syslog(__METHOD__ . ' - Delete attribute', LOG_DEBUG);
507
            $resql = $this->db->query($sql);
508
            if (!$resql) {
509
                $this->errors[] = "Error " . $this->db->lasterror();
510
                $error++;
511
            }
512
        }
513
514
        if (!$error) {
515
            $this->db->commit();
516
            return 1;
517
        } else {
518
            $this->db->rollback();
519
            return -1 * $error;
520
        }
521
    }
522
523
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
524
    /**
525
     * Load array lines
526
     *
527
     * @param   string      $filters    Filter on other fields
528
     * @return  int                     Return integer <0 if KO, >0 if OK
529
     */
530
    public function fetch_lines($filters = '')
531
    {
532
		// phpcs:enable
533
        global $langs;
534
535
        $this->lines = array();
536
537
        $error = 0;
538
539
        // Clean parameters
540
        $this->id = $this->id > 0 ? $this->id : 0;
541
542
        // Check parameters
543
        if (empty($this->id)) {
544
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
545
            $error++;
546
        }
547
        if ($error) {
548
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
549
            return -1;
550
        }
551
552
        $sql = "SELECT td.rowid, td.fk_product_attribute, td.ref, td.value, td.position";
553
        $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element_line . " AS td";
554
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $this->table_element . " AS t ON t.rowid = td." . $this->fk_element;
555
        $sql .= " WHERE t.rowid = " . ((int) $this->id);
556
        $sql .= " AND t.entity IN (" . getEntity('product') . ")";
557
        if ($filters) {
558
            $sql .= $filters;
559
        }
560
        $sql .= $this->db->order("td.position", "asc");
561
562
        dol_syslog(__METHOD__, LOG_DEBUG);
563
        $resql = $this->db->query($sql);
564
        if (!$resql) {
565
            $this->errors[] = "Error " . $this->db->lasterror();
566
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
567
            return -3;
568
        }
569
570
        $num = $this->db->num_rows($resql);
571
        if ($num) {
572
            $i = 0;
573
            while ($i < $num) {
574
                $obj = $this->db->fetch_object($resql);
575
576
                $line = new ProductAttributeValue($this->db);
577
578
                $line->id = $obj->rowid;
579
                $line->fk_product_attribute = $obj->fk_product_attribute;
580
                $line->ref = $obj->ref;
581
                $line->value = $obj->value;
582
                $line->position = $obj->position;
583
584
                $this->lines[$i] = $line;
585
                $i++;
586
            }
587
        }
588
        $this->db->free($resql);
589
590
        return $num;
591
    }
592
593
    /**
594
     *  Retrieve an array of proposal lines
595
     *  @param  string              $filters        Filter on other fields
596
     *
597
     *  @return int     >0 if OK, <0 if KO
598
     */
599
    public function getLinesArray($filters = '')
600
    {
601
        return $this->fetch_lines($filters);
602
    }
603
604
    /**
605
     *      Add a proposal line into database (linked to product/service or not)
606
     *      The parameters are already supposed to be appropriate and with final values to the call
607
     *      of this method. Also, for the VAT rate, it must have already been defined
608
     *      by whose calling the method get_default_tva (societe_vendeuse, societe_acheteuse, '' product)
609
     *      and desc must already have the right value (it's up to the caller to manage multilanguage)
610
     *
611
     * @param   string  $ref            Ref of the value
612
     * @param   string  $value          Value
613
     * @param   int     $position       Position of line
614
     *  @param  int     $notrigger      disable line update trigger
615
     * @return  int                     >0 if OK, <0 if KO
616
     */
617
    public function addLine($ref, $value, $position = -1, $notrigger = 0)
618
    {
619
        global $langs, $user;
620
        dol_syslog(__METHOD__ . " id=" . $this->id . ", ref=" . $ref . ", value=" . $value . ", notrigger=" . $notrigger);
621
        $error = 0;
622
623
        // Clean parameters
624
        $this->id = $this->id > 0 ? $this->id : 0;
625
626
        // Check parameters
627
        if (empty($this->id)) {
628
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
629
            $error++;
630
        }
631
        if ($error) {
632
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
633
            return -1;
634
        }
635
636
        $this->db->begin();
637
638
        //Fetch current line from the database and then clone the object and set it in $oldcopy property
639
        $this->line = new ProductAttributeValue($this->db);
640
641
        // Position to use
642
        $positiontouse = $position;
643
        if ($positiontouse == -1) {
644
            $positionmax = $this->line_max(0);
645
            $positiontouse = $positionmax + 1;
646
        }
647
648
        $this->line->context = $this->context;
649
        $this->line->fk_product_attribute = $this->id;
650
        $this->line->ref = $ref;
651
        $this->line->value = $value;
652
        $this->line->position = $positiontouse;
653
654
        $result = $this->line->create($user, $notrigger);
655
656
        if ($result < 0) {
657
            $this->error = $this->line->error;
658
            $this->errors = $this->line->errors;
659
            $this->db->rollback();
660
            return -1;
661
        } else {
662
            $this->db->commit();
663
            return $this->line->id;
664
        }
665
    }
666
667
668
    /**
669
     *  Update a line
670
     *
671
     * @param   int     $lineid         Id of line
672
     * @param   string  $ref            Ref of the value
673
     * @param   string  $value          Value
674
     * @param   int     $notrigger      disable line update trigger
675
     * @return  int                     >=0 if OK, <0 if KO
676
     */
677
    public function updateLine($lineid, $ref, $value, $notrigger = 0)
678
    {
679
        global $user;
680
681
        dol_syslog(__METHOD__ . " lineid=$lineid, ref=$ref, value=$value, notrigger=$notrigger");
682
683
        // Clean parameters
684
        $lineid = $lineid > 0 ? $lineid : 0;
685
686
        $this->db->begin();
687
688
        //Fetch current line from the database and then clone the object and set it in $oldcopy property
689
        $this->line = new ProductAttributeValue($this->db);
690
        $result = $this->line->fetch($lineid);
691
        if ($result > 0) {
692
            $this->line->oldcopy = clone $this->line;
693
694
            $this->line->context = $this->context;
695
            $this->line->ref = $ref;
696
            $this->line->value = $value;
697
698
            $result = $this->line->update($user, $notrigger);
699
        }
700
701
        if ($result < 0) {
702
            $this->error = $this->line->error;
703
            $this->errors = $this->line->errors;
704
            $this->db->rollback();
705
            return -1;
706
        } else {
707
            $this->db->commit();
708
            return $result;
709
        }
710
    }
711
712
    /**
713
     *  Delete a line
714
     *
715
     * @param   User    $user      Object user
716
     * @param   int     $lineid         Id of line to delete
717
     * @param   int     $notrigger      disable line update trigger
718
     * @return  int                     >0 if OK, <0 if KO
719
     */
720
    public function deleteLine(User $user, $lineid, $notrigger = 0)
721
    {
722
        dol_syslog(__METHOD__ . " lineid=$lineid, notrigger=$notrigger");
723
724
        // Clean parameters
725
        $lineid = $lineid > 0 ? $lineid : 0;
726
727
        $this->db->begin();
728
729
        //Fetch current line from the database
730
        $this->line = new ProductAttributeValue($this->db);
731
        $result = $this->line->fetch($lineid);
732
        if ($result > 0) {
733
            $this->line->context = $this->context;
734
735
            $result = $this->line->delete($user, $notrigger);
736
        }
737
738
        if ($result < 0) {
739
            $this->error = $this->line->error;
740
            $this->errors = $this->line->errors;
741
            $this->db->rollback();
742
            return -1;
743
        } else {
744
            $this->db->commit();
745
            return $result;
746
        }
747
    }
748
749
    /**
750
     * Returns the number of values for this attribute
751
     *
752
     * @return int
753
     */
754
    public function countChildValues()
755
    {
756
        global $langs;
757
        $error = 0;
758
        $count = 0;
759
760
        // Clean parameters
761
        $this->id = $this->id > 0 ? $this->id : 0;
762
763
        // Check parameters
764
        if (empty($this->id)) {
765
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
766
            $error++;
767
        }
768
        if ($error) {
769
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
770
            return -1;
771
        }
772
773
        $sql = "SELECT COUNT(*) AS count";
774
        $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element_line;
775
        $sql .= " WHERE " . $this->fk_element . " = " . ((int) $this->id);
776
777
        dol_syslog(__METHOD__, LOG_DEBUG);
778
        $resql = $this->db->query($sql);
779
        if (!$resql) {
780
            $this->errors[] = "Error " . $this->db->lasterror();
781
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
782
            return -1;
783
        }
784
785
        if ($obj = $this->db->fetch_object($resql)) {
786
            $count = $obj->count;
787
        }
788
789
        return $count;
790
    }
791
792
    /**
793
     * Return the number of product variants using this attribute
794
     *
795
     * @return int<-1,max>      -1 if K0, nb of variants using this attribute
796
     */
797
    public function countChildProducts()
798
    {
799
        global $langs;
800
        $error = 0;
801
        $count = 0;
802
803
        // Clean parameters
804
        $this->id = ($this->id > 0) ? $this->id : 0;
805
806
        // Check parameters
807
        if (empty($this->id)) {
808
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
809
            $error++;
810
        }
811
        if ($error) {
812
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
813
            return -1;
814
        }
815
816
        $sql = "SELECT COUNT(*) AS count";
817
        $sql .= " FROM " . MAIN_DB_PREFIX . "product_attribute_combination2val AS pac2v";
818
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_attribute_combination AS pac ON pac2v.fk_prod_combination = pac.rowid";
819
        $sql .= " WHERE pac2v.fk_prod_attr = " . ((int) $this->id);
820
        $sql .= " AND pac.entity IN (" . getEntity('product') . ")";
821
822
        dol_syslog(__METHOD__, LOG_DEBUG);
823
        $resql = $this->db->query($sql);
824
        if (!$resql) {
825
            $this->errors[] = "Error " . $this->db->lasterror();
826
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
827
            return -1;
828
        }
829
830
        if ($obj = $this->db->fetch_object($resql)) {
831
            $count = $obj->count;
832
        }
833
834
        return $count;
835
    }
836
837
    /**
838
     * Test if this attribute is used by a Product
839
     *
840
     * @return -1|0|1           Return -1 if KO, 0 if not used, 1 if used
0 ignored issues
show
Documentation Bug introduced by
The doc comment -1|0|1 at position 0 could not be parsed: Unknown type name '-1' at position 0 in -1|0|1.
Loading history...
841
     */
842
    public function isUsed()
843
    {
844
        global $langs;
845
        $error = 0;
846
847
        // Clean parameters
848
        $this->id = $this->id > 0 ? $this->id : 0;
849
850
        // Check parameters
851
        if (empty($this->id)) {
852
            $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
853
            $error++;
854
        }
855
        if ($error) {
856
            dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
857
            return -1;
858
        }
859
860
        $sql = "SELECT COUNT(*) AS nb FROM " . MAIN_DB_PREFIX . "product_attribute_combination2val WHERE fk_prod_attr = " . ((int) $this->id);
861
862
        dol_syslog(__METHOD__, LOG_DEBUG);
863
        $resql = $this->db->query($sql);
864
        if (!$resql) {
865
            $this->errors[] = "Error " . $this->db->lasterror();
866
            return -1;
867
        }
868
869
        $used = 0;
870
        if ($obj = $this->db->fetch_object($resql)) {
871
            $used = $obj->nb;
872
        }
873
874
        return $used ? 1 : 0;
875
    }
876
877
    /**
878
     *  Save a new position (field position) for details lines.
879
     *  You can choose to set position for lines with already a position or lines without any position defined.
880
     *
881
     * @param   boolean     $renum             True to renum all already ordered lines, false to renum only not already ordered lines.
882
     * @param   string      $rowidorder        ASC or DESC
883
     * @return  int                            Return integer <0 if KO, >0 if OK
884
     */
885
    public function attributeOrder($renum = false, $rowidorder = 'ASC')
886
    {
887
        // Count number of attributes to reorder (according to choice $renum)
888
        $nl = 0;
889
        $sql = "SELECT count(rowid) FROM " . MAIN_DB_PREFIX . $this->table_element;
890
        $sql .= " WHERE entity IN (" . getEntity('product') . ")";
891
        if (!$renum) {
892
            $sql .= " AND position = 0";
893
        } else {
894
            $sql .= " AND position <> 0";
895
        }
896
897
        dol_syslog(__METHOD__, LOG_DEBUG);
898
        $resql = $this->db->query($sql);
899
        if ($resql) {
900
            $row = $this->db->fetch_row($resql);
901
            $nl = $row[0];
902
        } else {
903
            dol_print_error($this->db);
904
        }
905
        if ($nl > 0) {
906
            // The goal of this part is to reorder all attributes.
907
            $rows = array();
908
909
            // We first search all attributes
910
            $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . $this->table_element;
911
            $sql .= " WHERE entity IN (" . getEntity('product') . ")";
912
            $sql .= " ORDER BY position ASC, rowid " . $rowidorder;
913
914
            dol_syslog(__METHOD__ . " search all attributes", LOG_DEBUG);
915
            $resql = $this->db->query($sql);
916
            if ($resql) {
917
                $i = 0;
918
                $num = $this->db->num_rows($resql);
919
                while ($i < $num) {
920
                    $row = $this->db->fetch_row($resql);
921
                    $rows[] = $row[0]; // Add attributes into array rows
922
                    $i++;
923
                }
924
925
                // Now we set a new number for each attributes
926
                if (!empty($rows)) {
927
                    foreach ($rows as $key => $row) {
928
                        $this->updatePositionOfAttribute($row, ($key + 1));
929
                    }
930
                }
931
            } else {
932
                dol_print_error($this->db);
933
            }
934
        }
935
        return 1;
936
    }
937
938
    /**
939
     *  Update position of line (rang)
940
     *
941
     * @param   int     $rowid      Id of line
942
     * @param   int     $position   Position
943
     * @return  int                 Return integer <0 if KO, >0 if OK
944
     */
945
    public function updatePositionOfAttribute($rowid, $position)
946
    {
947
        global $hookmanager;
948
949
        $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET position = " . ((int) $position);
950
        $sql .= " WHERE rowid = " . ((int) $rowid);
951
952
        dol_syslog(__METHOD__, LOG_DEBUG);
953
        if (!$this->db->query($sql)) {
954
            dol_print_error($this->db);
955
            return -1;
956
        } else {
957
            $parameters = array('rowid' => $rowid, 'position' => $position);
958
            $action = '';
959
            $reshook = $hookmanager->executeHooks('afterPositionOfAttributeUpdate', $parameters, $this, $action);
960
            return ($reshook >= 0 ? 1 : -1);
961
        }
962
    }
963
964
    /**
965
     *  Get position of attribute
966
     *
967
     * @param   int     $rowid      Id of line
968
     * @return  int                 Value of position in table of attributes
969
     */
970
    public function getPositionOfAttribute($rowid)
971
    {
972
        $sql = "SELECT position FROM " . MAIN_DB_PREFIX . $this->table_element;
973
        $sql .= " WHERE entity IN (" . getEntity('product') . ")";
974
975
        dol_syslog(__METHOD__, LOG_DEBUG);
976
        $resql = $this->db->query($sql);
977
        if ($resql) {
978
            $row = $this->db->fetch_row($resql);
979
            return $row[0];
980
        }
981
982
        return 0;
983
    }
984
985
    /**
986
     *  Update a attribute to have a higher position
987
     *
988
     * @param   int     $rowid      Id of line
989
     * @return  int                 Return integer <0 KO, >0 OK
990
     */
991
    public function attributeMoveUp($rowid)
992
    {
993
        $this->attributeOrder(false, 'ASC');
994
995
        // Get position of attribute
996
        $position = $this->getPositionOfAttribute($rowid);
997
998
        // Update position of attribute
999
        $this->updateAttributePositionUp($rowid, $position);
1000
1001
        return 1;
1002
    }
1003
1004
    /**
1005
     *  Update a attribute to have a lower position
1006
     *
1007
     * @param   int     $rowid      Id of line
1008
     * @return  int                 Return integer <0 KO, >0 OK
1009
     */
1010
    public function attributeMoveDown($rowid)
1011
    {
1012
        $this->attributeOrder(false, 'ASC');
1013
1014
        // Get position of line
1015
        $position = $this->getPositionOfAttribute($rowid);
1016
1017
        // Get max value for position
1018
        $max = $this->getMaxAttributesPosition();
1019
1020
        // Update position of attribute
1021
        $this->updateAttributePositionDown($rowid, $position, $max);
1022
1023
        return 1;
1024
    }
1025
1026
    /**
1027
     *  Update position of attribute (up)
1028
     *
1029
     * @param   int     $rowid      Id of line
1030
     * @param   int     $position   Position
1031
     * @return  void
1032
     */
1033
    public function updateAttributePositionUp($rowid, $position)
1034
    {
1035
        if ($position > 1) {
1036
            $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET position = " . ((int) $position);
1037
            $sql .= " WHERE entity IN (" . getEntity('product') . ")";
1038
            $sql .= " AND position = " . ((int) ($position - 1));
1039
            if ($this->db->query($sql)) {
1040
                $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET position = " . ((int) ($position - 1));
1041
                $sql .= " WHERE rowid = " . ((int) $rowid);
1042
                if (!$this->db->query($sql)) {
1043
                    dol_print_error($this->db);
1044
                }
1045
            } else {
1046
                dol_print_error($this->db);
1047
            }
1048
        }
1049
    }
1050
1051
    /**
1052
     *  Update position of attribute (down)
1053
     *
1054
     * @param   int     $rowid      Id of line
1055
     * @param   int     $position   Position
1056
     * @param   int     $max        Max
1057
     * @return  void
1058
     */
1059
    public function updateAttributePositionDown($rowid, $position, $max)
1060
    {
1061
        if ($position < $max) {
1062
            $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET position = " . ((int) $position);
1063
            $sql .= " WHERE entity IN (" . getEntity('product') . ")";
1064
            $sql .= " AND position = " . ((int) ($position + 1));
1065
            if ($this->db->query($sql)) {
1066
                $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET position = " . ((int) ($position + 1));
1067
                $sql .= " WHERE rowid = " . ((int) $rowid);
1068
                if (!$this->db->query($sql)) {
1069
                    dol_print_error($this->db);
1070
                }
1071
            } else {
1072
                dol_print_error($this->db);
1073
            }
1074
        }
1075
    }
1076
1077
    /**
1078
     *  Get max value used for position of attributes
1079
     *
1080
     * @return     int              Max value of position in table of attributes
1081
     */
1082
    public function getMaxAttributesPosition()
1083
    {
1084
        // Search the last position of attributes
1085
        $sql = "SELECT max(position) FROM " . MAIN_DB_PREFIX . $this->table_element;
1086
        $sql .= " WHERE entity IN (" . getEntity('product') . ")";
1087
1088
        dol_syslog(__METHOD__, LOG_DEBUG);
1089
        $resql = $this->db->query($sql);
1090
        if ($resql) {
1091
            $row = $this->db->fetch_row($resql);
1092
            return $row[0];
1093
        }
1094
1095
        return 0;
1096
    }
1097
1098
    /**
1099
     *  Update position of attributes with ajax
1100
     *
1101
     *  @param  array   $rows   Array of rows
1102
     *  @return void
1103
     */
1104
    public function attributesAjaxOrder($rows)
1105
    {
1106
        $num = count($rows);
1107
        for ($i = 0; $i < $num; $i++) {
1108
            $this->updatePositionOfAttribute($rows[$i], ($i + 1));
1109
        }
1110
    }
1111
1112
    /**
1113
     *  Return a link to the object card (with optionally the picto)
1114
     *
1115
     *  @param  int     $withpicto                  Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
1116
     *  @param  string  $option                     On what the link point to ('nolink', ...)
1117
     *  @param  int     $notooltip                  1=Disable tooltip
1118
     *  @param  string  $morecss                    Add more css on link
1119
     *  @param  int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
1120
     *  @return string                              String with URL
1121
     */
1122
    public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1123
    {
1124
        global $conf, $langs, $hookmanager;
1125
1126
        if (!empty($conf->dol_no_mouse_hover)) {
1127
            $notooltip = 1; // Force disable tooltips
1128
        }
1129
1130
        $result = '';
1131
1132
        $label = img_picto('', $this->picto) . ' <u>' . $langs->trans("ProductAttribute") . '</u>';
1133
        if (isset($this->status)) {
1134
            $label .= ' ' . $this->getLibStatut(5);
1135
        }
1136
        $label .= '<br>';
1137
        $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1138
        if (!empty($this->label)) {
1139
            $label .= '<br><b>' . $langs->trans('Label') . ':</b> ' . $this->label;
1140
        }
1141
1142
        $url = dol_buildpath('/variants/card.php', 1) . '?id=' . $this->id;
1143
1144
        if ($option != 'nolink') {
1145
            // Add param to save lastsearch_values or not
1146
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1147
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1148
                $add_save_lastsearch_values = 1;
1149
            }
1150
            if ($url && $add_save_lastsearch_values) {
1151
                $url .= '&save_lastsearch_values=1';
1152
            }
1153
        }
1154
1155
        $linkclose = '';
1156
        if (empty($notooltip)) {
1157
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1158
                $label = $langs->trans("ShowProductAttribute");
1159
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
1160
            }
1161
            $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
1162
            $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
1163
        } else {
1164
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
1165
        }
1166
1167
        if ($option == 'nolink' || empty($url)) {
1168
            $linkstart = '<span';
1169
        } else {
1170
            $linkstart = '<a href="' . $url . '"';
1171
        }
1172
        $linkstart .= $linkclose . '>';
1173
        if ($option == 'nolink' || empty($url)) {
1174
            $linkend = '</span>';
1175
        } else {
1176
            $linkend = '</a>';
1177
        }
1178
1179
        $result .= $linkstart;
1180
1181
        if (empty($this->showphoto_on_popup)) {
1182
            if ($withpicto) {
1183
                $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1184
            }
1185
        } else {
1186
            if ($withpicto) {
1187
                require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
1188
1189
                list($class, $module) = explode('@', $this->picto);
1190
                $upload_dir = $conf->$module->multidir_output[$conf->entity] . "/$class/" . dol_sanitizeFileName($this->ref);
1191
                $filearray = dol_dir_list($upload_dir, "files");
1192
                $filename = $filearray[0]['name'];
1193
                if (!empty($filename)) {
1194
                    $pospoint = strpos($filearray[0]['name'], '.');
1195
1196
                    $pathtophoto = $class . '/' . $this->ref . '/thumbs/' . substr($filename, 0, $pospoint) . '_mini' . substr($filename, $pospoint);
1197
                    if (!getDolGlobalString(strtoupper($module . '_' . $class) . '_FORMATLISTPHOTOSASUSERS')) {
1198
                        $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>';
1199
                    } else {
1200
                        $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>';
1201
                    }
1202
1203
                    $result .= '</div>';
1204
                } else {
1205
                    $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1206
                }
1207
            }
1208
        }
1209
1210
        if ($withpicto != 2) {
1211
            $result .= $this->ref;
1212
        }
1213
1214
        $result .= $linkend;
1215
        //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
1216
1217
        global $action, $hookmanager;
1218
        $hookmanager->initHooks(array('variantsdao'));
1219
        $parameters = array('id' => $this->id, 'getnomurl' => $result);
1220
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1221
        if ($reshook > 0) {
1222
            $result = $hookmanager->resPrint;
1223
        } else {
1224
            $result .= $hookmanager->resPrint;
1225
        }
1226
1227
        return $result;
1228
    }
1229
1230
    /**
1231
     *  Return the label of the status
1232
     *
1233
     *  @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
1234
     *  @return string                 Label of status
1235
     */
1236
    public function getLabelStatus($mode = 0)
1237
    {
1238
        return $this->LibStatut(0, $mode);
1239
    }
1240
1241
    /**
1242
     * Return label of status of product attribute
1243
     *
1244
     * @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
1245
     * @return     string       Label
1246
     */
1247
    public function getLibStatut($mode = 0)
1248
    {
1249
        return $this->LibStatut(0, $mode);
1250
    }
1251
1252
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1253
    /**
1254
     * Return label of a status
1255
     *
1256
     * @param      int          $status     Id status
1257
     * @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
1258
     * @return     string       Label
1259
     */
1260
    public function LibStatut($status, $mode = 1)
1261
    {
1262
		// phpcs:enable
1263
        return '';
1264
    }
1265
1266
    // --------------------
1267
    // TODO: All functions here must be redesigned and moved as they are not business functions but output functions
1268
    // --------------------
1269
1270
    /* This is to show add lines */
1271
1272
    /**
1273
     *  Show add free and predefined products/services form
1274
     *
1275
     *  @param  int             $dateSelector       1=Show also date range input fields
1276
     *  @param  Societe         $seller             Object thirdparty who sell
1277
     *  @param  Societe         $buyer              Object thirdparty who buy
1278
     *  @param  string          $defaulttpldir      Directory where to find the template
1279
     *  @return void
1280
     */
1281
    public function formAddObjectLine($dateSelector, $seller, $buyer, $defaulttpldir = '/variants/tpl')
1282
    {
1283
        global $conf, $user, $langs, $object, $hookmanager;
1284
        global $form;
1285
1286
        // Output template part (modules that overwrite templates must declare this into descriptor)
1287
        // Use global variables + $dateSelector + $seller and $buyer
1288
        // Note: This is deprecated. If you need to overwrite the tpl file, use instead the hook 'formAddObjectLine'.
1289
        $dirtpls = array_merge($conf->modules_parts['tpl'], array($defaulttpldir));
1290
        foreach ($dirtpls as $module => $reldir) {
1291
            if (!empty($module)) {
1292
                $tpl = dol_buildpath($reldir . '/productattributevalueline_create.tpl.php');
1293
            } else {
1294
                $tpl = DOL_DOCUMENT_ROOT . $reldir . '/productattributevalueline_create.tpl.php';
1295
            }
1296
1297
            if (empty($conf->file->strict_mode)) {
1298
                $res = @include $tpl;
1299
            } else {
1300
                $res = include $tpl; // for debug
1301
            }
1302
            if ($res) {
1303
                break;
1304
            }
1305
        }
1306
    }
1307
1308
    /* This is to show array of line of details */
1309
1310
    /**
1311
     *  Return HTML table for object lines
1312
     *  TODO Move this into an output class file (htmlline.class.php)
1313
     *  If lines are into a template, title must also be into a template
1314
     *  But for the moment we don't know if it's possible as we keep a method available on overloaded objects.
1315
     *
1316
     *  @param  string      $action             Action code
1317
     *  @param  Societe     $seller             Object of seller third party
1318
     *  @param  Societe     $buyer              Object of buyer third party
1319
     *  @param  int         $selected           Object line selected
1320
     *  @param  int         $dateSelector       1=Show also date range input fields
1321
     *  @param  string      $defaulttpldir      Directory where to find the template
1322
     *  @param  int         $addcreateline      1=Add create line
1323
     *  @return void
1324
     */
1325
    public function printObjectLines($action, $seller, $buyer, $selected = 0, $dateSelector = 0, $defaulttpldir = '/variants/tpl', $addcreateline = 0)
1326
    {
1327
        global $conf, $hookmanager, $langs, $user, $form, $object;
1328
        global $mysoc;
1329
        // TODO We should not use global var for this
1330
        global $disableedit, $disablemove, $disableremove;
1331
1332
        $num = count($this->lines);
1333
1334
        $parameters = array('num' => $num, 'selected' => $selected, 'table_element_line' => $this->table_element_line);
1335
        $reshook = $hookmanager->executeHooks('printObjectLineTitle', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1336
        if (empty($reshook)) {
1337
            // Output template part (modules that overwrite templates must declare this into descriptor)
1338
            // Use global variables + $dateSelector + $seller and $buyer
1339
            // Note: This is deprecated. If you need to overwrite the tpl file, use instead the hook.
1340
            $dirtpls = array_merge($conf->modules_parts['tpl'], array($defaulttpldir));
1341
            foreach ($dirtpls as $module => $reldir) {
1342
                if (!empty($module)) {
1343
                    $tpl = dol_buildpath($reldir . '/productattributevalueline_title.tpl.php');
1344
                } else {
1345
                    $tpl = DOL_DOCUMENT_ROOT . $reldir . '/productattributevalueline_title.tpl.php';
1346
                }
1347
                if (empty($conf->file->strict_mode)) {
1348
                    $res = @include $tpl;
1349
                } else {
1350
                    $res = include $tpl; // for debug
1351
                }
1352
                if ($res) {
1353
                    break;
1354
                }
1355
            }
1356
        }
1357
1358
1359
        if ($addcreateline) {
1360
            // Form to add new line
1361
            if ($action != 'selectlines') {
1362
                if ($action != 'editline') {
1363
                    // Add products/services form
1364
1365
                    $parameters = array();
1366
                    $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1367
                    if ($reshook < 0) {
1368
                        setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1369
                    }
1370
                    if (empty($reshook)) {
1371
                        $object->formAddObjectLine(1, $mysoc, $buyer);
1372
                    }
1373
                }
1374
            }
1375
        }
1376
1377
        $i = 0;
1378
1379
        print "<!-- begin printObjectLines() -->\n";
1380
        foreach ($this->lines as $line) {
1381
            if (is_object($hookmanager)) {   // Old code is commented on preceding line.
1382
                $parameters = array('line' => $line, 'num' => $num, 'i' => $i, 'selected' => $selected, 'table_element_line' => $line->table_element);
1383
                $reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1384
            }
1385
            if (empty($reshook)) {
1386
                $this->printObjectLine($action, $line, '', $num, $i, $dateSelector, $seller, $buyer, $selected, null, $defaulttpldir);
1387
            }
1388
1389
            $i++;
1390
        }
1391
        print "<!-- end printObjectLines() -->\n";
1392
    }
1393
1394
    /**
1395
     *  Return HTML content of a detail line
1396
     *  TODO Move this into an output class file (htmlline.class.php)
1397
     *
1398
     *  @param  string              $action             GET/POST action
1399
     *  @param  CommonObjectLine    $line               Selected object line to output
1400
     *  @param  string              $var                Is it a an odd line (true)
1401
     *  @param  int                 $num                Number of line (0)
1402
     *  @param  int                 $i                  I
1403
     *  @param  int                 $dateSelector       1=Show also date range input fields
1404
     *  @param  Societe             $seller             Object of seller third party
1405
     *  @param  Societe             $buyer              Object of buyer third party
1406
     *  @param  int                 $selected           Object line selected
1407
     *  @param  Extrafields         $extrafields        Object of extrafields
1408
     *  @param  string              $defaulttpldir      Directory where to find the template (deprecated)
1409
     *  @return void
1410
     */
1411
    public function printObjectLine($action, $line, $var, $num, $i, $dateSelector, $seller, $buyer, $selected = 0, $extrafields = null, $defaulttpldir = '/variants/tpl')
1412
    {
1413
        global $conf, $langs, $user, $object, $hookmanager;
1414
        global $form;
1415
        global $object_rights, $disableedit, $disablemove, $disableremove; // TODO We should not use global var for this !
1416
1417
        $object_rights = $user->rights->variants;
1418
1419
        // Line in view mode
1420
        if ($action != 'editline' || $selected != $line->id) {
1421
            // Output template part (modules that overwrite templates must declare this into descriptor)
1422
            // Use global variables + $dateSelector + $seller and $buyer
1423
            // Note: This is deprecated. If you need to overwrite the tpl file, use instead the hook printObjectLine and printObjectSubLine.
1424
            $dirtpls = array_merge($conf->modules_parts['tpl'], array($defaulttpldir));
1425
            foreach ($dirtpls as $module => $reldir) {
1426
                if (!empty($module)) {
1427
                    $tpl = dol_buildpath($reldir . '/productattributevalueline_view.tpl.php');
1428
                } else {
1429
                    $tpl = DOL_DOCUMENT_ROOT . $reldir . '/productattributevalueline_view.tpl.php';
1430
                }
1431
1432
                if (empty($conf->file->strict_mode)) {
1433
                    $res = @include $tpl;
1434
                } else {
1435
                    $res = include $tpl; // for debug
1436
                }
1437
                if ($res) {
1438
                    break;
1439
                }
1440
            }
1441
        }
1442
1443
        // Line in update mode
1444
        if ($action == 'editline' && $selected == $line->id) {
1445
            // Output template part (modules that overwrite templates must declare this into descriptor)
1446
            // Use global variables + $dateSelector + $seller and $buyer
1447
            // Note: This is deprecated. If you need to overwrite the tpl file, use instead the hook printObjectLine and printObjectSubLine.
1448
            $dirtpls = array_merge($conf->modules_parts['tpl'], array($defaulttpldir));
1449
            foreach ($dirtpls as $module => $reldir) {
1450
                if (!empty($module)) {
1451
                    $tpl = dol_buildpath($reldir . '/productattributevalueline_edit.tpl.php');
1452
                } else {
1453
                    $tpl = DOL_DOCUMENT_ROOT . $reldir . '/productattributevalueline_edit.tpl.php';
1454
                }
1455
1456
                if (empty($conf->file->strict_mode)) {
1457
                    $res = @include $tpl;
1458
                } else {
1459
                    $res = include $tpl; // for debug
1460
                }
1461
                if ($res) {
1462
                    break;
1463
                }
1464
            }
1465
        }
1466
    }
1467
1468
    /* This is to show array of line of details of source object */
1469
}
1470