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_ProductAlert
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: * ProductAlert observer
30: *
31: * @category Mage
32: * @package Mage_ProductAlert
33: * @author Magento Core Team <core@magentocommerce.com>
34: */
35: class Mage_ProductAlert_Model_Observer
36: {
37: /**
38: * Error email template configuration
39: */
40: const XML_PATH_ERROR_TEMPLATE = 'catalog/productalert_cron/error_email_template';
41:
42: /**
43: * Error email identity configuration
44: */
45: const XML_PATH_ERROR_IDENTITY = 'catalog/productalert_cron/error_email_identity';
46:
47: /**
48: * 'Send error emails to' configuration
49: */
50: const XML_PATH_ERROR_RECIPIENT = 'catalog/productalert_cron/error_email';
51:
52: /**
53: * Allow price alert
54: *
55: */
56: const XML_PATH_PRICE_ALLOW = 'catalog/productalert/allow_price';
57:
58: /**
59: * Allow stock alert
60: *
61: */
62: const XML_PATH_STOCK_ALLOW = 'catalog/productalert/allow_stock';
63:
64: /**
65: * Website collection array
66: *
67: * @var array
68: */
69: protected $_websites;
70:
71: /**
72: * Warning (exception) errors array
73: *
74: * @var array
75: */
76: protected $_errors = array();
77:
78: /**
79: * Retrieve website collection array
80: *
81: * @return array
82: */
83: protected function _getWebsites()
84: {
85: if (is_null($this->_websites)) {
86: try {
87: $this->_websites = Mage::app()->getWebsites();
88: }
89: catch (Exception $e) {
90: $this->_errors[] = $e->getMessage();
91: }
92: }
93: return $this->_websites;
94: }
95:
96: /**
97: * Process price emails
98: *
99: * @param Mage_ProductAlert_Model_Email $email
100: * @return Mage_ProductAlert_Model_Observer
101: */
102: protected function _processPrice(Mage_ProductAlert_Model_Email $email)
103: {
104: $email->setType('price');
105: foreach ($this->_getWebsites() as $website) {
106: /* @var $website Mage_Core_Model_Website */
107:
108: if (!$website->getDefaultGroup() || !$website->getDefaultGroup()->getDefaultStore()) {
109: continue;
110: }
111: if (!Mage::getStoreConfig(
112: self::XML_PATH_PRICE_ALLOW,
113: $website->getDefaultGroup()->getDefaultStore()->getId()
114: )) {
115: continue;
116: }
117: try {
118: $collection = Mage::getModel('productalert/price')
119: ->getCollection()
120: ->addWebsiteFilter($website->getId())
121: ->setCustomerOrder();
122: }
123: catch (Exception $e) {
124: $this->_errors[] = $e->getMessage();
125: return $this;
126: }
127:
128: $previousCustomer = null;
129: $email->setWebsite($website);
130: foreach ($collection as $alert) {
131: try {
132: if (!$previousCustomer || $previousCustomer->getId() != $alert->getCustomerId()) {
133: $customer = Mage::getModel('customer/customer')->load($alert->getCustomerId());
134: if ($previousCustomer) {
135: $email->send();
136: }
137: if (!$customer) {
138: continue;
139: }
140: $previousCustomer = $customer;
141: $email->clean();
142: $email->setCustomer($customer);
143: }
144: else {
145: $customer = $previousCustomer;
146: }
147:
148: $product = Mage::getModel('catalog/product')
149: ->setStoreId($website->getDefaultStore()->getId())
150: ->load($alert->getProductId());
151: if (!$product) {
152: continue;
153: }
154: $product->setCustomerGroupId($customer->getGroupId());
155: if ($alert->getPrice() > $product->getFinalPrice()) {
156: $productPrice = $product->getFinalPrice();
157: $product->setFinalPrice(Mage::helper('tax')->getPrice($product, $productPrice));
158: $product->setPrice(Mage::helper('tax')->getPrice($product, $product->getPrice()));
159: $email->addPriceProduct($product);
160:
161: $alert->setPrice($productPrice);
162: $alert->setLastSendDate(Mage::getModel('core/date')->gmtDate());
163: $alert->setSendCount($alert->getSendCount() + 1);
164: $alert->setStatus(1);
165: $alert->save();
166: }
167: }
168: catch (Exception $e) {
169: $this->_errors[] = $e->getMessage();
170: }
171: }
172: if ($previousCustomer) {
173: try {
174: $email->send();
175: }
176: catch (Exception $e) {
177: $this->_errors[] = $e->getMessage();
178: }
179: }
180: }
181: return $this;
182: }
183:
184: /**
185: * Process stock emails
186: *
187: * @param Mage_ProductAlert_Model_Email $email
188: * @return Mage_ProductAlert_Model_Observer
189: */
190: protected function _processStock(Mage_ProductAlert_Model_Email $email)
191: {
192: $email->setType('stock');
193:
194: foreach ($this->_getWebsites() as $website) {
195: /* @var $website Mage_Core_Model_Website */
196:
197: if (!$website->getDefaultGroup() || !$website->getDefaultGroup()->getDefaultStore()) {
198: continue;
199: }
200: if (!Mage::getStoreConfig(
201: self::XML_PATH_STOCK_ALLOW,
202: $website->getDefaultGroup()->getDefaultStore()->getId()
203: )) {
204: continue;
205: }
206: try {
207: $collection = Mage::getModel('productalert/stock')
208: ->getCollection()
209: ->addWebsiteFilter($website->getId())
210: ->addStatusFilter(0)
211: ->setCustomerOrder();
212: }
213: catch (Exception $e) {
214: $this->_errors[] = $e->getMessage();
215: return $this;
216: }
217:
218: $previousCustomer = null;
219: $email->setWebsite($website);
220: foreach ($collection as $alert) {
221: try {
222: if (!$previousCustomer || $previousCustomer->getId() != $alert->getCustomerId()) {
223: $customer = Mage::getModel('customer/customer')->load($alert->getCustomerId());
224: if ($previousCustomer) {
225: $email->send();
226: }
227: if (!$customer) {
228: continue;
229: }
230: $previousCustomer = $customer;
231: $email->clean();
232: $email->setCustomer($customer);
233: }
234: else {
235: $customer = $previousCustomer;
236: }
237:
238: $product = Mage::getModel('catalog/product')
239: ->setStoreId($website->getDefaultStore()->getId())
240: ->load($alert->getProductId());
241: /* @var $product Mage_Catalog_Model_Product */
242: if (!$product) {
243: continue;
244: }
245:
246: $product->setCustomerGroupId($customer->getGroupId());
247:
248: if ($product->isSalable()) {
249: $email->addStockProduct($product);
250:
251: $alert->setSendDate(Mage::getModel('core/date')->gmtDate());
252: $alert->setSendCount($alert->getSendCount() + 1);
253: $alert->setStatus(1);
254: $alert->save();
255: }
256: }
257: catch (Exception $e) {
258: $this->_errors[] = $e->getMessage();
259: }
260: }
261:
262: if ($previousCustomer) {
263: try {
264: $email->send();
265: }
266: catch (Exception $e) {
267: $this->_errors[] = $e->getMessage();
268: }
269: }
270: }
271:
272: return $this;
273: }
274:
275: /**
276: * Send email to administrator if error
277: *
278: * @return Mage_ProductAlert_Model_Observer
279: */
280: protected function _sendErrorEmail()
281: {
282: if (count($this->_errors)) {
283: if (!Mage::getStoreConfig(self::XML_PATH_ERROR_TEMPLATE)) {
284: return $this;
285: }
286:
287: $translate = Mage::getSingleton('core/translate');
288: /* @var $translate Mage_Core_Model_Translate */
289: $translate->setTranslateInline(false);
290:
291: $emailTemplate = Mage::getModel('core/email_template');
292: /* @var $emailTemplate Mage_Core_Model_Email_Template */
293: $emailTemplate->setDesignConfig(array('area' => 'backend'))
294: ->sendTransactional(
295: Mage::getStoreConfig(self::XML_PATH_ERROR_TEMPLATE),
296: Mage::getStoreConfig(self::XML_PATH_ERROR_IDENTITY),
297: Mage::getStoreConfig(self::XML_PATH_ERROR_RECIPIENT),
298: null,
299: array('warnings' => join("\n", $this->_errors))
300: );
301:
302: $translate->setTranslateInline(true);
303: $this->_errors[] = array();
304: }
305: return $this;
306: }
307:
308: /**
309: * Run process send product alerts
310: *
311: * @return Mage_ProductAlert_Model_Observer
312: */
313: public function process()
314: {
315: $email = Mage::getModel('productalert/email');
316: /* @var $email Mage_ProductAlert_Model_Email */
317: $this->_processPrice($email);
318: $this->_processStock($email);
319: $this->_sendErrorEmail();
320:
321: return $this;
322: }
323: }
324: