dolibarr 21.0.0-beta
ProductAttributeValue.class.php
1<?php
2/* Copyright (C) 2016 Marcos García <marcosgdf@gmail.com>
3 * Copyright (C) 2022 Open-Dsi <support@open-dsi.fr>
4 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
5 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
27{
31 public $module = 'variants';
32
36 public $element = 'productattributevalue';
37
41 public $table_element = 'product_attribute_value';
42
71 public $fields = array(
72 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
73 'fk_product_attribute' => array('type' => 'integer:ProductAttribute:variants/class/ProductAttribute.class.php', 'label' => 'ProductAttribute', 'enabled' => 1, 'visible' => 0, 'position' => 10, 'notnull' => 1, 'index' => 1,),
74 'ref' => array('type' => 'varchar(255)', 'label' => 'Ref', 'visible' => 1, 'enabled' => 1, 'position' => 20, 'notnull' => 1, 'index' => 1, 'searchall' => 1, 'comment' => "Reference of object", 'css' => ''),
75 'value' => array('type' => 'varchar(255)', 'label' => 'Value', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'help' => "", 'showoncombobox' => 1,),
76 'position' => array('type' => 'integer', 'label' => 'Rank', 'enabled' => 1, 'visible' => 0, 'default' => '0', 'position' => 200, 'notnull' => 1,),
77 );
78
83 public $id;
84
89 public $fk_product_attribute;
90
95 public $ref;
96
101 public $value;
102
107 public $position;
108
114 public function __construct(DoliDB $db)
115 {
116 global $conf, $langs;
117
118 $this->db = $db;
119
120 $this->ismultientitymanaged = 1;
121 $this->isextrafieldmanaged = 1;
122 $this->entity = $conf->entity;
123
124 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
125 $this->fields['rowid']['visible'] = 0;
126 }
127 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
128 $this->fields['entity']['enabled'] = 0;
129 }
130
131 // Unset fields that are disabled
132 foreach ($this->fields as $key => $val) {
133 if (isset($val['enabled']) && empty($val['enabled'])) {
134 unset($this->fields[$key]);
135 }
136 }
137
138 // Translate some data of arrayofkeyval
139 if (is_object($langs)) {
140 foreach ($this->fields as $key => $val) {
141 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
142 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
143 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
144 }
145 }
146 }
147 }
148 }
149
157 public function create(User $user, $notrigger = 0)
158 {
159 global $langs;
160 $error = 0;
161
162 // Clean parameters
163 $this->fk_product_attribute = $this->fk_product_attribute > 0 ? $this->fk_product_attribute : 0;
164 $this->ref = strtoupper(dol_sanitizeFileName(dol_string_nospecial(trim($this->ref)))); // Ref must be uppercase
165 $this->value = trim($this->value);
166
167 // Check parameters
168 if (empty($this->fk_product_attribute)) {
169 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductAttribute"));
170 $error++;
171 }
172 if (empty($this->ref)) {
173 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
174 $error++;
175 }
176 if (empty($this->value)) {
177 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Value"));
178 $error++;
179 }
180 // Position to use
181 if (empty($this->position)) {
182 $positionmax = $this->getMaxAttributesValuesPosition($this->fk_product_attribute);
183 $this->position = $positionmax + 1;
184 }
185 if ($error) {
186 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
187 return -1;
188 }
189
190 $this->db->begin();
191
192 $sql = "INSERT INTO " . MAIN_DB_PREFIX . $this->table_element . " (";
193 $sql .= " fk_product_attribute, ref, value, entity, position";
194 $sql .= ")";
195 $sql .= " VALUES (";
196 $sql .= " " . ((int) $this->fk_product_attribute);
197 $sql .= ", '" . $this->db->escape($this->ref) . "'";
198 $sql .= ", '" . $this->db->escape($this->value) . "'";
199 $sql .= ", " . ((int) $this->entity);
200 $sql .= ", " . ((int) $this->position);
201 $sql .= ")";
202
203 dol_syslog(__METHOD__, LOG_DEBUG);
204 $resql = $this->db->query($sql);
205 if (!$resql) {
206 $this->errors[] = "Error " . $this->db->lasterror();
207 $error++;
208 }
209
210 if (!$error) {
211 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element);
212 $result = $this->insertExtraFields();
213 if ($result < 0) {
214 $error++;
215 }
216 }
217
218 if (!$error && !$notrigger) {
219 // Call trigger
220 $result = $this->call_trigger('PRODUCT_ATTRIBUTE_VALUE_CREATE', $user);
221 if ($result < 0) {
222 $error++;
223 }
224 // End call triggers
225 }
226
227 if ($error) {
228 $this->db->rollback();
229 return -1 * $error;
230 } else {
231 $this->db->commit();
232 return $this->id;
233 }
234 }
235
242 public function fetch($id)
243 {
244 global $langs;
245 $error = 0;
246
247 // Clean parameters
248 $id = $id > 0 ? $id : 0;
249
250 // Check parameters
251 if (empty($id)) {
252 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
253 $error++;
254 }
255 if ($error) {
256 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
257 return -1;
258 }
259
260 $sql = "SELECT rowid, fk_product_attribute, ref, value";
261 $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
262 $sql .= " WHERE rowid = " . ((int) $id);
263 $sql .= " AND entity IN (" . getEntity('product') . ")";
264
265 dol_syslog(__METHOD__, LOG_DEBUG);
266 $resql = $this->db->query($sql);
267 if (!$resql) {
268 $this->errors[] = "Error " . $this->db->lasterror();
269 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
270 return -1;
271 }
272
273 $numrows = $this->db->num_rows($resql);
274 if ($numrows) {
275 $obj = $this->db->fetch_object($resql);
276
277 $this->id = $obj->rowid;
278 $this->fk_product_attribute = $obj->fk_product_attribute;
279 $this->ref = $obj->ref;
280 $this->value = $obj->value;
281 $this->fetch_optionals();
282 }
283 $this->db->free($resql);
284
285 return $numrows;
286 }
287
296 public function fetchAllByProductAttribute($prodattr_id, $only_used = false, $returnonlydata = 0)
297 {
298 $return = array();
299
300 $sql = "SELECT v.fk_product_attribute, v.rowid, v.ref, v.value FROM " . MAIN_DB_PREFIX . "product_attribute_value v ";
301
302 $sql .= "WHERE v.fk_product_attribute = " . ((int) $prodattr_id);
303
304 if ($only_used) {
305 $sql .= " AND EXISTS (SELECT c2v.fk_prod_attr_val ";
306 $sql .= "FROM " . MAIN_DB_PREFIX . "product_attribute_combination2val c2v ";
307 $sql .= "LEFT JOIN " . MAIN_DB_PREFIX . "product_attribute_combination c ON c.rowid = c2v.fk_prod_combination ";
308 $sql .= "LEFT JOIN " . MAIN_DB_PREFIX . "product p ON p.rowid = c.fk_product_child";
309 $sql .= " WHERE c2v.rowid IS NOT NULL AND p.tosell = 1 AND c2v.fk_prod_attr_val = v.rowid)";
310 }
311
312 $sql .= " ORDER BY v.position ASC";
313
314 $query = $this->db->query($sql);
315
316 if ($query) {
317 while ($result = $this->db->fetch_object($query)) {
318 if (empty($returnonlydata)) {
319 $tmp = new ProductAttributeValue($this->db);
320 } else {
321 $tmp = new stdClass();
322 }
323
324 $tmp->fk_product_attribute = $result->fk_product_attribute;
325 $tmp->id = $result->rowid;
326 $tmp->ref = $result->ref;
327 $tmp->value = $result->value;
328
329 $return[] = $tmp;
330 }
331 }
332
333 return $return;
334 }
335
343 public function update(User $user, $notrigger = 0)
344 {
345 global $langs;
346 $error = 0;
347
348 // Clean parameters
349 $this->fk_product_attribute = $this->fk_product_attribute > 0 ? $this->fk_product_attribute : 0;
350 $this->ref = strtoupper(dol_sanitizeFileName(dol_string_nospecial(trim($this->ref)))); // Ref must be uppercase
351 $this->value = trim($this->value);
352
353 // Check parameters
354 if (empty($this->fk_product_attribute)) {
355 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductAttribute"));
356 $error++;
357 }
358 if (empty($this->ref)) {
359 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
360 $error++;
361 }
362 if (empty($this->value)) {
363 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Value"));
364 $error++;
365 }
366 if ($error) {
367 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
368 return -1;
369 }
370
371 $this->db->begin();
372
373 $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET";
374
375 $sql .= " fk_product_attribute = " . ((int) $this->fk_product_attribute);
376 $sql .= ", ref = '" . $this->db->escape($this->ref) . "'";
377 $sql .= ", value = '" . $this->db->escape($this->value) . "'";
378 $sql .= ", position = " . ((int) $this->position);
379
380 $sql .= " WHERE rowid = " . ((int) $this->id);
381
382 dol_syslog(__METHOD__, LOG_DEBUG);
383 $resql = $this->db->query($sql);
384 if (!$resql) {
385 $this->errors[] = "Error " . $this->db->lasterror();
386 $error++;
387 }
388
389 if (!$error && !$notrigger) {
390 // Call trigger
391 $result = $this->call_trigger('PRODUCT_ATTRIBUTE_VALUE_MODIFY', $user);
392 if ($result < 0) {
393 $error++;
394 }
395 // End call triggers
396 }
397
398 if (!$error) {
399 $this->db->commit();
400 return 1;
401 } else {
402 $this->db->rollback();
403 return -1 * $error;
404 }
405 }
406
414 public function delete(User $user, $notrigger = 0)
415 {
416 global $langs;
417 $error = 0;
418
419 // Clean parameters
420 $this->id = $this->id > 0 ? $this->id : 0;
421
422 // Check parameters
423 if (empty($this->id)) {
424 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
425 $error++;
426 }
427 if ($error) {
428 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
429 return -1;
430 }
431
432 $result = $this->isUsed();
433 if ($result < 0) {
434 return -1;
435 } elseif ($result > 0) {
436 $this->errors[] = $langs->trans('ErrorAttributeValueIsUsedIntoProduct');
437 return -1;
438 }
439
440 $this->db->begin();
441
442 if (!$error && !$notrigger) {
443 // Call trigger
444 $result = $this->call_trigger('PRODUCT_ATTRIBUTE_VALUE_DELETE', $user);
445 if ($result < 0) {
446 $error++;
447 }
448 // End call triggers
449 }
450
451 if (!$error) {
452 $sql = "DELETE FROM " . MAIN_DB_PREFIX . $this->table_element . " WHERE rowid = " . ((int) $this->id);
453
454 dol_syslog(__METHOD__, LOG_DEBUG);
455 $resql = $this->db->query($sql);
456 if (!$resql) {
457 $this->errors[] = "Error " . $this->db->lasterror();
458 $error++;
459 }
460 }
461 if (!$error) {
462 $result = $this->insertExtraFields();
463 if ($result < 0) {
464 $error++;
465 }
466 }
467 if (!$error) {
468 $this->db->commit();
469 return 1;
470 } else {
471 $this->db->rollback();
472 return -1 * $error;
473 }
474 }
475
482 public function getMaxAttributesValuesPosition($fk_product_attribute)
483 {
484 // Search the last position of attributes
485 $sql = "SELECT max(position) FROM " . MAIN_DB_PREFIX . $this->table_element;
486 $sql .= " WHERE entity IN (" . getEntity('product') . ")";
487 $sql .= ' AND fk_product_attribute='.(int) $fk_product_attribute;
488 dol_syslog(__METHOD__, LOG_DEBUG);
489 $resql = $this->db->query($sql);
490 if ($resql) {
491 $row = $this->db->fetch_row($resql);
492 return $row[0];
493 }
494 return 0;
495 }
496
502 public function isUsed()
503 {
504 global $langs;
505 $error = 0;
506
507 // Clean parameters
508 $this->id = $this->id > 0 ? $this->id : 0;
509
510 // Check parameters
511 if (empty($this->id)) {
512 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
513 $error++;
514 }
515 if ($error) {
516 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
517 return -1;
518 }
519
520 $sql = "SELECT COUNT(*) AS nb FROM " . MAIN_DB_PREFIX . "product_attribute_combination2val WHERE fk_prod_attr_val = " . ((int) $this->id);
521
522 dol_syslog(__METHOD__, LOG_DEBUG);
523 $resql = $this->db->query($sql);
524 if (!$resql) {
525 $this->errors[] = "Error " . $this->db->lasterror();
526 return -1;
527 }
528
529 $used = 0;
530 if ($obj = $this->db->fetch_object($resql)) {
531 $used = $obj->nb;
532 }
533
534 return $used ? 1 : 0;
535 }
536}
print $object position
Definition edit.php:204
$object ref
Definition info.php:89
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
errorsToString()
Method to output saved errors.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class ProductAttributeValue Used to represent a product attribute value.
create(User $user, $notrigger=0)
Creates a value for a product attribute.
getMaxAttributesValuesPosition($fk_product_attribute)
Get max value used for position of attributes.
fetch($id)
Gets a product attribute value.
update(User $user, $notrigger=0)
Updates a product attribute value.
isUsed()
Test if used by a product.
__construct(DoliDB $db)
Constructor.
fetchAllByProductAttribute($prodattr_id, $only_used=false, $returnonlydata=0)
Returns all product attribute values of a product attribute.
Class to manage Dolibarr users.
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='', $keepspaces=0)
Clean a string from all punctuation characters to use it as a ref or login.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79