Replenishment_Automator - Version 1.0.97

Version Notes

Updates to support custom fields in orders, bug fixes.

Download this release

Release Info

Developer Andrew Pearson
Extension Replenishment_Automator
Version 1.0.97
Comparing to
See all releases


Version 1.0.97

Files changed (37) hide show
  1. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Customer/Address/Attributes.php +119 -0
  2. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Customer/Address/Options.php +92 -0
  3. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Customer/Attributes.php +119 -0
  4. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Customer/Options.php +92 -0
  5. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Display.php +24 -0
  6. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Order/Fields.php +107 -0
  7. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Order/Item/Buy/Options.php +24 -0
  8. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Order/Item/Buy/Request.php +107 -0
  9. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Order/Options.php +31 -0
  10. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Product/Attributes.php +119 -0
  11. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Product/Options.php +95 -0
  12. app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Product/Options.php.bak +63 -0
  13. app/code/local/Windsorcircle/Export/Block/Adminhtml/Version.php +17 -0
  14. app/code/local/Windsorcircle/Export/Helper/Data.php +256 -0
  15. app/code/local/Windsorcircle/Export/Model/Brand/Attribute.php +44 -0
  16. app/code/local/Windsorcircle/Export/Model/Date.php +31 -0
  17. app/code/local/Windsorcircle/Export/Model/Format.php +490 -0
  18. app/code/local/Windsorcircle/Export/Model/Ftp.php +107 -0
  19. app/code/local/Windsorcircle/Export/Model/Ftp/Type.php +14 -0
  20. app/code/local/Windsorcircle/Export/Model/Image/Type.php +23 -0
  21. app/code/local/Windsorcircle/Export/Model/Observer.php +94 -0
  22. app/code/local/Windsorcircle/Export/Model/Openssl.php +67 -0
  23. app/code/local/Windsorcircle/Export/Model/Order.php +1192 -0
  24. app/code/local/Windsorcircle/Export/Model/Products.php +436 -0
  25. app/code/local/Windsorcircle/Export/Model/Sftp.php +19 -0
  26. app/code/local/Windsorcircle/Export/Model/Source/Canceled/State.php +39 -0
  27. app/code/local/Windsorcircle/Export/Model/Source/Canceled/Status.php +28 -0
  28. app/code/local/Windsorcircle/Export/Model/Source/Store.php +22 -0
  29. app/code/local/Windsorcircle/Export/Model/State.php +34 -0
  30. app/code/local/Windsorcircle/Export/Model/Status.php +34 -0
  31. app/code/local/Windsorcircle/Export/Model/System/Config/Backend/Attributes.php +52 -0
  32. app/code/local/Windsorcircle/Export/controllers/Background.php +122 -0
  33. app/code/local/Windsorcircle/Export/controllers/IndexController.php +557 -0
  34. app/code/local/Windsorcircle/Export/controllers/LoadCartController.php +70 -0
  35. app/code/local/Windsorcircle/Export/etc/config.xml +123 -0
  36. app/code/local/Windsorcircle/Export/etc/system.xml +212 -0
  37. package.xml +18 -0
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Customer/Address/Attributes.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Customer Address Attributes Class
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Customer_Address_Attributes
12
+ extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
13
+ {
14
+ /**
15
+ * @var
16
+ */
17
+ protected $_customerAddressRenderer;
18
+
19
+ /**
20
+ * @var
21
+ */
22
+ protected $_customerAddressDisplayRenderer;
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ $version = explode('.', Mage::getVersion());
30
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
31
+ $this->addColumn('attribute_code', array(
32
+ 'label' => Mage::helper('customer')->__('Customer Address Attribute'),
33
+ 'renderer' => $this->_getCustomerAddressRenderer(),
34
+ ));
35
+ $this->addColumn('output_name', array(
36
+ 'label' => Mage::helper('cataloginventory')->__('Output Name'),
37
+ 'style' => 'width:120px',
38
+ 'renderer' => $this->_getCustomerDisplay(),
39
+ ));
40
+ }
41
+ parent::__construct();
42
+ }
43
+
44
+ /**
45
+ * Retrieve customer attribute code column renderer
46
+ *
47
+ * @return Windsorcircle_Export_Block_Adminhtml_Form_Field_Customer_Options
48
+ */
49
+ protected function _getCustomerAddressRenderer()
50
+ {
51
+ if (!$this->_customerAddressRenderer) {
52
+ $version = explode('.', Mage::getVersion());
53
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
54
+ $layout = Mage::app()->getLayout();
55
+ } else {
56
+ $layout = $this->getLayout();
57
+ }
58
+ $this->_customerAddressRenderer = $layout->createBlock(
59
+ 'windsorcircle_export/adminhtml_form_field_customer_address_options', '',
60
+ array('is_render_to_js_template' => true)
61
+ );
62
+ $this->_customerAddressRenderer->setClass('customer_address_group_select');
63
+ $this->_customerAddressRenderer->setExtraParams('style="width:120px"');
64
+ }
65
+ return $this->_customerAddressRenderer;
66
+ }
67
+
68
+ /**
69
+ * Retrieve display column renderer
70
+ *
71
+ * @return Windsorcircle_Export_Block_Adminhtml_Form_Field_Customer_Display
72
+ */
73
+ protected function _getCustomerDisplay()
74
+ {
75
+ if (!$this->_customerAddressDisplayRenderer) {
76
+ $version = explode('.', Mage::getVersion());
77
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
78
+ $layout = Mage::app()->getLayout();
79
+ } else {
80
+ $layout = $this->getLayout();
81
+ }
82
+ $this->_customerAddressDisplayRenderer = $layout->createBlock(
83
+ 'windsorcircle_export/adminhtml_form_field_display', ''
84
+ );
85
+ }
86
+ return $this->_customerAddressDisplayRenderer;
87
+ }
88
+
89
+ /**
90
+ * Prepare to render
91
+ */
92
+ protected function _prepareToRender()
93
+ {
94
+ $this->addColumn('attribute_code', array(
95
+ 'label' => Mage::helper('customer')->__('Customer Address Attribute'),
96
+ 'renderer' => $this->_getCustomerAddressRenderer(),
97
+ ));
98
+ $this->addColumn('output_name', array(
99
+ 'label' => Mage::helper('cataloginventory')->__('Output Name'),
100
+ 'style' => 'width:240px',
101
+ 'renderer' => $this->_getCustomerDisplay(),
102
+ ));
103
+ $this->_addAfter = false;
104
+ $this->_addButtonLabel = Mage::helper('cataloginventory')->__('Add Custom Attribute');
105
+ }
106
+
107
+ /**
108
+ * Prepare existing row data object
109
+ *
110
+ * @param Varien_Object
111
+ */
112
+ protected function _prepareArrayRow(Varien_Object $row)
113
+ {
114
+ $row->setData(
115
+ 'option_extra_attr_' . $this->_getCustomerAddressRenderer()->calcOptionHash($row->getData('attribute_code')),
116
+ 'selected="selected"'
117
+ );
118
+ }
119
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Customer/Address/Options.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Customer Address Options Class
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Customer_Address_Options extends Mage_Core_Block_Html_Select
12
+ {
13
+ /**
14
+ * Customer groups cache
15
+ *
16
+ * @var array
17
+ */
18
+ private $_customerAddressAttributes;
19
+
20
+ /**
21
+ * Retrieve allowed customer groups
22
+ *
23
+ * @param int $groupId return name by customer group id
24
+ * @return array|string
25
+ */
26
+ protected function _getCustomerAddressAttributes()
27
+ {
28
+ if (is_null($this->_customerAddressAttributes)) {
29
+ $this->_customerAddressAttributes = array();
30
+
31
+ $type = Mage::getModel('eav/entity_type')->loadByCode('customer_address');
32
+ $collection = Mage::getResourceModel('eav/entity_attribute_collection')->setEntityTypeFilter($type);
33
+
34
+ $this->_customerAddressAttributes[0] = '';
35
+ foreach ($collection as $item) {
36
+ $label = $item->getFrontendLabel();
37
+ if (!empty($label)) {
38
+ /* @var $item Mage_Catalog_Model_Resource_Eav_Attribute */
39
+ $this->_customerAddressAttributes[$item->getAttributeCode()] = $label;
40
+ }
41
+ }
42
+ }
43
+ return $this->_customerAddressAttributes;
44
+ }
45
+
46
+ public function setInputName($value)
47
+ {
48
+ return $this->setName($value);
49
+ }
50
+
51
+ /**
52
+ * Render block HTML
53
+ *
54
+ * @return string
55
+ */
56
+ public function _toHtml()
57
+ {
58
+ if (!$this->getOptions()) {
59
+ $coreHelper = Mage::helper('core');
60
+ foreach ($this->_getCustomerAddressAttributes() as $attributeCode => $label) {
61
+ if (version_compare(Mage::getVersion(), '1.4.0.0', '<')) {
62
+ $this->addOption($attributeCode, $this->quoteEscape($this->htmlEscape($label)));
63
+ } else {
64
+ if (method_exists($coreHelper, 'quoteEscape')) {
65
+ $this->addOption($attributeCode, $coreHelper->quoteEscape($this->escapeHtml($label)));
66
+ } else {
67
+ $this->addOption($attributeCode, $this->quoteEscape($this->escapeHtml($label)));
68
+ }
69
+ }
70
+ }
71
+ }
72
+ return parent::_toHtml();
73
+ }
74
+
75
+ /**
76
+ * Used for when Magento quoteEscape function is not available
77
+ *
78
+ * Escape quotes inside html attributes
79
+ * Use $addSlashes = false for escaping js that inside html attribute (onClick, onSubmit etc)
80
+ *
81
+ * @param string $data
82
+ * @param bool $addSlashes
83
+ * @return string
84
+ */
85
+ public function quoteEscape($data, $addSlashes = false)
86
+ {
87
+ if ($addSlashes === true) {
88
+ $data = addslashes($data);
89
+ }
90
+ return htmlspecialchars($data, ENT_QUOTES, null, false);
91
+ }
92
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Customer/Attributes.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Customer Attributes Class
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Customer_Attributes
12
+ extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
13
+ {
14
+ /**
15
+ * @var
16
+ */
17
+ protected $_customerRenderer;
18
+
19
+ /**
20
+ * @var
21
+ */
22
+ protected $_customerDisplayRenderer;
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ $version = explode('.', Mage::getVersion());
30
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
31
+ $this->addColumn('attribute_code', array(
32
+ 'label' => Mage::helper('customer')->__('Customer Attribute'),
33
+ 'renderer' => $this->_getCustomerRenderer(),
34
+ ));
35
+ $this->addColumn('output_name', array(
36
+ 'label' => Mage::helper('cataloginventory')->__('Output Name'),
37
+ 'style' => 'width:120px',
38
+ 'renderer' => $this->_getCustomerDisplay(),
39
+ ));
40
+ }
41
+ parent::__construct();
42
+ }
43
+
44
+ /**
45
+ * Retrieve customer attribute code column renderer
46
+ *
47
+ * @return Windsorcircle_Export_Block_Adminhtml_Form_Field_Customer_Options
48
+ */
49
+ protected function _getCustomerRenderer()
50
+ {
51
+ if (!$this->_customerRenderer) {
52
+ $version = explode('.', Mage::getVersion());
53
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
54
+ $layout = Mage::app()->getLayout();
55
+ } else {
56
+ $layout = $this->getLayout();
57
+ }
58
+ $this->_customerRenderer = $layout->createBlock(
59
+ 'windsorcircle_export/adminhtml_form_field_customer_options', '',
60
+ array('is_render_to_js_template' => true)
61
+ );
62
+ $this->_customerRenderer->setClass('customer_group_select');
63
+ $this->_customerRenderer->setExtraParams('style="width:120px"');
64
+ }
65
+ return $this->_customerRenderer;
66
+ }
67
+
68
+ /**
69
+ * Retrieve display column renderer
70
+ *
71
+ * @return Windsorcircle_Export_Block_Adminhtml_Form_Field_Customer_Display
72
+ */
73
+ protected function _getCustomerDisplay()
74
+ {
75
+ if (!$this->_customerDisplayRenderer) {
76
+ $version = explode('.', Mage::getVersion());
77
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
78
+ $layout = Mage::app()->getLayout();
79
+ } else {
80
+ $layout = $this->getLayout();
81
+ }
82
+ $this->_customerDisplayRenderer = $layout->createBlock(
83
+ 'windsorcircle_export/adminhtml_form_field_display', ''
84
+ );
85
+ }
86
+ return $this->_customerDisplayRenderer;
87
+ }
88
+
89
+ /**
90
+ * Prepare to render
91
+ */
92
+ protected function _prepareToRender()
93
+ {
94
+ $this->addColumn('attribute_code', array(
95
+ 'label' => Mage::helper('customer')->__('Customer Attribute'),
96
+ 'renderer' => $this->_getCustomerRenderer(),
97
+ ));
98
+ $this->addColumn('output_name', array(
99
+ 'label' => Mage::helper('cataloginventory')->__('Output Name'),
100
+ 'style' => 'width:240px',
101
+ 'renderer' => $this->_getCustomerDisplay(),
102
+ ));
103
+ $this->_addAfter = false;
104
+ $this->_addButtonLabel = Mage::helper('cataloginventory')->__('Add Custom Attribute');
105
+ }
106
+
107
+ /**
108
+ * Prepare existing row data object
109
+ *
110
+ * @param Varien_Object
111
+ */
112
+ protected function _prepareArrayRow(Varien_Object $row)
113
+ {
114
+ $row->setData(
115
+ 'option_extra_attr_' . $this->_getCustomerRenderer()->calcOptionHash($row->getData('attribute_code')),
116
+ 'selected="selected"'
117
+ );
118
+ }
119
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Customer/Options.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Customer Options Class
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Customer_Options extends Mage_Core_Block_Html_Select
12
+ {
13
+ /**
14
+ * Customer groups cache
15
+ *
16
+ * @var array
17
+ */
18
+ private $_customerAttributes;
19
+
20
+ /**
21
+ * Retrieve allowed customer groups
22
+ *
23
+ * @param int $groupId return name by customer group id
24
+ * @return array|string
25
+ */
26
+ protected function _getCustomerAttributes()
27
+ {
28
+ if (is_null($this->_customerAttributes)) {
29
+ $this->_customerAttributes = array();
30
+
31
+ $type = Mage::getModel('eav/entity_type')->loadByCode('customer');
32
+ $collection = Mage::getResourceModel('eav/entity_attribute_collection')->setEntityTypeFilter($type);
33
+
34
+ $this->_customerAttributes[0] = '';
35
+ foreach ($collection as $item) {
36
+ $label = $item->getFrontendLabel();
37
+ if (!empty($label)) {
38
+ /* @var $item Mage_Catalog_Model_Resource_Eav_Attribute */
39
+ $this->_customerAttributes[$item->getAttributeCode()] = $label;
40
+ }
41
+ }
42
+ }
43
+ return $this->_customerAttributes;
44
+ }
45
+
46
+ public function setInputName($value)
47
+ {
48
+ return $this->setName($value);
49
+ }
50
+
51
+ /**
52
+ * Render block HTML
53
+ *
54
+ * @return string
55
+ */
56
+ public function _toHtml()
57
+ {
58
+ if (!$this->getOptions()) {
59
+ $coreHelper = Mage::helper('core');
60
+ foreach ($this->_getCustomerAttributes() as $attributeCode => $label) {
61
+ if (version_compare(Mage::getVersion(), '1.4.0.0', '<')) {
62
+ $this->addOption($attributeCode, $this->quoteEscape($this->htmlEscape($label)));
63
+ } else {
64
+ if (method_exists($coreHelper, 'quoteEscape')) {
65
+ $this->addOption($attributeCode, $coreHelper->quoteEscape($this->escapeHtml($label)));
66
+ } else {
67
+ $this->addOption($attributeCode, $this->quoteEscape($this->escapeHtml($label)));
68
+ }
69
+ }
70
+ }
71
+ }
72
+ return parent::_toHtml();
73
+ }
74
+
75
+ /**
76
+ * Used for when Magento quoteEscape function is not available
77
+ *
78
+ * Escape quotes inside html attributes
79
+ * Use $addSlashes = false for escaping js that inside html attribute (onClick, onSubmit etc)
80
+ *
81
+ * @param string $data
82
+ * @param bool $addSlashes
83
+ * @return string
84
+ */
85
+ public function quoteEscape($data, $addSlashes = false)
86
+ {
87
+ if ($addSlashes === true) {
88
+ $data = addslashes($data);
89
+ }
90
+ return htmlspecialchars($data, ENT_QUOTES, null, false);
91
+ }
92
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Display.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Display field for admin
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Display extends Mage_Adminhtml_Block_Template
12
+ {
13
+ public function _toHtml()
14
+ {
15
+ $column = $this->getColumn();
16
+ $columnName = $this->getColumnName();
17
+ $inputName = $this->getInputName();
18
+
19
+ return '<input type="text" name="' . $inputName . '" value="#{' . $columnName . '}" ' .
20
+ ($column['size'] ? 'size="' . $column['size'] . '"' : '') . ' class="' .
21
+ (isset($column['class']) ? $column['class'] : 'input-text') . '"'.
22
+ (isset($column['style']) ? ' style="'.$column['style'] . '"' : '') . ' readonly />';
23
+ }
24
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Order/Fields.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Order Attribute Class used for select field in Admin
4
+ *
5
+ * @category WindsorCircle
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2016 WindsorCircle (www.windsorcircle.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Order_Fields
12
+ extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
13
+ {
14
+ /**
15
+ * @var
16
+ */
17
+ protected $_renderer;
18
+
19
+ /**
20
+ * @var
21
+ */
22
+ protected $_displayRenderer;
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ $version = explode('.', Mage::getVersion());
30
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
31
+ $this->addColumn('attribute_code', array(
32
+ 'label' => Mage::helper('windsorcircle_export')->__('Order Field'),
33
+ 'renderer' => $this->_getOrderRenderer(),
34
+ ));
35
+ $this->addColumn('output_name', array(
36
+ 'label' => Mage::helper('windsorcircle_export')->__('Output Name'),
37
+ 'style' => 'width:240px',
38
+ 'renderer' => $this->_getOrderDisplay(),
39
+ ));
40
+ }
41
+ parent::__construct();
42
+ }
43
+
44
+ /**
45
+ * Retrieve customer attribute code column renderer
46
+ *
47
+ * @return Windsorcircle_Export_Block_Adminhtml_Form_Field_Order_Options
48
+ */
49
+ protected function _getOrderRenderer()
50
+ {
51
+ if (!$this->_renderer) {
52
+ $version = explode('.', Mage::getVersion());
53
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
54
+ $layout = Mage::app()->getLayout();
55
+ } else {
56
+ $layout = $this->getLayout();
57
+ }
58
+ $this->_renderer = $layout->createBlock(
59
+ 'windsorcircle_export/adminhtml_form_field_order_options', '',
60
+ array('is_render_to_js_template' => true)
61
+ );
62
+ $this->_renderer->setClass('order_options_value');
63
+ $this->_renderer->setExtraParams('style="width:240px"');
64
+ }
65
+ return $this->_renderer;
66
+ }
67
+
68
+ /**
69
+ * Retrieve display column renderer
70
+ *
71
+ * @return Windsorcircle_Export_Block_Adminhtml_Form_Field_Display
72
+ */
73
+ protected function _getOrderDisplay()
74
+ {
75
+ if (!$this->_displayRenderer) {
76
+ $version = explode('.', Mage::getVersion());
77
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
78
+ $layout = Mage::app()->getLayout();
79
+ } else {
80
+ $layout = $this->getLayout();
81
+ }
82
+ $this->_displayRenderer = $layout->createBlock(
83
+ 'windsorcircle_export/adminhtml_form_field_display', ''
84
+ );
85
+ }
86
+ return $this->_displayRenderer;
87
+ }
88
+
89
+ /**
90
+ * Prepare to render
91
+ */
92
+ protected function _prepareToRender()
93
+ {
94
+ $this->addColumn('attribute_code', array(
95
+ 'label' => Mage::helper('windsorcircle_export')->__('Order Field'),
96
+ 'style' => 'width:120px',
97
+ 'renderer' => $this->_getOrderRenderer(),
98
+ ));
99
+ $this->addColumn('output_name', array(
100
+ 'label' => Mage::helper('windsorcircle_export')->__('Output Name'),
101
+ 'style' => 'width:240px',
102
+ 'renderer' => $this->_getOrderDisplay(),
103
+ ));
104
+ $this->_addAfter = false;
105
+ $this->_addButtonLabel = Mage::helper('windsorcircle_export')->__('Add Order Field');
106
+ }
107
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Order/Item/Buy/Options.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Display field for Order Item Buy Request Options in admin
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Order_Item_Buy_Options extends Mage_Adminhtml_Block_Template
12
+ {
13
+ public function _toHtml()
14
+ {
15
+ $column = $this->getColumn();
16
+ $columnName = $this->getColumnName();
17
+ $inputName = $this->getInputName();
18
+
19
+ return '<input type="text" name="' . $inputName . '" value="#{' . $columnName . '}" ' .
20
+ ($column['size'] ? 'size="' . $column['size'] . '"' : '') . ' class="' .
21
+ (isset($column['class']) ? $column['class'] : 'input-text') . '"'.
22
+ (isset($column['style']) ? ' style="'.$column['style'] . '"' : '') . ' />';
23
+ }
24
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Order/Item/Buy/Request.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Form Field Options for Buy Request Product Options
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2015 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Order_Item_Buy_Request
12
+ extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
13
+ {
14
+ /**
15
+ * @var
16
+ */
17
+ protected $_orderItemRenderer;
18
+
19
+ /**
20
+ * @var
21
+ */
22
+ protected $_orderItemDisplayRenderer;
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ $version = explode('.', Mage::getVersion());
30
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
31
+ $this->addColumn('attribute_code', array(
32
+ 'label' => Mage::helper('sales')->__('Order Item Product Option'),
33
+ 'renderer' => $this->_getOrderItemRenderer(),
34
+ ));
35
+ $this->addColumn('output_name', array(
36
+ 'label' => Mage::helper('sales')->__('Output Name'),
37
+ 'style' => 'width:240px',
38
+ 'renderer' => $this->_getOrderItemDisplay(),
39
+ ));
40
+ }
41
+ parent::__construct();
42
+ }
43
+
44
+ /**
45
+ * Retrieve customer attribute code column renderer
46
+ *
47
+ * @return Windsorcircle_Export_Block_Adminhtml_Form_Field_Order_Item_Buy_Options
48
+ */
49
+ protected function _getOrderItemRenderer()
50
+ {
51
+ if (!$this->_orderItemRenderer) {
52
+ $version = explode('.', Mage::getVersion());
53
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
54
+ $layout = Mage::app()->getLayout();
55
+ } else {
56
+ $layout = $this->getLayout();
57
+ }
58
+ $this->_orderItemRenderer = $layout->createBlock(
59
+ 'windsorcircle_export/adminhtml_form_field_order_item_buy_options', '',
60
+ array('is_render_to_js_template' => true)
61
+ );
62
+ $this->_orderItemRenderer->setClass('order_item_product_options_value');
63
+ $this->_orderItemRenderer->setExtraParams('style="width:240px"');
64
+ }
65
+ return $this->_orderItemRenderer;
66
+ }
67
+
68
+ /**
69
+ * Retrieve display column renderer
70
+ *
71
+ * @return Windsorcircle_Export_Block_Adminhtml_Form_Field_Display
72
+ */
73
+ protected function _getOrderItemDisplay()
74
+ {
75
+ if (!$this->_orderItemDisplayRenderer) {
76
+ $version = explode('.', Mage::getVersion());
77
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
78
+ $layout = Mage::app()->getLayout();
79
+ } else {
80
+ $layout = $this->getLayout();
81
+ }
82
+ $this->_orderItemDisplayRenderer = $layout->createBlock(
83
+ 'windsorcircle_export/adminhtml_form_field_display', ''
84
+ );
85
+ }
86
+ return $this->_orderItemDisplayRenderer;
87
+ }
88
+
89
+ /**
90
+ * Prepare to render
91
+ */
92
+ protected function _prepareToRender()
93
+ {
94
+ $this->addColumn('attribute_code', array(
95
+ 'label' => Mage::helper('sales')->__('Order Item Product Option'),
96
+ 'style' => 'width:120px',
97
+ 'renderer' => $this->_getOrderItemRenderer(),
98
+ ));
99
+ $this->addColumn('output_name', array(
100
+ 'label' => Mage::helper('sales')->__('Output Name'),
101
+ 'style' => 'width:240px',
102
+ 'renderer' => $this->_getOrderItemDisplay(),
103
+ ));
104
+ $this->_addAfter = false;
105
+ $this->_addButtonLabel = Mage::helper('sales')->__('Add Buy Request Option');
106
+ }
107
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Order/Options.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Order Input Block in Admin Panel
4
+ *
5
+ * @method getColumn()
6
+ * @method getColumnName()
7
+ * @method getInputName()
8
+ * @method setClass($class)
9
+ * @method setExtraParams($string)
10
+ *
11
+ * @category WindsorCircle
12
+ * @package Windsorcircle_Export
13
+ * @author Mark Hodge <mhodge@lyonscg.com>
14
+ * @copyright Copyright (c) 2016 WindsorCircle (www.windsorcircle.com)
15
+ */
16
+
17
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Order_Options extends Mage_Adminhtml_Block_Template
18
+ {
19
+ public function _toHtml()
20
+ {
21
+ $column = $this->getColumn();
22
+ $columnName = $this->getColumnName();
23
+ $inputName = $this->getInputName();
24
+
25
+ return '<input type="text" name="' . $inputName . '" value="#{' . $columnName . '}" ' .
26
+ ($column['size'] ? 'size="' . $column['size'] . '"' : '') . ' class="' .
27
+ (isset($column['class']) ? $column['class'] : 'input-text') . '"'.
28
+ (isset($column['style']) ? ' style="'.$column['style'] . '"' : '') . ' />';
29
+ }
30
+ }
31
+
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Product/Attributes.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Produt Attributes Class
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Product_Attributes
12
+ extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
13
+ {
14
+ /**
15
+ * @var
16
+ */
17
+ protected $_productRenderer;
18
+
19
+ /**
20
+ * @var
21
+ */
22
+ protected $_productDisplayRenderer;
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ $version = explode('.', Mage::getVersion());
30
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
31
+ $this->addColumn('attribute_code', array(
32
+ 'label' => Mage::helper('customer')->__('Product Attribute'),
33
+ 'renderer' => $this->_getProductRenderer(),
34
+ ));
35
+ $this->addColumn('output_name', array(
36
+ 'label' => Mage::helper('cataloginventory')->__('Output Name'),
37
+ 'style' => 'width:120px',
38
+ 'renderer' => $this->_getProductDisplay(),
39
+ ));
40
+ }
41
+ parent::__construct();
42
+ }
43
+
44
+ /**
45
+ * Retrieve product attribute code column renderer
46
+ *
47
+ * @return Windsorcircle_Export_Block_Adminhtml_Form_Field_Product_Options
48
+ */
49
+ protected function _getProductRenderer()
50
+ {
51
+ if (!$this->_productRenderer) {
52
+ $version = explode('.', Mage::getVersion());
53
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
54
+ $layout = Mage::app()->getLayout();
55
+ } else {
56
+ $layout = $this->getLayout();
57
+ }
58
+ $this->_productRenderer = $layout->createBlock(
59
+ 'windsorcircle_export/adminhtml_form_field_product_options', '',
60
+ array('is_render_to_js_template' => true)
61
+ );
62
+ $this->_productRenderer->setClass('product_group_select');
63
+ $this->_productRenderer->setExtraParams('style="width:120px"');
64
+ }
65
+ return $this->_productRenderer;
66
+ }
67
+
68
+ /**
69
+ * Retrieve display column renderer
70
+ *
71
+ * @return Windsorcircle_Export_Block_Adminhtml_Form_Field_Product_Display
72
+ */
73
+ protected function _getProductDisplay()
74
+ {
75
+ if (!$this->_productDisplayRenderer) {
76
+ $version = explode('.', Mage::getVersion());
77
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
78
+ $layout = Mage::app()->getLayout();
79
+ } else {
80
+ $layout = $this->getLayout();
81
+ }
82
+ $this->_productDisplayRenderer = $layout->createBlock(
83
+ 'windsorcircle_export/adminhtml_form_field_display', ''
84
+ );
85
+ }
86
+ return $this->_productDisplayRenderer;
87
+ }
88
+
89
+ /**
90
+ * Prepare to render
91
+ */
92
+ protected function _prepareToRender()
93
+ {
94
+ $this->addColumn('attribute_code', array(
95
+ 'label' => Mage::helper('customer')->__('Product Attribute'),
96
+ 'renderer' => $this->_getProductRenderer(),
97
+ ));
98
+ $this->addColumn('output_name', array(
99
+ 'label' => Mage::helper('cataloginventory')->__('Output Name'),
100
+ 'style' => 'width:240px',
101
+ 'renderer' => $this->_getProductDisplay(),
102
+ ));
103
+ $this->_addAfter = false;
104
+ $this->_addButtonLabel = Mage::helper('cataloginventory')->__('Add Custom Attribute');
105
+ }
106
+
107
+ /**
108
+ * Prepare existing row data object
109
+ *
110
+ * @param Varien_Object
111
+ */
112
+ protected function _prepareArrayRow(Varien_Object $row)
113
+ {
114
+ $row->setData(
115
+ 'option_extra_attr_' . $this->_getProductRenderer()->calcOptionHash($row->getData('attribute_code')),
116
+ 'selected="selected"'
117
+ );
118
+ }
119
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Product/Options.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Product Options Class
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Product_Options extends Mage_Core_Block_Html_Select
12
+ {
13
+ /**
14
+ * Customer groups cache
15
+ *
16
+ * @var array
17
+ */
18
+ private $_productAttributes;
19
+
20
+ /**
21
+ * Retrieve allowed customer groups
22
+ *
23
+ * @param int $groupId return name by customer group id
24
+ * @return array|string
25
+ */
26
+ protected function _getProductAttributes()
27
+ {
28
+ if (is_null($this->_productAttributes)) {
29
+ $this->_productAttributes = array();
30
+ if (version_compare(Mage::getVersion(), '1.4.0.0', '<')) {
31
+ $entityCode = 'catalog_product';
32
+ } else {
33
+ $entityCode = Mage_Catalog_Model_Product::ENTITY;
34
+ }
35
+ $type = Mage::getModel('eav/entity_type')->loadByCode($entityCode);
36
+ $collection = Mage::getResourceModel('eav/entity_attribute_collection')->setEntityTypeFilter($type);
37
+ $this->_productAttributes[0] = '';
38
+ foreach ($collection as $item) {
39
+ $label = $item->getFrontendLabel();
40
+ if (!empty($label)) {
41
+ /* @var $item Mage_Catalog_Model_Resource_Eav_Attribute */
42
+ $this->_productAttributes[$item->getAttributeCode()] = $label;
43
+ }
44
+ }
45
+ }
46
+ return $this->_productAttributes;
47
+ }
48
+
49
+ public function setInputName($value)
50
+ {
51
+ return $this->setName($value);
52
+ }
53
+
54
+ /**
55
+ * Render block HTML
56
+ *
57
+ * @return string
58
+ */
59
+ public function _toHtml()
60
+ {
61
+ if (!$this->getOptions()) {
62
+ $coreHelper = Mage::helper('core');
63
+ foreach ($this->_getProductAttributes() as $attributeCode => $label) {
64
+ if (version_compare(Mage::getVersion(), '1.4.0.0', '<')) {
65
+ $this->addOption($attributeCode, $this->quoteEscape($this->htmlEscape($label)));
66
+ } else {
67
+ if (method_exists($coreHelper, 'quoteEscape')) {
68
+ $this->addOption($attributeCode, $coreHelper->quoteEscape($this->escapeHtml($label)));
69
+ } else {
70
+ $this->addOption($attributeCode, $this->quoteEscape($this->escapeHtml($label)));
71
+ }
72
+ }
73
+ }
74
+ }
75
+ return parent::_toHtml();
76
+ }
77
+
78
+ /**
79
+ * Used for when Magento quoteEscape function is not available
80
+ *
81
+ * Escape quotes inside html attributes
82
+ * Use $addSlashes = false for escaping js that inside html attribute (onClick, onSubmit etc)
83
+ *
84
+ * @param string $data
85
+ * @param bool $addSlashes
86
+ * @return string
87
+ */
88
+ public function quoteEscape($data, $addSlashes = false)
89
+ {
90
+ if ($addSlashes === true) {
91
+ $data = addslashes($data);
92
+ }
93
+ return htmlspecialchars($data, ENT_QUOTES, null, false);
94
+ }
95
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Form/Field/Product/Options.php.bak ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Product Options Class
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Form_Field_Product_Options extends Mage_Core_Block_Html_Select
12
+ {
13
+ /**
14
+ * Customer groups cache
15
+ *
16
+ * @var array
17
+ */
18
+ private $_productAttributes;
19
+
20
+ /**
21
+ * Retrieve allowed customer groups
22
+ *
23
+ * @param int $groupId return name by customer group id
24
+ * @return array|string
25
+ */
26
+ protected function _getProductAttributes()
27
+ {
28
+ if (is_null($this->_productAttributes)) {
29
+ $this->_productAttributes = array();
30
+ $type = Mage::getModel('eav/entity_type')->loadByCode(Mage_Catalog_Model_Product::ENTITY);
31
+ $collection = Mage::getResourceModel('eav/entity_attribute_collection')->setEntityTypeFilter($type);
32
+ $this->_productAttributes[0] = '';
33
+ foreach ($collection as $item) {
34
+ $label = $item->getFrontendLabel();
35
+ if (!empty($label)) {
36
+ /* @var $item Mage_Catalog_Model_Resource_Eav_Attribute */
37
+ $this->_productAttributes[$item->getAttributeCode()] = $label;
38
+ }
39
+ }
40
+ }
41
+ return $this->_productAttributes;
42
+ }
43
+
44
+ public function setInputName($value)
45
+ {
46
+ return $this->setName($value);
47
+ }
48
+
49
+ /**
50
+ * Render block HTML
51
+ *
52
+ * @return string
53
+ */
54
+ public function _toHtml()
55
+ {
56
+ if (!$this->getOptions()) {
57
+ foreach ($this->_getProductAttributes() as $attributeCode => $label) {
58
+ $this->addOption($attributeCode, $this->escapeHtml($label));
59
+ }
60
+ }
61
+ return parent::_toHtml();
62
+ }
63
+ }
app/code/local/Windsorcircle/Export/Block/Adminhtml/Version.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Version Block class
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
8
+ * @author Mark Hodge (mhodge@lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Block_Adminhtml_Version extends Mage_Adminhtml_Block_System_Config_Form_Field
12
+ {
13
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
14
+ {
15
+ return (string) Mage::helper('windsorcircle_export')->getExtensionVersion();
16
+ }
17
+ }
app/code/local/Windsorcircle/Export/Helper/Data.php ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Windsorcircle_Export_Helper_Data extends Mage_Core_Helper_Abstract
3
+ {
4
+ /**
5
+ * Custom Attributes variable
6
+ *
7
+ * @var
8
+ */
9
+ protected $_customProductAttributes;
10
+ protected $_customCustomerAttributes;
11
+ protected $_customCustomerAddressAttributes;
12
+ protected $_customOrderItemBuyRequestAttributes;
13
+ protected $_customOrderAttributes;
14
+
15
+ /**
16
+ * Enterprise check variable
17
+ *
18
+ * @var
19
+ */
20
+ protected $_isEnterprise = null;
21
+
22
+ /**
23
+ * Get Extension Version
24
+ *
25
+ * @return string
26
+ */
27
+ public function getExtensionVersion()
28
+ {
29
+ return (string) Mage::getConfig()->getModuleConfig('Windsorcircle_Export')->version;
30
+ }
31
+
32
+ /**
33
+ * Check if Enterprise version
34
+ *
35
+ * @return bool
36
+ */
37
+ public function isEnterprise()
38
+ {
39
+ if (is_null($this->_isEnterprise)) {
40
+ if (method_exists('Mage', 'getEdition')) {
41
+ $this->_isEnterprise = (bool)Mage::getEdition() === 'Enterprise';
42
+ } else {
43
+ if (Mage::getConfig()->getModuleConfig('Enterprise_Enterprise')
44
+ && Mage::getConfig()->getModuleConfig('Enterprise_AdminGws')
45
+ && Mage::getConfig()->getModuleConfig('Enterprise_Checkout')
46
+ && Mage::getConfig()->getModuleConfig('Enterprise_Customer')
47
+ ) {
48
+ $this->_isEnterprise = true;
49
+ } else {
50
+ $this->_isEnterprise = false;
51
+ }
52
+ }
53
+ }
54
+ return $this->_isEnterprise;
55
+ }
56
+
57
+ /**
58
+ * Replace all tabs with spaces and replace all new lines with html <br />
59
+ *
60
+ * @param $string
61
+ * @param int $tabspaces
62
+ * @return mixed
63
+ */
64
+ public function formatString($string, $tabspaces = 4) {
65
+ $string = str_replace(array('\t', "\t"), str_repeat(" ",$tabspaces), $string);
66
+ // use str_replace instead of nl2br because nl2br inserts html line breaks before all newlines but does not replace newlines
67
+ $string = str_replace(array("\r\n", '\r\n', "\n\r", '\n\r', "\n", '\n', "\r", '\r'), '<br />', $string);
68
+ return $string;
69
+ }
70
+
71
+ /**
72
+ * Make value readable by Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
73
+ *
74
+ * @param mixed $value
75
+ * @return array
76
+ */
77
+ public function makeArrayFieldValue($value, $prefix = null)
78
+ {
79
+ $value = $this->_unserializeValue($value);
80
+ if (!$this->_isEncodedArrayFieldValue($value)) {
81
+ $value = $this->_encodeArrayFieldValue($value, $prefix);
82
+ }
83
+ return $value;
84
+ }
85
+
86
+ /**
87
+ * Make value ready for store
88
+ *
89
+ * @param mixed $value
90
+ * @return string
91
+ */
92
+ public function makeStorableArrayFieldValue($value)
93
+ {
94
+ if ($this->_isEncodedArrayFieldValue($value)) {
95
+ $value = $this->_decodeArrayFieldValue($value);
96
+ }
97
+ $value = $this->_serializeValue($value);
98
+ return $value;
99
+ }
100
+
101
+ /**
102
+ * Create a value from a storable representation
103
+ *
104
+ * @param mixed $value
105
+ * @return array
106
+ */
107
+ protected function _unserializeValue($value)
108
+ {
109
+ if (is_string($value) && !empty($value)) {
110
+ return unserialize($value);
111
+ } else {
112
+ return array();
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Check whether value is in form retrieved by _encodeArrayFieldValue()
118
+ *
119
+ * @param mixed
120
+ * @return bool
121
+ */
122
+ protected function _isEncodedArrayFieldValue($value)
123
+ {
124
+ if (!is_array($value)) {
125
+ return false;
126
+ }
127
+ unset($value['__empty']);
128
+ foreach ($value as $_id => $row) {
129
+ if (!is_array($row) || !array_key_exists('attribute_code', $row)) {
130
+ return false;
131
+ }
132
+ }
133
+ return true;
134
+ }
135
+
136
+ /**
137
+ * Encode value to be used in Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
138
+ *
139
+ * @param array
140
+ * @return array
141
+ */
142
+ protected function _encodeArrayFieldValue(array $value, $prefix = null)
143
+ {
144
+ $result = array();
145
+ foreach ($value as $attributeCode) {
146
+ $version = explode('.', Mage::getVersion());
147
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
148
+ $_id = '_' . md5(uniqid(microtime().mt_rand(), true));
149
+ } else {
150
+ $_id = Mage::helper('core')->uniqHash('_');
151
+ }
152
+ $result[$_id] = array(
153
+ 'attribute_code' => $attributeCode,
154
+ 'output_name' => $prefix . $attributeCode,
155
+ );
156
+ }
157
+ return $result;
158
+ }
159
+
160
+ /**
161
+ * Decode value from used in Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
162
+ *
163
+ * @param array
164
+ * @return array
165
+ */
166
+ protected function _decodeArrayFieldValue(array $value)
167
+ {
168
+ $result = array();
169
+ unset($value['__empty']);
170
+ foreach ($value as $_id => $row) {
171
+ if (!is_array($row) || !array_key_exists('attribute_code', $row) || empty($row['attribute_code'])) {
172
+ continue;
173
+ }
174
+ if (!in_array($row['attribute_code'], $result)) {
175
+ $result[] = $row['attribute_code'];
176
+ }
177
+ }
178
+ return $result;
179
+ }
180
+
181
+ /**
182
+ * Generate a storable representation of a value
183
+ *
184
+ * @param mixed $value
185
+ * @return string
186
+ */
187
+ protected function _serializeValue($value)
188
+ {
189
+ if (is_numeric($value)) {
190
+ $data = (float)$value;
191
+ return (string)$data;
192
+ } else if (is_array($value)) {
193
+ $data = array();
194
+ foreach ($value as $attributeCode) {
195
+ if (!array_key_exists($attributeCode, $data)) {
196
+ $data[] = $attributeCode;
197
+ }
198
+ }
199
+ return serialize($data);
200
+ } else {
201
+ return '';
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Get Custom Attributes from Admin Setting
207
+ *
208
+ * @return array|mixed
209
+ */
210
+ /**
211
+ * Get Custom Attributes from Admin Setting
212
+ *
213
+ * @param string $type Should be 'product', 'customer', 'customer_address', 'order', or 'order_item_buy_request'
214
+ *
215
+ * @return array
216
+ */
217
+ public function getCustomAttributes($type)
218
+ {
219
+ /** If not of the correct type then just return */
220
+ if (!in_array($type, array('product', 'customer', 'customer_address', 'order', 'order_item_buy_request'))) { return false; }
221
+
222
+ $variableName = '_custom' . implode('', array_map("ucfirst", explode('_', $type))). 'Attributes';
223
+
224
+ if (!$this->$variableName) {
225
+ $customAttributes = Mage::helper('windsorcircle_export')
226
+ ->makeArrayFieldValue(Mage::getStoreConfig('windsorcircle_export_options/messages/custom_' . $type . '_attributes'));
227
+
228
+
229
+ $this->$variableName = array();
230
+ foreach ($customAttributes as $attribute) {
231
+ if (array_key_exists('attribute_code', $attribute)) {
232
+ array_push($this->$variableName, $attribute['attribute_code']);
233
+ }
234
+ }
235
+ }
236
+ return $this->$variableName;
237
+ }
238
+
239
+ /**
240
+ * Get Current Memory Usage
241
+ *
242
+ * @return string
243
+ */
244
+ public function getMemoryUsage()
245
+ {
246
+ $mem_usage = memory_get_usage(true);
247
+
248
+ if ($mem_usage < 1024) {
249
+ return $mem_usage . " bytes";
250
+ } elseif ($mem_usage < 1048576) {
251
+ return round($mem_usage / 1024, 2) . " kilobytes";
252
+ } else {
253
+ return round($mem_usage / 1048576, 2) . " megabytes";
254
+ }
255
+ }
256
+ }
app/code/local/Windsorcircle/Export/Model/Brand/Attribute.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Brand Attribute
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
8
+ * @author Mark Hodge (mhodge@lyonscg.com)
9
+ */
10
+ class Windsorcircle_Export_Model_Brand_Attribute
11
+ {
12
+ /**
13
+ * Select field in admin area for Image Type
14
+ * @return array
15
+ */
16
+ public function toOptionArray(){
17
+
18
+ $version = explode('.', Mage::getVersion());
19
+ if ( $version[0] == 1 && $version[1] <= 3 )
20
+ {
21
+ $attributeItems = Mage::getResourceModel('eav/entity_attribute_collection')
22
+ ->setEntityTypeFilter( Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId() )
23
+ ->addVisibleFilter()
24
+ ->getItems();
25
+ } else {
26
+ $attributeItems = Mage::getResourceModel('catalog/product_attribute_collection')->getItems();
27
+ }
28
+
29
+ $attributes = array();
30
+ $sortAttributes = array();
31
+ foreach ($attributeItems as $attribute) {
32
+ if ($attribute->getIsVisible()) {
33
+ $sortAttributes[] = $attribute->getFrontendLabel();
34
+
35
+ $attributes[] = array('value' => $attribute->getAttributeCode(),
36
+ 'label' => $attribute->getFrontendLabel());
37
+ }
38
+ }
39
+
40
+ array_multisort($sortAttributes, SORT_ASC, $attributes);
41
+ array_unshift($attributes, array('value' => 0, 'label' => '--' . Mage::helper('windsorcircle_export')->__('Please Select a value') . '--'));
42
+ return $attributes;
43
+ }
44
+ }
app/code/local/Windsorcircle/Export/Model/Date.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Windsorcircle_Export_Model_Date extends Mage_Core_Model_Abstract
3
+ {
4
+ protected function _construct(){
5
+ $this->_init('windsorcircle_export/date');
6
+ }
7
+
8
+ /**
9
+ * Checks if the authDate is within one minute of the current time
10
+ * @param string $authDate
11
+ * @throws Exception
12
+ * @return bool true on success
13
+ */
14
+ public function checkDate($authDate){
15
+ date_default_timezone_set('UTC');
16
+ $currentDate = strtotime(gmdate('c'));
17
+
18
+ if(empty($authDate)){
19
+ $authDate = strtotime('+1 week');
20
+ } else {
21
+ $authDate = strtotime($authDate);
22
+ }
23
+
24
+ $diff = $currentDate - $authDate;
25
+
26
+ if(abs($diff) <= 600)
27
+ return true;
28
+ else
29
+ throw new Exception('authDate is not correct');
30
+ }
31
+ }
app/code/local/Windsorcircle/Export/Model/Format.php ADDED
@@ -0,0 +1,490 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Windsorcircle_Export_Model_Format extends Mage_Core_Model_Abstract
3
+ {
4
+ // Debug Parameter
5
+ protected $debug = false;
6
+
7
+ // Windsorcircle log file
8
+ protected $logFile = 'windsorcircle.log';
9
+
10
+ /**
11
+ * Constructor
12
+ */
13
+ protected function _construct()
14
+ {
15
+ $this->_init('windsorcircle_export/format');
16
+
17
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
18
+ }
19
+
20
+ /**
21
+ * Create Headers for file
22
+ *
23
+ * @return array
24
+ */
25
+ protected function createHeaders()
26
+ {
27
+ $returnArray = array(
28
+ 'ID',
29
+ 'StoreID',
30
+ 'Active',
31
+ 'VSKU',
32
+ 'PSKU',
33
+ 'Product_Type',
34
+ 'Title',
35
+ 'Link',
36
+ 'Image_link',
37
+ 'Price',
38
+ 'Sale_price',
39
+ 'Sale_Price_Effective_Date',
40
+ 'Brand',
41
+ 'Availability',
42
+ 'Quantity',
43
+ 'Shipping_Weight',
44
+ 'Catalog_Product_Type',
45
+ 'Visibility'
46
+ );
47
+
48
+ $customAttributes = Mage::helper('windsorcircle_export')->getCustomAttributes('product');
49
+ foreach ($customAttributes as $customAttribute) {
50
+ $returnArray['custom_product_' . $customAttribute] = 'custom_product_' . $customAttribute;
51
+ }
52
+
53
+ return $returnArray;
54
+ }
55
+
56
+ /**
57
+ * Put Order Data in tab-delimited format
58
+ * @param array $orderData
59
+ * @throws Exception
60
+ * @return string String of Order Data File
61
+ */
62
+ public function formatOrderData(array $orderData, $prefix = '_Orders_'){
63
+ $file = Mage::getBaseDir('tmp') . DS . Mage::getStoreConfig('windsorcircle_export_options/messages/client_name') . $prefix . Mage::registry('windsor_file_timestamp') . '.txt';
64
+ $handle = fopen($file, 'w');
65
+
66
+ if($handle == false){
67
+ throw new Exception('Cannot create Orders file');
68
+ }
69
+
70
+ // Output data
71
+ foreach($orderData as $order){
72
+ fputcsv($handle, $order, "\t");
73
+ }
74
+
75
+ fclose($handle);
76
+
77
+ return $file;
78
+ }
79
+
80
+ /**
81
+ * Put Order Details Data in tab-delimited format
82
+ *
83
+ * @param array $orderDetailsData
84
+ * @throws Exception
85
+ * @return string String of Order Details Data File
86
+ */
87
+ public function formatOrderDetailsData(array $orderDetailsData, $prefix = '_Order_'){
88
+ $file = Mage::getBaseDir('tmp') . DS . Mage::getStoreConfig('windsorcircle_export_options/messages/client_name') . $prefix . 'Details_' . Mage::registry('windsor_file_timestamp') . '.txt';
89
+ $handle = fopen($file, 'w');
90
+
91
+ if($handle == false){
92
+ throw new Exception('Cannot create Order Details File');
93
+ }
94
+
95
+ // Output data
96
+ foreach($orderDetailsData as $orderDetails){
97
+ foreach($orderDetails as $item){
98
+ fputcsv($handle, $item, "\t");
99
+ }
100
+ }
101
+
102
+ fclose($handle);
103
+
104
+ return $file;
105
+ }
106
+
107
+ /**
108
+ * Create product data from last export date and add to lastexport file
109
+ *
110
+ * @param string $lastExport
111
+ * @param string $lastExpDate
112
+ * @throws Exception
113
+ */
114
+ public function createProductData($lastExport,$lastExpDate)
115
+ {
116
+ if ($this->debug) {
117
+ Mage::log('Creating Product Data', null, $this->logFile);
118
+ }
119
+
120
+ $handle = fopen($lastExport, 'a');
121
+
122
+ if($handle == false){
123
+ throw new Exception('Cannot create Products file');
124
+ }
125
+
126
+ $headers[] = $this->createHeaders();
127
+
128
+ //don't put headers if the file was already created earlier
129
+ if($lastExpDate == "0000-00-00 00:00:00") {
130
+ fputcsv($handle, $headers[0] , "\t");
131
+ }
132
+
133
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
134
+
135
+ $products = Mage::getModel('catalog/product')->getCollection()
136
+ ->addAttributeToSelect(array_unique(array_merge($this->getDefaultAttributes(), Mage::helper('windsorcircle_export')->getCustomAttributes('product'))), 'left');
137
+
138
+ // If no custom attribute for brand then we will use default brand attribute
139
+ $attribute = Mage::getStoreConfig('windsorcircle_export_options/messages/brand_attribute');
140
+ if (empty($attribute)) {
141
+ $brand = Mage::getModel('catalog/resource_eav_attribute')
142
+ ->loadByCode('catalog_product', 'brand');
143
+ if($brand->getId() !== null) {
144
+ $products->addAttributeToSelect('brand', 'left');
145
+ }
146
+ } else {
147
+ $brand = Mage::getModel('catalog/resource_eav_attribute')
148
+ ->loadByCode('catalog_product', $attribute);
149
+ if($brand->getId() !== null) {
150
+ $products->addAttributeToSelect($attribute, 'left');
151
+ }
152
+ }
153
+
154
+ $products->joinTable(
155
+ 'cataloginventory/stock_item',
156
+ 'product_id=entity_id',
157
+ array('is_in_stock', 'backorders', 'qty', 'manage_stock', 'use_config_manage_stock'),
158
+ '{{table}}.stock_id=1',
159
+ 'left');
160
+
161
+ $stores = Mage::getStoreConfig('windsorcircle_export_options/messages/store');
162
+ if (!empty($stores)) {
163
+ $stores = explode(',', $stores);
164
+
165
+ $websites = array();
166
+ foreach ($stores as $store) {
167
+ $websites[] = Mage::app()->getStore($store)->getWebsiteId();
168
+ }
169
+
170
+ $subQuery = new Zend_Db_Expr(
171
+ '(SELECT parent_id, child_id ' .
172
+ 'FROM ' . $products->getTable('catalog/product_relation') . ' AS `subrelation` ' .
173
+ 'JOIN ' . $products->getTable('catalog/product_website') . ' AS `subwebsite` ' .
174
+ 'ON (`subwebsite`.`product_id` = `subrelation`.`parent_id`) ' .
175
+ 'WHERE (`subwebsite`.`website_id` IN (' . implode(',', $websites) . ')))'
176
+ );
177
+
178
+ $products->getSelect()->joinLeft(
179
+ array('_table_relation' => $subQuery),
180
+ '(_table_relation.child_id = e.entity_id)',
181
+ array('relation' => 'parent_id')
182
+ );
183
+
184
+ $products->getSelect()->joinLeft(
185
+ array('_table_parent_sku_relation' => $products->getTable('catalog/product')),
186
+ '(_table_parent_sku_relation.entity_id=_table_relation.parent_id)',
187
+ array('parent_sku_relation' => 'sku')
188
+ );
189
+
190
+ $products
191
+ ->joinField('websites', 'catalog/product_website', 'website_id', 'product_id=entity_id', null, 'inner')
192
+ ->addFieldToFilter('websites', array('in' => $websites));
193
+
194
+ } else {
195
+ $products
196
+ ->joinField('relation', 'catalog/product_relation', 'parent_id', 'child_id=entity_id', null, 'left')
197
+ ->joinField('parent_sku_relation', 'catalog/product', 'sku', 'entity_id=relation', null, 'left');
198
+ }
199
+
200
+ $products->addAttributeToSort('type_id', 'ASC');
201
+
202
+ if($lastExpDate != "0000-00-00 00:00:00") {
203
+ $products->addAttributeToFilter('created_at',array('gteq' => $lastExpDate));
204
+ }
205
+
206
+ Mage::getSingleton('core/resource_iterator')->walk($products->getSelect(), array(array($this, 'productCallback')), array('arg1' => '====', 'handle' => $handle));
207
+
208
+ fclose($handle);
209
+
210
+ return;
211
+ }
212
+
213
+ /**
214
+ *
215
+ * Product Call Back Function for magento's core resource iterator walk function
216
+ * @param array $args
217
+ */
218
+ public function productCallback($args) {
219
+ $product = Mage::getModel('catalog/product');
220
+ $product->setData($args['row']);
221
+ Mage::getSingleton('windsorcircle_export/products')->getProductsAdvanced($product, $args['handle']);
222
+ }
223
+
224
+ /**
225
+ * Put Product Data in tab-delimited format
226
+ * @param array $products
227
+ * @throws Exception
228
+ * @return string String of Product Data File
229
+ */
230
+ public function formatProductData(array $products){
231
+ $file = Mage::getBaseDir('tmp') . DS . Mage::getStoreConfig('windsorcircle_export_options/messages/client_name') . '_Products_' . Mage::registry('windsor_file_timestamp') . '.txt';
232
+ $handle = fopen($file, 'w');
233
+
234
+ if($handle == false){
235
+ throw new Exception('Cannot create Products file');
236
+ }
237
+
238
+ // Output data
239
+ foreach($products as $product){
240
+ fputcsv($handle, $product, "\t");
241
+ }
242
+
243
+ fclose($handle);
244
+
245
+ return $file;
246
+ }
247
+
248
+ /**
249
+ * Get Products data
250
+ * @return string File of export
251
+ */
252
+ public function advancedFormatProductData($additionalProductIds = array()) {
253
+
254
+ $lastExportFolder = Mage::getBaseDir('media') . DS . 'windsorcircle_export';
255
+ $lastExport = $lastExportFolder . DS . 'lastexport.txt';
256
+ $updatedProd = $lastExportFolder . DS . 'updated.txt';
257
+ if (!file_exists($lastExportFolder)) { mkdir($lastExportFolder); }
258
+
259
+ $newExport = Mage::getBaseDir('tmp') . DS . Mage::getStoreConfig('windsorcircle_export_options/messages/client_name') . '_Products_' . Mage::registry('windsor_file_timestamp') . '.txt';
260
+ if (!file_exists($lastExport)) {
261
+ $lastExpDate = "0000-00-00 00:00:00";
262
+ $this->createProductData($lastExport,$lastExpDate);
263
+ if (file_exists($updatedProd)) { @unlink($updatedProd); }
264
+ } else {
265
+ $lastExpDate = date("Y-m-d H:i:s", filemtime($lastExport));
266
+ $this->createProductData($lastExport,$lastExpDate);
267
+ //next step: refresh and delete
268
+ $this->applyPatch($updatedProd,$lastExport, $additionalProductIds);
269
+ }
270
+ //copy to tmp folder
271
+ copy($lastExport,$newExport);
272
+
273
+ return $newExport;
274
+ }
275
+
276
+ /**
277
+ * This is called from the Background controller and gets product data only if the updated.txt file is set or
278
+ * the lastexport.txt file is not present
279
+ *
280
+ * @param array $additionalProductIds
281
+ *
282
+ * @return string
283
+ * @throws Exception
284
+ */
285
+ public function getProductDataIfUpdated($additionalProductIds = array()) {
286
+ $lastExportFolder = Mage::getBaseDir('media') . DS . 'windsorcircle_export';
287
+ $lastExport = $lastExportFolder . DS . 'lastexport.txt';
288
+ $updatedProd = $lastExportFolder . DS . 'updated.txt';
289
+ if (!file_exists($lastExportFolder)) { mkdir($lastExportFolder); }
290
+
291
+ $newExport = Mage::getBaseDir('tmp') . DS . Mage::getStoreConfig('windsorcircle_export_options/messages/client_name') . '_Products_' . Mage::registry('windsor_file_timestamp') . '.txt';
292
+ if (!file_exists($lastExport)) {
293
+ $lastExpDate = "0000-00-00 00:00:00";
294
+ $this->createProductData($lastExport, $lastExpDate);
295
+ if (file_exists($updatedProd)) { @unlink($updatedProd); }
296
+
297
+ //copy to tmp folder
298
+ copy($lastExport,$newExport);
299
+
300
+ return $newExport;
301
+ } elseif (file_exists($updatedProd) || !empty($additionalProductIds)) {
302
+ $this->applyPatch($updatedProd, $lastExport, $additionalProductIds);
303
+
304
+ //copy to tmp folder
305
+ copy($lastExport,$newExport);
306
+
307
+ return $newExport;
308
+ }
309
+
310
+ return;
311
+ }
312
+
313
+ /**
314
+ * Refresh existing file using the file with updated products ids
315
+ * @param $patch_file_name
316
+ * @param $data_file_name
317
+ * @param array $additonalProductIds
318
+ * @throws Exception
319
+ */
320
+ public function applyPatch($patch_file_name, $data_file_name, $additonalProductIds = array())
321
+ {
322
+ if ($this->debug) {
323
+ Mage::log('Applying Product Patch to Product File', null, $this->logFile);
324
+ }
325
+
326
+ $patch = array();
327
+
328
+ if(file_exists($patch_file_name)) {
329
+ $patchFile = file($patch_file_name);
330
+ foreach($patchFile as $line) {
331
+ preg_match('/(-|!)(\d+)/', $line, $match);
332
+ if(isset($match[1]) && !empty($match[1])) {
333
+ $patch[$match[1]][$match[2]] = $match[2];
334
+ }
335
+ }
336
+ if (!empty($additonalProductIds)) {
337
+ foreach ($additonalProductIds as $additonalProductId) {
338
+ $patch['!'][$additonalProductId] = $additonalProductId;
339
+ }
340
+ }
341
+ } else if (!empty($additonalProductIds)) {
342
+ foreach ($additonalProductIds as $additonalProductId) {
343
+ $patch['!'][$additonalProductId] = $additonalProductId;
344
+ }
345
+ } else {
346
+ return;
347
+ }
348
+
349
+ if(isset($patch) && count($patch) > 0 && file_exists($data_file_name)) {
350
+ try {
351
+ $handle = fopen($data_file_name, "r");
352
+ $newhandle = fopen($data_file_name.'-new.txt', "w+");
353
+ if (!$handle) {
354
+ throw new Exception('! Cannot load Products file !');
355
+ }
356
+
357
+ fputcsv($newhandle, $this->createHeaders(), "\t");
358
+
359
+ $products = Mage::getModel('catalog/product')->getCollection()
360
+ ->addAttributeToSelect(array_unique(array_merge($this->getDefaultAttributes(), Mage::helper('windsorcircle_export')->getCustomAttributes('product'))), 'left');
361
+
362
+ // If no custom attribute for brand then we will use default brand attribute
363
+ $attribute = Mage::getStoreConfig('windsorcircle_export_options/messages/brand_attribute');
364
+ if (empty($attribute)) {
365
+ $brand = Mage::getModel('catalog/resource_eav_attribute')
366
+ ->loadByCode('catalog_product', 'brand');
367
+ if($brand->getId() !== null) {
368
+ $products->addAttributeToSelect('brand', 'left');
369
+ }
370
+ } else {
371
+ $brand = Mage::getModel('catalog/resource_eav_attribute')
372
+ ->loadByCode('catalog_product', $attribute);
373
+ if($brand->getId() !== null) {
374
+ $products->addAttributeToSelect($attribute, 'left');
375
+ }
376
+ }
377
+
378
+ $products->joinTable(
379
+ 'cataloginventory/stock_item',
380
+ 'product_id=entity_id',
381
+ array('is_in_stock', 'backorders', 'qty', 'manage_stock', 'use_config_manage_stock'),
382
+ '{{table}}.stock_id=1',
383
+ 'left');
384
+
385
+ $stores = Mage::getStoreConfig('windsorcircle_export_options/messages/store');
386
+ if (!empty($stores)) {
387
+ $stores = explode(',', $stores);
388
+
389
+ $websites = array();
390
+ foreach ($stores as $store) {
391
+ $websites[] = Mage::app()->getStore($store)->getWebsiteId();
392
+ }
393
+
394
+ $subQuery = new Zend_Db_Expr(
395
+ '(SELECT parent_id, child_id ' .
396
+ 'FROM ' . $products->getTable('catalog/product_relation') . ' AS `subrelation` ' .
397
+ 'JOIN ' . $products->getTable('catalog/product_website') . ' AS `subwebsite` ' .
398
+ 'ON (`subwebsite`.`product_id` = `subrelation`.`parent_id`) ' .
399
+ 'WHERE (`subwebsite`.`website_id` IN (' . implode(',', $websites) . ')))'
400
+ );
401
+
402
+ $products->getSelect()->joinLeft(
403
+ array('_table_relation' => $subQuery),
404
+ '(_table_relation.child_id = e.entity_id)',
405
+ array('relation' => 'parent_id')
406
+ );
407
+
408
+ $products->getSelect()->joinLeft(
409
+ array('_table_parent_sku_relation' => $products->getTable('catalog/product')),
410
+ '(_table_parent_sku_relation.entity_id=_table_relation.parent_id)',
411
+ array('parent_sku_relation' => 'sku')
412
+ );
413
+
414
+ $products
415
+ ->joinField('websites', 'catalog/product_website', 'website_id', 'product_id=entity_id', null, 'inner')
416
+ ->addFieldToFilter('websites', array('in' => $websites));
417
+
418
+ } else {
419
+ $products
420
+ ->joinField('relation', 'catalog/product_relation', 'parent_id', 'child_id=entity_id', null, 'left')
421
+ ->joinField('parent_sku_relation', 'catalog/product', 'sku', 'entity_id=relation', null, 'left');
422
+ }
423
+
424
+ $products->addAttributeToFilter('entity_id', array('in' => $patch['!']));
425
+
426
+ Mage::getSingleton('core/resource_iterator')->walk($products->getSelect(), array(array($this, 'productCallback')), array('arg1' => '====', 'handle' => $newhandle));
427
+
428
+ while(($data = fgetcsv($handle, 0, "\t")) != false) {
429
+ if(intval($data[0]) > 0 ) {
430
+ if(isset($patch['-'][$data[0]]) || isset($patch['!'][$data[0]])) {
431
+ $data = null;
432
+ }
433
+
434
+ if ($data) {
435
+ fputcsv($newhandle, $data, "\t");
436
+ }
437
+ }
438
+ }
439
+
440
+ unset($patch);
441
+ fclose($handle);
442
+ fclose($newhandle);
443
+ } catch(Exception $e) {
444
+ die($e->getMessage());
445
+ }
446
+
447
+ if(file_exists($patch_file_name)) {
448
+ @unlink($patch_file_name);
449
+ }
450
+ @unlink($data_file_name);
451
+ rename($data_file_name.'-new.txt', $data_file_name);
452
+ }
453
+ }
454
+
455
+ /**
456
+ * Set Debug flag
457
+ *
458
+ * @param $flag
459
+ * @return $this
460
+ */
461
+ public function setDebug($flag)
462
+ {
463
+ $this->debug = $flag;
464
+ return $this;
465
+ }
466
+
467
+ /**
468
+ * Get Default Attributes for Products
469
+ *
470
+ * @return array
471
+ */
472
+ protected function getDefaultAttributes()
473
+ {
474
+ return array(
475
+ 'name',
476
+ 'price',
477
+ 'special_price',
478
+ 'special_from_date',
479
+ 'special_to_date',
480
+ 'image',
481
+ 'small_image',
482
+ 'status',
483
+ 'weight',
484
+ 'weight_type',
485
+ 'url_path',
486
+ 'type_id',
487
+ 'visibility'
488
+ );
489
+ }
490
+ }
app/code/local/Windsorcircle/Export/Model/Ftp.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Windsorcircle_Export_Model_Ftp extends Mage_Core_Model_Abstract
3
+ {
4
+
5
+ protected function _construct(){
6
+ $this->_init('windsorcircle_export/ftp');
7
+ }
8
+
9
+ /**
10
+ * Create a blank .flg file
11
+ *
12
+ * @param $file
13
+ * @return array Array[0] - Base File Name, Array[1] - Absolute File Location
14
+ * @throws Exception
15
+ */
16
+ protected function createFlgFile($file){
17
+ $file = Mage::getBaseDir('tmp') . DS . basename($file, '.txt') . '.flg';
18
+ $handle = fopen($file, 'w');
19
+
20
+ if($handle == false){
21
+ throw new Exception('Cannot create flg file for '. basename($file, '.txt'));
22
+ }
23
+
24
+ fclose($handle);
25
+ return array(basename($file), $file);
26
+ }
27
+
28
+ /**
29
+ * Send files via FTP Type (Ftp or SFtp)
30
+ *
31
+ * @param array $files
32
+ * @return bool
33
+ * @throws Exception
34
+ */
35
+ public function sendFiles(array $files){
36
+
37
+ try {
38
+ // Value of 1 is FTP, value of 2 is SFTP
39
+ if(Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_type') == '1'){
40
+ require_once(Mage::getBaseDir('lib') . DS . 'Varien' . DS . 'Io' . DS . 'Ftp.php');
41
+ $ftp = new Varien_Io_Ftp();
42
+ $ftp->open(array('host' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_host'),
43
+ 'user' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_user'),
44
+ 'password' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_password'),
45
+ 'path' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_folder'),
46
+ 'passive' => true
47
+ ));
48
+ $prefix = '';
49
+ } elseif (Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_type') == '2'){
50
+ $ftp = Mage::getModel('windsorcircle_export/sftp');
51
+ $ftp->open(array('host' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_host'),
52
+ 'username' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_user'),
53
+ 'password' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_password')
54
+ ));
55
+ $prefix = '/' . Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_folder') . '/';
56
+ }
57
+ } catch (Exception $e){
58
+ throw new Exception('FTP Exception: '.$e);
59
+ }
60
+
61
+ foreach($files as $key => $file) {
62
+ // Varien_Io_Ftp suppresses error messages so only way to check if successfull is if not null
63
+ if($ftp->write($prefix . basename($files[$key]), $file) != null){
64
+ $flgFile = $this->createFlgFile($file);
65
+ $ftp->write($prefix . $flgFile[0], $flgFile[1]);
66
+ } else {
67
+ $ftp->close();
68
+ throw new Exception('Error writing file to server');
69
+ }
70
+ }
71
+
72
+ $ftp->close();
73
+
74
+ return true;
75
+ }
76
+
77
+ /**
78
+ * Test connection to ftp server
79
+ *
80
+ * @throws Exception
81
+ */
82
+ public function testConnection()
83
+ {
84
+ try {
85
+ // Value of 1 is FTP, value of 2 is SFTP
86
+ if(Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_type') == '1'){
87
+ require_once(Mage::getBaseDir('lib') . DS . 'Varien' . DS . 'Io' . DS . 'Ftp.php');
88
+ $ftp = new Varien_Io_Ftp();
89
+ $ftp->open(array('host' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_host'),
90
+ 'user' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_user'),
91
+ 'password' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_password'),
92
+ 'path' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_folder'),
93
+ 'passive' => true
94
+ ));
95
+ } elseif (Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_type') == '2'){
96
+ $ftp = Mage::getModel('windsorcircle_export/sftp');
97
+ $ftp->open(array('host' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_host'),
98
+ 'username' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_user'),
99
+ 'password' => Mage::getStoreConfig('windsorcircle_export_options/messages/ftp_password')
100
+ ));
101
+ }
102
+ } catch (Exception $e){
103
+ return 'Error connecting - ' . $e;
104
+ }
105
+ return 'Connection Successful!';
106
+ }
107
+ }
app/code/local/Windsorcircle/Export/Model/Ftp/Type.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Windsorcircle_Export_Model_Ftp_Type{
3
+
4
+ /**
5
+ * Select field in admin area for FTP Type
6
+ * @return array
7
+ */
8
+ public function toOptionArray(){
9
+ return array(
10
+ array('value'=>1, 'label'=>Mage::helper('windsorcircle_export')->__('FTP')),
11
+ array('value'=>2, 'label'=>Mage::helper('windsorcircle_export')->__('SFTP'))
12
+ );
13
+ }
14
+ }
app/code/local/Windsorcircle/Export/Model/Image/Type.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Image Type Source File
4
+ *
5
+ * @category Lyons
6
+ * @package package_name
7
+ * @copyright Copyright (c) 2012 Lyons Consulting Group (www.lyonscg.com)
8
+ * @author Mark Hodge (mhodge@lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Model_Image_Type{
12
+
13
+ /**
14
+ * Select field in admin area for Image Type
15
+ * @return array
16
+ */
17
+ public function toOptionArray(){
18
+ return array(
19
+ array('value'=>1, 'label'=>Mage::helper('windsorcircle_export')->__('Standard')),
20
+ array('value'=>2, 'label'=>Mage::helper('windsorcircle_export')->__('Small'))
21
+ );
22
+ }
23
+ }
app/code/local/Windsorcircle/Export/Model/Observer.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Windsorcircle_Export_Model_Observer
4
+ {
5
+ /**
6
+ * Variable for saving product ids updated
7
+ *
8
+ * @var bool
9
+ */
10
+ protected $updated = array();
11
+
12
+ /**
13
+ * Saving product type related data
14
+ *
15
+ * @param $observer
16
+ */
17
+ public function afterProductSave($observer)
18
+ {
19
+ $event = $observer->getEvent();
20
+ $product = $event->getProduct();
21
+ $oldProd = Mage::getModel('catalog/product')->load($product->getId())->getOrigData();
22
+ $productId = $product->getId();
23
+ if (isset($oldProd['entity_id']) && $oldProd['entity_id'] !== NULL) {
24
+ $updatedFile = @fopen($this->getMediaUpdateFile(), 'a');
25
+ if (!$updatedFile) {
26
+ Mage::log('Could not open update file to save id - ' . $productId, null, 'windsorcircle.log');
27
+ } else {
28
+ fputs($updatedFile, "!" . $productId . "\n");
29
+ fclose($updatedFile);
30
+ $this->updated[] = $productId;
31
+ }
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Init indexing process after product delete commit
37
+ *
38
+ * @param $observer
39
+ */
40
+ public function afterProductDelete($observer)
41
+ {
42
+ $event = $observer->getEvent();
43
+ $product = $event->getProduct();
44
+ $updatedFile = @fopen($this->getMediaUpdateFile(), 'a');
45
+ $productId = $product->getId();
46
+ if (!$updatedFile) {
47
+ Mage::log('Could not open update file to save id - ' . $productId, null, 'windsorcircle.log');
48
+ } else {
49
+ fputs($updatedFile, "-" . $productId . "\n");
50
+ fclose($updatedFile);
51
+ $this->updated[] = $productId;
52
+ }
53
+ }
54
+
55
+ /**
56
+ * After product inventory update save product ids to updated.txt file
57
+ *
58
+ * @param $observer
59
+ */
60
+ public function afterProductInventoryUpdate($observer)
61
+ {
62
+ $event = $observer->getEvent();
63
+ $product = $event->getItem();
64
+ $productId = $product->getProductId();
65
+
66
+ if (in_array($productId, $this->updated)) {
67
+ return;
68
+ }
69
+
70
+ $updatedFile = @fopen($this->getMediaUpdateFile(), 'a');
71
+ if (!$updatedFile) {
72
+ Mage::log('Could not open update file to save id - ' . $productId, null, 'windsorcircle.log');
73
+ } else {
74
+ fputs($updatedFile, '!' . $productId . "\n");
75
+ fclose($updatedFile);
76
+ $this->updated[] = $productId;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Get Media Update file 'updated.txt'
82
+ *
83
+ * @return resource
84
+ */
85
+ public function getMediaUpdateFile()
86
+ {
87
+ $updatedProdFolder = Mage::getBaseDir('media') . DS . 'windsorcircle_export';
88
+ $updatedProd = $updatedProdFolder . DS . 'updated.txt';
89
+ if (!file_exists($updatedProdFolder)) {
90
+ mkdir($updatedProdFolder);
91
+ }
92
+ return $updatedProd;
93
+ }
94
+ }
app/code/local/Windsorcircle/Export/Model/Openssl.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class WindsorCircle_Export_Model_Openssl
3
+ {
4
+ // Unencoded base64 variable
5
+ private $unencoded = '';
6
+
7
+ // Hash of API key
8
+ private $hash = '';
9
+
10
+ // Verified key of $this->unencoded
11
+ private $verified = '';
12
+
13
+ // urlDecoded authDate
14
+ private $authDate = '';
15
+
16
+ /**
17
+ * Checks if the decrypted authToken is equal to the hash digest of the API key
18
+ *
19
+ * @param $authToken
20
+ * @param $authDate
21
+ * @return bool
22
+ * @throws Exception
23
+ */
24
+ public function valid($authToken, $authDate){
25
+
26
+ if(empty($authToken)){
27
+ throw new Exception('authToken is empty.');
28
+ }
29
+
30
+ // URL decode authDate
31
+ $this->authDate = urldecode($authDate);
32
+
33
+ // Base 64 encoded authToken
34
+ $this->unencoded = base64_decode($authToken);
35
+
36
+ // Computes a digest based off of API key
37
+ $this->hash = hash('sha1', Mage::getStoreConfig('windsorcircle_export_options/messages/api_key') . $this->authDate, true);
38
+
39
+ // Decrypts $this->unencoded with the public key
40
+ openssl_public_decrypt($this->unencoded, $this->verified, Mage::getStoreConfig('windsorcircle_export_options/messages/public_key'));
41
+
42
+ // compares authToken and hash
43
+ $equal = strcmp($this->verified, $this->hash);
44
+
45
+ // If equal returns 0, otherwise < 0 or > 0
46
+ if($equal == 0)
47
+ return true;
48
+ else{
49
+ throw new Exception('authToken and computed hash do not match.');
50
+ }
51
+ }
52
+
53
+ /**
54
+ * OpenSSL Decryption of message using iv value
55
+ *
56
+ * @param $message
57
+ * @param $iv
58
+ * @return string
59
+ */
60
+ public function decrypt($message, $iv)
61
+ {
62
+ $encryptionMethod = 'AES-128-CBC';
63
+ $apiKey = Mage::getStoreConfig('windsorcircle_export_options/messages/api_key');
64
+
65
+ return openssl_decrypt($message, $encryptionMethod, $apiKey, false, $iv);
66
+ }
67
+ }
app/code/local/Windsorcircle/Export/Model/Order.php ADDED
@@ -0,0 +1,1192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Windsorcircle_Export_Model_Order extends Mage_Core_Model_Abstract
3
+ {
4
+ // Order Data
5
+ protected $orderData = array();
6
+
7
+ // Order Items Data
8
+ protected $orderDetailsData = array();
9
+
10
+ // Array of Order Item Ids
11
+ protected $orderItems = array();
12
+
13
+ // Abandoned Shopping Cart Quote Data
14
+ protected $quoteAscData = array();
15
+
16
+ // Abandoned Shopping Cart Quote Items Data
17
+ protected $quoteAscDetailsData = array();
18
+
19
+ // Order ID Array
20
+ protected $orderIdArray = array();
21
+
22
+ // Quote ID Array
23
+ protected $quoteIdArray = array();
24
+
25
+ // Shipped Array
26
+ protected $shippedArray = array();
27
+
28
+ // Page Size - defaults to 10,000
29
+ protected $pageSize = 10000;
30
+
31
+ // Debug Parameter
32
+ protected $debug = false;
33
+
34
+ // Windsorcircle log file
35
+ protected $logFile = 'windsorcircle.log';
36
+
37
+ /**
38
+ * Constructor
39
+ */
40
+ protected function _construct(){
41
+ $this->_init('windsorcircle_export/order');
42
+ }
43
+
44
+ /**
45
+ * Get Orders and OrderDetails between dates
46
+ * @param string $startDate
47
+ * @param string $endDate
48
+ * @return array Returns Array of Order (Array[0]) and Order Details (Array[1])
49
+ */
50
+ public function getOrders($startDate, $endDate){
51
+ $this->getOrder($startDate, $endDate)
52
+ ->getOrderItems()
53
+ ->getOrder($startDate, $endDate, true)
54
+ ->getOrderItems();
55
+
56
+ return array($this->orderData, $this->orderDetailsData, $this->orderItems);
57
+ }
58
+
59
+ /**
60
+ * Get Abandoned Shopping Cart Order Data
61
+ *
62
+ * @param string $startDate Start Date of Orders
63
+ * @param string $endDate End Date of Orders
64
+ * @return array
65
+ */
66
+ public function getAscOrders($startDate, $endDate) {
67
+ $this->getAscOrder($startDate, $endDate)
68
+ ->getAscOrderItems();
69
+
70
+ return array($this->quoteAscData, $this->quoteAscDetailsData, $this->orderItems);
71
+ }
72
+
73
+ /**
74
+ * Set page size for order/order items collections
75
+ *
76
+ * @param $pageSize
77
+ * @return $this
78
+ */
79
+ public function setPageSize($pageSize)
80
+ {
81
+ $this->pageSize = (int) $pageSize;
82
+ return $this;
83
+ }
84
+
85
+ /**
86
+ * Set debug flag
87
+ *
88
+ * @param $flag
89
+ * @return $this
90
+ */
91
+ public function setDebug($flag) {
92
+ $this->debug = $flag;
93
+ return $this;
94
+ }
95
+
96
+ /**
97
+ * Get Order Data between dates
98
+ *
99
+ * @param string $startDate Start Date of Orders
100
+ * @param string $endDate End Data of Orders
101
+ * @param bool|false $canceled
102
+ * @return $this
103
+ */
104
+ protected function getOrder($startDate, $endDate, $canceled = false) {
105
+ if ($this->debug) {
106
+ if ($canceled) {
107
+ Mage::log('Canceled Orders Started', null, $this->logFile);
108
+ } else {
109
+ Mage::log('Orders Started', null, $this->logFile);
110
+ }
111
+ }
112
+
113
+ $orders = Mage::getModel('sales/order')->getCollection();
114
+
115
+ if ($canceled) {
116
+ $canceledStates = Mage::getStoreConfig('windsorcircle_export_options/messages/canceled_state');
117
+ $canceledStates = explode(',', $canceledStates);
118
+ if (is_array($canceledStates)) {
119
+ $filter = array();
120
+ foreach ($canceledStates as $canceledState) {
121
+ $filter[] = array('eq' => $canceledState);
122
+ }
123
+ $orders->addFieldToFilter('state', $filter);
124
+ } else {
125
+ $orders->addFieldToFilter('state', array(array('eq' => 'closed'), array('eq' => 'canceled')));
126
+ }
127
+ }
128
+
129
+ if (Mage::getSingleton('core/resource')->getTableName('newsletter/subscriber')) {
130
+ $newsletterExists = Mage::getSingleton('core/resource')->getConnection('core_read')
131
+ ->showTableStatus(Mage::getSingleton('core/resource')->getTableName('newsletter/subscriber'));
132
+ } else {
133
+ $newsletterExists = false;
134
+ }
135
+
136
+ $mainTableAlias = 'main_table';
137
+
138
+ $version = explode('.', Mage::getVersion());
139
+ if ( $version[0] == 1 && $version[1] <= 3 )
140
+ {
141
+ $mainTableAlias = 'e';
142
+
143
+ $orders->addFieldToFilter(
144
+ array(
145
+ array('attribute' => 'updated_at', 'datetime' => true, 'from' => $startDate, 'to' => $endDate),
146
+ array('attribute' => 'created_at', 'datetime' => true, 'from' => $startDate, 'to' => $endDate)
147
+ ))
148
+ ->addAttributeToSort('increment_id', 'ASC');
149
+ $orders->getSelect()->joinLeft(array('customer' => 'customer_entity'), 'e.customer_id = customer.entity_id', array('customer_email' => 'customer.email'));
150
+
151
+ if ($newsletterExists) {
152
+ $orders->getSelect()->joinLeft(array('newsletter' => Mage::getSingleton('core/resource')->getTableName('newsletter/subscriber')), 'customer.email = newsletter.subscriber_email', array('newsletter.subscriber_status'));
153
+ }
154
+
155
+ $orders->getSelect()->joinLeft(array('customer_group' => Mage::getSingleton('core/resource')->getTableName('customer/customer_group')), 'customer.group_id = customer_group.customer_group_id', array('customer_group.customer_group_code'));
156
+ } else if ($version[0] == 1 && $version[1] > 3 && $version[1] <= 5 ||
157
+ $this->isEnterprise() && $version[0] == 1 && in_array($version[1], array(9, 10)))
158
+ {
159
+
160
+ $adapter = $orders->getSelect()->getAdapter();
161
+ $startDate = $adapter->quote($startDate);
162
+ $endDate = $adapter->quote($endDate);
163
+
164
+ $orders->getSelect()->where(vsprintf('(main_table.updated_at >= %s AND main_table.updated_at <= %s)' .
165
+ ' ' . Zend_Db_Select::SQL_OR . ' (main_table.created_at >= %s AND main_table.created_at <= %s)',
166
+ array($startDate, $endDate, $startDate, $endDate)));
167
+
168
+ $orders->addAttributeToSort('main_table.increment_id', 'ASC');
169
+
170
+ if ($newsletterExists) {
171
+ $orders->getSelect()->joinLeft(array('newsletter' => Mage::getSingleton('core/resource')->getTableName('newsletter/subscriber')), 'main_table.customer_email = newsletter.subscriber_email',array('newsletter.subscriber_status'));
172
+ }
173
+
174
+ $orders->getSelect()->joinLeft(array('customer' => Mage::getSingleton('core/resource')->getTableName('customer/entity')), 'main_table.customer_id = customer.entity_id', array('customer_email' => 'customer.email'));
175
+ $orders->getSelect()->joinLeft(array('customer_group' => Mage::getSingleton('core/resource')->getTableName('customer/customer_group')), 'customer.group_id = customer_group.customer_group_id', array('customer_group.customer_group_code'));
176
+ } else {
177
+ $conditions = array();
178
+ $condition = array('datetime' => true, 'from' => $startDate, 'to' => $endDate);
179
+ $conditions[] = $orders->getConnection()->prepareSqlCondition('main_table.updated_at', $condition);
180
+ $conditions[] = $orders->getConnection()->prepareSqlCondition('main_table.created_at', $condition);
181
+
182
+ $resultCondition = '(' . join(') ' . Zend_Db_Select::SQL_OR . ' (', $conditions) . ')';
183
+
184
+ $orders->getSelect()->where($resultCondition);
185
+
186
+ $orders->addAttributeToSort('main_table.increment_id', 'ASC');
187
+
188
+ if ($newsletterExists) {
189
+ $orders->getSelect()->joinLeft(array('newsletter' => Mage::getSingleton('core/resource')->getTableName('newsletter/subscriber')), 'main_table.customer_email = newsletter.subscriber_email',array('newsletter.subscriber_status'));
190
+ }
191
+
192
+ $orders->getSelect()->joinLeft(array('customer' => Mage::getSingleton('core/resource')->getTableName('customer/entity')), 'main_table.customer_id = customer.entity_id', array('customer_entity_id' => 'customer.entity_id', 'customer_email' => 'customer.email'));
193
+ $orders->getSelect()->joinLeft(array('customer_group' => Mage::getSingleton('core/resource')->getTableName('customer/customer_group')), 'customer.group_id = customer_group.customer_group_id', array('customer_group.customer_group_code'));
194
+ }
195
+
196
+ // Add Shipment Table
197
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
198
+ $orders->getSelect()->joinLeft(array('shipment' => 'sales_order_entity'), 'e.entity_id = shipment.entity_id', array('last_shipment_date' => 'max(shipment.updated_at)'));
199
+ } else {
200
+ $orders->getSelect()->joinLeft(array('shipment' => Mage::getSingleton('core/resource')->getTableName('sales/shipment')), $mainTableAlias . '.entity_id=shipment.order_id', array('last_shipment_date' => 'max(shipment.updated_at)'));
201
+ }
202
+
203
+ // Limit by store
204
+ $stores = Mage::getStoreConfig('windsorcircle_export_options/messages/store');
205
+ if (!empty($stores)) {
206
+ $stores = explode(',', $stores);
207
+ $orders->addFieldToFilter($mainTableAlias . '.store_id', array('in' => $stores));
208
+ }
209
+
210
+ // Custom Customer attributes to add to order
211
+ $this->addCustomerCustomAttributes($orders);
212
+
213
+ if (!$canceled) {
214
+ $state = Mage::getModel('windsorcircle_export/state');
215
+ $this->addHeaders();
216
+ } else {
217
+ $this->orderIdArray = array();
218
+ }
219
+
220
+ $helper = Mage::helper('windsorcircle_export');
221
+
222
+ $orders->setPageSize($this->pageSize);
223
+ $totalPages = $orders->getLastPageNumber();
224
+ $currentPage = 1;
225
+
226
+ // Add group by to collection
227
+ // if duplicate order id's come back for some reason it will not throw a magento duplicate id error
228
+ //
229
+ // NOTE: This needs to be called after getLastPageNumber since some versions of Magento
230
+ // do not clear the group by clause when getting total record counts
231
+ $orders->getSelect()->group(array($mainTableAlias . '.entity_id'));
232
+
233
+ do {
234
+ if ($this->debug) {
235
+ $log = 'Page: ' . $currentPage;
236
+ $log.= ' - Memory: ' . $helper->getMemoryUsage();
237
+ Mage::log($log, null, $this->logFile);
238
+ }
239
+
240
+ $orders->setCurPage($currentPage);
241
+
242
+ foreach($orders as $orderOriginal){
243
+ $orderData = $orderOriginal->getData();
244
+ $customerGroupCode = $orderData['customer_group_code'];
245
+
246
+ if (isset($orderData['subscriber_status'])) {
247
+ $subscriber_status = $orderData['subscriber_status'];
248
+ } else {
249
+ $subscriber_status = '';
250
+ }
251
+
252
+ $order = Mage::getSingleton('sales/order')->load($orderData['entity_id']);
253
+ $orderData = $order->getData();
254
+ $couponCode = isset($order['coupon_code']) ? $order['coupon_code'] : $order->getCouponCode();
255
+
256
+ if ($canceled && !empty($this->orderData[$orderData['increment_id']]) && is_array($this->oderData[$orderData['increment_id']])) {
257
+ $this->orderData[$orderData['increment_id']]['cancelled'] = 'Y';
258
+ } else {
259
+ if(empty($orderData['shipping_address_id']) && !empty($orderData['billing_address_id'])) {
260
+ $shippingAddress = Mage::getSingleton('sales/order_address')->load($orderData['billing_address_id'])->getData();
261
+ $billingAddress = Mage::getSingleton('sales/order_address')->load($orderData['billing_address_id'])->getData();
262
+ } elseif(!empty($orderData['shipping_address_id']) && !empty($orderData['billing_address_id'])) {
263
+ $shippingAddress = Mage::getSingleton('sales/order_address')->load($orderData['shipping_address_id'])->getData();
264
+ $billingAddress = Mage::getSingleton('sales/order_address')->load($orderData['billing_address_id'])->getData();
265
+ }
266
+
267
+ if(empty($orderData['shipping_address_id']) && empty($orderData['billing_address_id'])) {
268
+ $custBName = '';
269
+ $custName = '';
270
+ $custFName = '';
271
+ $custLName = '';
272
+ $custAddr1 = '';
273
+ $custCity = '';
274
+ $custState = '';
275
+ $custZip = '';
276
+ $custCountry = '';
277
+ $custPhone = '';
278
+
279
+ $shipName = '';
280
+ $shipFName = '';
281
+ $shipLName = '';
282
+ $shipAddr1 = '';
283
+ $shipCity = '';
284
+ $shipState = '';
285
+ $shipZip = '';
286
+ $shipCountry = '';
287
+ } else {
288
+ $custBName = $billingAddress['company'];
289
+ $custName = $billingAddress['firstname'] . ' ' . $billingAddress['lastname'];
290
+ $custFName = $billingAddress['firstname'];
291
+ $custLName = $billingAddress['lastname'];
292
+ $custAddr1 = $helper->formatString($billingAddress['street']);
293
+ $custCity = $helper->formatString($billingAddress['city']);
294
+ $custState = $helper->formatString($billingAddress['region']);
295
+ $custZip = $helper->formatString($billingAddress['postcode']);
296
+ $custCountry = $helper->formatString($billingAddress['country_id']);
297
+ $custPhone = $billingAddress['telephone'];
298
+
299
+ $shipName = $shippingAddress['firstname'] . ' ' . $shippingAddress['lastname'];
300
+ $shipFName = $shippingAddress['firstname'];
301
+ $shipLName = $shippingAddress['lastname'];
302
+ $shipAddr1 = $helper->formatString($shippingAddress['street']);
303
+ $shipCity = $helper->formatString($shippingAddress['city']);
304
+ $shipState = $helper->formatString($shippingAddress['region']);
305
+ $shipZip = $helper->formatString($shippingAddress['postcode']);
306
+ $shipCountry = $helper->formatString($shippingAddress['country_id']);
307
+ }
308
+
309
+ $this->orderIdArray['entity_id'][] = $orderData['entity_id'];
310
+ $this->orderIdArray['order_id'][$orderData['entity_id']] = $orderData['increment_id'];
311
+
312
+ $custEmailOpt = $this->getNewsletterStatus($subscriber_status);
313
+
314
+ // Format for time fields
315
+ // Could be put in a custom class
316
+ $time = '';
317
+ $time = new DateTime($orderData['created_at']);
318
+ $orderDate = $time->format('Ymd');
319
+ $orderTime = $time->format('H:i:s');
320
+
321
+ // Array of Order Data
322
+ $this->orderData[$orderData['increment_id']] = array(
323
+ 'orderId' => $orderData['increment_id'],
324
+ 'orderDate' => $orderDate,
325
+ 'orderTime' => $orderTime,
326
+ 'storeId' => $orderData['store_id'],
327
+ 'custId' => $orderData['customer_id'],
328
+ 'custGroupId' => $orderData['customer_group_id'],
329
+ 'custGroupName' => $customerGroupCode,
330
+ 'custBName' => $custBName,
331
+ 'custName' => $custName,
332
+ 'custFName' => $custFName,
333
+ 'custLName' => $custLName,
334
+ 'custEmail' => $orderData['customer_email'],
335
+ 'custEmailOpt' => $custEmailOpt,
336
+ 'custAddr1' => $custAddr1,
337
+ 'custAddr2' => '',
338
+ 'custCity' => $custCity,
339
+ 'custState' => $custState,
340
+ 'custZip' => $custZip,
341
+ 'custCountry' => $custCountry,
342
+ 'custPhone' => $custPhone,
343
+ 'shipName' => $shipName,
344
+ 'shipFName' => $shipFName,
345
+ 'shipLName' => $shipLName,
346
+ 'shipAddr1' => $shipAddr1,
347
+ 'shipAddr2' => '',
348
+ 'shipCity' => $shipCity,
349
+ 'shipState' => $shipState,
350
+ 'shipZip' => $shipZip,
351
+ 'shipCountry' => $shipCountry,
352
+ 'shipMethod' => $orderData['shipping_description'],
353
+ 'shipCost' => $orderData['base_shipping_amount'],
354
+ 'couponCodes' => $couponCode,
355
+ 'couponDiscount'=> $orderData['discount_amount'],
356
+ 'discountType' => '',
357
+ 'discount' => '',
358
+ 'prodTotal' => ($orderData['base_subtotal'] + $orderData['discount_amount']),
359
+ 'cancelled' => (!empty($state) ? $state->canceled($orderData['state']) : ($canceled ? 'Y' : 'N')),
360
+ 'orderStatus' => $orderData['status'],
361
+ 'shipped' => 'N',
362
+ 'shipment_date' => $orderOriginal['last_shipment_date']
363
+ );
364
+
365
+ $this->shippedArray[$orderData['increment_id']] = $orderData['total_qty_ordered'];
366
+
367
+ $this->appendCustomerCustomFields($orderOriginal);
368
+ }
369
+ }
370
+
371
+ $currentPage++;
372
+
373
+ // Clear orders collection (memory cleanup)
374
+ $orders->clear();
375
+
376
+ } while($currentPage <= $totalPages);
377
+
378
+ return $this;
379
+ }
380
+
381
+ protected function getAscOrder($startDate, $endDate) {
382
+ /** @var Mage_Sales_Model_Resource_Quote_Collection $quotes */
383
+ $quotes = Mage::getModel('sales/quote')->getCollection();
384
+
385
+ $version = explode('.', Mage::getVersion());
386
+ if ( $version[0] == 1 && $version[1] <= 3 )
387
+ {
388
+ $quotes->getSelect()->orWhere('updated_at >= :startDate AND updated_at <= :endDate');
389
+ $quotes->getSelect()->orWhere('created_at <= :startDate AND created_at <= :endDate');
390
+
391
+ $quotes->addBindParam('startDate', $startDate);
392
+ $quotes->addBindParam('endDate', $endDate);
393
+
394
+ $quotes->addFieldToFilter('items_qty', array('gt' => 0))
395
+ ->setOrder('increment_id', 'ASC');
396
+ } else if ($version[0] == 1 && $version[1] > 3 && $version[1] <= 5 ||
397
+ $this->isEnterprise() && $version[0] == 1 && in_array($version[1], array(9, 10)))
398
+ {
399
+
400
+ $adapter = $quotes->getSelect()->getAdapter();
401
+ $startDate = $adapter->quote($startDate);
402
+ $endDate = $adapter->quote($endDate);
403
+
404
+ $quotes->getSelect()->where(vsprintf('(main_table.updated_at >= %s AND main_table.updated_at <= %s)' .
405
+ ' ' . Zend_Db_Select::SQL_OR . ' (main_table.created_at >= %s AND main_table.created_at <= %s)',
406
+ array($startDate, $endDate, $startDate, $endDate)));
407
+
408
+ $quotes->addFieldToFilter('main_table.items_qty', array('gt' => 0))
409
+ ->setOrder('main_table.entity_id', 'ASC');
410
+
411
+ $quotes->getSelect()->joinLeft(array('address_billing' => Mage::getSingleton('core/resource')->getTableName('sales/quote_address')), 'main_table.entity_id = address_billing.quote_id and address_billing.address_type = "billing"', array('billing_id' => 'address_billing.address_id'));
412
+ $quotes->getSelect()->joinLeft(array('address_shipping' => Mage::getSingleton('core/resource')->getTableName('sales/quote_address')), 'main_table.entity_id = address_shipping.quote_id and address_shipping.address_type = "shipping"', array('shipping_id' => 'address_shipping.address_id'));
413
+ } else {
414
+ $conditions = array();
415
+ $condition = array('datetime' => true, 'from' => $startDate, 'to' => $endDate);
416
+ $conditions[] = $quotes->getConnection()->prepareSqlCondition('main_table.updated_at', $condition);
417
+ $conditions[] = $quotes->getConnection()->prepareSqlCondition('main_table.created_at', $condition);
418
+
419
+ $resultCondition = '(' . join(') ' . Zend_Db_Select::SQL_OR . ' (', $conditions) . ')';
420
+
421
+ $quotes->getSelect()->where($resultCondition);
422
+
423
+ $quotes->addFieldToFilter('main_table.items_qty', array('gt' => 0))
424
+ ->setOrder('main_table.entity_id', 'ASC');
425
+ $quotes->getSelect()->joinLeft(array('address_billing' => Mage::getSingleton('core/resource')->getTableName('sales/quote_address')), 'main_table.entity_id = address_billing.quote_id and address_billing.address_type = "billing"', array('billing_id' => 'address_billing.address_id'));
426
+ $quotes->getSelect()->joinLeft(array('address_shipping' => Mage::getSingleton('core/resource')->getTableName('sales/quote_address')), 'main_table.entity_id = address_shipping.quote_id and address_shipping.address_type = "shipping"', array('shipping_id' => 'address_shipping.address_id'));
427
+ }
428
+
429
+ // Limit by store
430
+ $stores = Mage::getStoreConfig('windsorcircle_export_options/messages/store');
431
+ if (!empty($stores)) {
432
+ $stores = explode(',', $stores);
433
+ $quotes->addFieldToFilter('store_id', array('in' => $stores));
434
+ }
435
+
436
+ $this->addAscHeaders();
437
+ $helper = Mage::helper('windsorcircle_export');
438
+
439
+ // Set Page size as 100 at a time
440
+ $quotes->setPageSize(100);
441
+ $totalPages = $quotes->getLastPageNumber();
442
+ $currentPage = 1;
443
+
444
+ do {
445
+ $quotes->setCurPage($currentPage);
446
+
447
+ foreach($quotes->getData() as $quoteData){
448
+
449
+ if ($quoteData['customer_id']) {
450
+ $customer = Mage::getModel('customer/customer')->load($quoteData['customer_id']);
451
+ $billingAddress = Mage::getSingleton('customer/address')
452
+ ->setData(array())
453
+ ->load($customer->getDefaultBilling());
454
+ $shippingAddress = Mage::getSingleton('customer/address')
455
+ ->setData(array())
456
+ ->load($customer->getDefaultShipping());
457
+ } else {
458
+ $billingAddress = Mage::getSingleton('sales/quote_address')->setData(array())->load($quoteData['billing_id']);
459
+ $shippingAddress = Mage::getSingleton('sales/quote_address')->setData(array())->load($quoteData['shipping_id']);
460
+ }
461
+
462
+ if (!$billingAddress->isEmpty()) {
463
+ $custBName = $billingAddress->getCompany();
464
+ $custName = implode(' ', array($billingAddress->getFirstname(), $billingAddress->getLastname()));
465
+ $custFName = $billingAddress->getFirstname();
466
+ $custLName = $billingAddress->getLastname();
467
+ $custAddr1 = $helper->formatString(implode('\n', $billingAddress->getStreet()));
468
+ $custCity = $helper->formatString($billingAddress->getCity());
469
+ $custState = $helper->formatString($billingAddress->getRegion());
470
+ $custZip = $helper->formatString($billingAddress->getPostcode());
471
+ $custCountry = $helper->formatString($billingAddress->getCountryId());
472
+ $custPhone = $billingAddress->getTelephone();
473
+ } else {
474
+ $custBName = '';
475
+ $custName = '';
476
+ $custFName = '';
477
+ $custLName = '';
478
+ $custAddr1 = '';
479
+ $custCity = '';
480
+ $custState = '';
481
+ $custZip = '';
482
+ $custCountry= '';
483
+ $custPhone = '';
484
+ }
485
+
486
+ if (!$shippingAddress->isEmpty()) {
487
+ $shipName = implode(' ', array($shippingAddress->getFirstname(), $shippingAddress->getLastname()));
488
+ $shipFName = $shippingAddress->getFirstname();
489
+ $shipLName = $shippingAddress->getLastname();
490
+ $shipAddr1 = $helper->formatString(implode('\n', $shippingAddress->getStreet()));
491
+ $shipCity = $helper->formatString($shippingAddress->getCity());
492
+ $shipState = $helper->formatString($shippingAddress->getRegion());
493
+ $shipZip = $helper->formatString($shippingAddress->getPostcode());
494
+ $shipCountry = $helper->formatString($shippingAddress->getCountryId());
495
+ } else {
496
+ $shipName = '';
497
+ $shipFName = '';
498
+ $shipLName = '';
499
+ $shipAddr1 = '';
500
+ $shipCity = '';
501
+ $shipState = '';
502
+ $shipZip = '';
503
+ $shipCountry= '';
504
+ }
505
+
506
+ $this->quoteIdArray['entity_id'][] = $quoteData['entity_id'];
507
+
508
+ // Format for time fields
509
+ $createdTime = new DateTime($quoteData['created_at']);
510
+ $createdTime = $createdTime->format('Ymd H:i:s');
511
+ $updatedTime = new DateTime($quoteData['updated_at']);
512
+ $updatedTime = $updatedTime->format('Ymd H:i:s');
513
+ $convertedAt = '';
514
+
515
+ // Current Store Cart Url
516
+ Mage::app()->setCurrentStore($quoteData['store_id']);
517
+ $cartUrl = Mage::helper('checkout/url')->getCheckoutUrl();
518
+
519
+ // Array of Order Data
520
+ $this->quoteAscData[$quoteData['entity_id']] = array(
521
+ 'orderId' => $quoteData['entity_id'],
522
+ 'reserved_order_id' => $quoteData['reserved_order_id'],
523
+ 'createdtimestamp' => $createdTime,
524
+ 'updatedtimestamp' => $updatedTime,
525
+ 'convertedtimestamp' => $convertedAt,
526
+ 'is_active' => $quoteData['is_active'],
527
+ 'storeId' => $quoteData['store_id'],
528
+ 'cartUrl' => $cartUrl,
529
+ 'custId' => $quoteData['customer_id'],
530
+ 'custBName' => $custBName,
531
+ 'custName' => $custName,
532
+ 'custFName' => $custFName,
533
+ 'custLName' => $custLName,
534
+ 'custEmail' => $quoteData['customer_email'],
535
+ 'custAddr1' => $custAddr1,
536
+ 'custAddr2' => '',
537
+ 'custCity' => $custCity,
538
+ 'custState' => $custState,
539
+ 'custZip' => $custZip,
540
+ 'custCountry' => $custCountry,
541
+ 'custPhone' => $custPhone,
542
+ 'shipName' => $shipName,
543
+ 'shipFName' => $shipFName,
544
+ 'shipLName' => $shipLName,
545
+ 'shipAddr1' => $shipAddr1,
546
+ 'shipAddr2' => '',
547
+ 'shipCity' => $shipCity,
548
+ 'shipState' => $shipState,
549
+ 'shipZip' => $shipZip,
550
+ 'shipCountry' => $shipCountry,
551
+ 'shipMethod' => isset($quoteData['shipping_description']) ? $quoteData['shipping_description']:'',
552
+ 'shipCost' => isset($quoteData['base_shipping_amount']) ? $quoteData['base_shipping_amount']:'',
553
+ 'couponCodes' => $quoteData['coupon_code'],
554
+ 'couponDiscount' => $quoteData['base_subtotal'] - $quoteData['base_subtotal_with_discount'],
555
+ 'discountType' => '',
556
+ 'discount' => '',
557
+ 'prodTotal' => $quoteData['base_subtotal_with_discount'],
558
+ );
559
+ }
560
+
561
+ $currentPage++;
562
+
563
+ // Clear orders collection (memory cleanup)
564
+ $quotes->clear();
565
+ $quotes->resetData();
566
+
567
+ } while($currentPage <= $totalPages);
568
+
569
+ // Set Store back to Admin
570
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
571
+ return $this;
572
+ }
573
+
574
+ /**
575
+ * Adds headers to array
576
+ */
577
+ protected function addHeaders(){
578
+ $this->orderData[0] = array(
579
+ 'orderId' => 'OrderId',
580
+ 'orderDate' => 'OrderDate',
581
+ 'orderTime' => 'OrderTime',
582
+ 'storeId' => 'StoreId',
583
+ 'custId' => 'CustId',
584
+ 'custGroupId' => 'CustGroupId',
585
+ 'custGroupName' => 'CustGroupName',
586
+ 'custBName' => 'CustBName',
587
+ 'custName' => 'CustName',
588
+ 'custFName' => 'CustFName',
589
+ 'custLName' => 'CustLName',
590
+ 'custEmail' => 'CustEmail',
591
+ 'custEmailOpt' => 'CustEmailOpt',
592
+ 'custAddr1' => 'CustAddr1',
593
+ 'custAddr2' => 'CustAddr2',
594
+ 'custCity' => 'CustCity',
595
+ 'custState' => 'CustState',
596
+ 'custZip' => 'CustZip',
597
+ 'custCountry' => 'CustCountry',
598
+ 'custPhone' => 'CustPhone',
599
+ 'shipName' => 'ShipName',
600
+ 'shipFName' => 'ShipFName',
601
+ 'shipLName' => 'ShipLName',
602
+ 'shipAddr1' => 'ShipAddr1',
603
+ 'shipAddr2' => 'ShipAddr2',
604
+ 'shipCity' => 'ShipCity',
605
+ 'shipState' => 'ShipState',
606
+ 'shipZip' => 'ShipZip',
607
+ 'shipCountry' => 'ShipCountry',
608
+ 'shipMethod' => 'ShipMethod',
609
+ 'shipCost' => 'ShipCost',
610
+ 'couponCodes' => 'CouponCodes',
611
+ 'couponDiscount'=> 'CouponDiscount',
612
+ 'discountType' => 'DiscountType',
613
+ 'discount' => 'Discount',
614
+ 'prodTotal' => 'ProdTotal',
615
+ 'cancelled' => 'Cancelled',
616
+ 'orderStatus' => 'OrderStatus',
617
+ 'shipped' => 'Shipped',
618
+ 'shipment_date' => 'ShipmentDate'
619
+ );
620
+
621
+ $customAttributes = Mage::helper('windsorcircle_export')->getCustomAttributes('customer');
622
+ foreach ($customAttributes as $customAttribute) {
623
+ $this->orderData[0]['custom_customer_' . $customAttribute] = 'custom_customer_' . $customAttribute;
624
+ }
625
+
626
+ $customAttributes = Mage::helper('windsorcircle_export')->getCustomAttributes('customer_address');
627
+ foreach ($customAttributes as $customAttribute) {
628
+ $this->orderData[0]['custom_customer_address_' . $customAttribute] = 'custom_customer_address_' . $customAttribute;
629
+ }
630
+
631
+ $orderFields = Mage::helper('windsorcircle_export')->getCustomAttributes('order');
632
+ foreach ($orderFields as $orderField) {
633
+ $this->orderData[0]['custom_order_' . $orderField] = 'custom_order_' . $orderField;
634
+ }
635
+
636
+ $this->orderDetailsData[0][0] = array(
637
+ 'orderId' => 'OrderId',
638
+ 'storeId' => 'StoreId',
639
+ 'prodId' => 'ProdId',
640
+ 'qtyOrdered' => 'QtyOrdered',
641
+ 'qtyReturned' => 'QtyReturned',
642
+ 'masterId' => 'PSKU',
643
+ 'simpleId' => 'VSKU',
644
+ 'price' => 'Price',
645
+ 'productOptions'=> 'ProductOptions'
646
+ );
647
+
648
+ $buyRequests = Mage::helper('windsorcircle_export')->getCustomAttributes('order_item_buy_request');
649
+ foreach ($buyRequests as $buyRequest) {
650
+ $this->orderDetailsData[0][0]['custom_order_item_buy_request_' . $buyRequest] = 'custom_order_item_buy_request_' . $buyRequest;
651
+ }
652
+ }
653
+
654
+ protected function addAscHeaders(){
655
+ $this->quoteAscData[0] = array(
656
+ 'orderId' => 'CartID',
657
+ 'reserved_order_id' => 'ReservedOrderID',
658
+ 'createdtimestamp' => 'CreatedTimestamp',
659
+ 'updatedtimestamp' => 'UpdatedTimestamp',
660
+ 'convertedtimestamp' => 'ConvertedTimestamp',
661
+ 'is_active' => 'IsActive',
662
+ 'storeId' => 'StoreID',
663
+ 'cartUrl' => 'CartURL',
664
+ 'custId' => 'CustID',
665
+ 'custBName' => 'CustBName',
666
+ 'custName' => 'CustName',
667
+ 'custFName' => 'CustFName',
668
+ 'custLName' => 'CustLName',
669
+ 'custEmail' => 'CustEmail',
670
+ 'custAddr1' => 'CustAddr1',
671
+ 'custAddr2' => 'CustAddr2',
672
+ 'custCity' => 'CustCity',
673
+ 'custState' => 'CustState',
674
+ 'custZip' => 'CustZip',
675
+ 'custCountry' => 'CustCountry',
676
+ 'custPhone' => 'CustPhone',
677
+ 'shipName' => 'ShipName',
678
+ 'shipFName' => 'ShipFName',
679
+ 'shipLName' => 'ShipLName',
680
+ 'shipAddr1' => 'ShipAddr1',
681
+ 'shipAddr2' => 'ShipAddr2',
682
+ 'shipCity' => 'ShipCity',
683
+ 'shipState' => 'ShipState',
684
+ 'shipZip' => 'ShipZip',
685
+ 'shipCountry' => 'ShipCountry',
686
+ 'shipMethod' => 'ShipMethod',
687
+ 'shipCost' => 'ShipCost',
688
+ 'couponCodes' => 'CouponCodes',
689
+ 'couponDiscount' => 'CouponDiscount',
690
+ 'discountType' => 'DiscountType',
691
+ 'discount' => 'Discount',
692
+ 'prodTotal' => 'ProdTotal',
693
+ );
694
+
695
+ $this->quoteAscDetailsData[0][0] = array(
696
+ 'cartId' => 'CartID',
697
+ 'storeId' => 'StoreID',
698
+ 'simpleId' => 'VSKU',
699
+ 'masterId' => 'PSKU',
700
+ 'prodId' => 'ProdID',
701
+ 'price' => 'Price',
702
+ 'quantity' => 'Quantity',
703
+ 'productOptions'=> 'ProductOptions'
704
+ );
705
+
706
+ $buyRequests = Mage::helper('windsorcircle_export')->getCustomAttributes('order_item_buy_request');
707
+ foreach ($buyRequests as $buyRequest) {
708
+ $this->quoteAscDetailsData[0][0]['custom_quote_item_buy_request_' . $buyRequest] = 'custom_quote_item_buy_request_' . $buyRequest;
709
+ }
710
+ }
711
+
712
+ protected function getNewsletterStatus($status){
713
+ if (empty($status) || $status == 3) {
714
+ return '3';
715
+ } elseif (!empty($status) && $status == 1) {
716
+ return '1';
717
+ } else {
718
+ return '';
719
+ }
720
+ }
721
+
722
+ protected function getOrderItems(){
723
+ if ($this->debug) {
724
+ Mage::log('Order Details Started', null, $this->logFile);
725
+ }
726
+
727
+ if(!empty($this->orderIdArray['entity_id'])){
728
+ $version = explode('.', Mage::getVersion());
729
+ $orderItems = Mage::getModel('sales/order_item')->getCollection()
730
+ ->addFieldToFilter('order_id', array('in' => $this->orderIdArray['entity_id']));
731
+
732
+ // If Magento version 1.3 then you must use addOrder instead of addAttributeToSort otherwise it breaks
733
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
734
+ $orderItems->addOrder('product_type', 'ASC');
735
+ } else {
736
+ $orderItems->addAttributeToSort('product_type', 'ASC');
737
+ }
738
+
739
+ $orderItems->setPageSize($this->pageSize);
740
+ $totalPages = $orderItems->getLastPageNumber();
741
+ $currentPage = 1;
742
+
743
+ // If version 1.4 or above then we need to add group by clause so we do not get duplicate ids
744
+ // NOTE: This needs to be called after getLastPageNumber since some versions of Magento do not clear
745
+ // the group by clause
746
+ if ( $version[0] == 1 && $version[1] > 3 ) {
747
+ $orderItems->getSelect()->group('main_table.item_id');
748
+ }
749
+
750
+ // Items array
751
+ $items = array();
752
+ $itemCheck = array();
753
+
754
+ $helper = Mage::helper('windsorcircle_export');
755
+
756
+ do {
757
+ if ($this->debug) {
758
+ $log = 'Page: ' . $currentPage;
759
+ $log.= ' - Memory: ' . $helper->getMemoryUsage();
760
+ Mage::log($log, null, $this->logFile);
761
+ }
762
+
763
+ $orderItems->setCurPage($currentPage);
764
+
765
+ $categorySkus = array();
766
+
767
+ foreach($orderItems->getData() as $item) {
768
+ $itemCheck[$item['item_id']] = array('type' => $item['product_type'], 'sku' => $item['sku']);
769
+
770
+ $items[$item['item_id']] = array(
771
+ 'order_id' => $item['order_id'],
772
+ 'store_id' => $item['store_id'],
773
+ 'item_id' => $item['item_id'],
774
+ 'product_id' => $item['product_id'],
775
+ 'sku' => $item['sku'],
776
+ 'product_type' => $item['product_type'],
777
+ 'parent_item_id' => $item['parent_item_id'],
778
+ 'qty_ordered' => $item['qty_ordered'],
779
+ 'qty_refunded' => $item['qty_refunded'],
780
+ 'qty_shipped' => $item['qty_shipped'],
781
+ 'base_price' => $item['base_price'],
782
+ 'product_options' => $item['product_options']
783
+ );
784
+
785
+ $this->orderItems[] = $item['product_id'];
786
+
787
+ // If we are on version 1.3 or below then we need to set the shippedArray amount to qty_ordered
788
+ // since the order does not fill in the total_qty_ordered column
789
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
790
+ if ($item['parent_item_id'] === null) {
791
+ $realOrderId = $this->orderIdArray['order_id'][$item['order_id']];
792
+ $this->shippedArray[$realOrderId] = $this->shippedArray[$realOrderId] + $item['qty_ordered'];
793
+ }
794
+ }
795
+
796
+ if (empty($item['sku'])) {
797
+ $categorySkus[] = $item['item_id'];
798
+ }
799
+ if (!empty($item['parent_item_id'])) {
800
+ $categorySkus[] = $item['parent_item_id'];
801
+ }
802
+ }
803
+
804
+ // This will only populate if the sku from the sales_flat_order_item table is empty
805
+ if (!empty($categorySkus)) {
806
+ $categorySkuCollection = Mage::getModel('sales/order_item')->getCollection()
807
+ ->addFieldToFilter('item_id', array('in' => $categorySkus));
808
+
809
+ $categorySkuCollection->getSelect()
810
+ ->joinLeft(
811
+ array('catalog/product' => Mage::getSingleton('core/resource')->getTableName('catalog/product')),
812
+ 'main_table.product_id=`catalog/product`.entity_id',
813
+ array('sku' => 'catalog/product.sku')
814
+ );
815
+
816
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
817
+ $categorySkuCollection->addOrder('product_type', 'ASC');
818
+ } else {
819
+ $categorySkuCollection->addAttributeToSort('product_type', 'ASC');
820
+ $categorySkuCollection->getSelect()->group('main_table.item_id');
821
+ }
822
+
823
+ foreach ($categorySkuCollection as $categorySku) {
824
+ $items[$categorySku['item_id']]['sku'] = $categorySku['sku'];
825
+ }
826
+ }
827
+
828
+ $currentPage++;
829
+
830
+ $orderItems->clear();
831
+ $orderItems->resetData();
832
+
833
+ } while($currentPage <= $totalPages);
834
+
835
+ foreach($items as $item){
836
+ $parentType = false;
837
+
838
+ $realOrderId = $this->orderIdArray['order_id'][$item['order_id']];
839
+
840
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
841
+ $order = Mage::getSingleton('sales/order')->load($item['order_id']);
842
+ $storeId = $order->getStoreId();
843
+ } else {
844
+ $storeId = $item['store_id'];
845
+ }
846
+
847
+ if((isset($item['product_type']) && $item['product_type'] == 'configurable') || $item['product_type'] == '') {
848
+ $this->orderDetailsData[$realOrderId][$item['item_id']] = array(
849
+ 'orderId' => $realOrderId,
850
+ 'storeId' => $storeId,
851
+ 'prodId' => $item['product_id'],
852
+ 'qtyOrdered' => $item['qty_ordered'],
853
+ 'qtyReturned' => $item['qty_refunded'],
854
+ 'masterId' => '',
855
+ 'simpleId' => $item['sku'],
856
+ 'price' => number_format($item['base_price'], 2,'.',''));
857
+ } elseif((isset($item['parent_item_id']) && $item['parent_item_id'] != null) &&
858
+ (isset($itemCheck[$item['parent_item_id']]['type']) && $itemCheck[$item['parent_item_id']]['type'] == 'bundle'))
859
+ {
860
+ $parentType = 'bundle';
861
+ $this->orderDetailsData[$realOrderId][$item['item_id']]['orderId'] = $realOrderId;
862
+ $this->orderDetailsData[$realOrderId][$item['item_id']]['storeId'] = $storeId;
863
+ $this->orderDetailsData[$realOrderId][$item['item_id']]['prodId'] = $item['product_id'];
864
+ $this->orderDetailsData[$realOrderId][$item['item_id']]['qtyOrdered'] = $item['qty_ordered'];
865
+ $this->orderDetailsData[$realOrderId][$item['item_id']]['qtyReturned'] = $item['qty_refunded'];
866
+ $this->orderDetailsData[$realOrderId][$item['item_id']]['masterId'] = $this->orderDetailsData[$realOrderId][$item['parent_item_id']]['simpleId'];
867
+ $this->orderDetailsData[$realOrderId][$item['item_id']]['simpleId'] = $item['sku'];
868
+ $this->orderDetailsData[$realOrderId][$item['item_id']]['price'] = '0.00';
869
+ } elseif((isset($item['parent_item_id']) && $item['parent_item_id'] != null) &&
870
+ (isset($itemCheck[$item['parent_item_id']]['type']) && $itemCheck[$item['parent_item_id']]['type'] != 'simple'))
871
+ {
872
+ $this->orderDetailsData[$realOrderId][$item['parent_item_id']]['orderId'] = $realOrderId;
873
+ $this->orderDetailsData[$realOrderId][$item['parent_item_id']]['storeId'] = $storeId;
874
+ $this->orderDetailsData[$realOrderId][$item['parent_item_id']]['prodId'] = $item['product_id'];
875
+ $this->orderDetailsData[$realOrderId][$item['parent_item_id']]['qtyOrdered'] = $item['qty_ordered'];
876
+ $this->orderDetailsData[$realOrderId][$item['parent_item_id']]['qtyReturned'] = $item['qty_refunded'];
877
+ $this->orderDetailsData[$realOrderId][$item['parent_item_id']]['masterId'] = $this->orderDetailsData[$realOrderId][$item['parent_item_id']]['simpleId'];
878
+ $this->orderDetailsData[$realOrderId][$item['parent_item_id']]['simpleId'] = $item['sku'];
879
+
880
+ // Force base_price to be a float because a string '0.0000' is not empty from php
881
+ $item['base_price'] = (float) $item['base_price'];
882
+ if(!empty($item['base_price'])) {
883
+ $this->orderDetailsData[$realOrderId][$item['parent_item_id']]['price'] = number_format($item['base_price'], 2,'.','');
884
+ }
885
+ } else {
886
+ $this->orderDetailsData[$realOrderId][$item['item_id']] = array(
887
+ 'orderId' => $realOrderId,
888
+ 'storeId' => $storeId,
889
+ 'prodId' => $item['product_id'],
890
+ 'qtyOrdered' => $item['qty_ordered'],
891
+ 'qtyReturned' => $item['qty_refunded'],
892
+ 'masterId' => '',
893
+ 'simpleId' => $item['sku'],
894
+ 'price' => number_format($item['base_price'], 2,'.',''));
895
+ }
896
+
897
+ if ($item['parent_item_id'] === null) {
898
+ $this->shippedArray[$realOrderId] = $this->shippedArray[$realOrderId] - $item['qty_shipped'];
899
+ if ($this->shippedArray[$realOrderId] <= 0) {
900
+ if (isset($this->orderData[$realOrderId]['shipped'])) {
901
+ $this->orderData[$realOrderId]['shipped'] = 'Y';
902
+ }
903
+ }
904
+ }
905
+
906
+ $this->appendProductOptions($item, $parentType, false);
907
+ }
908
+ }
909
+ return $this;
910
+ }
911
+
912
+ protected function getAscOrderItems() {
913
+ if(!empty($this->quoteIdArray['entity_id'])){
914
+ $version = explode('.', Mage::getVersion());
915
+
916
+ $quoteItems = Mage::getModel('sales/quote_item')->getCollection()
917
+ ->join('catalog/product',
918
+ 'main_table.product_id=`catalog/product`.entity_id',
919
+ array('sku' => 'IF(ISNULL(`catalog/product`.sku), main_table.sku, `catalog/product`.sku)'))
920
+ ->addFieldToFilter('quote_id', array('in' => $this->quoteIdArray['entity_id']))
921
+ ->addOrder('product_type', 'ASC');
922
+
923
+ $quoteItems->getSelect()->joinLeft(array('item_option' => Mage::getSingleton('core/resource')->getTableName('sales/quote_item_option')), "item_option.item_id=main_table.item_id AND code='info_buyRequest'", array('product_options' => 'value'));
924
+
925
+ $quoteItems->setPageSize(100);
926
+ $totalPages = $quoteItems->getLastPageNumber();
927
+ $currentPage = 1;
928
+
929
+ // Items array
930
+ $items = array();
931
+ $itemCheck = array();
932
+
933
+ do {
934
+ $quoteItems->setCurPage($currentPage);
935
+
936
+ foreach($quoteItems->getData() as $item) {
937
+ $itemCheck[$item['item_id']] = array('type' => $item['product_type'], 'sku' => $item['sku']);
938
+
939
+ $items[] = array(
940
+ 'quote_id' => $item['quote_id'],
941
+ 'store_id' => $item['store_id'],
942
+ 'item_id' => $item['item_id'],
943
+ 'sku' => $item['sku'],
944
+ 'product_id' => $item['product_id'],
945
+ 'product_type' => $item['product_type'],
946
+ 'parent_item_id' => $item['parent_item_id'],
947
+ 'qty' => $item['qty'],
948
+ 'base_price' => $item['base_price'],
949
+ 'product_options' => $item['product_options']
950
+ );
951
+
952
+ $this->orderItems[] = $item['product_id'];
953
+ }
954
+
955
+ $currentPage++;
956
+
957
+ $quoteItems->clear();
958
+ $quoteItems->resetData();
959
+
960
+ } while($currentPage <= $totalPages);
961
+
962
+ foreach($items as $item){
963
+ $parentType = false;
964
+ if ( $version[0] == 1 && $version[1] <= 3 ) {
965
+ $quote = Mage::getSingleton('sales/quote')->load($item['quote_id']);
966
+ $storeId = $quote->getStoreId();
967
+ } else {
968
+ $storeId = $item['store_id'];
969
+ }
970
+
971
+ if($item['product_type'] == 'configurable' || $item['product_type'] == '') {
972
+ $this->quoteAscDetailsData[$item['quote_id']][$item['item_id']] = array(
973
+ 'cartId'=> $item['quote_id'],
974
+ 'storeId' => $storeId,
975
+ 'simpleId' => $item['sku'],
976
+ 'masterId' => '',
977
+ 'prodId' => $item['product_id'],
978
+ 'price' => number_format($item['base_price'], 2,'.',''),
979
+ 'quantity' => $item['qty']);
980
+ } elseif($item['parent_item_id'] != null
981
+ && $itemCheck[$item['parent_item_id']]['type'] == 'bundle'
982
+ ) {
983
+ $parentType = 'bundle';
984
+ $this->quoteAscDetailsData[$item['quote_id']][$item['item_id']]['cartId'] = $item['quote_id'];
985
+ $this->quoteAscDetailsData[$item['quote_id']][$item['item_id']]['storeId'] = $storeId;
986
+ $this->quoteAscDetailsData[$item['quote_id']][$item['item_id']]['simpleId'] = $item['sku'];
987
+ $this->quoteAscDetailsData[$item['quote_id']][$item['item_id']]['masterId'] = $this->quoteAscDetailsData[$item['quote_id']][$item['parent_item_id']]['simpleId'];
988
+ $this->quoteAscDetailsData[$item['quote_id']][$item['item_id']]['prodId'] = $item['product_id'];
989
+ $this->quoteAscDetailsData[$item['quote_id']][$item['item_id']]['price'] = '0.00';
990
+ $this->quoteAscDetailsData[$item['quote_id']][$item['item_id']]['quantity'] = $item['qty'];
991
+ } elseif($item['parent_item_id'] != null
992
+ && $itemCheck[$item['parent_item_id']]['type'] != 'simple'
993
+ ) {
994
+ $this->quoteAscDetailsData[$item['quote_id']][$item['parent_item_id']]['cartId'] = $item['quote_id'];
995
+ $this->quoteAscDetailsData[$item['quote_id']][$item['parent_item_id']]['storeId'] = $storeId;
996
+ $this->quoteAscDetailsData[$item['quote_id']][$item['parent_item_id']]['simpleId'] = $item['sku'];
997
+ $this->quoteAscDetailsData[$item['quote_id']][$item['parent_item_id']]['masterId'] = $this->quoteAscDetailsData[$item['quote_id']][$item['parent_item_id']]['simpleId'];
998
+ $this->quoteAscDetailsData[$item['quote_id']][$item['parent_item_id']]['prodId'] = $item['product_id'];
999
+
1000
+ // Force base_price to be a float because a string '0.0000' is not empty from php
1001
+ $item['base_price'] = (float) $item['base_price'];
1002
+ if(!empty($item['base_price'])) {
1003
+ $this->quoteAscDetailsData[$item['quote_id']][$item['parent_item_id']]['price'] = number_format($item['base_price'], 2,'.','');
1004
+ }
1005
+
1006
+ $this->quoteAscDetailsData[$item['quote_id']][$item['parent_item_id']]['quantity'] = $item['qty'];
1007
+ } else {
1008
+ $this->quoteAscDetailsData[$item['quote_id']][$item['item_id']] = array(
1009
+ 'cartId'=> $item['quote_id'],
1010
+ 'storeId' => $storeId,
1011
+ 'simpleId' => $item['sku'],
1012
+ 'masterId' => '',
1013
+ 'prodId' => $item['product_id'],
1014
+ 'price' => number_format($item['base_price'], 2,'.',''),
1015
+ 'quantity' => $item['qty']);
1016
+ }
1017
+
1018
+ $this->appendProductOptions($item, $parentType, true);
1019
+ }
1020
+ }
1021
+ }
1022
+
1023
+ /**
1024
+ * Check if Enterprise version
1025
+ *
1026
+ * @return bool
1027
+ */
1028
+ public function isEnterprise()
1029
+ {
1030
+ if (Mage::getConfig()->getModuleConfig('Enterprise_Enterprise') && Mage::getConfig()->getModuleConfig('Enterprise_AdminGws') && Mage::getConfig()->getModuleConfig('Enterprise_Checkout') && Mage::getConfig()->getModuleConfig('Enterprise_Customer')) {
1031
+ return true;
1032
+ }
1033
+ return false;
1034
+ }
1035
+
1036
+ /**
1037
+ * Add Customer Custom Attributes to Collection
1038
+ *
1039
+ * @param $collection
1040
+ */
1041
+ protected function addCustomerCustomAttributes(&$collection)
1042
+ {
1043
+ foreach (array('customer', 'customer_address') as $type) {
1044
+ $attributes = Mage::getStoreConfig('windsorcircle_export_options/messages/custom_' . $type . '_attributes');
1045
+ $attributes = Mage::helper('windsorcircle_export')->makeArrayFieldValue($attributes);
1046
+ $model = $type === 'customer' ? 'customer/customer' : 'customer/address';
1047
+ $customerType = Mage::getResourceSingleton($model)->getType();
1048
+
1049
+ if ($type === 'customer') {
1050
+ $billingAttribute = Mage::getSingleton('eav/config')->getCollectionAttribute($customerType, 'default_billing');
1051
+ $billingTable = $billingAttribute->getBackendTable();
1052
+ $billingId = $billingAttribute->getId();
1053
+ $billingAlias = $type . '_billing';
1054
+
1055
+ $collection->getSelect()->joinLeft(array($billingAlias => $billingTable), $type . '.entity_id = ' . $billingAlias . '.entity_id AND ' . $billingAlias . '.attribute_id = \'' . $billingId . '\'', array(/*$billingAlias => $billingAlias . '.value'*/));
1056
+
1057
+ $entityTable = Mage::getSingleton('core/resource')->getTableName('customer/entity');
1058
+ $describe = Mage::getModel('core/resource')->getConnection('core_read')->describeTable($entityTable);
1059
+ } else {
1060
+ $collection->getSelect()->joinLeft(array($type => Mage::getSingleton('core/resource')->getTableName('customer/address_entity')), $type . '.parent_id = customer.entity_id AND ' . $type . '.entity_id = customer_billing.value', array());
1061
+
1062
+ $entityTable = Mage::getSingleton('core/resource')->getTableName('customer/address_entity');
1063
+ $describe = Mage::getModel('core/resource')->getConnection('core_read')->describeTable($entityTable);
1064
+ }
1065
+
1066
+ foreach ($attributes as $attribute) {
1067
+ $attributeCode = $attribute['attribute_code'];
1068
+ $tableAlias = 'custom_' . $type . '_' . $attributeCode;
1069
+
1070
+ if (isset($describe[$attributeCode])) {
1071
+ $collection->getSelect()->joinLeft(array($tableAlias => $entityTable), $type . '.entity_id = ' . $tableAlias . '.entity_id', array($tableAlias => $tableAlias . '.' . $attributeCode));
1072
+ } else {
1073
+ $eavAttribute = Mage::getSingleton('eav/config')->getCollectionAttribute($customerType, $attributeCode);
1074
+ $backendTable = $eavAttribute->getBackendTable();
1075
+ $attributeId = $eavAttribute->getId();
1076
+
1077
+ $collection->getSelect()->joinLeft(array($tableAlias => $backendTable), $type . '.entity_id = ' . $tableAlias . '.entity_id AND ' . $tableAlias . '.attribute_id = \'' . $attributeId . '\'', array($tableAlias => $tableAlias . '.value'));
1078
+ }
1079
+ }
1080
+ }
1081
+ }
1082
+
1083
+ /**
1084
+ * Append Customer Custom Fields to passed in order
1085
+ */
1086
+ protected function appendCustomerCustomFields($order)
1087
+ {
1088
+ $helper = Mage::helper('windsorcircle_export');
1089
+ $customCustomerAttributes = Mage::helper('windsorcircle_export')->getCustomAttributes('customer');
1090
+ $customCustomerAddressAttributes = Mage::helper('windsorcircle_export')->getCustomAttributes('customer_address');
1091
+ $customOrderFields = Mage::helper('windsorcircle_export')->getCustomAttributes('order');
1092
+
1093
+ foreach ($customCustomerAttributes as $customAttribute) {
1094
+ if ($order->getData('custom_customer_' . $customAttribute) === null) {
1095
+ $this->orderData[$order['increment_id']]['custom_customer_' . $customAttribute] = '';
1096
+ continue;
1097
+ }
1098
+
1099
+ $frontend = Mage::getResourceSingleton('customer/customer')->getAttribute($customAttribute)->getFrontend();
1100
+ $frontend->getAttribute()->setAttributeCode('custom_customer_' . $customAttribute);
1101
+ $data = $frontend->getValue($order);
1102
+ $this->orderData[$order['increment_id']]['custom_customer_' . $customAttribute] = $helper->formatString($data);
1103
+ }
1104
+
1105
+ foreach ($customCustomerAddressAttributes as $customAddressAttribute) {
1106
+ if ($order->getData('custom_customer_address_' . $customAddressAttribute) === null) {
1107
+ $this->orderData[$order['increment_id']]['custom_customer_address_' . $customAddressAttribute] = '';
1108
+ continue;
1109
+ }
1110
+
1111
+ $frontend = Mage::getResourceSingleton('customer/address')->getAttribute($customAddressAttribute)->getFrontend();
1112
+ $frontend->getAttribute()->setAttributeCode('custom_customer_address_' . $customAddressAttribute);
1113
+ $data = $frontend->getValue($order);
1114
+ $this->orderData[$order['increment_id']]['custom_customer_address_' . $customAddressAttribute] = $helper->formatString($data);
1115
+ }
1116
+
1117
+ foreach ($customOrderFields as $customOrderField) {
1118
+ $data = $order->getData($customOrderField);
1119
+ $this->orderData[$order['increment_id']]['custom_order_' . $customOrderField] = $helper->formatString($data);
1120
+ }
1121
+ }
1122
+
1123
+ /**
1124
+ * Append Product Options
1125
+ *
1126
+ * @param $item
1127
+ * @param bool|false $parentType
1128
+ * @param bool|false $asc
1129
+ */
1130
+ protected function appendProductOptions($item, $parentType = false, $asc = false)
1131
+ {
1132
+ $columnName = 'custom_order_item_buy_request_';
1133
+ if ($asc) { $columnName = 'custom_quote_item_buy_request_'; }
1134
+ $buyRequest = '';
1135
+
1136
+ if (!$asc) {
1137
+ $realOrderId = $this->orderIdArray['order_id'][$item['order_id']];
1138
+ }
1139
+
1140
+ // If parent type is bundle then use item_id instead of parent_item_id
1141
+ $id = (isset($item['parent_item_id'])
1142
+ && !empty($item['parent_item_id'])
1143
+ && $parentType != 'bundle') ? $item['parent_item_id'] : $item['item_id'];
1144
+
1145
+ if (!empty($item['product_options'])) {
1146
+ $productOptions = unserialize($item['product_options']);
1147
+
1148
+ if (!$asc) {
1149
+ if ($productOptions !== false && isset($productOptions['info_buyRequest'])) {
1150
+ $buyRequest = $productOptions['info_buyRequest'];
1151
+ }
1152
+ $this->orderDetailsData[$realOrderId][$id]['productOptions'] = $item['product_options'];
1153
+ } else {
1154
+ if ($productOptions !== false) {
1155
+ $buyRequest = $productOptions;
1156
+ }
1157
+ $this->quoteAscDetailsData[$item['quote_id']][$id]['productOptions'] = $item['product_options'];
1158
+ }
1159
+ } else {
1160
+ if (!$asc) {
1161
+ $this->orderDetailsData[$realOrderId][$id]['productOptions'] = '';
1162
+ } else {
1163
+ $this->quoteAscDetailsData[$item['quote_id']][$id]['productOptions'] = '';
1164
+ }
1165
+ }
1166
+
1167
+ $helper = Mage::helper('windsorcircle_export');
1168
+ $customProductOptions = Mage::helper('windsorcircle_export')->getCustomAttributes('order_item_buy_request');
1169
+
1170
+ foreach ($customProductOptions as $customProductOption) {
1171
+ if (isset($buyRequest[$customProductOption]) && !empty($buyRequest[$customProductOption])) {
1172
+ if (is_array($buyRequest[$customProductOption])) {
1173
+ $productOption = implode(',', $buyRequest[$customProductOption]);
1174
+ } else {
1175
+ $productOption = $buyRequest[$customProductOption];
1176
+ }
1177
+
1178
+ if ($asc) {
1179
+ $this->quoteAscDetailsData[$item['quote_id']][$id][$columnName . $customProductOption] = $helper->formatString($productOption);
1180
+ } else {
1181
+ $this->orderDetailsData[$realOrderId][$id][$columnName . $customProductOption] = $helper->formatString($productOption);
1182
+ }
1183
+ } else {
1184
+ if ($asc) {
1185
+ $this->quoteAscDetailsData[$item['quote_id']][$id][$columnName . $customProductOption] = '';
1186
+ } else {
1187
+ $this->orderDetailsData[$realOrderId][$id][$columnName . $customProductOption] = '';
1188
+ }
1189
+ }
1190
+ }
1191
+ }
1192
+ }
app/code/local/Windsorcircle/Export/Model/Products.php ADDED
@@ -0,0 +1,436 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class WindsorCircle_Export_Model_Products extends Mage_Core_Model_Abstract
3
+ {
4
+ protected $productData = array();
5
+
6
+ protected $allowedCountries = array();
7
+
8
+ protected $taxCollection = array();
9
+
10
+ protected $categoryList = array();
11
+
12
+ protected $breadcrumb = array();
13
+
14
+ protected $completedBreadcrumbIds = array();
15
+
16
+ protected $treeCollection = '';
17
+
18
+ protected $attributeValues = array();
19
+
20
+ protected function _construct(){
21
+ $this->_init('windsorcircle_export/products');
22
+ }
23
+
24
+ protected function loadTreeCollection() {
25
+ // Get Current Store
26
+ $previousStore = Mage::app()->getStore(null)->getId();
27
+
28
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
29
+
30
+ $this->treeCollection = Mage::getResourceSingleton('catalog/category_tree')
31
+ ->load();
32
+
33
+ $collection = Mage::getSingleton('catalog/category')->getCollection()
34
+ ->addAttributeToSelect('name')
35
+ ->addAttributeToSelect('is_active');
36
+
37
+ $this->treeCollection->addCollectionData($collection, true);
38
+
39
+ // Set store back to previous store
40
+ Mage::app()->setCurrentStore($previousStore);
41
+ }
42
+
43
+ /**
44
+ *
45
+ * Build Category Array by Node
46
+ * Recursive function for getting all children from a root node
47
+ * @param Varien_Data_Tree_Node $node
48
+ * $return array $result
49
+ */
50
+ protected function nodeToArray(Varien_Data_Tree_Node $node, $storeId = false)
51
+ {
52
+ if($node->getIsActive()) {
53
+ $this->categoryList[$storeId][$node->getLevel()][$node->getId()] = array('name' => $node->getName(), 'parent_id' => $node->getParentId());
54
+ }
55
+
56
+ foreach($node->getChildren() as $child) {
57
+ $this->nodeToArray($child, $storeId);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Load Tree Array
63
+ *
64
+ * @param bool $parentId
65
+ * @param bool $storeId
66
+ */
67
+ protected function loadTree($parentId = false, $storeId = false) {
68
+
69
+ if($parentId == false) {
70
+ $parentId = 1;
71
+ }
72
+
73
+ if($this->treeCollection == '') {
74
+ $this->loadTreeCollection();
75
+ }
76
+
77
+ $root = $this->treeCollection->getNodeById($parentId);
78
+
79
+ if($root && $root->getId() == 1) {
80
+ $root->setName(Mage::helper('catalog')->__('Root'));
81
+ }
82
+
83
+ if($root != null) {
84
+ if($storeId == false) {
85
+ $this->nodeToArray($root);
86
+ } else {
87
+ $this->nodeToArray($root, $storeId);
88
+ krsort($this->categoryList[$storeId]);
89
+ }
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Get category list for product
95
+ * Recursive function for getting children
96
+ *
97
+ * @param $productCategoryIds
98
+ * @param $storeCategoryList
99
+ * @param bool $levelFlag
100
+ * @param bool $parentId
101
+ *
102
+ * @return string
103
+ */
104
+ protected function searchArray($productCategoryIds, $storeCategoryList, $levelFlag = false, $parentId = false) {
105
+ $string = '';
106
+
107
+ if($levelFlag == false) {
108
+ reset($storeCategoryList);
109
+ $levelFlag = key($storeCategoryList);
110
+ }
111
+
112
+ for($i = $levelFlag; $i > 1; $i--) {
113
+ foreach($storeCategoryList[$i] as $id => $data) {
114
+ if(in_array($id, $productCategoryIds)) {
115
+ if($parentId != false) {
116
+ if($id == $parentId) {
117
+ if(($i - 1) != 0) {
118
+ $this->completedBreadcrumbIds[$id] = $id;
119
+ $string = $data['name'];
120
+ $additionalString = $this->searchArray($productCategoryIds, $storeCategoryList, ($i - 1), $data['parent_id']);
121
+ !empty($additionalString) ? $string = $additionalString . ' > ' . $string : '';
122
+ return $string;
123
+ }
124
+ }
125
+ } else {
126
+ if(!in_array($id, $this->completedBreadcrumbIds)) {
127
+ $string = $data['name'];
128
+ $additionalString = $this->searchArray($productCategoryIds, $storeCategoryList, ($i - 1), $data['parent_id']);
129
+ !empty($additionalString) ? $string = $additionalString . ' > ' . $string : '';
130
+ $this->breadcrumb[] = $string;
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ return $string;
137
+ }
138
+
139
+ /**
140
+ * Get products partly from the catalog
141
+ *
142
+ * @param Mage_Catalog_Model_Product $product
143
+ * @param $handle
144
+ */
145
+ public function getProductsAdvanced($product, $handle){
146
+
147
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
148
+
149
+ $helper = Mage::helper('windsorcircle_export');
150
+
151
+ $productData_Adv = array();
152
+
153
+ $stores = Mage::getStoreConfig('windsorcircle_export_options/messages/store');
154
+ if (!empty($stores)) {
155
+ $stores = explode(',', $stores);
156
+ }
157
+
158
+ foreach ($product->getStoreIds() as $_store) {
159
+
160
+ if (!empty($stores) && !in_array($_store, $stores)) {
161
+ continue;
162
+ }
163
+
164
+ Mage::app()->setCurrentStore($_store);
165
+
166
+ $outputIndividual = false;
167
+ if ($product->isVisibleInSiteVisibility()) {
168
+ $outputIndividual = true;
169
+ }
170
+
171
+ if (empty($this->categoryList[$_store])) {
172
+ $root_id = Mage::app()->getStore()->getRootCategoryId();
173
+ $this->loadTree($root_id, $_store);
174
+ }
175
+ $this->breadcrumb = array();
176
+ $this->completedBreadcrumbIds = array();
177
+
178
+ $this->searchArray($product->getCategoryIds(), $this->categoryList[$_store]);
179
+
180
+ // Image Array
181
+ $images = $this->getImages($product);
182
+
183
+ $parentIdRelation = $product->getParentSkuRelation();
184
+
185
+ // Unset $product request path and url if previously set from getProductUrl function
186
+ $product->unsRequestPath();
187
+ $product->unsUrl();
188
+ $url = $product->setStoreId($_store)->getProductUrl(false);
189
+ $categoryList = '"' . implode('","', $this->breadcrumb) . '"';
190
+
191
+ // If no custom attribute for brand then we will use default brand attribute
192
+ $attribute = Mage::getStoreConfig('windsorcircle_export_options/messages/brand_attribute');
193
+ if (empty($attribute)) {
194
+ $brandName = $this->getAttributeValue('brand', $product->getBrand());
195
+ } else {
196
+ $brandName = $this->getAttributeValue($attribute, $product->getData($attribute));
197
+ }
198
+
199
+ $keyName = $product->getId() . ':' . $_store;
200
+
201
+ if (empty($productData_Adv[$keyName])) {
202
+
203
+ $productData_Adv[$keyName] = array(
204
+ $product->getId(),
205
+ $_store,
206
+ ($product->getStatus() == 1 ? 'Y' : 'N'),
207
+ $product->getSku(),
208
+ (!empty($parentIdRelation) ? $parentIdRelation : ''),
209
+ $categoryList,
210
+ $helper->formatString($product->getName()),
211
+ $url,
212
+ array_shift($images),
213
+ $product->getPrice(),
214
+ $product->getSpecialPrice(),
215
+ $this->formatDates($product),
216
+ (!empty($brandName) ? $brandName : ''),
217
+ $this->getAvailability($product),
218
+ $product->getQty(),
219
+ $this->getShippingWeight($product),
220
+ $product->getTypeId(),
221
+ $product->getVisibility()
222
+ );
223
+
224
+ $customAttributes = Mage::helper('windsorcircle_export')->getCustomAttributes('product');
225
+
226
+ foreach ($customAttributes as $customAttribute) {
227
+ if ($product->getData($customAttribute) === null) {
228
+ array_push($productData_Adv[$keyName], '');
229
+ continue;
230
+ }
231
+ $data = $product->getResource()->getAttribute($customAttribute)->getFrontEnd()->getValue($product);
232
+ array_push($productData_Adv[$keyName], $helper->formatString($data));
233
+ }
234
+
235
+ // If product is available for purchase individually then output product without parent
236
+ if ($outputIndividual
237
+ && !empty($productData_Adv[$keyName])
238
+ && (!empty($parentIdRelation))
239
+ ) {
240
+ $productData_Adv[$keyName . ':individual'] = array_values($productData_Adv[$keyName]);
241
+ // Remove parent id or parent id relation from array for invidual product
242
+ $productData_Adv[$keyName . ':individual'][4] = '';
243
+ fputcsv($handle, $productData_Adv[$keyName . ':individual'], "\t");
244
+ }
245
+ }
246
+
247
+ fputcsv($handle, $productData_Adv[$keyName], "\t");
248
+ }
249
+
250
+ return;
251
+ }
252
+
253
+ /**
254
+ * Format dates for specials in ISO 8601 format
255
+ *
256
+ * @param Mage_Catalog_Model_Product $product
257
+ *
258
+ * @return string FromDate/ToDate or if no ToDate then just returns FromDate
259
+ */
260
+ protected function formatDates(Mage_Catalog_Model_Product $product){
261
+ $formatDate = array();
262
+
263
+ if($product->getSpecialFromDate() != null){
264
+ $formatDate[] = date_format(date_create($product->getSpecialFromDate()), 'c');
265
+ }
266
+
267
+ if($product->getSpecialToDate() != null){
268
+ $formatDate[] = date_format(date_create($product->getSpecialToDate()), 'c');
269
+ }
270
+
271
+ if($formatDate == null){
272
+ return '';
273
+ } else {
274
+ return implode('/', $formatDate);
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Gets availability of product
280
+ *
281
+ * @param Mage_Catalog_Model_Product $product
282
+ *
283
+ * @return string in_stock|out of stock|available for order
284
+ */
285
+ protected function getAvailability(Mage_Catalog_Model_Product $product){
286
+ if ($product->getData('use_config_manage_stock') == 1) {
287
+ if (Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_ITEM . 'manage_stock') == 0) {
288
+ return 'in stock';
289
+ }
290
+ } else if ($product->getData('manage_stock') == 0) {
291
+ return 'in stock';
292
+ }
293
+
294
+ if ($product->getData('is_in_stock') == 1) {
295
+ return 'in stock';
296
+ } else if ($product->getData('backorders') == 0) {
297
+ return 'out of stock';
298
+ }
299
+ return 'available for order';
300
+ }
301
+
302
+ /**
303
+ * getImages URL
304
+ *
305
+ * @param Mage_Catalog_Model_Product $product
306
+ *
307
+ * @return array ImageUrls
308
+ */
309
+ protected function getImages(Mage_Catalog_Model_Product $product){
310
+ $allImages = array();
311
+ $imageType = Mage::getStoreConfig('windsorcircle_export_options/messages/image_type');
312
+ if(!empty($imageType) && $imageType == '2') {
313
+ $productImage = $product->getSmallImage();
314
+ } else {
315
+ $productImage = $product->getImage();
316
+ }
317
+ if(!empty($productImage) && $productImage != 'no_selection') {
318
+ $allImages[] = Mage::getModel('catalog/product_media_config')
319
+ ->getMediaUrl($productImage);
320
+ }
321
+ return $allImages;
322
+ }
323
+
324
+ /**
325
+ * Shipping Weight of product
326
+ * @param Mage_Catalog_Model_Product $product
327
+ * @return string Product Weight
328
+ */
329
+ protected function getShippingWeight(Mage_Catalog_Model_Product $product){
330
+ $weight = (float) $product->getWeight();
331
+ $weight = !empty($weight) ? $weight . ' lb' : '';
332
+
333
+ return $weight;
334
+ }
335
+
336
+ /**
337
+ * Get Attribute Option Text
338
+ *
339
+ * @param string $attribute
340
+ * @param int $option
341
+ *
342
+ * @return string
343
+ */
344
+ protected function getAttributeValue($attribute, $option) {
345
+ if(empty($attribute) || empty($option)) {
346
+ return;
347
+ }
348
+
349
+ if(isset($this->attributeValues[$attribute][$option])) {
350
+ return $this->attributeValues[$attribute][$option];
351
+ }
352
+
353
+ $attribute_model = Mage::getModel('eav/entity_attribute');
354
+ $attribute_table = Mage::getModel('eav/entity_attribute_source_table');
355
+
356
+ $attribute_code = $attribute_model->getIdByCode('catalog_product', $attribute);
357
+ $loadedAttribute = $attribute_model->load($attribute_code);
358
+
359
+ $attribute_table->setAttribute($loadedAttribute);
360
+
361
+ $optionValue = $attribute_table->getOptionText($option);
362
+
363
+ if(!empty($optionValue)) {
364
+ if (is_array($optionValue)) {
365
+ $optionValue = implode(',', $optionValue);
366
+ }
367
+
368
+ $this->attributeValues[$attribute][$option] = $optionValue;
369
+ return $optionValue;
370
+ } else {
371
+ return $option;
372
+ }
373
+ }
374
+
375
+ /**
376
+ * Get taxes of product (e.g. Country:State:Value:TaxShipping => US:IL:0.0825:y)
377
+ * @param Mage_Catalog_Model_Product $product
378
+ * @return string TaxRates of current product
379
+ */
380
+ protected function getTax(Mage_Catalog_Model_Product $product){
381
+ $taxRate = array();
382
+
383
+ if(empty($this->taxCollection[$product->getTaxClassId()])){
384
+ $taxCollection = Mage::getModel('tax/calculation')->getCollection()
385
+ ->addFieldToFilter('product_tax_class_id', array('eq' => $product->getTaxClassId()));
386
+
387
+ foreach($taxCollection as $taxes){
388
+ $tax = Mage::getSingleton('tax/calculation')->getRatesByCustomerAndProductTaxClasses($taxes['customer_tax_class_id'], $product->getTaxClassId());
389
+ foreach($tax as $taxRule){
390
+ $this->taxCollection[$product->getTaxClassId()][] = $taxRule['country'] . ':' . $taxRule['state'] . ':' . $taxRule['value'] . ':y';
391
+ // Use data as array key so there is not duplicate data
392
+ $taxRate[$taxRule['country'].$taxRule['state'].$taxRule['postcode'].$taxRule['product_class']] = $taxRule['country'] . ':' . $taxRule['state'] . ':' . $taxRule['value'] . ':y';
393
+ }
394
+ }
395
+ } else {
396
+ foreach($this->taxCollection[$product->getTaxClassId()] as $taxRule){
397
+ $taxRate[] = $taxRule;
398
+ }
399
+ }
400
+
401
+ return implode(',', $taxRate);
402
+ }
403
+
404
+ /**
405
+ * Shipping country of product
406
+ * @param Mage_Catalog_Model_Product $product
407
+ * @return string All 2 Letter Country Codes that product can sell too
408
+ */
409
+ protected function getShippingCountry(Mage_Catalog_Model_Product $product){
410
+ $countryNames = array();
411
+
412
+ $storeIds = $product->getStoreIds();
413
+
414
+ foreach($storeIds as $id){
415
+ if(array_key_exists($id, $this->allowedCountries)){
416
+ foreach($this->allowedCountries[$id] as $country){
417
+ $countryNames[$country['value']] = $country['value'];
418
+ }
419
+ } else {
420
+ Mage::app()->setCurrentStore($id);
421
+
422
+ $this->allowedCountries[$id] = Mage::getResourceModel('directory/country_collection')->loadByStore()->toOptionArray(false);
423
+
424
+ foreach($this->allowedCountries[$id] as $country){
425
+ $countryNames[$country['value']] = $country['value'];
426
+ }
427
+ }
428
+ }
429
+
430
+ // Set store back to admin
431
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
432
+
433
+ ksort($countryNames);
434
+ return implode(',', $countryNames);
435
+ }
436
+ }
app/code/local/Windsorcircle/Export/Model/Sftp.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once(Mage::getBaseDir('lib') . DS . 'Varien' . DS . 'Io' . DS . 'Sftp.php');
3
+
4
+ class Windsorcircle_Export_Model_Sftp extends Varien_Io_Sftp
5
+ {
6
+ protected function _construct(){
7
+ $this->_init('windsorcircle_export/sftp');
8
+ }
9
+
10
+ /**
11
+ * Write a file
12
+ * Overrides default class because $mode by default is set to NET_SFTP_STRING
13
+ * @param $src Must be a local file name
14
+ */
15
+ public function write($filename, $src, $mode = NET_SFTP_LOCAL_FILE)
16
+ {
17
+ return $this->_connection->put($filename, $src, $mode);
18
+ }
19
+ }
app/code/local/Windsorcircle/Export/Model/Source/Canceled/State.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Source file for Canceled Order State
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2015 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Model_Source_Canceled_State
12
+ {
13
+ /**
14
+ * Option Array for Canceled Order State
15
+ *
16
+ * @return array
17
+ */
18
+ public function toOptionArray()
19
+ {
20
+ $arr = array();
21
+ if ((Mage::helper('windsorcircle_export')->isEnterprise()
22
+ && version_compare(Mage::getVersion(), '1.10.0.0', '<'))
23
+ || version_compare(Mage::getVersion(), '1.5.0.0', '<')
24
+ ) {
25
+ $visible = Mage::getModel('sales/order_config')->getVisibleOnFrontStates();
26
+ $invisible = Mage::getModel('sales/order_config')->getInvisibleOnFrontStates();
27
+ $orderStates = array_merge(
28
+ array_combine($invisible, $invisible),
29
+ array_combine($visible, $visible)
30
+ );
31
+ } else {
32
+ $orderStates = Mage::getModel('sales/order_config')->getStates();
33
+ }
34
+ foreach ($orderStates as $value => $label) {
35
+ $arr[] = array('value' => $value, 'label' => $label);
36
+ }
37
+ return $arr;
38
+ }
39
+ }
app/code/local/Windsorcircle/Export/Model/Source/Canceled/Status.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Source file for Canceled Order Status
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2015 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Model_Source_Canceled_Status
12
+ {
13
+ /**
14
+ * Option Array for Canceled Order Status
15
+ *
16
+ * @return array
17
+ */
18
+ public function toOptionArray()
19
+ {
20
+ $orderStatuses = Mage::getSingleton('sales/order_status')->getCollection();
21
+ $arr = array();
22
+ foreach ($orderStatuses as $orderStatus) {
23
+ $arr[] = array('value' => $orderStatus->getStatus(),
24
+ 'label' => Mage::helper('windsorcircle_export')->__($orderStatus->getLabel()));
25
+ }
26
+ return $arr;
27
+ }
28
+ }
app/code/local/Windsorcircle/Export/Model/Source/Store.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Source file for Store/Website selection in admin
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2016 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Model_Source_Store
12
+ {
13
+ /**
14
+ * Get admin website/store values for admin selection
15
+ *
16
+ * @return array
17
+ */
18
+ public function toOptionArray()
19
+ {
20
+ return Mage::getSingleton('adminhtml/system_store')->getStoreValuesForForm(false, true);
21
+ }
22
+ }
app/code/local/Windsorcircle/Export/Model/State.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class WindsorCircle_Export_Model_State
3
+ {
4
+ /**
5
+ * Canceled State Variable
6
+ *
7
+ * @var array
8
+ */
9
+ protected $_canceledState;
10
+
11
+ /**
12
+ * Check state
13
+ *
14
+ * @param string $state
15
+ * @return string 'Y' - Yes or 'N' - No
16
+ */
17
+ public function canceled($state){
18
+ if (!$this->_canceledState) {
19
+ $canceledState = Mage::getStoreConfig('windsorcircle_export_options/messages/canceled_state');
20
+ $this->_canceledState = explode(',', $canceledState);
21
+
22
+ if (is_array($this->_canceledState)) {
23
+ $this->_canceledState = array_map('strtolower', $this->_canceledState);
24
+ }
25
+ }
26
+
27
+ if (is_array($this->_canceledState)
28
+ && in_array(strtolower($state), $this->_canceledState)
29
+ ) {
30
+ return 'Y';
31
+ }
32
+ return 'N';
33
+ }
34
+ }
app/code/local/Windsorcircle/Export/Model/Status.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class WindsorCircle_Export_Model_Status
3
+ {
4
+ /**
5
+ * Canceled Status Variable
6
+ *
7
+ * @var array
8
+ */
9
+ protected $_canceledStatus;
10
+
11
+ /**
12
+ * Check status
13
+ *
14
+ * @param string $status
15
+ * @return string 'Y' - Yes or 'N' - No
16
+ */
17
+ public function canceled($status){
18
+ if (!$this->_canceledStatus) {
19
+ $canceledStatus = Mage::getStoreConfig('windsorcircle_export_options/messages/canceled_status');
20
+ $this->_canceledStatus = explode(',', $canceledStatus);
21
+
22
+ if (is_array($this->_canceledStatus)) {
23
+ $this->_canceledStatus = array_map('strtolower', $this->_canceledStatus);
24
+ }
25
+ }
26
+
27
+ if (is_array($this->_canceledStatus)
28
+ && in_array(strtolower($status), $this->_canceledStatus)
29
+ ) {
30
+ return 'Y';
31
+ }
32
+ return 'N';
33
+ }
34
+ }
app/code/local/Windsorcircle/Export/Model/System/Config/Backend/Attributes.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Backend Class to save value in admin
4
+ *
5
+ * @category Lyons
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2014 Lyons Consulting Group (www.lyonscg.com)
9
+ */
10
+
11
+ class Windsorcircle_Export_Model_System_Config_Backend_Attributes extends Mage_Core_Model_Config_Data
12
+ {
13
+ /**
14
+ * Process data after load
15
+ */
16
+ protected function _afterLoad()
17
+ {
18
+ $value = $this->getValue();
19
+
20
+ $prefix = '';
21
+ switch($this->getPath()) {
22
+ case 'windsorcircle_export_options/messages/custom_product_attributes':
23
+ $prefix = 'custom_product_';
24
+ break;
25
+ case 'windsorcircle_export_options/messages/custom_customer_attributes':
26
+ $prefix = 'custom_customer_';
27
+ break;
28
+ case 'windsorcircle_export_options/messages/custom_customer_address_attributes':
29
+ $prefix = 'custom_customer_address_';
30
+ break;
31
+ case 'windsorcircle_export_options/messages/custom_order_item_buy_request_attributes':
32
+ $prefix = 'custom_order_item_buy_request_';
33
+ break;
34
+ case 'windsorcircle_export_options/messages/custom_order_attributes':
35
+ $prefix = 'custom_order_';
36
+ break;
37
+ }
38
+
39
+ $value = Mage::helper('windsorcircle_export')->makeArrayFieldValue($value, $prefix);
40
+ $this->setValue($value);
41
+ }
42
+
43
+ /**
44
+ * Prepare data before save
45
+ */
46
+ protected function _beforeSave()
47
+ {
48
+ $value = $this->getValue();
49
+ $value = Mage::helper('windsorcircle_export')->makeStorableArrayFieldValue($value);
50
+ $this->setValue($value);
51
+ }
52
+ }
app/code/local/Windsorcircle/Export/controllers/Background.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Load Magento core
4
+ $mageFilename = dirname(dirname(dirname(dirname(dirname(dirname(__FILE__)))))) . '/Mage.php';
5
+ if (!file_exists($mageFilename)) {
6
+ echo 'Magento file does not exist!';
7
+ exit;
8
+ }
9
+
10
+ require_once $mageFilename;
11
+
12
+ umask(0);
13
+
14
+ Mage::app();
15
+
16
+ // Set memory limit from configuration otherwise default to 512M
17
+ $memoryLimitValue = Mage::getStoreConfig('windsorcircle_export_options/messages/memory_limit');
18
+ if ($memoryLimitValue && is_numeric($memoryLimitValue)) {
19
+ ini_set('memory_limit', "{$memoryLimitValue}M");
20
+ } else {
21
+ ini_set('memory_limit','512M');
22
+ }
23
+
24
+ // Set the timestamp for the files in the registry
25
+ Mage::register('windsor_file_timestamp', date('YmdHis'));
26
+ // Set Custom Entry Point in case Url Rewrites is disabled (this forces index.php instead of using Background.php)
27
+ Mage::register('custom_entry_point', true);
28
+
29
+ $parameters = array();
30
+ foreach ($argv as $parameter) {
31
+ if (strstr($parameter, '=')) {
32
+ list($key, $value) = explode('=', $parameter);
33
+ $parameters[$key] = $value;
34
+ } else {
35
+ $parameters[] = $parameter;
36
+ }
37
+ }
38
+
39
+ $files = array();
40
+
41
+ // Debug flag
42
+ $debug = (isset($parameters['debug']) && $parameters['debug'] == 1) ? (bool) $parameters['debug'] : false;
43
+
44
+ // Page size value - defaults to 10,000
45
+ $pageSize = isset($parameters['pageSize']) ? (int) $parameters['pageSize'] : 10000;
46
+
47
+ if(!empty($parameters['dataType'])) {
48
+ switch ($parameters['dataType']) {
49
+ case 'ProductsRebuild':
50
+ Mage::log('Getting Products Data', null, 'windsorcircle.log');
51
+
52
+ $lastExportFolder = Mage::getBaseDir('media') . DS . 'windsorcircle_export';
53
+ @unlink($lastExportFolder . DS . 'lastexport.txt');
54
+ @unlink($lastExportFolder . DS . 'updated.txt');
55
+ $files[] = Mage::getModel('windsorcircle_export/format')
56
+ ->setDebug($debug)
57
+ ->advancedFormatProductData();
58
+
59
+ Mage::log('All Products Gathered', null, 'windsorcircle.log');
60
+ break;
61
+ case 'ExecOrders':
62
+ Mage::log('Getting Orders Data', null, 'windsorcircle.log');
63
+
64
+ // Get Order Data and Order Details Data
65
+ $orders = Mage::getModel('windsorcircle_export/order')
66
+ ->setDebug($debug)
67
+ ->setPageSize($pageSize)
68
+ ->getOrders($parameters['startDate'], $parameters['endDate']);
69
+
70
+ // Format Order Data and Order Details Data
71
+ $files[] = Mage::getSingleton('windsorcircle_export/format')->formatOrderData($orders[0]);
72
+ $files[] = Mage::getSingleton('windsorcircle_export/format')->formatOrderDetailsData($orders[1]);
73
+
74
+ Mage::log('All Orders received', null, 'windsorcircle.log');
75
+ break;
76
+ case 'ExecOrdersPlus':
77
+ $formatModel = Mage::getSingleton('windsorcircle_export/format')
78
+ ->setDebug($debug);
79
+
80
+ // Get Order Data and Order Details Data
81
+ $orders = Mage::getModel('windsorcircle_export/order')
82
+ ->setDebug($debug)
83
+ ->setPageSize($pageSize)
84
+ ->getOrders($parameters['startDate'], $parameters['endDate']);
85
+
86
+ // Format Order Data and Order Details Data
87
+ $files[] = $formatModel->formatOrderData($orders[0]);
88
+ $files[] = $formatModel->formatOrderDetailsData($orders[1]);
89
+
90
+ // Get flag for inventory enable update
91
+ $inventoryEnabled = Mage::getStoreConfigFlag('windsorcircle_export_options/messages/inventory_enable');
92
+
93
+ // Get order item ids from orders
94
+ if ($inventoryEnabled) {
95
+ $orderItemIds = $orders[2];
96
+ } else {
97
+ $orderItemIds = array();
98
+ }
99
+
100
+ // Get product data if updated
101
+ if ($productFile = $formatModel->getProductDataIfUpdated($orderItemIds)) {
102
+ $files[] = $productFile;
103
+ }
104
+ break;
105
+ }
106
+ }
107
+
108
+ if(!empty($files)) {
109
+ Mage::log('Sending Files to FTP Server', null, 'windsorcircle.log');
110
+
111
+ try {
112
+ // Attempt to send files via FTP (FTP or SFTP)
113
+ Mage::getModel('windsorcircle_export/ftp')->sendFiles($files);
114
+ Mage::log('Files Sent', null, 'windsorcircle.log');
115
+ } catch (Exception $e) {
116
+ Mage::log('Error sending files', null, 'windsorcircle.log');
117
+ }
118
+
119
+ // Remove all files from tmp directory after script is complete
120
+ $mask = Mage::getBaseDir('tmp') . DS . Mage::getStoreConfig('windsorcircle_export_options/messages/client_name') . '_*';
121
+ array_map('unlink', glob($mask));
122
+ }
app/code/local/Windsorcircle/Export/controllers/IndexController.php ADDED
@@ -0,0 +1,557 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Windsorcircle_Export_IndexController extends Mage_Core_Controller_Front_Action
3
+ {
4
+ public function indexAction(){
5
+
6
+ $this->setMemoryLimit();
7
+
8
+ // Set the timestamp for the files in the registry
9
+ Mage::register('windsor_file_timestamp', date('YmdHis'));
10
+
11
+ $filename = Mage::getBaseDir('log') . DS . 'windsorcircle.log';
12
+
13
+ // If lastlog has been sent then copy log to '.prev' file
14
+ if ($this->getRequest()->getParam('dataType') == 'LastLog') {
15
+ $io = new Varien_Io_File();
16
+ $path = $io->dirname($filename);
17
+ $io->open(array('path' => $path));
18
+ $io->cp('windsorcircle.log', 'windsorcircle.log.prev');
19
+ }
20
+
21
+ // Removing log file
22
+ if(file_exists($filename)) {
23
+ @unlink($filename);
24
+ }
25
+
26
+ Mage::log('Checking Parameters', null, 'windsorcircle.log');
27
+
28
+ // Get params from URL
29
+ $params = new Varien_Object($this->getRequest()->getParams());
30
+
31
+ // Required params must be set!
32
+ if(empty($params['authToken']) || empty($params['startDate']) || empty($params['endDate']) || empty($params['authDate']))
33
+ {
34
+ throw new Exception('Must provide all parameters (authToken, startDate, endDate, AuthDate).');
35
+ }
36
+
37
+ $files = array();
38
+
39
+ // Check the authDate to make sure it is within one minute of request
40
+ Mage::getModel('windsorcircle_export/date')->checkDate($params['authDate']);
41
+
42
+ // Check to make sure that the authToken sent in the URL is valid
43
+ Mage::getModel('windsorcircle_export/openssl')->valid($params['authToken'], $params['authDate']);
44
+
45
+ Mage::log('All Parameters Checked OK', null, 'windsorcircle.log');
46
+
47
+ // If version parameter is passed then return current module version
48
+ if (isset($params['Version'])) {
49
+ $this->getResponse()
50
+ ->setBody(
51
+ 'Module Version: ' . Mage::helper('windsorcircle_export')->getExtensionVersion()
52
+ . '<br />'
53
+ . 'Magento Version: ' . Mage::getVersion()
54
+ );
55
+ return;
56
+ }
57
+
58
+ // Debug flag
59
+ $debug = (isset($params['debug']) && $params['debug'] == 1) ? (bool) $params['debug'] : false;
60
+
61
+ // Page size value - defaults to 10,000
62
+ $pageSize = isset($params['pageSize']) ? (int) $params['pageSize'] : 10000;
63
+
64
+ switch ($params['dataType']) {
65
+ case 'ASC':
66
+ $formatModel = Mage::getSingleton('windsorcircle_export/format')->setDebug($debug);
67
+
68
+ $orderModel = Mage::getModel('windsorcircle_export/order')
69
+ ->setDebug($debug)
70
+ ->setPageSize($pageSize);
71
+
72
+ // Get Order Data and Order Details Data
73
+ $orders = $orderModel->getOrders($params['startDate'], $params['endDate']);
74
+
75
+ // Format Order Data and Order Details Data
76
+ $files[] = $formatModel->formatOrderData($orders[0]);
77
+ $files[] = $formatModel->formatOrderDetailsData($orders[1]);
78
+
79
+ // Get flag for inventory enable update
80
+ $inventoryEnabled = Mage::getStoreConfigFlag('windsorcircle_export_options/messages/inventory_enable');
81
+
82
+ // Get order item ids from orders
83
+ if ($inventoryEnabled) {
84
+ $orderItemIds = $orders[2];
85
+ } else {
86
+ $orderItemIds = array();
87
+ }
88
+
89
+ // Get Abandoned Shopping Cart Order Data and Order Details Data
90
+ if (!empty($params['ascStartDate']) && !empty($params['ascEndDate'])) {
91
+ $ascOrders = $orderModel->getAscOrders($params['ascStartDate'], $params['ascEndDate']);
92
+ } else {
93
+ $ascOrders = $orderModel->getAscOrders($params['startDate'], $params['endDate']);
94
+ }
95
+
96
+ // Format Abandoned Shopping Cart Order Data and Order Details Data
97
+ $files[] = $formatModel->formatOrderData($ascOrders[0], '_ASC_');
98
+ $files[] = $formatModel->formatOrderDetailsData($ascOrders[1], '_ASC_');
99
+
100
+ // Get order item ids from ASC orders
101
+ if ($inventoryEnabled) {
102
+ $ascOrderItemIds = $ascOrders[2];
103
+ } else {
104
+ $ascOrderItemIds = array();
105
+ }
106
+
107
+ // Get product data if updated
108
+ if ($productFile = $formatModel->getProductDataIfUpdated(array_merge($orderItemIds, $ascOrderItemIds))) {
109
+ $files[] = $productFile;
110
+ }
111
+ break;
112
+ case 'Orders':
113
+ Mage::log('Getting Orders Data', null, 'windsorcircle.log');
114
+
115
+ // Get Order Data and Order Details Data
116
+ $orders = Mage::getModel('windsorcircle_export/order')
117
+ ->setDebug($debug)
118
+ ->setPageSize($pageSize)
119
+ ->getOrders($params['startDate'], $params['endDate']);
120
+
121
+ // Format Order Data and Order Details Data
122
+ $files[] = Mage::getSingleton('windsorcircle_export/format')->formatOrderData($orders[0]);
123
+ $files[] = Mage::getSingleton('windsorcircle_export/format')->formatOrderDetailsData($orders[1]);
124
+
125
+ Mage::log('All Orders received', null, 'windsorcircle.log');
126
+ break;
127
+ case 'ExecOrders':
128
+ $cmd = PHP_BINDIR . '/php -f ' . Mage::getModuleDir('controllers', 'Windsorcircle_Export') . DS . 'Background.php';
129
+ $cmd .= !empty($params['dataType']) ? ' dataType=' . escapeshellarg($params['dataType']) : '';
130
+ $cmd .= !empty($params['startDate']) ? ' startDate=' . escapeshellarg($params['startDate']) : '';
131
+ $cmd .= !empty($params['endDate']) ? ' endDate=' . escapeshellarg($params['endDate']) : '';
132
+ $cmd .= !empty($debug) ? ' debug=' . escapeshellarg($debug) : '';
133
+ $cmd .= !empty($pageSize) ? ' pageSize=' . escapeshellarg($pageSize) : '';
134
+
135
+ if ($this->execCommand($cmd)) {
136
+ $this->getResponse()->setBody('Request sent Successfully!');
137
+ }
138
+ return;
139
+ break;
140
+ case 'OrdersPlus':
141
+ $formatModel = Mage::getSingleton('windsorcircle_export/format')->setDebug($debug);
142
+
143
+ // Get Order Data and Order Details Data
144
+ $orders = Mage::getModel('windsorcircle_export/order')
145
+ ->setDebug($debug)
146
+ ->setPageSize($pageSize)
147
+ ->getOrders($params['startDate'], $params['endDate']);
148
+
149
+ // Format Order Data and Order Details Data
150
+ $files[] = $formatModel->formatOrderData($orders[0]);
151
+ $files[] = $formatModel->formatOrderDetailsData($orders[1]);
152
+
153
+ // Get flag for inventory enable update
154
+ $inventoryEnabled = Mage::getStoreConfigFlag('windsorcircle_export_options/messages/inventory_enable');
155
+
156
+ // Get order item ids from orders
157
+ if ($inventoryEnabled) {
158
+ $orderItemIds = $orders[2];
159
+ } else {
160
+ $orderItemIds = array();
161
+ }
162
+
163
+ // Get product data if updated
164
+ if ($productFile = $formatModel->getProductDataIfUpdated($orderItemIds)) {
165
+ $files[] = $productFile;
166
+ }
167
+ break;
168
+ case 'ExecOrdersPlus':
169
+ $cmd = PHP_BINDIR . '/php -f ' . Mage::getModuleDir('controllers', 'Windsorcircle_Export') . DS . 'Background.php';
170
+ $cmd .= !empty($params['dataType']) ? ' dataType=' . escapeshellarg($params['dataType']) : '';
171
+ $cmd .= !empty($params['startDate']) ? ' startDate=' . escapeshellarg($params['startDate']) : '';
172
+ $cmd .= !empty($params['endDate']) ? ' endDate=' . escapeshellarg($params['endDate']) : '';
173
+ $cmd .= !empty($debug) ? ' debug=' . escapeshellarg($debug) : '';
174
+ $cmd .= !empty($pageSize) ? ' pageSize=' . escapeshellarg($pageSize) : '';
175
+
176
+ if ($this->execCommand($cmd)) {
177
+ $this->getResponse()->setBody('Request sent Successfully!');
178
+ }
179
+ return;
180
+ break;
181
+ case 'ProductsRebuild':
182
+ $cmd = PHP_BINDIR . '/php -f ' . Mage::getModuleDir('controllers', 'Windsorcircle_Export') . DS . 'Background.php';
183
+ $cmd .= !empty($params['dataType']) ? ' dataType=' . escapeshellarg($params['dataType']) : '';
184
+ $cmd .= !empty($params['startDate']) ? ' startDate=' . escapeshellarg($params['startDate']) : '';
185
+ $cmd .= !empty($params['endDate']) ? ' endDate=' . escapeshellarg($params['endDate']) : '';
186
+ $cmd .= !empty($params['ascStartDate'])? ' ascStartDate=' . escapeshellarg($params['ascStartDate']) : '';
187
+ $cmd .= !empty($params['ascEndDate'])? ' ascEndDate=' . escapeshellarg($params['ascEndDate']) : '';
188
+ $cmd .= !empty($debug) ? ' debug=' . escapeshellarg($debug) : '';
189
+
190
+ if ($this->execCommand($cmd)) {
191
+ $this->getResponse()->setBody('Request sent Successfully!');
192
+ } else {
193
+ $this->removeProductsFile();
194
+ $this->getResponse()->setBody(' Products file removed.');
195
+ }
196
+ return;
197
+ break;
198
+ case 'Products':
199
+ Mage::log('Getting Products Data', null, 'windsorcircle.log');
200
+
201
+ // Get Products data
202
+ $files[] = Mage::getSingleton('windsorcircle_export/format')
203
+ ->setDebug($debug)
204
+ ->advancedFormatProductData();
205
+
206
+ Mage::log('All Products Gathered', null, 'windsorcircle.log');
207
+ break;
208
+ case 'CheckPermissions':
209
+ $dir = Mage::getBaseDir('media') . DS . 'windsorcircle_export';
210
+ $io = new Varien_Io_File();
211
+
212
+ try {
213
+ $io->checkAndCreateFolder($dir);
214
+ if (is_writable($io->dirname($dir))) {
215
+ $writable = true;
216
+ } else {
217
+ $writable = false;
218
+ }
219
+ } catch (Exception $e) {
220
+ $writable = false;
221
+ }
222
+
223
+ $response = 'media/windsorcircle_export folder';
224
+ if ($writable) {
225
+ $response.= ' is writable';
226
+ } else {
227
+ $response.= ' is not writable';
228
+ }
229
+
230
+ $this->getResponse()->setBody($response);
231
+ break;
232
+ case 'Config':
233
+ $break = '<br />';
234
+
235
+ $secure = false;
236
+ if (Mage::app()->getRequest()->isSecure()) {
237
+ $secure = true;
238
+ }
239
+
240
+ $prefix = 'windsorcircle_export_options/messages/';
241
+ $response = 'Version: ' . (string) Mage::helper('windsorcircle_export')->getExtensionVersion();
242
+ $response.= $break . 'Client Name: ' . Mage::getStoreConfig($prefix . 'client_name');
243
+
244
+ if ($secure) {
245
+ $response.= $break . 'API Key: ' . Mage::getStoreConfig($prefix . 'api_key');
246
+ }
247
+
248
+ $response.= $break . 'FTP Type: ' . Mage::getStoreConfig($prefix . 'ftp_type');
249
+ $response.= $break . 'FTP Host: ' . Mage::getStoreConfig($prefix . 'ftp_host');
250
+ $response.= $break . 'FTP Folder: ' . Mage::getStoreConfig($prefix . 'ftp_folder');
251
+ $response.= $break . 'FTP User: ' . Mage::getStoreConfig($prefix . 'ftp_user');
252
+
253
+ if ($secure) {
254
+ $response.= $break . 'FTP Password: ' . Mage::getStoreConfig($prefix . 'ftp_password');
255
+ }
256
+
257
+ $response.= $break . 'Store: ' . Mage::getStoreConfig($prefix . 'store');
258
+ $response.= $break . 'Brand Attribute: ' . Mage::getStoreConfig($prefix . 'brand_attribute');
259
+ $response.= $break . 'Canceled State: ' . Mage::getStoreConfig($prefix . 'canceled_state');
260
+
261
+ $imageType = Mage::getStoreConfig($prefix . 'image_type');
262
+ if(!empty($imageType) && $imageType == '2') {
263
+ $imageType = 'Small Image';
264
+ } else {
265
+ $imageType = 'Base Image';
266
+ }
267
+ $response.= $break . 'Image Type: ' . $imageType;
268
+
269
+ $memoryLimit = Mage::getStoreConfig($prefix . 'memory_limit');
270
+ if (empty($memoryLimit)) {
271
+ $memoryLimit = '512';
272
+ }
273
+ $response.= $break . 'Memory Limit: ' . $memoryLimit . 'M';
274
+
275
+ $response.= $break . 'Inventory Enable: ' . Mage::getStoreConfig($prefix . 'inventory_enable');
276
+
277
+ $productsValue = array();
278
+ $productAttributes = unserialize(Mage::getStoreConfig($prefix . 'custom_product_attributes'));
279
+ if (!empty($productAttributes)) {
280
+ foreach ($productAttributes as $value) {
281
+ $productsValue[] = $value;
282
+ }
283
+ }
284
+ $response.= $break . 'Custom Product Attributes: ' . implode(',', $productsValue);
285
+
286
+ $customerValue = array();
287
+ $customerAttributes = unserialize(Mage::getStoreConfig($prefix . 'custom_customer_attributes'));
288
+ if (!empty($customerAttributes)) {
289
+ foreach ($customerAttributes as $value) {
290
+ $customerValue[] = $value;
291
+ }
292
+ }
293
+ $response.= $break . 'Custom Customer Attributes: ' . implode(',', $customerValue);
294
+
295
+ $customerAddressValue = array();
296
+ $customerAddressAttributes = unserialize(Mage::getStoreConfig($prefix . 'custom_customer_address_attributes'));
297
+ if (!empty($customerAddressAttributes)) {
298
+ foreach ($customerAddressAttributes as $value) {
299
+ $customerAddressValue[] = $value;
300
+ }
301
+ }
302
+ $response.= $break . 'Custom Customer Addresss Attributes: ' . implode(',', $customerAddressValue);
303
+
304
+ $buyRequestValue = array();
305
+ $buyRequestAttributes = unserialize(Mage::getStoreConfig($prefix . 'custom_order_item_buy_request_attributes'));
306
+ if (!empty($buyRequestAttributes)) {
307
+ foreach ($buyRequestAttributes as $value) {
308
+ $buyRequestValue[] = $value;
309
+ }
310
+ }
311
+ $response.= $break . 'Custom Order Items Buy Request Attributes: ' . implode(',', $buyRequestValue);
312
+
313
+ $this->getResponse()->setBody($response);
314
+ break;
315
+ case 'Count':
316
+ $break = '<br />';
317
+
318
+ // Get Updated.txt file count
319
+ $filename = Mage::getBaseDir('media') . DS . 'windsorcircle_export' . DS . 'updated.txt';
320
+ $io = new Varien_Io_File();
321
+ $path = $io->dirname($filename);
322
+ $io->open(array('path' => $path));
323
+
324
+ try {
325
+ $io->streamOpen($filename, 'r+');
326
+ $linecount = 0;
327
+ while($io->streamRead()) {
328
+ $linecount++;
329
+ }
330
+ $io->streamClose();
331
+ } catch (Exception $e) {
332
+ $linecount = 0;
333
+ }
334
+ $response = 'updated.txt - ' . $linecount;
335
+
336
+ // Get number of orders returned for orders
337
+ $orders = Mage::getModel('sales/order')->getCollection();
338
+
339
+ if (version_compare(Mage::getVersion(), '1.4.0.0', '<')) {
340
+ $orders
341
+ ->addFieldToFilter(
342
+ array(
343
+ array('attribute' => 'updated_at',
344
+ 'datetime' => true, 'from' => $params['startDate'], 'to' => $params['endDate']),
345
+ array('attribute' => 'created_at',
346
+ 'datetime' => true, 'from' => $params['startDate'], 'to' => $params['endDate'])
347
+ )
348
+ );
349
+ } else {
350
+ $orders
351
+ ->getSelect()
352
+ ->where(
353
+ '(main_table.updated_at >= :start_date' .
354
+ ' AND main_table.updated_at <= :end_date) ' .
355
+ Varien_Db_Select::SQL_OR .
356
+ ' (main_table.created_at >= :start_date' .
357
+ ' AND main_table.created_at <= :end_date)'
358
+ );
359
+
360
+ $orders->addBindParam('start_date', $params['startDate']);
361
+ $orders->addBindParam('end_date', $params['endDate']);
362
+ }
363
+ $response.= $break . 'Total Orders - ' . $orders->getSize();
364
+
365
+ // Get number of order items returned for order items
366
+ $orders->getSelect()->reset(Varien_Db_Select::COLUMNS);
367
+ $orders->getSelect()->columns('entity_id');
368
+
369
+ $orderItems = Mage::getModel('sales/order_item')->getCollection()
370
+ ->addFieldToFilter('order_id', array('in' => $orders->getSelect()));
371
+
372
+ $orderItems->addBindParam('start_date', $params['startDate']);
373
+ $orderItems->addBindParam('end_date', $params['endDate']);
374
+
375
+ $items = array();
376
+ $itemCheck = array();
377
+ foreach($orderItems->getData() as $item) {
378
+ $itemCheck[$item['item_id']] = array('type' => $item['product_type']);
379
+
380
+ $items[$item['item_id']] = array(
381
+ 'product_type' => $item['product_type'],
382
+ 'parent_item_id' => $item['parent_item_id']
383
+ );
384
+ }
385
+
386
+ $actualItems = array();
387
+ foreach ($items as $key => $item) {
388
+ if((isset($item['product_type'])
389
+ && $item['product_type'] == 'configurable')
390
+ || $item['product_type'] == ''
391
+ ) {
392
+ $actualItems[$key] = 1;
393
+ } elseif (
394
+ (isset($item['parent_item_id'])
395
+ && $item['parent_item_id'] != null)
396
+ && (isset($itemCheck[$item['parent_item_id']]['type'])
397
+ && $itemCheck[$item['parent_item_id']]['type'] == 'bundle')
398
+ ) {
399
+ $actualItems[$key] = 1;
400
+ } elseif(
401
+ (isset($item['parent_item_id'])
402
+ && $item['parent_item_id'] != null)
403
+ && (isset($itemCheck[$item['parent_item_id']]['type'])
404
+ && $itemCheck[$item['parent_item_id']]['type'] != 'simple')
405
+ ) {
406
+ // Do nothing since the parent should already be set
407
+ } else {
408
+ $actualItems[$key] = 1;
409
+ }
410
+ }
411
+
412
+ $response.= $break . 'Total Order Items - ' . count($actualItems);
413
+
414
+ $this->getResponse()->setBody($response);
415
+ break;
416
+ case 'LastLog':
417
+ $io = new Varien_Io_File();
418
+ $path = $io->dirname($filename . '.prev');
419
+ $io->open(array('path' => $path));
420
+ $response = $io->read('windsorcircle.log.prev');
421
+ $this->getResponse()->setBody($response);
422
+
423
+ // Removing log file
424
+ if(file_exists($filename . '.prev')) {
425
+ @unlink($filename . '.prev');
426
+ }
427
+ break;
428
+ case 'Report':
429
+ if (Mage::getStoreConfigFlag('windsorcircle_export_options/options/enable_report_output')) {
430
+ if (!empty($params['file'])) {
431
+ $io = new Varien_Io_File();
432
+ $path = $io->dirname(Mage::getBaseDir('var') . DS . 'report' . DS . $params['file']);
433
+ $io->open(array('path' => $path));
434
+ if ($io->fileExists($params['file'])) {
435
+ $response = $io->read($params['file']);
436
+ } else {
437
+ $response = 'File does not exist';
438
+ }
439
+ } else {
440
+ $response = 'file parameter is missing';
441
+ }
442
+ $this->getResponse()->setBody($response);
443
+ } else {
444
+ $this->getResponse()->setBody('Error reporting is disabled');
445
+ }
446
+ break;
447
+ case 'ServerDateTime':
448
+ $response = date('r');
449
+ $this->getResponse()->setBody($response);
450
+ break;
451
+ case 'TestConnection':
452
+ $testConnection = Mage::getModel('windsorcircle_export/ftp')->testConnection();
453
+ $this->getResponse()->setBody($testConnection);
454
+ break;
455
+ default:
456
+ Mage::log('Getting Orders Data', null, 'windsorcircle.log');
457
+
458
+ // Get Order Data and Order Details Data
459
+ $orders = Mage::getModel('windsorcircle_export/order')
460
+ ->setDebug($debug)
461
+ ->setPageSize($pageSize)
462
+ ->getOrders($params['startDate'], $params['endDate']);
463
+
464
+ // Format Order Data and Order Details Data
465
+ $files[] = Mage::getSingleton('windsorcircle_export/format')->formatOrderData($orders[0]);
466
+ $files[] = Mage::getSingleton('windsorcircle_export/format')->formatOrderDetailsData($orders[1]);
467
+
468
+ Mage::log('All Orders recieved', null, 'windsorcircle.log');
469
+
470
+ // Get flag for inventory enable update
471
+ $inventoryEnabled = Mage::getStoreConfigFlag('windsorcircle_export_options/messages/inventory_enable');
472
+
473
+ // Get order item ids from orders
474
+ if ($inventoryEnabled) {
475
+ $orderItemIds = $orders[2];
476
+ } else {
477
+ $orderItemIds = array();
478
+ }
479
+
480
+ Mage::log('Getting Products Data', null, 'windsorcircle.log');
481
+
482
+ // Get Products data
483
+ $files[] = Mage::getSingleton('windsorcircle_export/format')
484
+ ->setDebug($debug)
485
+ ->advancedFormatProductData($orderItemIds);
486
+
487
+ Mage::log('All Products Gathered', null, 'windsorcircle.log');
488
+
489
+ Mage::log('Sending Files to FTP Server', null, 'windsorcircle.log');
490
+ break;
491
+ }
492
+
493
+ if (!empty($files)) {
494
+ // Attempt to send files via FTP (FTP or SFTP)
495
+ try {
496
+ Mage::getModel('windsorcircle_export/ftp')->sendFiles($files);
497
+ Mage::log('Files Sent', null, 'windsorcircle.log');
498
+ $response = 'Files successfully sent';
499
+ } catch (Exception $e) {
500
+ Mage::log('Error sending files', null, 'windsorcircle.log');
501
+ $response = 'Error sending files';
502
+ }
503
+ $this->getResponse()->setBody($response);
504
+
505
+ // Remove all files from tmp directory after script is complete
506
+ $mask = Mage::getBaseDir('tmp') . DS . Mage::getStoreConfig('windsorcircle_export_options/messages/client_name') . '_*';
507
+ array_map('unlink', glob($mask));
508
+ } elseif (!in_array($params['dataType'],
509
+ array('CheckPermissions', 'Config', 'Count', 'Report', 'LastLog', 'ServerDateTime', 'TestConnection'))
510
+ ) {
511
+ $this->getResponse()->setBody('No Files to send');
512
+ }
513
+ }
514
+
515
+ /**
516
+ * Execute command
517
+ *
518
+ * @param $cmd
519
+ *
520
+ * @return bool
521
+ */
522
+ private function execCommand($cmd)
523
+ {
524
+ if (substr(php_uname(), 0, 7) == "Windows") {
525
+ if (!pclose(popen("start /B ". $cmd, "r"))) {
526
+ $this->getResponse()->setBody('Windows popen/pclose is not available.');
527
+ return false;
528
+ }
529
+ } else {
530
+ if (exec('echo EXEC') == 'EXEC') {
531
+ exec($cmd . " > /dev/null &");
532
+ } else {
533
+ $this->getResponse()->setBody('Exec is not available.');
534
+ return false;
535
+ }
536
+ }
537
+ return true;
538
+ }
539
+
540
+ /**
541
+ * Set memory limit - defaults to 512M
542
+ */
543
+ private function setMemoryLimit()
544
+ {
545
+ $memoryLimitValue = Mage::getStoreConfig('windsorcircle_export_options/messages/memory_limit');
546
+ if ($memoryLimitValue && is_numeric($memoryLimitValue)) {
547
+ ini_set('memory_limit', "{$memoryLimitValue}M");
548
+ } else {
549
+ ini_set('memory_limit','512M');
550
+ }
551
+ }
552
+
553
+ private function removeProductsFile() {
554
+ $lastExportFolder = Mage::getBaseDir('media') . DS . 'windsorcircle_export';
555
+ array_map('unlink', array($lastExportFolder . DS . 'lastexport.txt', $lastExportFolder . DS . 'updated.txt'));
556
+ }
557
+ }
app/code/local/Windsorcircle/Export/controllers/LoadCartController.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Abandoned Shipping Cart Reload Controller
4
+ *
5
+ * @category WindsorCircle
6
+ * @package Windsorcircle_Export
7
+ * @author Mark Hodge <mhodge@lyonscg.com>
8
+ * @copyright Copyright (c) 2016 WindsorCircle (www.windsorcircle.com)
9
+ */
10
+
11
+ require_once Mage::getModuleDir('controllers', 'Mage_Checkout') . DS . 'CartController.php';
12
+
13
+ class Windsorcircle_Export_LoadCartController extends Mage_Checkout_CartController
14
+ {
15
+ public function indexAction()
16
+ {
17
+ $params = $this->getRequest()->getQuery();
18
+ $cart = 'checkout/cart';
19
+
20
+ // If logged in then redirect to the cart page
21
+ if (Mage::helper('customer')->isLoggedIn()) {
22
+ $this->getResponse()->setRedirect(Mage::getUrl($cart, array('_query' => $params)), 301);
23
+ return;
24
+ }
25
+
26
+ $cartData = Mage::getModel('windsorcircle_export/openssl')
27
+ ->decrypt($params['cid'], $params['iv']);
28
+
29
+ // Remove encryption data from params url
30
+ unset($params['cid']);
31
+ unset($params['iv']);
32
+
33
+ if ($cartData) {
34
+ list($email, $quoteId) = explode(':', $cartData);
35
+ }
36
+
37
+ if (!empty($email) && !empty($quoteId)) {
38
+ $quote = Mage::getModel('sales/quote')->load($quoteId);
39
+
40
+ if (!$quote->getId()) {
41
+ $customerSession = Mage::getSingleton('customer/session');
42
+ $customerSession->setAfterAuthUrl(Mage::getUrl($cart, array('_query' => $params)));
43
+ $customerSession->addNotice('We are unable to access your shopping cart. Please login to continue.');
44
+ $this->_redirect('customer/account');
45
+ } else if (!$quote->getIsActive()) {
46
+ $this->_getSession()->addNotice('Your shopping cart is no longer available.');
47
+ $this->_redirect($cart, array('_query' => $params));
48
+ } else if ($quote->getCustomerEmail() == $email) {
49
+ if (!$quote->getCustomerId()) {
50
+ $this->_getSession()->setQuoteId($quote->getId());
51
+ $this->getResponse()->setRedirect(Mage::getUrl($cart, array('_query' => $params)), 301);
52
+ } else {
53
+ $customer = Mage::getModel('customer/customer')->load($quote->getCustomerId());
54
+ if ($customer->getId()) {
55
+ Mage::getSingleton('customer/session')->setCustomerAsLoggedIn($customer);
56
+ }
57
+ $this->getResponse()->setRedirect(Mage::getUrl($cart, array('_query' => $params)), 301);
58
+ }
59
+ } else {
60
+ $this->_getSession()->addNotice('Your shopping cart is no longer available.');
61
+ $this->_redirect($cart, array('_query' => $params));
62
+ }
63
+ } else {
64
+ $customerSession = Mage::getSingleton('customer/session');
65
+ $customerSession->setAfterAuthUrl(Mage::getUrl($cart, array('_query' => $params)));
66
+ $customerSession->addNotice('We are unable to access your shopping cart. Please login to continue.');
67
+ $this->_redirect('customer/account');
68
+ }
69
+ }
70
+ }
app/code/local/Windsorcircle/Export/etc/config.xml ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Windsorcircle_Export>
5
+ <version>1.0.97</version>
6
+ </Windsorcircle_Export>
7
+ </modules>
8
+ <frontend>
9
+ <routers>
10
+ <windsorcircle_export>
11
+ <use>standard</use>
12
+ <args>
13
+ <module>Windsorcircle_Export</module>
14
+ <frontName>WindsorCircleFeed</frontName>
15
+ </args>
16
+ </windsorcircle_export>
17
+ <windsorcircle_abandonedcart>
18
+ <use>standard</use>
19
+ <args>
20
+ <module>Windsorcircle_Export</module>
21
+ <frontName>WC_CR</frontName>
22
+ </args>
23
+ </windsorcircle_abandonedcart>
24
+ </routers>
25
+ <secure_url>
26
+ <windsorcircle_export>/WindsorCircleFeed/index</windsorcircle_export>
27
+ </secure_url>
28
+ </frontend>
29
+ <global>
30
+ <blocks>
31
+ <windsorcircle_export>
32
+ <class>Windsorcircle_Export_Block</class>
33
+ </windsorcircle_export>
34
+ </blocks>
35
+ <events>
36
+ <catalog_product_save_after>
37
+ <observers>
38
+ <windsorcircle_export>
39
+ <type>singleton</type>
40
+ <class>Windsorcircle_Export_Model_Observer</class>
41
+ <method>afterProductSave</method>
42
+ </windsorcircle_export>
43
+ </observers>
44
+ </catalog_product_save_after>
45
+ <catalog_product_delete_commit_after>
46
+ <observers>
47
+ <windsorcircle_export>
48
+ <type>singleton</type>
49
+ <class>Windsorcircle_Export_Model_Observer</class>
50
+ <method>afterProductDelete</method>
51
+ </windsorcircle_export>
52
+ </observers>
53
+ </catalog_product_delete_commit_after>
54
+ <cataloginventory_stock_item_save_commit_after>
55
+ <observers>
56
+ <windsorcircle_export>
57
+ <type>singleton</type>
58
+ <class>Windsorcircle_Export_Model_Observer</class>
59
+ <method>afterProductInventoryUpdate</method>
60
+ </windsorcircle_export>
61
+ </observers>
62
+ </cataloginventory_stock_item_save_commit_after>
63
+ </events>
64
+ <helpers>
65
+ <windsorcircle_export>
66
+ <class>Windsorcircle_Export_Helper</class>
67
+ </windsorcircle_export>
68
+ </helpers>
69
+ <models>
70
+ <windsorcircle_export>
71
+ <class>Windsorcircle_Export_Model</class>
72
+ </windsorcircle_export>
73
+ </models>
74
+ </global>
75
+ <adminhtml>
76
+ <acl>
77
+ <resources>
78
+ <admin>
79
+ <children>
80
+ <system>
81
+ <children>
82
+ <config>
83
+ <children>
84
+ <windsorcircle_export_options>
85
+ <title>WindsorCircle Module Section</title>
86
+ </windsorcircle_export_options>
87
+ </children>
88
+ </config>
89
+ </children>
90
+ </system>
91
+ </children>
92
+ </admin>
93
+ </resources>
94
+ </acl>
95
+ </adminhtml>
96
+ <default>
97
+ <windsorcircle_export_options>
98
+ <messages>
99
+ <client_name></client_name>
100
+ <api_key></api_key>
101
+ <ftp_type>2</ftp_type>
102
+ <ftp_host>ftp.windsorcircle.com</ftp_host>
103
+ <ftp_folder>upload</ftp_folder>
104
+ <ftp_user></ftp_user>
105
+ <ftp_password></ftp_password>
106
+ <public_key>-----BEGIN PUBLIC KEY-----
107
+ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCphQZPmjDiTiS1lqtamdJCTx2B
108
+ sl9+Sw20l/tDjUIDjoeOT8ZUHhMTYrFNarHwsfubjKW359hV4MZbpLeC65Ceiwes
109
+ eZuWNmGKJ9Uv/QLv2Qz1PEz47Z3OI88O9o61c2Fepk40ff/Ej2la4CbusQNDZpND
110
+ beaImcdzS0ZXTbH1MwIDAQAB
111
+ -----END PUBLIC KEY-----</public_key>
112
+ <brand_attribute>0</brand_attribute>
113
+ <canceled_state>canceled,closed</canceled_state>
114
+ <image_type>1</image_type>
115
+ <inventory_enable>0</inventory_enable>
116
+ <store>0</store>
117
+ </messages>
118
+ <options>
119
+ <enable_report_output>1</enable_report_output>
120
+ </options>
121
+ </windsorcircle_export_options>
122
+ </default>
123
+ </config>
app/code/local/Windsorcircle/Export/etc/system.xml ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <config>
2
+ <tabs>
3
+ <windsorcircleexportconfig translate="label" module="windsorcircle_export">
4
+ <label>WindsorCircle Config</label>
5
+ <sort_order>99999</sort_order>
6
+ </windsorcircleexportconfig>
7
+ </tabs>
8
+ <sections>
9
+ <windsorcircle_export_options translate="label" module="windsorcircle_export">
10
+ <label>Export Config Options</label>
11
+ <tab>windsorcircleexportconfig</tab>
12
+ <frontend_type>text</frontend_type>
13
+ <sort_order>1000</sort_order>
14
+ <show_in_default>1</show_in_default>
15
+ <show_in_website>0</show_in_website>
16
+ <show_in_store>0</show_in_store>
17
+ <groups>
18
+ <messages translate="label">
19
+ <label>Windsor Circle Config</label>
20
+ <frontend_type>text</frontend_type>
21
+ <sort_order>1</sort_order>
22
+ <show_in_default>1</show_in_default>
23
+ <show_in_website>1</show_in_website>
24
+ <show_in_store>1</show_in_store>
25
+ <fields>
26
+ <current_version translate="label">
27
+ <label>Current Version</label>
28
+ <frontend_type>label</frontend_type>
29
+ <frontend_model>Windsorcircle_Export_Block_Adminhtml_Version</frontend_model>
30
+ <sort_order>10</sort_order>
31
+ <show_in_default>1</show_in_default>
32
+ <show_in_website>0</show_in_website>
33
+ <show_in_store>0</show_in_store>
34
+ </current_version>
35
+ <client_name translate="label">
36
+ <label>Client Name</label>
37
+ <frontend_type>text</frontend_type>
38
+ <sort_order>20</sort_order>
39
+ <show_in_default>1</show_in_default>
40
+ <show_in_website>1</show_in_website>
41
+ <show_in_store>1</show_in_store>
42
+ </client_name>
43
+ <api_key translate="label">
44
+ <label>API Key</label>
45
+ <frontend_type>text</frontend_type>
46
+ <sort_order>30</sort_order>
47
+ <show_in_default>1</show_in_default>
48
+ <show_in_website>1</show_in_website>
49
+ <show_in_store>1</show_in_store>
50
+ </api_key>
51
+ <ftp_type translate="label">
52
+ <label>FTP Type</label>
53
+ <frontend_type>select</frontend_type>
54
+ <source_model>windsorcircle_export/ftp_type</source_model>
55
+ <sort_order>40</sort_order>
56
+ <show_in_default>1</show_in_default>
57
+ <show_in_website>1</show_in_website>
58
+ <show_in_store>1</show_in_store>
59
+ </ftp_type>
60
+ <ftp_host translate="label">
61
+ <label>FTP Host</label>
62
+ <frontend_type>text</frontend_type>
63
+ <sort_order>50</sort_order>
64
+ <show_in_default>1</show_in_default>
65
+ <show_in_website>1</show_in_website>
66
+ <show_in_store>1</show_in_store>
67
+ </ftp_host>
68
+ <ftp_folder>
69
+ <label>FTP Folder</label>
70
+ <comment>Folder to upload data, no leading or ending slash(/)</comment>
71
+ <frontend_type>text</frontend_type>
72
+ <sort_order>60</sort_order>
73
+ <show_in_default>1</show_in_default>
74
+ <show_in_website>1</show_in_website>
75
+ <show_in_store>1</show_in_store>
76
+ </ftp_folder>
77
+ <ftp_user translate="label">
78
+ <label>FTP User</label>
79
+ <frontend_type>text</frontend_type>
80
+ <sort_order>70</sort_order>
81
+ <show_in_default>1</show_in_default>
82
+ <show_in_website>1</show_in_website>
83
+ <show_in_store>1</show_in_store>
84
+ </ftp_user>
85
+ <ftp_password translate="label">
86
+ <label>FTP Password</label>
87
+ <frontend_type>password</frontend_type>
88
+ <sort_order>80</sort_order>
89
+ <show_in_default>1</show_in_default>
90
+ <show_in_website>1</show_in_website>
91
+ <show_in_store>1</show_in_store>
92
+ </ftp_password>
93
+ <public_key translate="label">
94
+ <label>Public Key</label>
95
+ <frontend_type>textarea</frontend_type>
96
+ <sort_order>90</sort_order>
97
+ <show_in_default>1</show_in_default>
98
+ <show_in_website>1</show_in_website>
99
+ <show_in_store>1</show_in_store>
100
+ </public_key>
101
+ <store translate="label">
102
+ <label>Store Selection</label>
103
+ <frontend_type>multiselect</frontend_type>
104
+ <source_model>windsorcircle_export/source_store</source_model>
105
+ <sort_order>95</sort_order>
106
+ <show_in_default>1</show_in_default>
107
+ <show_in_website>0</show_in_website>
108
+ <show_in_store>0</show_in_store>
109
+ </store>
110
+ <brand_attribute>
111
+ <label>Brand Attribute</label>
112
+ <comment>If no attribute is selected then this will use the 'brand' attribute code</comment>
113
+ <frontend_type>select</frontend_type>
114
+ <source_model>windsorcircle_export/brand_attribute</source_model>
115
+ <sort_order>100</sort_order>
116
+ <show_in_default>1</show_in_default>
117
+ <show_in_website>1</show_in_website>
118
+ <show_in_store>1</show_in_store>
119
+ </brand_attribute>
120
+ <canceled_state translate="label">
121
+ <label>Canceled State</label>
122
+ <frontend_type>multiselect</frontend_type>
123
+ <source_model>windsorcircle_export/source_canceled_state</source_model>
124
+ <sort_order>105</sort_order>
125
+ <show_in_default>1</show_in_default>
126
+ <show_in_website>1</show_in_website>
127
+ <show_in_store>1</show_in_store>
128
+ <can_be_empty>1</can_be_empty>
129
+ </canceled_state>
130
+ <image_type translate="label">
131
+ <label>Image Type</label>
132
+ <frontend_type>select</frontend_type>
133
+ <source_model>windsorcircle_export/image_type</source_model>
134
+ <sort_order>110</sort_order>
135
+ <show_in_default>1</show_in_default>
136
+ <show_in_website>1</show_in_website>
137
+ <show_in_store>1</show_in_store>
138
+ </image_type>
139
+ <memory_limit translate="label">
140
+ <label>Memory limit value (in MBytes)</label>
141
+ <frontend_type>text</frontend_type>
142
+ <sort_order>120</sort_order>
143
+ <show_in_default>1</show_in_default>
144
+ <show_in_website>0</show_in_website>
145
+ <show_in_store>0</show_in_store>
146
+ <comment><![CDATA[Set memory limit for module. If it's not specified or
147
+ value is non numeric - default system settings will be used. Example value 512M should be
148
+ entered as 512]]></comment>
149
+ </memory_limit>
150
+ <inventory_enable translate="label">
151
+ <label>Inventory Updates</label>
152
+ <frontend_type>select</frontend_type>
153
+ <source_model>adminhtml/system_config_source_yesno</source_model>
154
+ <sort_order>130</sort_order>
155
+ <show_in_default>1</show_in_default>
156
+ <show_in_website>0</show_in_website>
157
+ <show_in_store>0</show_in_store>
158
+ <comment><![CDATA[When enabled this will update the product inventory counts in Windsor Circle
159
+ for all items purchased. Enable this and notify Windsor Circle if you want to limit product recommendations
160
+ to in stock items]]></comment>
161
+ </inventory_enable>
162
+ <custom_product_attributes translate="label">
163
+ <label>Custom Product Attributes</label>
164
+ <frontend_model>windsorcircle_export/adminhtml_form_field_product_attributes</frontend_model>
165
+ <backend_model>windsorcircle_export/system_config_backend_attributes</backend_model>
166
+ <sort_order>140</sort_order>
167
+ <show_in_default>1</show_in_default>
168
+ <show_in_website>0</show_in_website>
169
+ <show_in_store>0</show_in_store>
170
+ </custom_product_attributes>
171
+ <custom_customer_attributes translate="label">
172
+ <label>Custom Customer Attributes</label>
173
+ <frontend_model>windsorcircle_export/adminhtml_form_field_customer_attributes</frontend_model>
174
+ <backend_model>windsorcircle_export/system_config_backend_attributes</backend_model>
175
+ <sort_order>150</sort_order>
176
+ <show_in_default>1</show_in_default>
177
+ <show_in_website>0</show_in_website>
178
+ <show_in_store>0</show_in_store>
179
+ </custom_customer_attributes>
180
+ <custom_customer_address_attributes translate="label">
181
+ <label>Custom Customer Address Attributes</label>
182
+ <frontend_model>windsorcircle_export/adminhtml_form_field_customer_address_attributes</frontend_model>
183
+ <backend_model>windsorcircle_export/system_config_backend_attributes</backend_model>
184
+ <sort_order>160</sort_order>
185
+ <show_in_default>1</show_in_default>
186
+ <show_in_website>0</show_in_website>
187
+ <show_in_store>0</show_in_store>
188
+ </custom_customer_address_attributes>
189
+ <custom_order_attributes translate="label">
190
+ <label>Custom Order Fields</label>
191
+ <frontend_model>windsorcircle_export/adminhtml_form_field_order_fields</frontend_model>
192
+ <backend_model>windsorcircle_export/system_config_backend_attributes</backend_model>
193
+ <sort_order>170</sort_order>
194
+ <show_in_default>1</show_in_default>
195
+ <show_in_website>0</show_in_website>
196
+ <show_in_store>0</show_in_store>
197
+ </custom_order_attributes>
198
+ <custom_order_item_buy_request_attributes translate="label">
199
+ <label>Custom Order Item Buy Request Options</label>
200
+ <frontend_model>windsorcircle_export/adminhtml_form_field_order_item_buy_request</frontend_model>
201
+ <backend_model>windsorcircle_export/system_config_backend_attributes</backend_model>
202
+ <sort_order>180</sort_order>
203
+ <show_in_default>1</show_in_default>
204
+ <show_in_website>0</show_in_website>
205
+ <show_in_store>0</show_in_store>
206
+ </custom_order_item_buy_request_attributes>
207
+ </fields>
208
+ </messages>
209
+ </groups>
210
+ </windsorcircle_export_options>
211
+ </sections>
212
+ </config>
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Windsor_Circle_Extension</name>
4
+ <version>1.0.97</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.windsorcircle.com/terms/magento-extension-license">Commercial</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Windsor Circle Predictive Marketing Platform</summary>
10
+ <description>Windsor Circle is a Predictive Lifecycle and Retention Marketing platform. We help retailers grow customer lifetime value and increase customer retention. Our clients see an average of 10x ROI and 17% lift in retention rates after 12 months. We have the industry&#x2019;s only guaranteed, enterprise grade data integrations between eCommerce and email software. Our platform includes a retention analytics suite, custom segmentation, and behavioral tracking to build rich consumer profiles.</description>
11
+ <notes>Updates to support custom fields in orders, bug fixes.</notes>
12
+ <authors><author><name>Andrew Pearson</name><user>WindsorCircle</user><email>partners@windsorcircle.com</email></author></authors>
13
+ <date>2016-06-10</date>
14
+ <time>18:51:52</time>
15
+ <contents><target name="magelocal"><dir name="Windsorcircle"><dir name="Export"><dir name="Block"><dir name="Adminhtml"><dir name="Form"><dir name="Field"><dir name="Customer"><dir name="Address"><file name="Attributes.php" hash="ffdbb6defd646c4c9b6f30f4787a6c9b"/><file name="Options.php" hash="c31d034ddccb6c181f21690e4326612e"/></dir><file name="Attributes.php" hash="7e9c9ca16a1adae73eb30aeef8b63b79"/><file name="Options.php" hash="102f0eb1087eaaf80a250177b6023141"/></dir><file name="Display.php" hash="9e43c94c67470327946438bea595107f"/><dir name="Order"><file name="Fields.php" hash="4024a4f2a592735a59c846f70f93aec9"/><dir name="Item"><dir name="Buy"><file name="Options.php" hash="9607b09e25d5f0f15f1d8498d2f16534"/><file name="Request.php" hash="358803606bd27be73ff2c911d391e3cf"/></dir></dir><file name="Options.php" hash="3f73e1287478bc65e4cba4c6212690b2"/></dir><dir name="Product"><file name="Attributes.php" hash="8741ae129b588fb9d2e7ff1ee9689596"/><file name="Options.php" hash="edf12c61ec3a3e047c29af63d8724a5a"/><file name="Options.php.bak" hash="95619f036b719dc584186452a33ef355"/></dir></dir></dir><file name="Version.php" hash="f8f4b7485ab0d136401f01e9284b93a7"/></dir></dir><dir name="Helper"><file name="Data.php" hash="a4da86ffde719c3f30ddd59b44fcbf9c"/></dir><dir name="Model"><dir name="Brand"><file name="Attribute.php" hash="952d937cce66c6a625810390b14ae02c"/></dir><file name="Date.php" hash="6b058b1291acdf50a214b794e3390540"/><file name="Format.php" hash="b7163120cc8e0581db17133ec2c29fce"/><dir name="Ftp"><file name="Type.php" hash="897f4164c60e418e521a813626d3a1b6"/></dir><file name="Ftp.php" hash="938aea2ecb855882930a07486d3a33ed"/><dir name="Image"><file name="Type.php" hash="da2f31fb30086cf41a2864fc7310d9cb"/></dir><file name="Observer.php" hash="06d03cdf264260f886141a499ec3a834"/><file name="Openssl.php" hash="f041b86a1d60e93300f03a32d7f42813"/><file name="Order.php" hash="30e7ee92b2a699c686d741c69250f712"/><file name="Products.php" hash="9cd67a7116a94aae0353645c273ba352"/><file name="Sftp.php" hash="deda9d1550c245a4accdb98508dc0cb3"/><dir name="Source"><dir name="Canceled"><file name="State.php" hash="e8d6825e5f43242f53a278ab31b736a9"/><file name="Status.php" hash="d92dd9116863e492325a35c97667c8fb"/></dir><file name="Store.php" hash="7875737e93fb61030a3e6391b9535785"/></dir><file name="State.php" hash="71b419e3c4176d5740e9fa032d14d5fd"/><file name="Status.php" hash="ba65dff129509be340941682abf2cbdc"/><dir name="System"><dir name="Config"><dir name="Backend"><file name="Attributes.php" hash="1c601b801c01189933ea409592d1cd51"/></dir></dir></dir></dir><dir name="controllers"><file name="Background.php" hash="e4daa88469e6f3c13e8355da91699a6d"/><file name="IndexController.php" hash="c8e28623b072ea7d8e4b2f6b2b25f28e"/><file name="LoadCartController.php" hash="ec2fbe6c9aaa78bef5f8aa829c99c451"/></dir><dir name="etc"><file name="config.xml" hash="264d5d7058dbc151565001fbae0a6fa8"/><file name="system.xml" hash="6977c82c8a127c83590dc26220e1157f"/></dir></dir></dir><dir name="modules"><file name="Windsorcircle_Export.xml" hash=""/></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>