PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/Supa/Product/Attribute/Service.php

https://bitbucket.org/resourcemode/smodels
PHP | 439 lines | 252 code | 73 blank | 114 comment | 22 complexity | c9633f8088851b6d885375cfd567d1db MD5 | raw file
  1. <?php
  2. /**
  3. * Smodels
  4. *
  5. * @copyright Copyright (c) 2012-2013 Daniel Latter.
  6. */
  7. namespace Supa\Product\Attribute;
  8. use Supa\Product\Attribute\Value\Collection as ProductAttributeValueCollection;
  9. use Supa\Product\Attribute\Mapper as ProductAttributeMapper;
  10. use Supa\Product\Attribute\Attribute as ProductAttribute;
  11. use Supa\Product\Attribute\Value\Value as ProductAttributeValue;
  12. use Supa\Product\Product;
  13. use Supa\User\User;
  14. use Supa\AbstractMapper;
  15. use \Supa\AbstractFilter;
  16. use Exception;
  17. /**
  18. * Product attribute service class
  19. */
  20. class Service {
  21. /**
  22. * Data mapper for product attribute object
  23. * @var \Supa\AbstractMapper
  24. */
  25. protected $mapper;
  26. protected $messages = array();
  27. protected $lastException = null;
  28. /**
  29. * Filter for creating an attribute
  30. * @var \Supa\AbstractFilter
  31. */
  32. protected $createFilter;
  33. /**
  34. * Filter for editing an attribute
  35. * @var \Supa\AbstractFilter
  36. */
  37. protected $editFilter;
  38. /**
  39. * Constructor for page class
  40. *
  41. * @param \Supa\AbstractMapper $mapper
  42. */
  43. public function __construct(\Supa\AbstractMapper $mapper) {
  44. $this->mapper = $mapper;
  45. }
  46. /**
  47. * Get product attribute by uid
  48. *
  49. * @param int $uid
  50. * @return ProductAttribute|null
  51. */
  52. public function getByUid($uid) {
  53. try {
  54. $productAttr = $this->mapper->loadByUid($uid);
  55. }catch(Exception $e) {
  56. $productAttr = null;
  57. $this->messages[] = $e->getMessage();
  58. $this->lastException = $e;
  59. }
  60. return $productAttr;
  61. }
  62. /**
  63. * Create a product attribute
  64. *
  65. * @param string $attributeName
  66. * @param User $user User who created attribute
  67. * @param array $attributeValues
  68. * @return ProductAttribute|null
  69. */
  70. public function createAttribute($attributeName, User $user, array $attributeValues = array()) {
  71. try {
  72. $attribute = array('name'=>$attributeName);
  73. $filter = $this->createFilter; //getServiceLocator()->get('ProductAttributeCreateFilter');
  74. $filter->prepareFilter();
  75. $filter->setData($attribute);
  76. if(!$filter->isValid()) {
  77. $this->messages = $filter->getFlatMessages();
  78. throw new Exception('Invalid data when creating product attribute');
  79. }
  80. $productAttr = new ProductAttribute($attribute);
  81. $productAttr->setCreatedBy($user);
  82. $productAttr = $this->mapper->create($productAttr);
  83. $productAttrValues = new ProductAttributeValueCollection(array());
  84. if(!empty($attributeValues)) {
  85. foreach($attributeValues as $attrValue) {
  86. $attr['name'] = $attrValue;
  87. $filter->setData($attr);
  88. if(!$filter->isValid()) {
  89. $this->messages = $filter->getFlatMessages();
  90. throw new Exception('Invalid attribute value given when adding attribute values');
  91. }
  92. $productAttrValues->append(new ProductAttributeValue($attr));
  93. }
  94. if($this->mapper->addAttrValues($productAttr, $productAttrValues)) {
  95. $productAttr->setValues($productAttrValues);
  96. }
  97. }
  98. }catch(Exception $e) {
  99. $productAttr = null;
  100. $this->messages[] = $e->getMessage();
  101. $this->lastException = $e;
  102. }
  103. return $productAttr;
  104. }
  105. /**
  106. * Delete a product attribute
  107. *
  108. * @param int $prodAttrUid
  109. * @throws Exception
  110. * @return bool True if product was deleted, false otherwise
  111. */
  112. public function deleteAttribute($prodAttrUid) {
  113. try {
  114. $prodAttrUid = (int)$prodAttrUid;
  115. if($prodAttrUid <= 0) {
  116. throw new Exception('Invalid uid when deleting product attribute');
  117. }
  118. $productAttr = $this->getByUid($prodAttrUid);
  119. if(is_null($productAttr)) throw new Exception($this->getLastException()->getMessage());
  120. if($this->mapper->isUsedByProducts($productAttr)) {
  121. throw new Exception('Unable to delete product attribute as products are using it');
  122. }
  123. $result = $this->mapper->delete($productAttr);
  124. }catch(Exception $e) {
  125. $result = false;
  126. $this->messages[] = $e->getMessage();
  127. $this->lastException = $e;
  128. }
  129. return $result;
  130. }
  131. /**
  132. * Update values that belong to an attribute
  133. *
  134. * @param ProductAttribute $productAttr
  135. * @param array $values
  136. * @return bool
  137. */
  138. public function updateAttributeValues(ProductAttribute $productAttr, array $values = array()) {
  139. if(empty($values)) {
  140. return false;
  141. }
  142. try {
  143. $bool = true;
  144. $filter = $this->editFilter;//$this->getServiceLocator()->get('ProductAttributeValueEditFilter');
  145. $filter->prepareFilter();
  146. $prodAttrValColl = new ProductAttributeValueCollection(array());
  147. foreach($values as $attrValue) {
  148. $filter->setData($attrValue);
  149. if(!$filter->isValid()) {
  150. $this->messages[] = $filter->getFlatMessages();
  151. continue;
  152. }
  153. $v = new ProductAttributeValue($attrValue);
  154. $prodAttrValColl->append($v);
  155. }
  156. $productAttr->setValues($prodAttrValColl);
  157. $this->mapper->updateAttrValue($productAttr);
  158. }catch(Exception $e) {
  159. $bool = false;
  160. $this->messages[] = $e->getMessage();
  161. $this->lastException = $e;
  162. }
  163. return $bool;
  164. }
  165. public function addAttributeValues(ProductAttribute $productAttr, array $newAttrValues = array()) {
  166. if(empty($newAttrValues)) {
  167. return false;
  168. }
  169. try {
  170. $bool = true;
  171. $filter = $this->createFilter; //$this->getServiceLocator()->get('ProductAttributeValueCreateFilter');
  172. $filter->prepareFilter();
  173. $prodAttrValColl = new ProductAttributeValueCollection(array());
  174. foreach($newAttrValues as $attrValue) {
  175. $filter->setData($attrValue);
  176. if(!$filter->isValid()) {
  177. $this->messages[] = $filter->getFlatMessages();
  178. continue;
  179. }
  180. $v = new ProductAttributeValue($attrValue);
  181. $prodAttrValColl->append($v);
  182. }
  183. $this->mapper->addAttrValues($productAttr, $prodAttrValColl);
  184. }catch(Exception $e) {
  185. $bool = false;
  186. $this->messages[] = $e->getMessage();
  187. $this->lastException = $e;
  188. }
  189. return $bool;
  190. }
  191. public function deleteAttributeValues(ProductAttribute $productAttr, array $attrValueUidsToDelete = array()) {
  192. if(empty($attrValueUidsToDelete)) {
  193. return false;
  194. }
  195. try {
  196. $bool = true;
  197. $prodAttrValColl = new ProductAttributeValueCollection(array());
  198. foreach($attrValueUidsToDelete as $attrValueUid) {
  199. // @todo change to get from db
  200. $attrValue = new ProductAttributeValue(array('uid'=>$attrValueUid)); //$this->getByUid($attrValueUid);
  201. // if(!$attrValue) {
  202. // $this->messages[] = sprintf('Unable to load attribute value: %s', $attrValue);
  203. // }
  204. $prodAttrValColl->append($attrValue);
  205. }
  206. $this->mapper->deleteAttrValues($productAttr, $prodAttrValColl);
  207. }catch(Exception $e) {
  208. $bool = false;
  209. $this->messages[] = $e->getMessage();
  210. $this->lastException = $e;
  211. }
  212. return $bool;
  213. }
  214. /**
  215. * Update a product attribute
  216. *
  217. * @param array $data The updated data for product attribute
  218. * @param User $user User who is updating attribute
  219. * @throws Exception
  220. * @return ProductAttribute|null
  221. */
  222. public function updateAttribute(array $data = array(), User $user) {
  223. try {
  224. $filter = $this->editFilter;//getServiceLocator()->get('ProductAttributeEditFilter');
  225. $filter->prepareFilter();
  226. $filter->setData($data);
  227. if(!$filter->isValid()) {
  228. $this->messages = $filter->getFlatMessages();
  229. throw new Exception('Invalid data given when updating product attribute');
  230. }
  231. // @todo only update changed values
  232. $productAttr = new ProductAttribute($data);
  233. $productAttr->setLastEditiedBy($user);
  234. $productAttr->setName($data['name']);
  235. $values = (isset($data['values']) && is_array($data['values']) ? $data['values'] : array());
  236. $this->updateAttributeValues($productAttr, $values);
  237. // determine attribute values to add or remove
  238. $currentAttrValueUids = (empty($data['currentAttrValueUids']) ? array() : $data['currentAttrValueUids']);
  239. $updatedAttrValueUids = (empty($data['updatedAttrValueUids']) ? array() : $data['updatedAttrValueUids']);
  240. $newAttrValues = (empty($data['newAttrValues']) ? array() : $data['newAttrValues']);
  241. $attrValueUidsToDelete = array(); $attrValueUidsToAdd = array();
  242. if(!empty($updatedAttrValueUids) || !empty($currentAttrValueUids)) {
  243. if(!empty($currentAttrValueUids)) {
  244. $attrValueUidsToDelete = array_diff($currentAttrValueUids, $updatedAttrValueUids);
  245. $attrValueUidsToAdd = array_diff($updatedAttrValueUids, $currentAttrValueUids);
  246. }else {
  247. $attrValueUidsToAdd = $updatedAttrValueUids;
  248. }
  249. }
  250. $this->addAttributeValues($productAttr, $newAttrValues);
  251. $this->deleteAttributeValues($productAttr, $attrValueUidsToDelete);
  252. $productAttr = $this->mapper->update($productAttr);
  253. // reset lazy load
  254. $productAttr->setValues($productAttr->getUID());
  255. }catch(Exception $e) {
  256. $productAttr = null;
  257. $this->messages[] = $e->getMessage();
  258. $this->lastException = $e;
  259. }
  260. return $productAttr;
  261. }
  262. /**
  263. * Get the values for a product attribute
  264. *
  265. * @param int $productAttrId
  266. * @throws Exception
  267. * @return ProductAttributeValueCollection|null
  268. */
  269. public function getAttrValues($productAttrId) {
  270. try {
  271. $productAttr = $this->getByUid($productAttrId);
  272. if(is_null($productAttr)) throw new Exception($this->getLastException()->getMessage());
  273. $productAttrValuesCollection = $this->mapper->getAttrValues($productAttr);
  274. }catch(Exception $e) {
  275. $productAttrValuesCollection = null;
  276. $this->messages[] = $e->getMessage();
  277. $this->lastException = $e;
  278. }
  279. return $productAttrValuesCollection;
  280. }
  281. /**
  282. * Update attribute values for a product
  283. *
  284. * @param Product $product
  285. * @param array $updatedAttrValueUids
  286. * @param arrray $currentAttrValueUids
  287. * @throws Exception
  288. * @return bool True on success, false on failure
  289. */
  290. public function updateAttrValuesForProduct(Product $product, $updatedAttrValueUids = array(), $currentAttrValueUids = array()) {
  291. try {
  292. // throw exception if both arrays are empty
  293. $bothEmpty = (empty($updatedAttrValueUids) ? (empty($currentAttrValueUids) ? true : false) : false);
  294. if($bothEmpty) throw new Exception('No attribute values given when trying to update for product');
  295. $attrValueUidsToDelete = array();
  296. $attrValueUidsToAdd = array();
  297. if(!empty($currentAttrValueUids)) {
  298. $attrValueUidsToDelete = array_diff($currentAttrValueUids, $updatedAttrValueUids);
  299. $attrValueUidsToAdd = array_diff($updatedAttrValueUids, $currentAttrValueUids);
  300. }else {
  301. $attrValueUidsToAdd = $updatedAttrValueUids;
  302. }
  303. if($attrValueUidsToAdd == $attrValueUidsToDelete) {
  304. return true;
  305. }
  306. $updated = $this->mapper->updateProductAttrValues($product, $attrValueUidsToAdd, $attrValueUidsToDelete);
  307. // reset lazy load
  308. // TODO: change?
  309. $product->setAttributes($product->getUID());
  310. }catch(Exception $e) {
  311. $updated = false;
  312. $this->messages[] = $e->getMessage();
  313. $this->lastException = $e;
  314. }
  315. return $updated;
  316. }
  317. /**
  318. * Get's the attributes belonging to a Product
  319. *
  320. * @param Product $product
  321. * @throws Exception
  322. * @return \ArrayIterator|false
  323. */
  324. public function getAttributesForProduct($product) {
  325. try {
  326. $productAttrCollection = $this->mapper->getProductAttributes($product);
  327. }catch(Exception $e) {
  328. $productAttrCollection = false;
  329. $this->messages[] = $e->getMessage();
  330. $this->lastException = $e;
  331. }
  332. return $productAttrCollection;
  333. }
  334. /**
  335. * Get any service class messages
  336. *
  337. * @return array
  338. */
  339. public function getMessages() {
  340. return $this->messages;
  341. }
  342. /**
  343. * Get last exception thrown by this class
  344. *
  345. * @return \Exception
  346. */
  347. public function getLastException() {
  348. return $this->lastException;
  349. }
  350. /**
  351. * Set the filter for editing a ProductAttribute
  352. *
  353. * @param \Supa\AbstractFilter $filter
  354. */
  355. public function setEditFilter(\Supa\AbstractFilter $filter) {
  356. $this->editFilter = $filter;
  357. }
  358. /**
  359. * Set the filter for creating a ProductAttribute
  360. *
  361. * @param \Supa\AbstractFilter $filter
  362. */
  363. public function setCreateFilter(\Supa\AbstractFilter $filter) {
  364. $this->createFilter = $filter;
  365. }
  366. }