Massgenerator.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\SalesRule\Model\Coupon;
  7. /**
  8. * SalesRule Mass Coupon Generator
  9. *
  10. * @author Magento Core Team <core@magentocommerce.com>
  11. */
  12. class Massgenerator extends \Magento\Framework\Model\AbstractModel implements
  13. \Magento\SalesRule\Model\Coupon\CodegeneratorInterface
  14. {
  15. /**
  16. * Maximum probability of guessing the coupon on the first attempt
  17. */
  18. const MAX_PROBABILITY_OF_GUESSING = 0.25;
  19. /**
  20. * Number of attempts to generate
  21. */
  22. const MAX_GENERATE_ATTEMPTS = 10;
  23. /**
  24. * Count of generated Coupons
  25. * @var int
  26. */
  27. protected $generatedCount = 0;
  28. /**
  29. * @var array
  30. */
  31. protected $generatedCodes = [];
  32. /**
  33. * Sales rule coupon
  34. *
  35. * @var \Magento\SalesRule\Helper\Coupon
  36. */
  37. protected $salesRuleCoupon;
  38. /**
  39. * @var \Magento\Framework\Stdlib\DateTime\DateTime
  40. */
  41. protected $date;
  42. /**
  43. * @var \Magento\SalesRule\Model\CouponFactory
  44. */
  45. protected $couponFactory;
  46. /**
  47. * @var \Magento\Framework\Stdlib\DateTime
  48. */
  49. protected $dateTime;
  50. /**
  51. * @param \Magento\Framework\Model\Context $context
  52. * @param \Magento\Framework\Registry $registry
  53. * @param \Magento\SalesRule\Helper\Coupon $salesRuleCoupon
  54. * @param \Magento\SalesRule\Model\CouponFactory $couponFactory
  55. * @param \Magento\Framework\Stdlib\DateTime\DateTime $date
  56. * @param \Magento\Framework\Stdlib\DateTime $dateTime
  57. * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
  58. * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
  59. * @param array $data
  60. */
  61. public function __construct(
  62. \Magento\Framework\Model\Context $context,
  63. \Magento\Framework\Registry $registry,
  64. \Magento\SalesRule\Helper\Coupon $salesRuleCoupon,
  65. \Magento\SalesRule\Model\CouponFactory $couponFactory,
  66. \Magento\Framework\Stdlib\DateTime\DateTime $date,
  67. \Magento\Framework\Stdlib\DateTime $dateTime,
  68. \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
  69. \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
  70. array $data = []
  71. ) {
  72. $this->salesRuleCoupon = $salesRuleCoupon;
  73. $this->date = $date;
  74. $this->couponFactory = $couponFactory;
  75. $this->dateTime = $dateTime;
  76. parent::__construct($context, $registry, $resource, $resourceCollection, $data);
  77. }
  78. /**
  79. * Initialize resource
  80. *
  81. * @return void
  82. */
  83. protected function _construct()
  84. {
  85. $this->_init(\Magento\SalesRule\Model\ResourceModel\Coupon::class);
  86. }
  87. /**
  88. * Generate coupon code
  89. *
  90. * @return string
  91. */
  92. public function generateCode()
  93. {
  94. $format = $this->getFormat();
  95. if (empty($format)) {
  96. $format = \Magento\SalesRule\Helper\Coupon::COUPON_FORMAT_ALPHANUMERIC;
  97. }
  98. $splitChar = $this->getDelimiter();
  99. $charset = $this->salesRuleCoupon->getCharset($format);
  100. $code = '';
  101. $charsetSize = count($charset);
  102. $split = max(0, (int)$this->getDash());
  103. $length = max(1, (int)$this->getLength());
  104. for ($i = 0; $i < $length; ++$i) {
  105. $char = $charset[\Magento\Framework\Math\Random::getRandomNumber(0, $charsetSize - 1)];
  106. if (($split > 0) && (($i % $split) === 0) && ($i !== 0)) {
  107. $char = $splitChar . $char;
  108. }
  109. $code .= $char;
  110. }
  111. return $this->getPrefix() . $code . $this->getSuffix();
  112. }
  113. /**
  114. * Retrieve delimiter
  115. *
  116. * @return string
  117. */
  118. public function getDelimiter()
  119. {
  120. if ($this->hasData('delimiter')) {
  121. return $this->getData('delimiter');
  122. } else {
  123. return $this->salesRuleCoupon->getCodeSeparator();
  124. }
  125. }
  126. /**
  127. * Generate Coupons Pool
  128. *
  129. * @throws \Magento\Framework\Exception\LocalizedException
  130. * @return $this
  131. */
  132. public function generatePool()
  133. {
  134. $this->generatedCount = 0;
  135. $this->generatedCodes = [];
  136. $size = $this->getQty();
  137. $maxAttempts = $this->getMaxAttempts() ? $this->getMaxAttempts() : self::MAX_GENERATE_ATTEMPTS;
  138. $this->increaseLength();
  139. /** @var $coupon \Magento\SalesRule\Model\Coupon */
  140. $coupon = $this->couponFactory->create();
  141. $nowTimestamp = $this->dateTime->formatDate($this->date->gmtTimestamp());
  142. for ($i = 0; $i < $size; $i++) {
  143. $attempt = 0;
  144. do {
  145. if ($attempt >= $maxAttempts) {
  146. throw new \Magento\Framework\Exception\LocalizedException(
  147. __('We cannot create the requested Coupon Qty. Please check your settings and try again.')
  148. );
  149. }
  150. $code = $this->generateCode();
  151. ++$attempt;
  152. } while ($this->getResource()->exists($code));
  153. $expirationDate = $this->getToDate();
  154. if ($expirationDate instanceof \DateTimeInterface) {
  155. $expirationDate = $expirationDate->format('Y-m-d H:i:s');
  156. }
  157. $coupon->setId(null)
  158. ->setRuleId($this->getRuleId())
  159. ->setUsageLimit($this->getUsesPerCoupon())
  160. ->setUsagePerCustomer($this->getUsagePerCustomer())
  161. ->setExpirationDate($expirationDate)
  162. ->setCreatedAt($nowTimestamp)
  163. ->setType(\Magento\SalesRule\Helper\Coupon::COUPON_TYPE_SPECIFIC_AUTOGENERATED)
  164. ->setCode($code)
  165. ->save();
  166. $this->generatedCount += 1;
  167. $this->generatedCodes[] = $code;
  168. }
  169. return $this;
  170. }
  171. /**
  172. * Increase the length of Code if probability is low
  173. *
  174. * @return void
  175. */
  176. protected function increaseLength()
  177. {
  178. $maxProbability = $this->getMaxProbability() ? $this->getMaxProbability() : self::MAX_PROBABILITY_OF_GUESSING;
  179. $chars = count($this->salesRuleCoupon->getCharset($this->getFormat()));
  180. $size = $this->getQty();
  181. $length = (int)$this->getLength();
  182. $maxCodes = pow($chars, $length);
  183. $probability = $size / $maxCodes;
  184. if ($probability > $maxProbability) {
  185. do {
  186. $length++;
  187. $maxCodes = pow($chars, $length);
  188. $probability = $size / $maxCodes;
  189. } while ($probability > $maxProbability);
  190. $this->setLength($length);
  191. }
  192. }
  193. /**
  194. * Validate data input
  195. *
  196. * @param array $data
  197. * @return bool
  198. */
  199. public function validateData($data)
  200. {
  201. return !empty($data)
  202. && !empty($data['qty'])
  203. && !empty($data['rule_id'])
  204. && !empty($data['length'])
  205. && !empty($data['format'])
  206. && (int)$data['qty'] > 0
  207. && (int)$data['rule_id'] > 0
  208. && (int)$data['length'] > 0;
  209. }
  210. /**
  211. * Return the generated coupon codes
  212. *
  213. * @return array
  214. */
  215. public function getGeneratedCodes()
  216. {
  217. return $this->generatedCodes;
  218. }
  219. /**
  220. * Retrieve count of generated Coupons
  221. *
  222. * @return int
  223. */
  224. public function getGeneratedCount()
  225. {
  226. return $this->generatedCount;
  227. }
  228. }