ProductAttribute.class.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. <?php
  2. /* Copyright (C) 2016 Marcos García <marcosgdf@gmail.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. */
  17. require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
  18. /**
  19. * Class ProductAttribute
  20. * Used to represent a product attribute
  21. */
  22. class ProductAttribute extends CommonObject
  23. {
  24. /**
  25. * Database handler
  26. * @var DoliDB
  27. */
  28. public $db;
  29. /**
  30. * Id of the product attribute
  31. * @var int
  32. */
  33. public $id;
  34. /**
  35. * Ref of the product attribute
  36. * @var string
  37. */
  38. public $ref;
  39. /**
  40. * External ref of the product attribute
  41. * @var string
  42. */
  43. public $ref_ext;
  44. /**
  45. * Label of the product attribute
  46. * @var string
  47. */
  48. public $label;
  49. /**
  50. * Order of attribute.
  51. * Lower ones will be shown first and higher ones last
  52. * @var int
  53. */
  54. public $rang;
  55. /**
  56. * Constructor
  57. *
  58. * @param DoliDB $db Database handler
  59. */
  60. public function __construct(DoliDB $db)
  61. {
  62. global $conf;
  63. $this->db = $db;
  64. $this->entity = $conf->entity;
  65. }
  66. /**
  67. * Fetches the properties of a product attribute
  68. *
  69. * @param int $id Attribute id
  70. * @return int <1 KO, >1 OK
  71. */
  72. public function fetch($id)
  73. {
  74. if (!$id) {
  75. return -1;
  76. }
  77. $sql = "SELECT rowid, ref, ref_ext, label, rang FROM ".MAIN_DB_PREFIX."product_attribute WHERE rowid = ".((int) $id)." AND entity IN (".getEntity('product').")";
  78. $query = $this->db->query($sql);
  79. if (!$this->db->num_rows($query)) {
  80. return -1;
  81. }
  82. $obj = $this->db->fetch_object($query);
  83. $this->id = $obj->rowid;
  84. $this->ref = $obj->ref;
  85. $this->ref_ext = $obj->ref_ext;
  86. $this->label = $obj->label;
  87. $this->rang = $obj->rang;
  88. return 1;
  89. }
  90. /**
  91. * Returns an array of all product variants
  92. *
  93. * @param int $returnonlydata 0: return object, 1: return only data
  94. * @return ProductAttribute[]
  95. */
  96. public function fetchAll($returnonlydata = 0)
  97. {
  98. $return = array();
  99. $sql = 'SELECT rowid, ref, ref_ext, label, rang FROM '.MAIN_DB_PREFIX."product_attribute WHERE entity IN (".getEntity('product').')';
  100. $sql .= $this->db->order('rang', 'asc');
  101. $query = $this->db->query($sql);
  102. if ($query) {
  103. while ($result = $this->db->fetch_object($query)) {
  104. if (empty($returnonlydata)) {
  105. $tmp = new ProductAttribute($this->db);
  106. } else {
  107. $tmp = new stdClass();
  108. }
  109. $tmp->id = $result->rowid;
  110. $tmp->ref = $result->ref;
  111. $tmp->ref_ext = $result->ref_ext;
  112. $tmp->label = $result->label;
  113. $tmp->rang = $result->rang;
  114. $return[] = $tmp;
  115. }
  116. } else {
  117. dol_print_error($this->db);
  118. }
  119. return $return;
  120. }
  121. /**
  122. * Creates a product attribute
  123. *
  124. * @param User $user Object user
  125. * @param int $notrigger Do not execute trigger
  126. * @return int <0 KO, Id of new variant if OK
  127. */
  128. public function create(User $user, $notrigger = 0)
  129. {
  130. if (empty($notrigger)) {
  131. // Call trigger
  132. $result = $this->call_trigger('PRODUCT_ATTRIBUTE_CREATE', $user);
  133. if ($result < 0) {
  134. return -1;
  135. }
  136. // End call triggers
  137. }
  138. //Ref must be uppercase
  139. $this->ref = strtoupper($this->ref);
  140. $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_attribute (ref, ref_ext, label, entity, rang)
  141. VALUES ('".$this->db->escape($this->ref)."', '".$this->db->escape($this->ref_ext)."', '".$this->db->escape($this->label)."', ".(int) $this->entity.", ".(int) $this->rang.")";
  142. $query = $this->db->query($sql);
  143. if ($query) {
  144. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'product_attribute');
  145. return $this->id;
  146. }
  147. return -1;
  148. }
  149. /**
  150. * Updates a product attribute
  151. *
  152. * @param User $user Object user
  153. * @param int $notrigger Do not execute trigger
  154. * @return int <0 KO, >0 OK
  155. */
  156. public function update(User $user, $notrigger = 0)
  157. {
  158. if (empty($notrigger)) {
  159. // Call trigger
  160. $result = $this->call_trigger('PRODUCT_ATTRIBUTE_MODIFY', $user);
  161. if ($result < 0) {
  162. return -1;
  163. }
  164. // End call triggers
  165. }
  166. //Ref must be uppercase
  167. $this->ref = trim(strtoupper($this->ref));
  168. $this->label = trim($this->label);
  169. $sql = "UPDATE ".MAIN_DB_PREFIX."product_attribute SET ref = '".$this->db->escape($this->ref)."', ref_ext = '".$this->db->escape($this->ref_ext)."', label = '".$this->db->escape($this->label)."', rang = ".(int) $this->rang." WHERE rowid = ".(int) $this->id;
  170. if ($this->db->query($sql)) {
  171. return 1;
  172. }
  173. return -1;
  174. }
  175. /**
  176. * Deletes a product attribute
  177. *
  178. * @param User $user Object user
  179. * @param int $notrigger Do not execute trigger
  180. * @return int <0 KO, >0 OK
  181. */
  182. public function delete(User $user, $notrigger = 0)
  183. {
  184. if (empty($notrigger)) {
  185. // Call trigger
  186. $result = $this->call_trigger('PRODUCT_ATTRIBUTE_DELETE', $user);
  187. if ($result < 0) {
  188. return -1;
  189. }
  190. // End call triggers
  191. }
  192. $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_attribute WHERE rowid = ".(int) $this->id;
  193. if ($this->db->query($sql)) {
  194. return 1;
  195. }
  196. return -1;
  197. }
  198. /**
  199. * Returns the number of values for this attribute
  200. *
  201. * @return int
  202. */
  203. public function countChildValues()
  204. {
  205. $sql = "SELECT COUNT(*) count FROM ".MAIN_DB_PREFIX."product_attribute_value WHERE fk_product_attribute = ".(int) $this->id;
  206. $query = $this->db->query($sql);
  207. $result = $this->db->fetch_object($query);
  208. return $result->count;
  209. }
  210. /**
  211. * Returns the number of products that are using this attribute
  212. *
  213. * @return int
  214. */
  215. public function countChildProducts()
  216. {
  217. $sql = "SELECT COUNT(*) count FROM ".MAIN_DB_PREFIX."product_attribute_combination2val pac2v
  218. LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination pac ON pac2v.fk_prod_combination = pac.rowid WHERE pac2v.fk_prod_attr = ".((int) $this->id)." AND pac.entity IN (".getEntity('product').")";
  219. $query = $this->db->query($sql);
  220. $result = $this->db->fetch_object($query);
  221. return $result->count;
  222. }
  223. /**
  224. * Reorders the order of the variants.
  225. * This is an internal function used by moveLine function
  226. *
  227. * @return int <0 KO >0 OK
  228. */
  229. protected function reorderLines()
  230. {
  231. global $user;
  232. $tmp_order = array();
  233. $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'product_attribute WHERE rang = 0';
  234. $sql .= $this->db->order('rang, rowid', 'asc');
  235. $query = $this->db->query($sql);
  236. if (!$query) {
  237. return -1;
  238. }
  239. while ($result = $this->db->fetch_object($query)) {
  240. $tmp_order[] = $result->rowid;
  241. }
  242. foreach ($tmp_order as $order => $rowid) {
  243. $tmp = new ProductAttribute($this->db);
  244. $tmp->fetch($rowid);
  245. $tmp->rang = $order + 1;
  246. if ($tmp->update($user) < 0) {
  247. return -1;
  248. }
  249. }
  250. return 1;
  251. }
  252. /**
  253. * Internal function to handle moveUp and moveDown functions
  254. *
  255. * @param string $type up/down
  256. * @return int <0 KO >0 OK
  257. */
  258. private function moveLine($type)
  259. {
  260. global $user;
  261. if ($this->reorderLines() < 0) {
  262. return -1;
  263. }
  264. $this->db->begin();
  265. if ($type == 'up') {
  266. $newrang = $this->rang - 1;
  267. } else {
  268. $newrang = $this->rang + 1;
  269. }
  270. $sql = 'UPDATE '.MAIN_DB_PREFIX.'product_attribute SET rang = '.((int) $this->rang).' WHERE rang = '.((int) $newrang);
  271. if (!$this->db->query($sql)) {
  272. $this->db->rollback();
  273. return -1;
  274. }
  275. $this->rang = $newrang;
  276. if ($this->update($user) < 0) {
  277. $this->db->rollback();
  278. return -1;
  279. }
  280. $this->db->commit();
  281. return 1;
  282. }
  283. /**
  284. * Shows this attribute before others
  285. *
  286. * @return int <0 KO >0 OK
  287. */
  288. public function moveUp()
  289. {
  290. return $this->moveLine('up');
  291. }
  292. /**
  293. * Shows this attribute after others
  294. *
  295. * @return int <0 KO >0 OK
  296. */
  297. public function moveDown()
  298. {
  299. return $this->moveLine('down');
  300. }
  301. /**
  302. * Updates the order of all variants. Used by AJAX page for drag&drop
  303. *
  304. * @param DoliDB $db Database handler
  305. * @param array $order Array with row id ordered in ascendent mode
  306. * @return int <0 KO >0 OK
  307. */
  308. public static function bulkUpdateOrder(DoliDB $db, array $order)
  309. {
  310. global $user;
  311. $tmp = new ProductAttribute($db);
  312. foreach ($order as $key => $attrid) {
  313. if ($tmp->fetch($attrid) < 0) {
  314. return -1;
  315. }
  316. $tmp->rang = $key;
  317. if ($tmp->update($user) < 0) {
  318. return -1;
  319. }
  320. }
  321. return 1;
  322. }
  323. }