1: <?php
2: /**
3: * Magento
4: *
5: * NOTICE OF LICENSE
6: *
7: * This source file is subject to the Open Software License (OSL 3.0)
8: * that is bundled with this package in the file LICENSE.txt.
9: * It is also available through the world-wide-web at this URL:
10: * http://opensource.org/licenses/osl-3.0.php
11: * If you did not receive a copy of the license and are unable to
12: * obtain it through the world-wide-web, please send an email
13: * to license@magentocommerce.com so we can send you a copy immediately.
14: *
15: * DISCLAIMER
16: *
17: * Do not edit or add to this file if you wish to upgrade Magento to newer
18: * versions in the future. If you wish to customize Magento for your
19: * needs please refer to http://www.magentocommerce.com for more information.
20: *
21: * @category Mage
22: * @package Mage_SalesRule
23: * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
24: * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
25: */
26:
27:
28: /**
29: * SalesRule Mass Coupon Generator
30: *
31: * @method Mage_SalesRule_Model_Resource_Coupon getResource()
32: *
33: * @category Mage
34: * @package Mage_SalesRule
35: * @author Magento Core Team <core@magentocommerce.com>
36: */
37: class Mage_SalesRule_Model_Coupon_Massgenerator extends Mage_Core_Model_Abstract
38: implements Mage_SalesRule_Model_Coupon_CodegeneratorInterface
39: {
40: /**
41: * Maximum probability of guessing the coupon on the first attempt
42: */
43: const MAX_PROBABILITY_OF_GUESSING = 0.25;
44: const MAX_GENERATE_ATTEMPTS = 10;
45:
46: /**
47: * Count of generated Coupons
48: * @var int
49: */
50: protected $_generatedCount = 0;
51:
52: /**
53: * Initialize resource
54: */
55: protected function _construct()
56: {
57: $this->_init('salesrule/coupon');
58: }
59:
60: /**
61: * Generate coupon code
62: *
63: * @return string
64: */
65: public function generateCode()
66: {
67: $format = $this->getFormat();
68: if (!$format) {
69: $format = Mage_SalesRule_Helper_Coupon::COUPON_FORMAT_ALPHANUMERIC;
70: }
71: $length = max(1, (int) $this->getLength());
72: $split = max(0, (int) $this->getDash());
73: $suffix = $this->getSuffix();
74: $prefix = $this->getPrefix();
75:
76: $splitChar = $this->getDelimiter();
77: $charset = Mage::helper('salesrule/coupon')->getCharset($format);
78:
79: $code = '';
80: $charsetSize = count($charset);
81: for ($i=0; $i<$length; $i++) {
82: $char = $charset[mt_rand(0, $charsetSize - 1)];
83: if ($split > 0 && ($i % $split) == 0 && $i != 0) {
84: $char = $splitChar . $char;
85: }
86: $code .= $char;
87: }
88:
89: $code = $prefix . $code . $suffix;
90: return $code;
91: }
92:
93: /**
94: * Retrieve delimiter
95: *
96: * @return string
97: */
98: public function getDelimiter()
99: {
100: if ($this->getData('delimiter')) {
101: return $this->getData('delimiter');
102: } else {
103: return Mage::helper('salesrule/coupon')->getCodeSeparator();
104: }
105: }
106:
107: /**
108: * Generate Coupons Pool
109: *
110: * @return Mage_SalesRule_Model_Coupon_Massgenerator
111: */
112: public function generatePool()
113: {
114: $this->_generatedCount = 0;
115: $size = $this->getQty();
116:
117: $maxProbability = $this->getMaxProbability() ? $this->getMaxProbability() : self::MAX_PROBABILITY_OF_GUESSING;
118: $maxAttempts = $this->getMaxAttempts() ? $this->getMaxAttempts() : self::MAX_GENERATE_ATTEMPTS;
119:
120: /** @var $coupon Mage_SalesRule_Model_Coupon */
121: $coupon = Mage::getModel('salesrule/coupon');
122:
123: $chars = count(Mage::helper('salesrule/coupon')->getCharset($this->getFormat()));
124: $length = (int) $this->getLength();
125: $maxCodes = pow($chars, $length);
126: $probability = $size / $maxCodes;
127: //increase the length of Code if probability is low
128: if ($probability > $maxProbability) {
129: do {
130: $length++;
131: $maxCodes = pow($chars, $length);
132: $probability = $size / $maxCodes;
133: } while ($probability > $maxProbability);
134: $this->setLength($length);
135: }
136:
137: $now = $this->getResource()->formatDate(
138: Mage::getSingleton('core/date')->gmtTimestamp()
139: );
140:
141: for ($i = 0; $i < $size; $i++) {
142: $attempt = 0;
143: do {
144: if ($attempt >= $maxAttempts) {
145: Mage::throwException(Mage::helper('salesrule')->__('Unable to create requested Coupon Qty. Please check settings and try again.'));
146: }
147: $code = $this->generateCode();
148: $attempt++;
149: } while ($this->getResource()->exists($code));
150:
151: $expirationDate = $this->getToDate();
152: if ($expirationDate instanceof Zend_Date) {
153: $expirationDate = $expirationDate->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
154: }
155:
156: $coupon->setId(null)
157: ->setRuleId($this->getRuleId())
158: ->setUsageLimit($this->getUsesPerCoupon())
159: ->setUsagePerCustomer($this->getUsesPerCustomer())
160: ->setExpirationDate($expirationDate)
161: ->setCreatedAt($now)
162: ->setType(Mage_SalesRule_Helper_Coupon::COUPON_TYPE_SPECIFIC_AUTOGENERATED)
163: ->setCode($code)
164: ->save();
165:
166: $this->_generatedCount++;
167: }
168: return $this;
169: }
170:
171: /**
172: * Validate input
173: *
174: * @param array $data
175: * @return bool
176: */
177: public function validateData($data)
178: {
179: return !empty($data) && !empty($data['qty']) && !empty($data['rule_id'])
180: && !empty($data['length']) && !empty($data['format'])
181: && (int)$data['qty'] > 0 && (int) $data['rule_id'] > 0
182: && (int) $data['length'] > 0;
183: }
184:
185: /**
186: * Retrieve count of generated Coupons
187: *
188: * @return int
189: */
190: public function getGeneratedCount()
191: {
192: return $this->_generatedCount;
193: }
194: }
195: