1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27: 28: 29: 30: 31: 32: 33:
34: class Mage_XmlConnect_Helper_Data extends Mage_Core_Helper_Abstract
35: {
36: 37: 38:
39: const PUSH_TITLE_LENGTH = 140;
40:
41: 42: 43:
44: const MESSAGE_TITLE_LENGTH = 255;
45:
46: 47: 48:
49: const CURLOPT_DEFAULT_TIMEOUT = 60;
50:
51: 52: 53: 54: 55:
56: protected $_excludedXmlConfigKeys = array('notifications/applicationMasterSecret');
57:
58: 59: 60: 61: 62:
63: protected $_appNames = array();
64:
65: 66: 67: 68: 69:
70: protected $_tplNames = array();
71:
72: 73: 74:
75: const XML_NODE_CONFIG_EXCLUDE_FROM_XML = 'xmlconnect/mobile_application/nodes_excluded_from_config_xml';
76:
77: 78: 79:
80: const DEVICE_TYPE_DEFAULT = 'unknown';
81:
82: 83: 84:
85: const DEVICE_TYPE_IPHONE = 'iphone';
86:
87: 88: 89:
90: const DEVICE_TYPE_IPAD = 'ipad';
91:
92: 93: 94:
95: const DEVICE_TYPE_ANDROID = 'android';
96:
97: 98: 99:
100: const = 'twitter';
101:
102: 103: 104:
105: const SOCIAL_NETWORK_FACEBOOK = 'facebook';
106:
107: 108: 109:
110: const SOCIAL_NETWORK_LINKEDIN = 'linkedin';
111:
112: 113: 114: 115: 116: 117:
118: public function getPreviewModel()
119: {
120: $deviceType = $this->getDeviceType();
121:
122: switch ($deviceType) {
123: case self::DEVICE_TYPE_IPHONE:
124: case self::DEVICE_TYPE_IPAD:
125: case self::DEVICE_TYPE_ANDROID:
126: $previewModel = Mage::getSingleton('xmlconnect/preview_' . strtolower($deviceType));
127: break;
128: default:
129: Mage::throwException(
130: Mage::helper('xmlconnect')->__('Device doesn\'t recognized: "%s". Unable to load preview model.', $deviceType)
131: );
132: break;
133: }
134: return $previewModel;
135: }
136:
137: 138: 139: 140: 141: 142: 143:
144: public function getDeviceHelper($application = null)
145: {
146: $deviceType = $this->getDeviceType($application);
147:
148: switch ($deviceType) {
149: case self::DEVICE_TYPE_IPHONE:
150: case self::DEVICE_TYPE_IPAD:
151: case self::DEVICE_TYPE_ANDROID:
152: $helper = Mage::helper('xmlconnect/' . $deviceType);
153: break;
154: default:
155: Mage::throwException(
156: Mage::helper('xmlconnect')->__('Device doesn\'t recognized: "%s". Unable to load a helper.', $deviceType)
157: );
158: break;
159: }
160: return $helper;
161: }
162:
163: 164: 165: 166: 167: 168:
169: public function getDeviceType($application = null)
170: {
171: $deviceType = null;
172: if (empty($application) && Mage::registry('current_app') !== null) {
173: $deviceType = (string) $this->getApplication()->getType();
174: } elseif ($application instanceof Mage_XmlConnect_Model_Application) {
175: $deviceType = (string) $application->getType();
176: }
177: if (empty($deviceType)) {
178: $deviceType = self::DEVICE_TYPE_DEFAULT;
179: }
180: return $deviceType;
181: }
182:
183: 184: 185: 186: 187: 188:
189: public function getApplication()
190: {
191: $model = Mage::registry('current_app');
192: if (!($model instanceof Mage_XmlConnect_Model_Application)) {
193: Mage::throwException(Mage::helper('xmlconnect')->__('App model not loaded.'));
194: }
195:
196: return $model;
197: }
198:
199: 200: 201: 202: 203: 204: 205: 206: 207: 208:
209: public function getFilterByKey($key)
210: {
211: switch ($key) {
212: case 'price':
213: $filterModelName = 'catalog/layer_filter_price';
214: break;
215: case 'decimal':
216: $filterModelName = 'catalog/layer_filter_decimal';
217: break;
218: case 'category':
219: $filterModelName = 'catalog/layer_filter_category';
220: break;
221: default:
222: $filterModelName = 'catalog/layer_filter_attribute';
223: break;
224: }
225: return array(Mage::getModel($filterModelName), $this->getLayout()->createBlock($filterModelName));
226: }
227:
228: 229: 230: 231: 232: 233: 234:
235: public function getUrl($route, $params = array())
236: {
237: return $this->_getUrl($route, $params);
238: }
239:
240: 241: 242: 243: 244: 245: 246:
247: public function getCountryOptionsArray($isItunes = false)
248: {
249: Varien_Profiler::start('TEST: ' . __METHOD__);
250: $deviceType = $this->getDeviceType();
251: switch ($deviceType) {
252: case self::DEVICE_TYPE_IPHONE:
253: case self::DEVICE_TYPE_IPAD:
254: $cacheKey = 'XMLCONNECT_COUNTRY_ITUNES_SELECT_STORE_' . Mage::app()->getStore()->getCode();
255: $deviceCountries = $this->getDeviceHelper()->getItunesCountriesArray();
256: break;
257: case self::DEVICE_TYPE_ANDROID:
258: $cacheKey = 'XMLCONNECT_COUNTRY_ANDROID_SELECT_STORE_' . Mage::app()->getStore()->getCode();
259: $deviceCountries = $this->getDeviceHelper()->getAndroidMarketCountriesArray();
260: break;
261: default:
262: Mage::throwException(
263: Mage::helper('xmlconnect')->__('Country options don\'t recognized for "%s".', $deviceType)
264: );
265: break;
266: }
267:
268: if (Mage::app()->useCache('config') && $cache = Mage::app()->loadCache($cacheKey)) {
269: $options = unserialize($cache);
270: } else {
271: if (isset($deviceCountries)) {
272: $options = Mage::getModel('directory/country')->getResourceCollection()
273: ->addFieldToFilter('country_id', array('in' => $deviceCountries))->loadByStore()
274: ->toOptionArray(false);
275: }
276: if (Mage::app()->useCache('config')) {
277: Mage::app()->saveCache(serialize($options), $cacheKey, array('config'));
278: }
279: }
280: Varien_Profiler::stop('TEST: ' . __METHOD__);
281:
282: if (count($options)) {
283: $options[] = array('value' => 'NEW_COUNTRIES', 'label' => 'New Territories As Added');
284: }
285:
286: return $options;
287: }
288:
289: 290: 291: 292: 293:
294: static public function getSupportedDevices()
295: {
296: $devices = array (
297: self::DEVICE_TYPE_IPAD => Mage::helper('xmlconnect')->__('iPad'),
298: self::DEVICE_TYPE_IPHONE => Mage::helper('xmlconnect')->__('iPhone'),
299: self::DEVICE_TYPE_ANDROID => Mage::helper('xmlconnect')->__('Android')
300: );
301:
302: return $devices;
303: }
304:
305: 306: 307: 308: 309:
310: public function getStatusOptions()
311: {
312: $options = array (
313: Mage_XmlConnect_Model_Application::APP_STATUS_SUCCESS => Mage::helper('xmlconnect')->__('Submitted'),
314: Mage_XmlConnect_Model_Application::APP_STATUS_INACTIVE => Mage::helper('xmlconnect')->__('Not Submitted'),
315: );
316: return $options;
317: }
318:
319: 320: 321: 322: 323:
324: public function getDeviceTypeOptions()
325: {
326: $devices = self::getSupportedDevices();
327: $options = array();
328: $options[] = array('value' => '', 'label' => Mage::helper('xmlconnect')->__('Please Select Device Type'));
329: foreach ($devices as $type => $label) {
330: $options[] = array('value' => $type, 'label' => $label);
331: }
332: return $options;
333: }
334:
335: 336: 337: 338: 339:
340: public function getDefaultApplicationDesignTabs()
341: {
342: return $this->getDeviceHelper()->getDefaultDesignTabs();
343: }
344:
345: 346: 347: 348: 349:
350: public function getDefaultCacheLifetime()
351: {
352: return (int)Mage::getStoreConfig(
353: Mage_XmlConnect_Model_Application::XML_PATH_DEFAULT_CACHE_LIFETIME
354: );
355: }
356:
357: 358: 359: 360: 361:
362: protected function _getTabLabelActionArray()
363: {
364: if (!isset($this->_tabLabelActionArray)) {
365: $this->_tabLabelActionArray = array();
366: foreach ($this->getDefaultApplicationDesignTabs() as $tab) {
367: $this->_tabLabelActionArray[$tab['action']] = $tab['label'];
368: }
369: }
370: return $this->_tabLabelActionArray;
371: }
372:
373: 374: 375: 376: 377: 378:
379: public function getTabLabel($action)
380: {
381: $action = (string) $action;
382: $tabs = $this->_getTabLabelActionArray();
383: return (isset($tabs[$action])) ? $tabs[$action] : false;
384: }
385:
386: 387: 388: 389: 390: 391: 392:
393: static public function arrayMergeRecursive($target, $changes)
394: {
395: if (!is_array($target)) {
396: $target = empty($target) ? array() : array($target);
397: }
398: if (!is_array($changes)) {
399: $changes = array($changes);
400: }
401: foreach ($changes as $key => $value) {
402: if (!array_key_exists($key, $target) and !is_numeric($key)) {
403: $target[$key] = $changes[$key];
404: continue;
405: }
406: if (is_array($value) or is_array($target[$key])) {
407: $target[$key] = self::arrayMergeRecursive($target[$key], $changes[$key]);
408: } else if (is_numeric($key)) {
409: if (!in_array($value, $target)) {
410: $target[] = $value;
411: }
412: } else {
413: $target[$key] = $value;
414: }
415: }
416:
417: return $target;
418: }
419:
420: 421: 422: 423: 424: 425:
426: public function htmlize($body)
427: {
428: $w3cUrl = 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd';
429: return <<<EOT
430: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "$w3cUrl">
431: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
432: <head>
433: <link rel="stylesheet" type="text/css" href="style.css" media="screen"/>
434: </head>
435: <body>$body</body></html>
436: EOT;
437: }
438:
439: 440: 441: 442: 443: 444: 445:
446: public function getArrayAsXmlItemValues($dataArray, $selected)
447: {
448: $items = array();
449: foreach ($dataArray as $k => $v) {
450: if (!$k) {
451: continue;
452: }
453: $items[] = '
454: <item' . ($k == $selected ? ' selected="1"' : '') . '>
455: <label>' . $v . '</label>
456: <value>' . ($k ? $k : '') . '</value>
457: </item>';
458: }
459: $result = implode(PHP_EOL, $items);
460: return $result;
461: }
462:
463: 464: 465: 466: 467: 468: 469:
470: public function getSoloXml($ssCcMonths, $ssCcYears)
471: {
472: $validatorMessage = $this->__('Please enter issue number or start date for switch/solo card type.');
473:
474: $solo = <<<EOT
475: <fieldset_optional>
476: <depend_on name="payment[cc_type]">
477: <show_value>
478: <item>SS</item>
479: <item>SM</item>
480: <item>SO</item>
481: </show_value>
482: </depend_on>
483:
484: <field name="payment[cc_ss_issue]" type="text" label="{$this->__('Issue Number')}">
485: <validators>
486: <validator relation="payment[cc_type]" type="credit_card_ukss" message="{$validatorMessage}"/>
487: </validators>
488: </field>;
489: <field name="payment[cc_ss_start_month]" type="select" label="{$this->__('Start Date - Month')}">
490: <values>
491: $ssCcMonths
492: </values>
493: </field>
494: <field name="payment[cc_ss_start_year]" type="select" label="{$this->__('Start Date - Year')}">
495: <values>
496: $ssCcYears
497: </values>
498: </field>
499: </fieldset_optional>
500: EOT;
501: return $solo;
502: }
503:
504: 505: 506: 507: 508: 509:
510: public function formatPriceForXml($price)
511: {
512: return sprintf('%01.2F', $price);
513: }
514:
515: 516: 517: 518: 519:
520: static public function getSupportedMessageTypes()
521: {
522: $messages = array (
523: Mage_XmlConnect_Model_Queue::MESSAGE_TYPE_PUSH => Mage::helper('xmlconnect')->__('Push message'),
524: Mage_XmlConnect_Model_Queue::MESSAGE_TYPE_AIRMAIL => Mage::helper('xmlconnect')->__('AirMail message'),
525: );
526:
527: return $messages;
528: }
529:
530: 531: 532: 533: 534:
535: public function getMessageTypeOptions()
536: {
537: $options = array();
538: $messages = self::getSupportedMessageTypes();
539: foreach ($messages as $type => $label) {
540: $options[] = array('value' => $type, 'label' => $label);
541: }
542: return $options;
543: }
544:
545: 546: 547: 548: 549:
550: public function getPushTitleLength()
551: {
552: return self::PUSH_TITLE_LENGTH;
553: }
554:
555: 556: 557: 558: 559:
560: public function getMessageTitleLength()
561: {
562: return self::MESSAGE_TITLE_LENGTH;
563: }
564:
565: 566: 567: 568: 569:
570: public function getApplicationOptions()
571: {
572: $options = array();
573:
574: foreach (Mage::getModel('xmlconnect/application')->getCollection() as $app) {
575: $options[] = array('value' => $app->getId(), 'label' => $app->getName());
576: }
577: if (count($options) > 1) {
578: array_unshift($options, array(
579: 'value' => '', 'label' => Mage::helper('xmlconnect')->__('Please Select Application')
580: ));
581: }
582: return $options;
583: }
584:
585: 586: 587: 588: 589: 590:
591: public function getApplications()
592: {
593: static $apps = array();
594:
595: if (empty($apps)) {
596: foreach (Mage::getModel('xmlconnect/application')->getCollection() as $app) {
597: $apps[$app->getCode()] = $app->getName();
598: }
599: }
600: return $apps;
601: }
602:
603: 604: 605: 606: 607: 608: 609:
610: public static function isTemplateAllowedForApplication($application = null)
611: {
612: return true;
613: }
614:
615: 616: 617: 618: 619: 620:
621: public function sendBroadcastMessage(Mage_XmlConnect_Model_Queue $queue)
622: {
623: if ($queue->getStatus() != Mage_XmlConnect_Model_Queue::STATUS_IN_QUEUE) {
624: return;
625: }
626:
627: try {
628: $applicationId = Mage::getModel('xmlconnect/template')->load($queue->getTemplateId())->getApplicationId();
629:
630: $app = Mage::getModel('xmlconnect/application')->load($applicationId);
631:
632: if (!$app->getId()) {
633: Mage::throwException(
634: Mage::helper('xmlconnect')->__('Can\'t load application with id "%s"', $applicationId)
635: );
636: }
637:
638: if (!$app->isNotificationsActive()) {
639: $queue->setStatus(Mage_XmlConnect_Model_Queue::STATUS_CANCELED);
640: return;
641: }
642:
643: $sendType = $queue->getData('type');
644: switch ($sendType) {
645: case Mage_XmlConnect_Model_Queue::MESSAGE_TYPE_AIRMAIL:
646: $configPath = 'xmlconnect/' . Mage_XmlConnect_Model_Queue::MESSAGE_TYPE_AIRMAIL . '/broadcast_url';
647: $params = $queue->getAirmailBroadcastParams();
648: break;
649:
650: case Mage_XmlConnect_Model_Queue::MESSAGE_TYPE_PUSH:
651: default:
652: $configPath = 'xmlconnect/' . Mage_XmlConnect_Model_Queue::MESSAGE_TYPE_PUSH . '/broadcast_url';
653: $params = $queue->getPushBroadcastParams();
654: break;
655: }
656:
657: $curl = new Varien_Http_Adapter_Curl();
658: $curl->setConfig($this->_getCurlConfig($app->getUserpwd()));
659:
660: $urbanUrl = Mage::getStoreConfig($configPath);
661: $curl->write(
662: Zend_Http_Client::POST, $urbanUrl, HTTP_REQUEST_HTTP_VER_1_1, $this->getHttpHeaders(), $params
663: );
664:
665: if ($curl->read() && $curl->getInfo(CURLINFO_HTTP_CODE) == 200) {
666: $queue->setStatus(Mage_XmlConnect_Model_Queue::STATUS_COMPLETED);
667: }
668: $curl->close();
669:
670: $queue->setIsSent(true);
671: $queue->save();
672: return;
673: } catch (Exception $e) {
674: Mage::logException($e);
675: throw $e;
676: }
677: }
678:
679: 680: 681: 682: 683:
684: public function ()
685: {
686: return array('Content-Type: application/json');
687: }
688:
689: 690: 691: 692: 693: 694: 695:
696: protected function _getCurlConfig($userPwd, $timeout = self::CURLOPT_DEFAULT_TIMEOUT)
697: {
698: return array ('timeout' => $timeout, 'userpwd' => $userPwd);
699: }
700:
701: 702: 703: 704: 705: 706: 707:
708: public function excludeXmlConfigKeys($data, $excludedKeys = array())
709: {
710: $excludedKeys = $this->getExcludedXmlConfigKeys();
711: if (!empty($excludedKeys)) {
712: foreach ($excludedKeys as $keyToExclude) {
713: if (strpos($keyToExclude, '/')) {
714: $keys = array();
715: foreach (explode('/', $keyToExclude) as $key) {
716: $key = trim($key);
717: if (!empty($key)) {
718: $keys[] = $key;
719: }
720: }
721: if (!empty($keys)) {
722: $keys = '$data["' . implode('"]["', $keys) . '"]';
723: eval('if (isset(' . $keys . ')) unset(' . $keys . ');');
724: }
725: } elseif (!empty($keyToExclude) && isset($data[$keyToExclude])) {
726: unset($data[$keyToExclude]);
727: }
728: }
729: }
730: return $data;
731: }
732:
733: 734: 735: 736: 737:
738: public function getExcludedXmlConfigKeys()
739: {
740: $toExclude = Mage::getStoreConfig(self::XML_NODE_CONFIG_EXCLUDE_FROM_XML);
741: $nodes = array();
742: foreach ($toExclude as $value) {
743: $nodes[] = trim($value, '/');
744: }
745:
746: return $nodes;
747: }
748:
749: 750: 751: 752: 753:
754: public function getApplicationName($appCode = null)
755: {
756: if (empty($appCode)) {
757: return '';
758: }
759: if (!isset($this->_appNames[$appCode])) {
760: $app = Mage::getModel('xmlconnect/application')->loadByCode($appCode);
761: if ($app->getId()) {
762: $this->_appNames[$appCode] = $app->getName();
763: } else {
764: return '';
765: }
766: }
767: return $this->_appNames[$appCode];
768: }
769:
770: 771: 772: 773: 774:
775: public function getTemplateName($templateId = null)
776: {
777: if (empty($templateId)) {
778: return '';
779: }
780: if (!isset($this->_tplNames[$templateId])) {
781: $template = Mage::getModel('xmlconnect/template')->load($templateId);
782: if ($template->getId()) {
783: $this->_tplNames[$templateId] = $template->getName();
784: } else {
785: return '';
786: }
787: }
788: return $this->_tplNames[$templateId];
789: }
790:
791: 792: 793: 794: 795: 796: 797: 798: 799:
800: public function _injectFieldToArray(&$target, $fieldPath, $fieldValue, $delimiter = '/')
801: {
802: $nameParts = explode($delimiter, $fieldPath);
803: foreach ($nameParts as $next) {
804: if (!isset($target[$next])) {
805: $target[$next] = array();
806: }
807: $target =& $target[$next];
808: }
809: $target = $fieldValue;
810: return null;
811: }
812:
813: 814: 815: 816: 817: 818:
819: public function urlToPath($icon)
820: {
821: $baseUrl = Mage::getBaseUrl('media');
822: $path = str_replace($baseUrl, '', $icon);
823: $filePath = Mage::getBaseDir('media') . DS . str_replace('/', DS, $path);
824: return $filePath;
825:
826: }
827:
828: 829: 830: 831: 832: 833: 834:
835: public function validateConfFieldNotEmpty($field, $native)
836: {
837: if (($native === false) || (!isset($native['body']) || !is_array($native['body'])
838: || !isset($native['body'][$field]) || !Zend_Validate::is($native['body'][$field], 'NotEmpty'))
839: ) {
840: return false;
841: }
842: return true;
843: }
844:
845: 846: 847: 848: 849: 850:
851: public function isNotificationsAllowed($application = null)
852: {
853: return $this->getDeviceHelper($application)->isNotificationsAllowed();
854: }
855:
856: 857: 858: 859: 860: 861: 862:
863: public function getActionUrl($action, $params = array())
864: {
865: $defaultParams = array(
866: '_store' => $this->getApplication()->getStoreId(),
867: '_nosid' => true,
868: '_secure' => $this->getApplication()->getUseSecureURLInFrontend()
869: );
870: $params = array_merge($defaultParams, $params);
871: return Mage::getUrl($action, $params);
872: }
873:
874: 875: 876: 877: 878: 879:
880: public function trimLineBreaks($string)
881: {
882: return preg_replace(array('@\r@', '@\n+@'), array('', PHP_EOL), $string);
883: }
884: }
885: