GroupRepository.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Customer\Model\ResourceModel;
  7. use Magento\Customer\Api\Data\GroupInterface;
  8. use Magento\Customer\Model\ResourceModel\Group\Collection;
  9. use Magento\Framework\Api\Search\FilterGroup;
  10. use Magento\Framework\Api\SearchCriteriaInterface;
  11. use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
  12. use Magento\Framework\Exception\InputException;
  13. use Magento\Framework\Exception\State\InvalidTransitionException;
  14. use Magento\Tax\Api\Data\TaxClassInterface;
  15. use Magento\Tax\Api\TaxClassManagementInterface;
  16. use Magento\Framework\Api\ExtensibleDataInterface;
  17. use Magento\Customer\Api\Data\GroupExtensionInterface;
  18. /**
  19. * Customer group CRUD class
  20. *
  21. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  22. */
  23. class GroupRepository implements \Magento\Customer\Api\GroupRepositoryInterface
  24. {
  25. /**
  26. * The default tax class id if no tax class id is specified
  27. */
  28. const DEFAULT_TAX_CLASS_ID = 3;
  29. /**
  30. * @var \Magento\Customer\Model\GroupRegistry
  31. */
  32. protected $groupRegistry;
  33. /**
  34. * @var \Magento\Customer\Model\GroupFactory
  35. */
  36. protected $groupFactory;
  37. /**
  38. * @var \Magento\Customer\Api\Data\GroupInterfaceFactory
  39. */
  40. protected $groupDataFactory;
  41. /**
  42. * @var \Magento\Customer\Model\ResourceModel\Group
  43. */
  44. protected $groupResourceModel;
  45. /**
  46. * @var \Magento\Framework\Reflection\DataObjectProcessor
  47. */
  48. protected $dataObjectProcessor;
  49. /**
  50. * @var \Magento\Customer\Api\Data\GroupSearchResultsInterfaceFactory
  51. */
  52. protected $searchResultsFactory;
  53. /**
  54. * @var \Magento\Tax\Api\TaxClassRepositoryInterface
  55. */
  56. private $taxClassRepository;
  57. /**
  58. * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface
  59. */
  60. protected $extensionAttributesJoinProcessor;
  61. /**
  62. * @var CollectionProcessorInterface
  63. */
  64. private $collectionProcessor;
  65. /**
  66. * @param \Magento\Customer\Model\GroupRegistry $groupRegistry
  67. * @param \Magento\Customer\Model\GroupFactory $groupFactory
  68. * @param \Magento\Customer\Api\Data\GroupInterfaceFactory $groupDataFactory
  69. * @param \Magento\Customer\Model\ResourceModel\Group $groupResourceModel
  70. * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor
  71. * @param \Magento\Customer\Api\Data\GroupSearchResultsInterfaceFactory $searchResultsFactory
  72. * @param \Magento\Tax\Api\TaxClassRepositoryInterface $taxClassRepositoryInterface
  73. * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor
  74. * @param CollectionProcessorInterface $collectionProcessor
  75. */
  76. public function __construct(
  77. \Magento\Customer\Model\GroupRegistry $groupRegistry,
  78. \Magento\Customer\Model\GroupFactory $groupFactory,
  79. \Magento\Customer\Api\Data\GroupInterfaceFactory $groupDataFactory,
  80. \Magento\Customer\Model\ResourceModel\Group $groupResourceModel,
  81. \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor,
  82. \Magento\Customer\Api\Data\GroupSearchResultsInterfaceFactory $searchResultsFactory,
  83. \Magento\Tax\Api\TaxClassRepositoryInterface $taxClassRepositoryInterface,
  84. \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor,
  85. CollectionProcessorInterface $collectionProcessor = null
  86. ) {
  87. $this->groupRegistry = $groupRegistry;
  88. $this->groupFactory = $groupFactory;
  89. $this->groupDataFactory = $groupDataFactory;
  90. $this->groupResourceModel = $groupResourceModel;
  91. $this->dataObjectProcessor = $dataObjectProcessor;
  92. $this->searchResultsFactory = $searchResultsFactory;
  93. $this->taxClassRepository = $taxClassRepositoryInterface;
  94. $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor;
  95. $this->collectionProcessor = $collectionProcessor ?: $this->getCollectionProcessor();
  96. }
  97. /**
  98. * {@inheritdoc}
  99. */
  100. public function save(\Magento\Customer\Api\Data\GroupInterface $group)
  101. {
  102. $this->_validate($group);
  103. /** @var \Magento\Customer\Model\Group $groupModel */
  104. $groupModel = null;
  105. if ($group->getId() || (string)$group->getId() === '0') {
  106. $this->_verifyTaxClassModel($group->getTaxClassId(), $group);
  107. $groupModel = $this->groupRegistry->retrieve($group->getId());
  108. $groupDataAttributes = $this->dataObjectProcessor->buildOutputDataArray(
  109. $group,
  110. \Magento\Customer\Api\Data\GroupInterface::class
  111. );
  112. foreach ($groupDataAttributes as $attributeCode => $attributeData) {
  113. $groupModel->setDataUsingMethod($attributeCode, $attributeData);
  114. }
  115. } else {
  116. $groupModel = $this->groupFactory->create();
  117. $groupModel->setCode($group->getCode());
  118. $taxClassId = $group->getTaxClassId() ?: self::DEFAULT_TAX_CLASS_ID;
  119. $this->_verifyTaxClassModel($taxClassId, $group);
  120. $groupModel->setTaxClassId($taxClassId);
  121. }
  122. try {
  123. $this->groupResourceModel->save($groupModel);
  124. } catch (\Magento\Framework\Exception\LocalizedException $e) {
  125. /**
  126. * Would like a better way to determine this error condition but
  127. * difficult to do without imposing more database calls
  128. */
  129. if ($e->getMessage() == (string)__('Customer Group already exists.')) {
  130. throw new InvalidTransitionException(__('Customer Group already exists.'));
  131. }
  132. throw $e;
  133. }
  134. $this->groupRegistry->remove($groupModel->getId());
  135. $groupDataObject = $this->groupDataFactory->create()
  136. ->setId($groupModel->getId())
  137. ->setCode($groupModel->getCode())
  138. ->setTaxClassId($groupModel->getTaxClassId())
  139. ->setTaxClassName($groupModel->getTaxClassName());
  140. if ($group->getExtensionAttributes()) {
  141. $groupDataObject->setExtensionAttributes($group->getExtensionAttributes());
  142. }
  143. return $groupDataObject;
  144. }
  145. /**
  146. * {@inheritdoc}
  147. */
  148. public function getById($id)
  149. {
  150. $groupModel = $this->groupRegistry->retrieve($id);
  151. $groupDataObject = $this->groupDataFactory->create()
  152. ->setId($groupModel->getId())
  153. ->setCode($groupModel->getCode())
  154. ->setTaxClassId($groupModel->getTaxClassId())
  155. ->setTaxClassName($groupModel->getTaxClassName());
  156. return $groupDataObject;
  157. }
  158. /**
  159. * {@inheritdoc}
  160. */
  161. public function getList(SearchCriteriaInterface $searchCriteria)
  162. {
  163. $searchResults = $this->searchResultsFactory->create();
  164. $searchResults->setSearchCriteria($searchCriteria);
  165. /** @var \Magento\Customer\Model\ResourceModel\Group\Collection $collection */
  166. $collection = $this->groupFactory->create()->getCollection();
  167. $groupInterfaceName = \Magento\Customer\Api\Data\GroupInterface::class;
  168. $this->extensionAttributesJoinProcessor->process($collection, $groupInterfaceName);
  169. $collection->addTaxClass();
  170. $this->collectionProcessor->process($searchCriteria, $collection);
  171. /** @var \Magento\Customer\Api\Data\GroupInterface[] $groups */
  172. $groups = [];
  173. /** @var \Magento\Customer\Model\Group $group */
  174. foreach ($collection as $group) {
  175. /** @var \Magento\Customer\Api\Data\GroupInterface $groupDataObject */
  176. $groupDataObject = $this->groupDataFactory->create()
  177. ->setId($group->getId())
  178. ->setCode($group->getCode())
  179. ->setTaxClassId($group->getTaxClassId())
  180. ->setTaxClassName($group->getTaxClassName());
  181. $data = $group->getData();
  182. $data = $this->extensionAttributesJoinProcessor->extractExtensionAttributes($groupInterfaceName, $data);
  183. if (isset($data[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY])
  184. && ($data[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY] instanceof GroupExtensionInterface)
  185. ) {
  186. $groupDataObject->setExtensionAttributes($data[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]);
  187. }
  188. $groups[] = $groupDataObject;
  189. }
  190. $searchResults->setTotalCount($collection->getSize());
  191. return $searchResults->setItems($groups);
  192. }
  193. /**
  194. * Helper function that adds a FilterGroup to the collection.
  195. *
  196. * @deprecated 101.0.0
  197. * @param FilterGroup $filterGroup
  198. * @param Collection $collection
  199. * @return void
  200. * @throws \Magento\Framework\Exception\InputException
  201. */
  202. protected function addFilterGroupToCollection(FilterGroup $filterGroup, Collection $collection)
  203. {
  204. $fields = [];
  205. $conditions = [];
  206. foreach ($filterGroup->getFilters() as $filter) {
  207. $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq';
  208. $fields[] = $this->translateField($filter->getField());
  209. $conditions[] = [$condition => $filter->getValue()];
  210. }
  211. if ($fields) {
  212. $collection->addFieldToFilter($fields, $conditions);
  213. }
  214. }
  215. /**
  216. * Translates a field name to a DB column name for use in collection queries.
  217. *
  218. * @deprecated 101.0.0
  219. * @param string $field a field name that should be translated to a DB column name.
  220. * @return string
  221. */
  222. protected function translateField($field)
  223. {
  224. switch ($field) {
  225. case GroupInterface::CODE:
  226. return 'customer_group_code';
  227. case GroupInterface::ID:
  228. return 'customer_group_id';
  229. case GroupInterface::TAX_CLASS_NAME:
  230. return 'class_name';
  231. default:
  232. return $field;
  233. }
  234. }
  235. /**
  236. * Delete customer group.
  237. *
  238. * @param GroupInterface $group
  239. * @return bool true on success
  240. * @throws \Magento\Framework\Exception\StateException If customer group cannot be deleted
  241. * @throws \Magento\Framework\Exception\LocalizedException
  242. */
  243. public function delete(GroupInterface $group)
  244. {
  245. return $this->deleteById($group->getId());
  246. }
  247. /**
  248. * Delete customer group by ID.
  249. *
  250. * @param int $id
  251. * @return bool true on success
  252. * @throws \Magento\Framework\Exception\NoSuchEntityException
  253. * @throws \Magento\Framework\Exception\StateException If customer group cannot be deleted
  254. * @throws \Magento\Framework\Exception\LocalizedException
  255. */
  256. public function deleteById($id)
  257. {
  258. $groupModel = $this->groupRegistry->retrieve($id);
  259. if ($id <= 0 || $groupModel->usesAsDefault()) {
  260. throw new \Magento\Framework\Exception\StateException(__('Cannot delete group.'));
  261. }
  262. $groupModel->delete();
  263. $this->groupRegistry->remove($id);
  264. return true;
  265. }
  266. /**
  267. * Validate group values.
  268. *
  269. * @param \Magento\Customer\Api\Data\GroupInterface $group
  270. * @throws InputException
  271. * @return void
  272. *
  273. * @SuppressWarnings(PHPMD.NPathComplexity)
  274. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  275. */
  276. private function _validate($group)
  277. {
  278. $exception = new InputException();
  279. if (!\Zend_Validate::is($group->getCode(), 'NotEmpty')) {
  280. $exception->addError(__('"%fieldName" is required. Enter and try again.', ['fieldName' => 'code']));
  281. }
  282. if ($exception->wasErrorAdded()) {
  283. throw $exception;
  284. }
  285. }
  286. /**
  287. * Verifies that the tax class model exists and is a customer tax class type.
  288. *
  289. * @param int $taxClassId The id of the tax class model to check
  290. * @param \Magento\Customer\Api\Data\GroupInterface $group The original group parameters
  291. * @return void
  292. * @throws InputException Thrown if the tax class model is invalid
  293. */
  294. protected function _verifyTaxClassModel($taxClassId, $group)
  295. {
  296. try {
  297. /* @var TaxClassInterface $taxClassData */
  298. $taxClassData = $this->taxClassRepository->get($taxClassId);
  299. } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
  300. throw InputException::invalidFieldValue('taxClassId', $group->getTaxClassId());
  301. }
  302. if ($taxClassData->getClassType() !== TaxClassManagementInterface::TYPE_CUSTOMER) {
  303. throw InputException::invalidFieldValue('taxClassId', $group->getTaxClassId());
  304. }
  305. }
  306. /**
  307. * Retrieve collection processor
  308. *
  309. * @deprecated 101.0.0
  310. * @return CollectionProcessorInterface
  311. */
  312. private function getCollectionProcessor()
  313. {
  314. if (!$this->collectionProcessor) {
  315. $this->collectionProcessor = \Magento\Framework\App\ObjectManager::getInstance()->get(
  316. 'Magento\Customer\Model\Api\SearchCriteria\GroupCollectionProcessor'
  317. );
  318. }
  319. return $this->collectionProcessor;
  320. }
  321. }