Shippit_Shippit - Version 4.3.4

Version Notes

Shippit Magento Integration module, using the Shippit v3 API.

Allows for retrieving shipping quotes during checkout and sending orders to Shippit.

Also adds Australian States and Territories to the available region options and Authority to Leave and Delivery Comments to the checkout process.

Download this release

Release Info

Developer Matthew Muscat
Extension Shippit_Shippit
Version 4.3.4
Comparing to
See all releases


Version 4.3.4

Files changed (84) hide show
  1. app/code/community/Shippit/Shippit/Block/Adminhtml/Sales/Order.php +28 -0
  2. app/code/community/Shippit/Shippit/Block/Adminhtml/Sales/Order/Grid.php +270 -0
  3. app/code/community/Shippit/Shippit/Block/Adminhtml/Sales/Order/Items.php +57 -0
  4. app/code/community/Shippit/Shippit/Block/Adminhtml/System/Config/Form/Field/Renderer/Shipping/Methods.php +32 -0
  5. app/code/community/Shippit/Shippit/Block/Adminhtml/System/Config/Form/Field/Renderer/Shippit/ServiceClass.php +34 -0
  6. app/code/community/Shippit/Shippit/Block/Adminhtml/System/Config/Form/Field/Sync/Order/ShippingMethodMapping.php +40 -0
  7. app/code/community/Shippit/Shippit/Block/Adminhtml/System/Config/Form/Fieldset/Version.php +42 -0
  8. app/code/community/Shippit/Shippit/Block/Checkout/Cart/Shipping.php +40 -0
  9. app/code/community/Shippit/Shippit/Block/Checkout/Shipping/AuthorityToLeave.php +88 -0
  10. app/code/community/Shippit/Shippit/Block/Checkout/Shipping/DeliveryInstructions.php +83 -0
  11. app/code/community/Shippit/Shippit/Exception.php +20 -0
  12. app/code/community/Shippit/Shippit/Helper/Api.php +174 -0
  13. app/code/community/Shippit/Shippit/Helper/Bugsnag.php +122 -0
  14. app/code/community/Shippit/Shippit/Helper/Carrier.php +89 -0
  15. app/code/community/Shippit/Shippit/Helper/Checkout.php +57 -0
  16. app/code/community/Shippit/Shippit/Helper/Data.php +155 -0
  17. app/code/community/Shippit/Shippit/Helper/Order/Items.php +150 -0
  18. app/code/community/Shippit/Shippit/Helper/Sync/Order.php +127 -0
  19. app/code/community/Shippit/Shippit/Helper/Sync/Shipping.php +57 -0
  20. app/code/community/Shippit/Shippit/Model/Api/Order.php +156 -0
  21. app/code/community/Shippit/Shippit/Model/Logger.php +101 -0
  22. app/code/community/Shippit/Shippit/Model/Observer/Adminhtml/Sales/Order.php +59 -0
  23. app/code/community/Shippit/Shippit/Model/Observer/Order/Sync.php +116 -0
  24. app/code/community/Shippit/Shippit/Model/Observer/Quote/AuthorityToLeave.php +58 -0
  25. app/code/community/Shippit/Shippit/Model/Observer/Quote/DeliveryInstructions.php +54 -0
  26. app/code/community/Shippit/Shippit/Model/Observer/Shipping/Tracking.php +34 -0
  27. app/code/community/Shippit/Shippit/Model/Observer/Shippit.php +57 -0
  28. app/code/community/Shippit/Shippit/Model/Observer/System/Config.php +105 -0
  29. app/code/community/Shippit/Shippit/Model/Request/Api/Order.php +659 -0
  30. app/code/community/Shippit/Shippit/Model/Request/Api/Shipment.php +143 -0
  31. app/code/community/Shippit/Shippit/Model/Request/Sync/Order.php +187 -0
  32. app/code/community/Shippit/Shippit/Model/Resource/Setup.php +20 -0
  33. app/code/community/Shippit/Shippit/Model/Resource/Sync/Order.php +67 -0
  34. app/code/community/Shippit/Shippit/Model/Resource/Sync/Order/Collection.php +23 -0
  35. app/code/community/Shippit/Shippit/Model/Resource/Sync/Order/Item.php +23 -0
  36. app/code/community/Shippit/Shippit/Model/Resource/Sync/Order/Item/Collection.php +43 -0
  37. app/code/community/Shippit/Shippit/Model/Shipping/Carrier/Shippit.php +355 -0
  38. app/code/community/Shippit/Shippit/Model/Shippit.php +66 -0
  39. app/code/community/Shippit/Shippit/Model/Sync/Order.php +127 -0
  40. app/code/community/Shippit/Shippit/Model/Sync/Order/Config.php +27 -0
  41. app/code/community/Shippit/Shippit/Model/Sync/Order/Item.php +28 -0
  42. app/code/community/Shippit/Shippit/Model/System/Config/Source/Catalog/Attributes.php +50 -0
  43. app/code/community/Shippit/Shippit/Model/System/Config/Source/Catalog/Attributes/Location.php +50 -0
  44. app/code/community/Shippit/Shippit/Model/System/Config/Source/Catalog/Products.php +41 -0
  45. app/code/community/Shippit/Shippit/Model/System/Config/Source/Shipping/Methods.php +48 -0
  46. app/code/community/Shippit/Shippit/Model/System/Config/Source/Shippit/Environment.php +34 -0
  47. app/code/community/Shippit/Shippit/Model/System/Config/Source/Shippit/MaxTimeslots.php +42 -0
  48. app/code/community/Shippit/Shippit/Model/System/Config/Source/Shippit/Methods.php +54 -0
  49. app/code/community/Shippit/Shippit/Model/System/Config/Source/Shippit/Sync/Mode.php +38 -0
  50. app/code/community/Shippit/Shippit/Model/System/Config/Source/Shippit/Sync/SendAllOrders.php +52 -0
  51. app/code/community/Shippit/Shippit/controllers/Adminhtml/Shippit/Order/SyncController.php +120 -0
  52. app/code/community/Shippit/Shippit/controllers/Adminhtml/Shippit/OrderController.php +212 -0
  53. app/code/community/Shippit/Shippit/controllers/OrderController.php +221 -0
  54. app/code/community/Shippit/Shippit/data/shippit_setup/data-install-4.0.0.php +157 -0
  55. app/code/community/Shippit/Shippit/data/shippit_setup/data-upgrade-4.1.0-4.1.1.php +120 -0
  56. app/code/community/Shippit/Shippit/data/shippit_setup/data-upgrade-4.1.6-4.1.7.php +48 -0
  57. app/code/community/Shippit/Shippit/data/shippit_setup/data-upgrade-4.2.3-4.2.4.php +53 -0
  58. app/code/community/Shippit/Shippit/data/shippit_setup/data-upgrade-4.3.2-4.3.3.php +35 -0
  59. app/code/community/Shippit/Shippit/etc/adminhtml.xml +72 -0
  60. app/code/community/Shippit/Shippit/etc/config.xml +304 -0
  61. app/code/community/Shippit/Shippit/etc/system.xml +367 -0
  62. app/code/community/Shippit/Shippit/sql/shippit_setup/install-4.0.0.php +197 -0
  63. app/code/community/Shippit/Shippit/sql/shippit_setup/upgrade-4.0.9-4.1.0.php +165 -0
  64. app/code/community/Shippit/Shippit/sql/shippit_setup/upgrade-4.1.0-4.1.1.php +33 -0
  65. app/code/community/Shippit/Shippit/sql/shippit_setup/upgrade-4.2.5-4.2.6.php +46 -0
  66. app/code/community/Shippit/Shippit/sql/shippit_setup/upgrade-4.2.6-4.3.0.php +35 -0
  67. app/design/adminhtml/default/default/layout/shippit.xml +8 -0
  68. app/design/adminhtml/default/default/template/shippit/system/config/form/field/array.phtml +177 -0
  69. app/design/frontend/base/default/layout/shippit.xml +32 -0
  70. app/design/frontend/base/default/template/shippit/checkout/onepage/shipping_method.phtml +44 -0
  71. app/design/frontend/base/default/template/shippit/checkout/onepage/shipping_method/authoritytoleave.phtml +28 -0
  72. app/design/frontend/base/default/template/shippit/checkout/onepage/shipping_method/deliveryinstructions.phtml +30 -0
  73. app/design/frontend/base/default/template/shippit/email/order/shipment/track.phtml +54 -0
  74. app/etc/modules/Shippit_Shippit.xml +13 -0
  75. lib/shippit-bugsnag/Autoload.php +15 -0
  76. lib/shippit-bugsnag/Client.php +557 -0
  77. lib/shippit-bugsnag/Configuration.php +101 -0
  78. lib/shippit-bugsnag/Diagnostics.php +54 -0
  79. lib/shippit-bugsnag/Error.php +245 -0
  80. lib/shippit-bugsnag/ErrorTypes.php +118 -0
  81. lib/shippit-bugsnag/Notification.php +198 -0
  82. lib/shippit-bugsnag/Request.php +103 -0
  83. lib/shippit-bugsnag/Stacktrace.php +145 -0
  84. package.xml +26 -0
app/code/community/Shippit/Shippit/Block/Adminhtml/Sales/Order.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Block_Adminhtml_Sales_Order extends Mage_Adminhtml_Block_Widget_Grid_Container
18
+ {
19
+ public function __construct()
20
+ {
21
+ $this->_blockGroup = 'shippit';
22
+ $this->_controller = 'adminhtml_sales_order';
23
+ $this->_headerText = Mage::helper('shippit')->__('Shippit Orders');
24
+
25
+ parent::__construct();
26
+ $this->_removeButton('add');
27
+ }
28
+ }
app/code/community/Shippit/Shippit/Block/Adminhtml/Sales/Order/Grid.php ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Block_Adminhtml_Sales_Order_Grid extends Mage_Adminhtml_Block_Widget_Grid
18
+ {
19
+ public function __construct()
20
+ {
21
+ parent::__construct();
22
+ $this->setId('shippit_order_grid');
23
+ $this->setDefaultSort('sync_id');
24
+ $this->setDefaultDir('DESC');
25
+ $this->setSaveParametersInSession(true);
26
+ $this->setUseAjax(true);
27
+ }
28
+
29
+ protected function _prepareCollection()
30
+ {
31
+ $collection = Mage::getResourceModel('shippit/sync_order_collection')
32
+ ->addFieldToSelect(
33
+ array(
34
+ 'sync_id',
35
+ 'service_class' => 'shipping_method',
36
+ 'track_number',
37
+ 'synced_at',
38
+ 'sync_status' => 'status'
39
+ )
40
+ )
41
+ ->join(
42
+ array(
43
+ 'order' => 'sales/order'
44
+ ),
45
+ 'main_table.order_id = order.entity_id',
46
+ array(
47
+ 'increment_id' => 'increment_id',
48
+ 'grand_total' => 'grand_total',
49
+ 'order_state' => 'state',
50
+ 'order_status' => 'status',
51
+ 'created_at' => 'created_at',
52
+ )
53
+ )
54
+ ->addFilterToMap(
55
+ 'sync_status',
56
+ 'main_table.status'
57
+ )
58
+ ->addFilterToMap(
59
+ 'service_class',
60
+ 'main_table.shipping_method'
61
+ )
62
+ ->addFilterToMap(
63
+ 'order_state',
64
+ 'order.state'
65
+ )
66
+ ->addFilterToMap(
67
+ 'order_status',
68
+ 'order.status'
69
+ );
70
+
71
+ $this->setCollection($collection);
72
+ parent::_prepareCollection();
73
+
74
+ return $this;
75
+ }
76
+
77
+ protected function _prepareColumns()
78
+ {
79
+ $helper = Mage::helper('shippit');
80
+ $currency = (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE);
81
+
82
+ $this->addColumn('sync_id', array(
83
+ 'header' => $helper->__('ID'),
84
+ 'index' => 'sync_id',
85
+ 'column_css_class' => 'no-display',
86
+ 'header_css_class' => 'no-display'
87
+ ));
88
+
89
+ $this->addColumn('increment_id', array(
90
+ 'header' => $helper->__('Order #'),
91
+ 'index' => 'increment_id',
92
+ ));
93
+
94
+ $this->addColumn('purchased_on', array(
95
+ 'header' => $helper->__('Purchased On'),
96
+ 'type' => 'datetime',
97
+ 'index' => 'created_at'
98
+ ));
99
+
100
+ $this->addColumn('items', array(
101
+ 'filter' => false,
102
+ 'header' => $helper->__('Items'),
103
+ 'getter' => 'getItems',
104
+ 'renderer' => 'shippit/adminhtml_sales_order_items'
105
+ ));
106
+
107
+ $this->addColumn('grand_total', array(
108
+ 'header' => $helper->__('Grand Total'),
109
+ 'index' => 'grand_total',
110
+ 'type' => 'currency',
111
+ 'currency_code' => $currency
112
+ ));
113
+
114
+ $this->addColumn('service_class', array(
115
+ 'header' => $helper->__('Service Class'),
116
+ 'index' => 'service_class',
117
+ 'frame_callback' => array($this, 'decorateServiceClass'),
118
+ 'type' => 'options',
119
+ 'options' => Mage::getSingleton('shippit/system_config_source_shippit_methods')->getMethods(true)
120
+ ));
121
+
122
+ $this->addColumn('order_state', array(
123
+ 'header' => $helper->__('State'),
124
+ 'index' => 'order_state',
125
+ 'type' => 'options',
126
+ 'options' => Mage::getSingleton('sales/order_config')->getStates(),
127
+ ));
128
+
129
+ $this->addColumn('order_status', array(
130
+ 'header' => $helper->__('Status'),
131
+ 'index' => 'order_status',
132
+ 'type' => 'options',
133
+ 'options' => Mage::getSingleton('sales/order_config')->getStatuses(),
134
+ ));
135
+
136
+ $this->addColumn('track_number', array(
137
+ 'header' => $helper->__('Shippit Reference'),
138
+ 'index' => 'track_number',
139
+ 'frame_callback' => array($this, 'decorateTrackNumber'),
140
+ ));
141
+
142
+ $this->addColumn('synced_at', array(
143
+ 'header' => $helper->__('Synced At'),
144
+ 'type' => 'datetime',
145
+ 'index' => 'synced_at'
146
+ ));
147
+
148
+ $this->addColumn('sync_status', array(
149
+ 'header' => $helper->__('Sync Status'),
150
+ 'index' => 'sync_status',
151
+ 'type' => 'options',
152
+ 'options' => Mage::getSingleton('shippit/sync_order_config')->getStatus(),
153
+ 'frame_callback' => array($this, 'decorateStatus'),
154
+ ));
155
+
156
+ $this->addColumn('actions', array(
157
+ 'header' => Mage::helper('shippit')->__('Action'),
158
+ 'width' => '150px',
159
+ 'type' => 'action',
160
+ 'getter' => 'getId',
161
+ 'actions' => array(
162
+ array(
163
+ 'caption' => Mage::helper('shippit')->__('Sync Now'),
164
+ 'url' => array('base'=>'*/*/sync'),
165
+ 'field' => 'id'
166
+ ),
167
+ array('caption' => Mage::helper('shippit')->__('Schedule Sync'),
168
+ 'url' => array('base'=>'*/*/schedule'),
169
+ 'field' => 'id'
170
+ ),
171
+ array('caption' => Mage::helper('shippit')->__('Remove'),
172
+ 'url' => array('base'=>'*/*/remove'),
173
+ 'field' => 'id'
174
+ ),
175
+ 'filter' => false,
176
+ 'sortable' => false
177
+ )
178
+ ));
179
+
180
+ return parent::_prepareColumns();
181
+ }
182
+
183
+ public function decorateServiceClass($value)
184
+ {
185
+ return ucfirst($value);
186
+ }
187
+
188
+ public function decorateTrackNumber($value)
189
+ {
190
+ if (empty($value)) {
191
+ return $value;
192
+ }
193
+
194
+ $cell = sprintf(
195
+ '<a href="https://www.shippit.com/track/%s" title="Track Order" target="_blank">%s</a>',
196
+ $value,
197
+ $value
198
+ );
199
+
200
+ return $cell;
201
+ }
202
+
203
+ public function decorateStatus($value)
204
+ {
205
+ $cell = sprintf(
206
+ '<span class="grid-severity-%s"><span>%s</span></span>',
207
+ $this->getGridSeverity($value),
208
+ $value
209
+ );
210
+ return $cell;
211
+ }
212
+
213
+ public function getGridSeverity($value)
214
+ {
215
+ $gridSeverity = 'critical';
216
+
217
+ switch ($value) {
218
+ case Shippit_Shippit_Model_Sync_Order::STATUS_PENDING_TEXT:
219
+ $gridSeverity = 'minor';
220
+ break;
221
+ case Shippit_Shippit_Model_Sync_Order::STATUS_FAILED_TEXT:
222
+ $gridSeverity = 'critical';
223
+ break;
224
+ case Shippit_Shippit_Model_Sync_Order::STATUS_SYNCED_TEXT:
225
+ $gridSeverity = 'notice';
226
+ break;
227
+ }
228
+
229
+ return $gridSeverity;
230
+ }
231
+
232
+ protected function _prepareMassaction(){
233
+ $this->setMassactionIdField('sync_id');
234
+ $this->getMassactionBlock()->setFormFieldName('sync_ids');
235
+
236
+ $this->getMassactionBlock()->addItem(
237
+ 'Sync Now',
238
+ array(
239
+ 'label' => Mage::helper('shippit')->__('Sync Now'),
240
+ 'url' => $this->getUrl('*/*/massSync')
241
+ )
242
+ );
243
+
244
+ $this->getMassactionBlock()->addItem(
245
+ 'Schedule Sync',
246
+ array(
247
+ 'label' => Mage::helper('shippit')->__('Schedule Sync'),
248
+ 'url' => $this->getUrl('*/*/massSchedule')
249
+ )
250
+ );
251
+
252
+ $this->getMassactionBlock()->addItem(
253
+ 'Remove',
254
+ array(
255
+ 'label' => Mage::helper('shippit')->__('Remove'),
256
+ 'url' => $this->getUrl('*/*/massRemove')
257
+ )
258
+ );
259
+ }
260
+
261
+ public function getRowUrl($row)
262
+ {
263
+
264
+ }
265
+
266
+ public function getGridUrl()
267
+ {
268
+ return $this->getUrl('*/*/grid', array('_current'=>true));
269
+ }
270
+ }
app/code/community/Shippit/Shippit/Block/Adminhtml/Sales/Order/Items.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Block_Adminhtml_Sales_Order_Items extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
18
+ {
19
+
20
+ public function render(Varien_Object $row)
21
+ {
22
+ return $this->decorateItems($row->getItems());
23
+ }
24
+
25
+ public function decorateItems($items)
26
+ {
27
+ if (empty($items)) {
28
+ return 'All Items';
29
+ }
30
+
31
+ $table = '<table class="data-table orders-table" cellspacing="0">';
32
+ $table .= '<thead>';
33
+ $table .= '<tr>';
34
+ $table .= '<th>Sku</th>';
35
+ $table .= '<th>Title</th>';
36
+ $table .= '<th>Qty</th>';
37
+ $table .= '<th>Location</th>';
38
+ $table .= '</tr>';
39
+ $table .= '</thead>';
40
+
41
+ $table .= '<tbody>';
42
+
43
+ foreach ($items as $item) {
44
+ $table .= '<tr>';
45
+ $table .= '<td>' . $item->getSku() . '</td>';
46
+ $table .= '<td>' . $item->getTitle() . '</td>';
47
+ $table .= '<td>' . $item->getQty() . '</td>';
48
+ $table .= '<td>' . ($item->getLocation() ? $item->getLocation() : 'N/A') . '</td>';
49
+ $table .= '</tr>';
50
+ }
51
+
52
+ $table .= '</tbody>';
53
+ $table .= '</table>';
54
+
55
+ return $table;
56
+ }
57
+ }
app/code/community/Shippit/Shippit/Block/Adminhtml/System/Config/Form/Field/Renderer/Shipping/Methods.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Block_Adminhtml_System_Config_Form_Field_Renderer_Shipping_Methods extends Mage_Core_Block_Abstract
18
+ {
19
+ protected function _toHtml()
20
+ {
21
+ $column = $this->getColumn();
22
+
23
+ // retrieve a list of shipping method, excluding shippit shipping methods
24
+ $options = Mage::getModel('shippit/system_config_source_shipping_methods')->toOptionArray(true);
25
+
26
+ foreach ($options as $option) {
27
+ $optionsHtml[] = '<option value="' . $option['value'] . '">' . $option['label'] . "</option>";
28
+ }
29
+
30
+ return '<select class="'.$column['class'].'" style="'.$column['style'].'" name="'.$this->getInputName().'">'.implode('', $optionsHtml).'</select>';
31
+ }
32
+ }
app/code/community/Shippit/Shippit/Block/Adminhtml/System/Config/Form/Field/Renderer/Shippit/ServiceClass.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Block_Adminhtml_System_Config_Form_Field_Renderer_Shippit_ServiceClass extends Mage_Core_Block_Abstract
18
+ {
19
+ protected function _toHtml()
20
+ {
21
+ $column = $this->getColumn();
22
+
23
+ // Priority Services are not presented here
24
+ // as they are only available via live quoting
25
+ // due to service availabilty requirements
26
+ $options = Mage::getModel('shippit/system_config_source_shippit_methods')->toOptionArray(false);
27
+
28
+ foreach ($options as $option) {
29
+ $optionsHtml[] = '<option value="' . $option['value'] . '">' . $option['label'] . "</option>";
30
+ }
31
+
32
+ return '<select class="'.$column['class'].'" style="'.$column['style'].'" name="'.$this->getInputName().'">'.implode('', $optionsHtml).'</select>';
33
+ }
34
+ }
app/code/community/Shippit/Shippit/Block/Adminhtml/System/Config/Form/Field/Sync/Order/ShippingMethodMapping.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Block_Adminhtml_System_Config_Form_Field_Sync_Order_ShippingMethodMapping extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
18
+ {
19
+ public function __construct()
20
+ {
21
+ $this->addColumn('shipping_method', array(
22
+ 'label' => Mage::helper('shippit')->__('Shipping Method'),
23
+ 'style' => 'width:200px',
24
+ 'renderer' => Mage::app()->getLayout()->createBlock('shippit/adminhtml_system_config_form_field_renderer_shipping_methods'),
25
+ ));
26
+ $this->addColumn('shippit_service', array(
27
+ 'label' => Mage::helper('shippit')->__('Shippit Service Class'),
28
+ 'style' => 'width:200px',
29
+ 'renderer' => Mage::app()->getLayout()->createBlock('shippit/adminhtml_system_config_form_field_renderer_shippit_serviceClass'),
30
+ ));
31
+
32
+ $this->_addAfter = false;
33
+ $this->_addButtonLabel = Mage::helper('shippit')->__('Add Mapping');
34
+
35
+ parent::__construct();
36
+
37
+ // use the array template to auto populate the array of saved data
38
+ $this->setTemplate('shippit/system/config/form/field/array.phtml');
39
+ }
40
+ }
app/code/community/Shippit/Shippit/Block/Adminhtml/System/Config/Form/Fieldset/Version.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Block_Adminhtml_System_Config_Form_Fieldset_Version extends Mage_Adminhtml_Block_System_Config_Form_Fieldset
18
+ {
19
+ protected $_fieldRenderer;
20
+
21
+ public function render(Varien_Data_Form_Element_Abstract $element)
22
+ {
23
+ $html = '
24
+ <tr>
25
+ <td class="label"><label for="' . $element->getHtmlId() . '">' . $element->getLabel() . '</label>
26
+ </td>
27
+ <td class="value" id="version_info">' . Mage::helper('shippit')->getModuleVersion() . '</td>
28
+ </tr>
29
+ ';
30
+
31
+ return $html;
32
+ }
33
+
34
+ protected function _getFieldRenderer()
35
+ {
36
+ if (empty($this->_fieldRenderer)) {
37
+ $this->_fieldRenderer = Mage::getBlockSingleton('adminhtml/system_config_form_field');
38
+ }
39
+
40
+ return $this->_fieldRenderer;
41
+ }
42
+ }
app/code/community/Shippit/Shippit/Block/Checkout/Cart/Shipping.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Block_Checkout_Cart_Shipping extends Mage_Checkout_Block_Cart_Shipping
18
+ {
19
+ /**
20
+ * Show City in Shipping Estimation
21
+ *
22
+ * @return bool
23
+ */
24
+ public function getCityActive()
25
+ {
26
+ return (bool) Mage::helper('shippit/carrier')->isActive()
27
+ || parent::getCityActive();
28
+ }
29
+
30
+ /**
31
+ * Show State in Shipping Estimation
32
+ *
33
+ * @return bool
34
+ */
35
+ public function getStateActive()
36
+ {
37
+ return (bool) Mage::helper('shippit/carrier')->isActive()
38
+ || parent::getStateActive();
39
+ }
40
+ }
app/code/community/Shippit/Shippit/Block/Checkout/Shipping/AuthorityToLeave.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Block_Checkout_Shipping_AuthorityToLeave extends Mage_Core_Block_Template
18
+ {
19
+ protected $helper;
20
+
21
+ public function __construct()
22
+ {
23
+ $this->helper = Mage::helper('shippit/checkout');
24
+
25
+ parent::__construct();
26
+ }
27
+
28
+ /**
29
+ * Get label text for the authority to leave field
30
+ *
31
+ * @return string
32
+ */
33
+ public function getLabelText()
34
+ {
35
+ return Mage::helper('shippit')->__('Authority to Leave without Signature');
36
+ }
37
+
38
+ /**
39
+ * Get field id
40
+ *
41
+ * @return string
42
+ */
43
+ public function getFieldId()
44
+ {
45
+ return Mage::helper('shippit')->getAuthorityToLeaveId();
46
+ }
47
+
48
+ /**
49
+ * Get the quote object from the session
50
+ *
51
+ * @return [Mage_Sales_Model_Quote] The Quote object
52
+ */
53
+ private function _getQuote()
54
+ {
55
+ return Mage::getSingleton('checkout/session')->getQuote();
56
+ }
57
+
58
+ /**
59
+ * Get the value of the authority to leave
60
+ *
61
+ * @return [boolean] True or false
62
+ */
63
+ public function getValue()
64
+ {
65
+ $quote = $this->_getQuote();
66
+
67
+ if ($quote->getShippitAuthorityToLeave()) {
68
+ return true;
69
+ }
70
+ else {
71
+ return false;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Render Authority to Leave Block
77
+ *
78
+ * @return string
79
+ */
80
+ protected function _toHtml()
81
+ {
82
+ if (!$this->helper->isAuthorityToLeaveActive()) {
83
+ return '';
84
+ }
85
+
86
+ return parent::_toHtml();
87
+ }
88
+ }
app/code/community/Shippit/Shippit/Block/Checkout/Shipping/DeliveryInstructions.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Block_Checkout_Shipping_DeliveryInstructions extends Mage_Core_Block_Template
18
+ {
19
+ protected $helper;
20
+
21
+ public function __construct()
22
+ {
23
+ $this->helper = Mage::helper('shippit/checkout');
24
+
25
+ parent::__construct();
26
+ }
27
+
28
+ /**
29
+ * Get label text for the field
30
+ *
31
+ * @return string
32
+ */
33
+ public function getLabelText()
34
+ {
35
+ return Mage::helper('shippit')->__('Delivery Instructions');
36
+ }
37
+
38
+ /**
39
+ * Get field id
40
+ *
41
+ * @return string
42
+ */
43
+ public function getFieldId()
44
+ {
45
+ return Mage::helper('shippit')->getDeliveryInstructionsId();
46
+ }
47
+
48
+ /**
49
+ * Get the quote object from the session
50
+ *
51
+ * @return [Mage_Sales_Model_Quote] The Quote object
52
+ */
53
+ private function _getQuote()
54
+ {
55
+ return Mage::getSingleton('checkout/session')->getQuote();
56
+ }
57
+
58
+ /**
59
+ * Get the value of the field
60
+ *
61
+ * @return [string] The field value
62
+ */
63
+ public function getValue()
64
+ {
65
+ $quote = $this->_getQuote();
66
+
67
+ return $quote->getShippitDeliveryInstructions();
68
+ }
69
+
70
+ /**
71
+ * Render Delivery Instructions Block
72
+ *
73
+ * @return string
74
+ */
75
+ protected function _toHtml()
76
+ {
77
+ if (!$this->helper->isDeliveryInstructionsActive()) {
78
+ return '';
79
+ }
80
+
81
+ return parent::_toHtml();
82
+ }
83
+ }
app/code/community/Shippit/Shippit/Exception.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Exception extends Mage_Core_Exception
18
+ {
19
+
20
+ }
app/code/community/Shippit/Shippit/Helper/Api.php ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Helper_Api extends Mage_Core_Helper_Abstract
18
+ {
19
+ const API_ENDPOINT_PRODUCTION = 'https://www.shippit.com/api/3';
20
+ const API_ENDPOINT_STAGING = 'https://shippit-staging.herokuapp.com/api/3';
21
+ const API_TIMEOUT = 5;
22
+ const API_USER_AGENT = 'Shippit_Shippit for Magento';
23
+
24
+ protected $api;
25
+ protected $apiUrl;
26
+ protected $logger;
27
+
28
+ public function __construct()
29
+ {
30
+ $this->helper = Mage::helper('shippit');
31
+ $this->logger = Mage::getModel('shippit/logger');
32
+
33
+ // We use Zend_HTTP_Client instead of Varien_Http_Client,
34
+ // as Varien_Http_Client does not handle PUT requests correctly
35
+ $this->api = new Zend_Http_Client;
36
+ $this->api->setConfig(
37
+ array(
38
+ 'timeout' => self::API_TIMEOUT,
39
+ 'useragent' => self::API_USER_AGENT . ' v' . $this->helper->getModuleVersion(),
40
+ )
41
+ )
42
+ ->setHeaders('Content-Type', 'application/json');
43
+ }
44
+
45
+ public function getApiEndpoint()
46
+ {
47
+ $environment = $this->helper->getEnvironment();
48
+
49
+ if ($environment == 'production') {
50
+ return self::API_ENDPOINT_PRODUCTION;
51
+ }
52
+ else {
53
+ return self::API_ENDPOINT_STAGING;
54
+ }
55
+ }
56
+
57
+ public function getApiUri($path, $apiKey = null)
58
+ {
59
+ if (is_null($apiKey)) {
60
+ $apiKey = $this->helper->getApiKey();
61
+ }
62
+
63
+ return $this->getApiEndpoint() . '/' . $path . '?auth_token=' . $apiKey;
64
+ }
65
+
66
+ public function call($uri, $requestData, $method = Zend_Http_Client::POST, $exceptionOnResponseError = true, $apiKey = null)
67
+ {
68
+ $uri = $this->getApiUri($uri, $apiKey);
69
+
70
+ $jsonRequestData = json_encode($requestData);
71
+
72
+ $apiRequest = $this->api
73
+ ->setMethod($method)
74
+ ->setUri($uri);
75
+
76
+ if (!is_null($requestData)) {
77
+ $apiRequest->setRawData($jsonRequestData);
78
+ }
79
+
80
+ try {
81
+ $apiResponse = null;
82
+ $apiResponse = $apiRequest->request($method);
83
+
84
+ // debug logging
85
+ $this->prepareMatadata($uri, $requestData, $apiResponse);
86
+ $this->logger->log('API Request', "Request to $uri");
87
+ }
88
+ catch (Exception $e) {
89
+ $this->prepareMatadata($uri, $requestData, $apiResponse);
90
+ $this->logger->log('API Request Error', 'An API Request Error Occurred', Zend_Log::ERR);
91
+
92
+ throw Mage::Exception('Shippit_Shippit', 'An API Communication Error Occurred - ' . "\n" . $e->getTraceAsString());
93
+ }
94
+
95
+ if ($exceptionOnResponseError && $apiResponse->isError()) {
96
+ $message = 'API Response Error' . "\n";
97
+ $message .= 'Response: ' . $apiResponse->getStatus() . ' - ' . $apiResponse->getMessage() . "\n";
98
+
99
+ $this->prepareMatadata($uri, $requestData, $apiResponse);
100
+ $this->logger->log('API Response Error', 'An API Response Error Occurred');
101
+
102
+ throw Mage::Exception('Shippit_Shippit', $message);
103
+ }
104
+
105
+ $apiResponseBody = json_decode($apiResponse->getBody());
106
+
107
+ return $apiResponseBody;
108
+ }
109
+
110
+ protected function prepareMatadata($uri, $requestData, $apiResponse = null)
111
+ {
112
+ if ($this->logger->bugsnag) {
113
+ // get the core meta data
114
+ $metaData = Mage::helper('shippit/bugsnag')->getMetaData();
115
+ }
116
+ else {
117
+ $metaData = array();
118
+ }
119
+
120
+ // add the request meta data
121
+ $requestMetaData = array(
122
+ 'api_request' => array(
123
+ 'request_uri' => $uri,
124
+ 'request_body' => $requestData,
125
+ )
126
+ );
127
+
128
+ if (!is_null($apiResponse)) {
129
+ $requestMetaData['api_request']['response_code'] = $apiResponse->getStatus();
130
+ $requestMetaData['api_request']['response_body'] = json_decode($apiResponse->getBody());
131
+ }
132
+
133
+ $metaData = array_merge($metaData, $requestMetaData);
134
+
135
+ $this->logger->setMetaData($metaData);
136
+ }
137
+
138
+ public function getQuote(Varien_Object $requestData)
139
+ {
140
+ $requestData = array(
141
+ 'quote' => $requestData->toArray()
142
+ );
143
+
144
+ return $this->call('quotes', $requestData)
145
+ ->response;
146
+ }
147
+
148
+ public function sendOrder(Varien_Object $requestData, $apiKey = null)
149
+ {
150
+ $requestData = array(
151
+ 'order' => $requestData->toArray()
152
+ );
153
+
154
+ return $this->call('orders', $requestData, Zend_Http_Client::POST, true, $apiKey)
155
+ ->response;
156
+ }
157
+
158
+ public function getMerchant()
159
+ {
160
+ return $this->call('merchant', null, Zend_Http_Client::GET, false);
161
+ }
162
+
163
+ public function putMerchant($requestData, $exceptionOnResponseError = false)
164
+ {
165
+ $requestData = array(
166
+ 'merchant' => $requestData->toArray()
167
+ );
168
+
169
+ $url = $this->getApiUri('merchant');
170
+
171
+ return $this->call('merchant', $requestData, Zend_Http_Client::PUT, $exceptionOnResponseError)
172
+ ->response;
173
+ }
174
+ }
app/code/community/Shippit/Shippit/Helper/Bugsnag.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Helper_Bugsnag extends Mage_Core_Helper_Abstract
18
+ {
19
+ private $severites = 'fatal,error';
20
+ private $client = false;
21
+ private $shippitBugsnagApiKey = 'b2873ea2ae95a3c9f2cb63ca1557abb5';
22
+
23
+ public function init()
24
+ {
25
+ if (!$this->client) {
26
+ if (file_exists(Mage::getBaseDir('lib') . '/shippit-bugsnag/Autoload.php')) {
27
+ require_once(Mage::getBaseDir('lib') . '/shippit-bugsnag/Autoload.php');
28
+ }
29
+ else {
30
+ Mage::log('Shippit Bugsnag Error', 'Couldn\'t activate Bugsnag Error Monitoring due to missing Bugsnag PHP library!', null, 'shippit.log');
31
+
32
+ return false;
33
+ }
34
+
35
+ // Allow override of bugsnag key
36
+ // this can be your own bugsnag api key, or an empty string
37
+ // to disable bugsnag logging if required
38
+ $apiKey = Mage::getStoreConfig('shippit/bugsnag/api_key');
39
+
40
+ // If no api key is provided, use the shippit bugsnag api key
41
+ if (is_null($apiKey)) {
42
+ $apiKey = $this->shippitBugsnagApiKey;
43
+ }
44
+ // Otherwise, if the api key is an empty value,
45
+ // don't run bugsnag and return early
46
+ elseif (empty($apiKey)) {
47
+ return $this->client;
48
+ }
49
+
50
+ $this->client = new Bugsnag_Client($apiKey);
51
+ $this->client->setReleaseStage($this->getReleaseStage())
52
+ ->setErrorReportingLevel($this->getErrorReportingLevel())
53
+ ->setMetaData($this->getMetaData());
54
+
55
+ $this->client->setNotifier($this->getNotiferData());
56
+
57
+ set_error_handler(
58
+ array($this->client, "errorHandler")
59
+ );
60
+ set_exception_handler(
61
+ array($this->client, "exceptionHandler")
62
+ );
63
+ }
64
+
65
+ return $this->client;
66
+ }
67
+
68
+ public function getReleaseStage()
69
+ {
70
+ return Mage::getIsDeveloperMode() ? "development" : "production";
71
+ }
72
+
73
+ public function getMetaData()
74
+ {
75
+ $metaData = array();
76
+
77
+ $metaData['magento'] = array(
78
+ 'edition' => Mage::getEdition(),
79
+ 'version' => Mage::getVersion(),
80
+ );
81
+ $metaData['module'] = $this->getModuleInfo();
82
+ $metaData['store'] = array(
83
+ 'url' => Mage::getBaseUrl(),
84
+ 'store' => Mage::getStoreConfig('general/store_information/name'),
85
+ 'contact_number' => Mage::getStoreConfig('general/store_information/phone'),
86
+ );
87
+
88
+ return $metaData;
89
+ }
90
+
91
+ public function getModuleInfo()
92
+ {
93
+ return array(
94
+ 'name' => 'Shippit_Shippit',
95
+ 'version' => Mage::helper('shippit')->getModuleVersion(),
96
+ );
97
+ }
98
+
99
+ public function getNotiferData()
100
+ {
101
+ return $this->getModuleInfo();
102
+ }
103
+
104
+ private function getErrorReportingLevel()
105
+ {
106
+ if (empty($this->severites)) {
107
+ $severites = "fatal,error";
108
+ }
109
+ else {
110
+ $severites = $this->severites;
111
+ }
112
+
113
+ $level = 0;
114
+ $severities = explode(",", $severites);
115
+
116
+ foreach ($severities as $severity) {
117
+ $level |= Bugsnag_ErrorTypes::getLevelsForSeverity($severity);
118
+ }
119
+
120
+ return $level;
121
+ }
122
+ }
app/code/community/Shippit/Shippit/Helper/Carrier.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Helper_Carrier extends Shippit_Shippit_Helper_Data
18
+ {
19
+ /**
20
+ * Path to module carrier options
21
+ */
22
+ const XML_PATH_SETTINGS = 'carriers/shippit/';
23
+
24
+ /**
25
+ * Return store config value for key
26
+ *
27
+ * @param string $key
28
+ * @return string
29
+ */
30
+ public function getStoreConfig($key, $flag = false)
31
+ {
32
+ $path = self::XML_PATH_SETTINGS . $key;
33
+
34
+ if ($flag) {
35
+ return Mage::getStoreConfigFlag($path);
36
+ }
37
+ else {
38
+ return Mage::getStoreConfig($path);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * @return bool
44
+ */
45
+ public function isActive()
46
+ {
47
+ return parent::isActive() && self::getStoreConfig('active', true);
48
+ }
49
+
50
+ public function getTitle()
51
+ {
52
+ return self::getStoreConfig('title');
53
+ }
54
+
55
+ public function getAllowedMethods()
56
+ {
57
+ return explode(',', self::getStoreConfig('allowed_methods'));
58
+ }
59
+
60
+ public function getMaxTimeslots()
61
+ {
62
+ return self::getStoreConfig('max_timeslots');
63
+ }
64
+
65
+ public function isEnabledProductActive()
66
+ {
67
+ return self::getStoreConfig('enabled_product_active', true);
68
+ }
69
+
70
+ public function getEnabledProductIds()
71
+ {
72
+ return explode(',', self::getStoreConfig('enabled_product_ids'));
73
+ }
74
+
75
+ public function isEnabledProductAttributeActive()
76
+ {
77
+ return self::getStoreConfig('enabled_product_attribute_active', true);
78
+ }
79
+
80
+ public function getEnabledProductAttributeCode()
81
+ {
82
+ return self::getStoreConfig('enabled_product_attribute_code');
83
+ }
84
+
85
+ public function getEnabledProductAttributeValue()
86
+ {
87
+ return self::getStoreConfig('enabled_product_attribute_value');
88
+ }
89
+ }
app/code/community/Shippit/Shippit/Helper/Checkout.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Helper_Checkout extends Shippit_Shippit_Helper_Data
18
+ {
19
+ /**
20
+ * Path to module sync order config options
21
+ */
22
+ const XML_PATH_SETTINGS = 'shippit/checkout/';
23
+
24
+ /**
25
+ * Return store config value for key
26
+ *
27
+ * @param string $key
28
+ * @return string
29
+ */
30
+ public function getStoreConfig($key, $flag = false)
31
+ {
32
+ $path = self::XML_PATH_SETTINGS . $key;
33
+
34
+ if ($flag) {
35
+ return Mage::getStoreConfigFlag($path);
36
+ }
37
+ else {
38
+ return Mage::getStoreConfig($path);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * @return bool
44
+ */
45
+ public function isAuthorityToLeaveActive()
46
+ {
47
+ return parent::isActive() && self::getStoreConfig('authority_to_leave_active', true);
48
+ }
49
+
50
+ /**
51
+ * @return bool
52
+ */
53
+ public function isDeliveryInstructionsActive()
54
+ {
55
+ return parent::isActive() && self::getStoreConfig('delivery_instructions_active', true);
56
+ }
57
+ }
app/code/community/Shippit/Shippit/Helper/Data.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Helper_Data extends Mage_Core_Helper_Abstract
18
+ {
19
+ /**
20
+ * Path to module general config options
21
+ */
22
+ const XML_PATH_SETTINGS = 'shippit/general/';
23
+
24
+ const AUTHORITY_TO_LEAVE_ID = 'shippit_authority_to_leave';
25
+ const DELIVERY_INSTRUCTIONS_ID = 'shippit_delivery_instructions';
26
+
27
+ const SYNC_MODE_REALTIME = 'realtime';
28
+ const SYNC_MODE_CRON = 'cron';
29
+ const SYNC_MODE_CUSTOM = 'custom';
30
+
31
+ const CARRIER_CODE = 'shippit';
32
+
33
+ /**
34
+ * Return store config value for key
35
+ *
36
+ * @param string $key
37
+ * @return string
38
+ */
39
+ public function getStoreConfig($key, $flag = false)
40
+ {
41
+ $path = self::XML_PATH_SETTINGS . $key;
42
+
43
+ if ($flag) {
44
+ return Mage::getStoreConfigFlag($path);
45
+ }
46
+ else {
47
+ return Mage::getStoreConfig($path);
48
+ }
49
+ }
50
+
51
+ /**
52
+ * @return bool
53
+ */
54
+ public function isActive()
55
+ {
56
+ return self::getStoreConfig('active', true);
57
+ }
58
+
59
+ public function getApiKey()
60
+ {
61
+ return self::getStoreConfig('api_key');
62
+ }
63
+
64
+ public function getEnvironment()
65
+ {
66
+ return self::getStoreConfig('environment');
67
+ }
68
+
69
+ public function isDebugActive()
70
+ {
71
+ return self::getStoreConfig('debug_active', true);
72
+ }
73
+
74
+ /**
75
+ * Begin Helpers not related to configuration values retrieval
76
+ */
77
+
78
+ public function getCarrierCode()
79
+ {
80
+ return self::CARRIER_CODE;
81
+ }
82
+
83
+ public function getModuleVersion()
84
+ {
85
+ $version = (string) Mage::getConfig()
86
+ ->getNode('modules/Shippit_Shippit/version');
87
+
88
+ return $version;
89
+ }
90
+
91
+ // Helper methods for authority to leave and delivery instructions fields
92
+
93
+ public function getAuthorityToLeaveId()
94
+ {
95
+ return self::AUTHORITY_TO_LEAVE_ID;
96
+ }
97
+
98
+ public function getDeliveryInstructionsId()
99
+ {
100
+ return self::DELIVERY_INSTRUCTIONS_ID;
101
+ }
102
+
103
+ /**
104
+ * Attempts to get the region code (ie: VIC), using the postcode
105
+ * Used as a fallback mechanism where the address does not contain region data
106
+ * (ie: saved addresses with text based region, or a postcode estimate shipping request)
107
+ *
108
+ * @uses Postcode ranges from https://en.wikipedia.org/wiki/Postcodes_in_Australia
109
+ *
110
+ * @param string $postcode The postcode
111
+ * @return mixed The region code, or false if unable to determine
112
+ */
113
+ public function getStateFromPostcode($postcode)
114
+ {
115
+ $postcode = (int) $postcode;
116
+
117
+ if ($postcode >= 1000 && $postcode <= 2599
118
+ || $postcode >= 2619 && $postcode <= 2899
119
+ || $postcode >= 2921 && $postcode <= 2999) {
120
+ return 'NSW';
121
+ }
122
+ elseif ($postcode >= 200 && $postcode <= 299
123
+ || $postcode >= 2600 && $postcode <= 2618
124
+ || $postcode >= 2900 && $postcode <= 2920) {
125
+ return 'ACT';
126
+ }
127
+ elseif ($postcode >= 3000 && $postcode <= 3999
128
+ || $postcode >= 8000 && $postcode <= 8999) {
129
+ return 'VIC';
130
+ }
131
+ elseif ($postcode >= 4000 && $postcode <= 4999
132
+ || $postcode >= 9000 && $postcode <= 9999) {
133
+ return 'QLD';
134
+ }
135
+ elseif ($postcode >= 5000 && $postcode <= 5799
136
+ || $postcode >= 5800 && $postcode <= 5999) {
137
+ return 'SA';
138
+ }
139
+ elseif ($postcode >= 6000 && $postcode <= 6797
140
+ || $postcode >= 6800 && $postcode <= 6999) {
141
+ return 'WA';
142
+ }
143
+ elseif ($postcode >= 7000 && $postcode <= 7799
144
+ || $postcode >= 7800 && $postcode <= 7999) {
145
+ return 'TAS';
146
+ }
147
+ elseif ($postcode >= 800 && $postcode <= 899
148
+ || $postcode >= 900 && $postcode <= 999) {
149
+ return 'NT';
150
+ }
151
+ else {
152
+ return false;
153
+ }
154
+ }
155
+ }
app/code/community/Shippit/Shippit/Helper/Order/Items.php ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Helper_Order_Items extends Mage_Core_Helper_Abstract
18
+ {
19
+ protected $locationAttributeCode = null;
20
+
21
+ public function getSkus($items)
22
+ {
23
+ $itemsSkus = array();
24
+
25
+ foreach ($items as $item) {
26
+ if (isset($item['sku'])) {
27
+ $itemSkus[] = $item['sku'];
28
+ }
29
+ }
30
+
31
+ return $itemSkus;
32
+ }
33
+
34
+ public function getIds($items)
35
+ {
36
+ $itemsIds = array();
37
+
38
+ foreach ($items as $item) {
39
+ if (isset($item['id'])) {
40
+ $itemsIds[] = $item['id'];
41
+ }
42
+ }
43
+
44
+ return $itemsIds;
45
+ }
46
+
47
+ public function getQtyToShip($item, $qtyRequested = null)
48
+ {
49
+ $qtyToShip = $item->getQtyToShip();
50
+
51
+ // if no quantity is provided, or the qty requested is
52
+ // greater than the pending shipment qty
53
+ // return the pending shipment qty
54
+ if (empty($qtyRequested) || $qtyRequested > $qtyToShip) {
55
+ return $qtyToShip;
56
+ }
57
+ // otherwise, return the qty requested
58
+ else {
59
+ return $qtyRequested;
60
+ }
61
+ }
62
+
63
+ public function getItemData($items, $itemKey, $itemValue, $itemDataKey)
64
+ {
65
+ if (PHP_VERSION_ID < 50500) {
66
+ foreach ($items as $key => $value) {
67
+ if (isset($value[$itemKey]) && $value[$itemKey] == $itemValue) {
68
+ if (isset($value[$itemDataKey])) {
69
+ return $value[$itemDataKey];
70
+ }
71
+ else {
72
+ return false;
73
+ }
74
+ }
75
+ }
76
+ }
77
+ else {
78
+ $searchResult = array_search($itemValue, array_column($items, $itemKey));
79
+
80
+ if ($searchResult !== false) {
81
+ return $items[$searchResult][$itemDataKey];
82
+ }
83
+ }
84
+
85
+ return false;
86
+ }
87
+
88
+ public function getLocation($item)
89
+ {
90
+ $attributeCode = $this->getLocationAttributeCode();
91
+
92
+ if ($attributeCode) {
93
+ return $this->getAttributeValue($item->getProduct(), $attributeCode);
94
+ }
95
+ else {
96
+ return null;
97
+ }
98
+ }
99
+
100
+ public function getLocationAttributeCode()
101
+ {
102
+ if (is_null($this->locationAttributeCode)) {
103
+ $helper = Mage::helper('shippit/sync_order');
104
+
105
+ if (!$helper->isProductLocationActive()) {
106
+ $this->locationAttributeCode = false;
107
+ }
108
+ else {
109
+ $this->locationAttributeCode = $helper->getProductLocationAttributeCode();
110
+ }
111
+ }
112
+
113
+ return $this->locationAttributeCode;
114
+ }
115
+
116
+ /**
117
+ * Get the product attribute value, ensuring we get
118
+ * the full text value if it's a select or multiselect attribute
119
+ *
120
+ * @param object $product The Product Object
121
+ * @param string $attributeCode The Attribute Code
122
+ * @return string The Product Attribute Value (full text)
123
+ */
124
+ public function getAttributeValue($product, $attributeCode)
125
+ {
126
+ $attribute = $product->getResource()->getAttribute($attributeCode);
127
+
128
+ if ($attribute && $attribute->usesSource()) {
129
+ $attributeValue = $product->getAttributeText($attributeCode);
130
+ }
131
+ else {
132
+ $attributeFunction = $this->getFunctionName($attributeCode);
133
+ $attributeValue = $product->{$attributeFunction}();
134
+ }
135
+
136
+ return $attributeValue;
137
+ }
138
+
139
+ private function getFunctionName($attributeCode, $prefix = 'get', $capitaliseFirstChar = true)
140
+ {
141
+ if ($capitaliseFirstChar) {
142
+ $attributeCode[0] = strtoupper($attributeCode[0]);
143
+ }
144
+
145
+ $function = create_function('$c', 'return strtoupper($c[1]);');
146
+ $functionName = preg_replace_callback('/_([a-z])/', $function, $attributeCode);
147
+
148
+ return $prefix . $functionName;
149
+ }
150
+ }
app/code/community/Shippit/Shippit/Helper/Sync/Order.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Helper_Sync_Order extends Shippit_Shippit_Helper_Data
18
+ {
19
+ /**
20
+ * Path to module sync order config options
21
+ */
22
+ const XML_PATH_SETTINGS = 'shippit/sync_order/';
23
+
24
+ /**
25
+ * Return store config value for key
26
+ *
27
+ * @param string $key
28
+ * @return string
29
+ */
30
+ public function getStoreConfig($key, $flag = false)
31
+ {
32
+ $path = self::XML_PATH_SETTINGS . $key;
33
+
34
+ if ($flag) {
35
+ return Mage::getStoreConfigFlag($path);
36
+ }
37
+ else {
38
+ return Mage::getStoreConfig($path);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * @return bool
44
+ */
45
+ public function isActive()
46
+ {
47
+ return parent::isActive() && self::getStoreConfig('active', true);
48
+ }
49
+
50
+ public function isManualSyncActive()
51
+ {
52
+ return parent::isActive() && self::getStoreConfig('manual_sync_active', true);
53
+ }
54
+
55
+ public function getMode()
56
+ {
57
+ return self::getStoreConfig('mode');
58
+ }
59
+
60
+ public function getSendAllOrders()
61
+ {
62
+ return self::getStoreConfig('send_all_orders');
63
+ }
64
+
65
+ public function isProductLocationActive()
66
+ {
67
+ return self::getStoreConfig('product_location_active', true);
68
+ }
69
+
70
+ public function getProductLocationAttributeCode()
71
+ {
72
+ return self::getStoreConfig('product_location_attribute_code');
73
+ }
74
+
75
+ public function getShippingMethodMapping()
76
+ {
77
+ $values = unserialize( self::getStoreConfig('shipping_method_mapping'));
78
+ $mappings = array();
79
+
80
+ if (!empty($values)) {
81
+ foreach ($values as $value) {
82
+ $mappings[$value['shipping_method']] = $value['shippit_service'];
83
+ }
84
+ }
85
+
86
+ return $mappings;
87
+ }
88
+
89
+ // Helper Methods
90
+ public function getShippitShippingMethod($shippingMethod)
91
+ {
92
+ // If the shipping method is a shippit method,
93
+ // processing using the selected shipping options
94
+ if (strpos($shippingMethod, self::CARRIER_CODE) !== FALSE) {
95
+ $shippingOptions = str_replace(self::CARRIER_CODE . '_', '', $shippingMethod);
96
+ $shippingOptions = explode('_', $shippingOptions);
97
+ $courierData = array();
98
+
99
+ if (isset($shippingOptions[0])) {
100
+ $method = strtolower($shippingOptions[0]);
101
+
102
+ // allows for legacy capability where
103
+ // "priority" was referred to as "premium"
104
+ if ($method == 'priority' || $method = 'premium') {
105
+ return 'priority';
106
+ }
107
+ elseif ($method == 'express') {
108
+ return 'express';
109
+ }
110
+ elseif ($method == 'standard') {
111
+ return 'standard';
112
+ }
113
+ }
114
+ }
115
+
116
+ // Use the mapping values and attempt to get a value
117
+ $shippingMethodMapping = $this->getShippingMethodMapping();
118
+
119
+ if (isset($shippingMethodMapping[$shippingMethod])
120
+ && !empty($shippingMethodMapping[$shippingMethod])) {
121
+ return $shippingMethodMapping[$shippingMethod];
122
+ }
123
+
124
+ // All options have failed, return false
125
+ return false;
126
+ }
127
+ }
app/code/community/Shippit/Shippit/Helper/Sync/Shipping.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Helper_Sync_Shipping extends Shippit_Shippit_Helper_Data
18
+ {
19
+ /**
20
+ * Path to module sync order config options
21
+ */
22
+ const XML_PATH_SETTINGS = 'shippit/sync_shipping/';
23
+
24
+ /**
25
+ * Return store config value for key
26
+ *
27
+ * @param string $key
28
+ * @return string
29
+ */
30
+ public function getStoreConfig($key, $flag = false)
31
+ {
32
+ $path = self::XML_PATH_SETTINGS . $key;
33
+
34
+ if ($flag) {
35
+ return Mage::getStoreConfigFlag($path);
36
+ }
37
+ else {
38
+ return Mage::getStoreConfig($path);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * @return bool
44
+ */
45
+ public function isActive()
46
+ {
47
+ return parent::isActive() && self::getStoreConfig('active', true);
48
+ }
49
+
50
+ /**
51
+ * @return bool
52
+ */
53
+ public function isUpdateTemplateActive()
54
+ {
55
+ return self::getStoreConfig('update_template_active', true);
56
+ }
57
+ }
app/code/community/Shippit/Shippit/Model/Api/Order.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ // Core Class responsible for Managing the process of syncing orders
18
+ // with the Shippit Platform. Handles both cron job processing and immediate
19
+ // request processing, ensuring it transitions orders into the failed state
20
+ // when exceeding the maximum number of attempts.
21
+
22
+ class Shippit_Shippit_Model_Api_Order extends Mage_Core_Model_Abstract
23
+ {
24
+ protected $api;
25
+ protected $helper;
26
+ protected $itemsHelper;
27
+
28
+ public function __construct()
29
+ {
30
+ $this->helper = Mage::helper('shippit/sync_order');
31
+ $this->itemsHelper = Mage::helper('shippit/order_items');
32
+ $this->api = Mage::helper('shippit/api');
33
+ $this->logger = Mage::getModel('shippit/logger');
34
+ }
35
+
36
+ public function run()
37
+ {
38
+ // get all stores, as we will emulate each storefront for integration run
39
+ $stores = Mage::app()->getStores();
40
+
41
+ // get emulation model
42
+ $appEmulation = Mage::getSingleton('core/app_emulation');
43
+
44
+ foreach ($stores as $store) {
45
+ // Start Store Emulation
46
+ $environment = $appEmulation->startEnvironmentEmulation($store);
47
+
48
+ $syncOrders = $this->getSyncOrders($store);
49
+
50
+ foreach ($syncOrders as $syncOrder) {
51
+ $this->sync($syncOrder);
52
+ }
53
+
54
+ // Stop Store Emulation
55
+ $appEmulation->stopEnvironmentEmulation($environment);
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Get a list of sync orders pending sync
61
+ * @return [type] [description]
62
+ */
63
+ public function getSyncOrders($store)
64
+ {
65
+ $storeId = $this->getStoreId($store);
66
+
67
+ return Mage::getModel('shippit/sync_order')
68
+ ->getCollection()
69
+ ->join(
70
+ array('order' => 'sales/order'),
71
+ 'order.entity_id = main_table.order_id',
72
+ array(),
73
+ null,
74
+ 'left'
75
+ )
76
+ ->addFieldToFilter('main_table.status', Shippit_Shippit_Model_Sync_Order::STATUS_PENDING)
77
+ ->addFieldToFilter('main_table.attempt_count', array('lteq' => Shippit_Shippit_Model_Sync_Order::SYNC_MAX_ATTEMPTS))
78
+ ->addFieldToFilter('order.state', array('eq' => Mage_Sales_Model_Order::STATE_PROCESSING))
79
+ ->addFieldToFilter('order.store_id', array('eq' => $storeId));
80
+ }
81
+
82
+ private function getStoreId($store)
83
+ {
84
+ if ($store instanceof Mage_Core_Model_Store) {
85
+ return $store->getId();
86
+ }
87
+ else {
88
+ return $store;
89
+ }
90
+ }
91
+
92
+ public function sync($syncOrder, $displayNotifications = false)
93
+ {
94
+ try {
95
+ $order = $syncOrder->getOrder();
96
+
97
+ // If the order is destined for international, override the shipping method as international
98
+ if ($order->getShippingAddress()->getCountry() != 'AU'
99
+ && $syncOrder->getShippingMethod() != 'international') {
100
+ $syncOrder->setShippingMethod('international');
101
+ }
102
+
103
+ // Add attempt
104
+ $syncOrder->setAttemptCount($syncOrder->getAttemptCount() + 1);
105
+
106
+ // Build the order request
107
+ $orderRequest = Mage::getModel('shippit/request_api_order')
108
+ ->processSyncOrder($syncOrder);
109
+
110
+ $apiResponse = $this->api->sendOrder($orderRequest, $syncOrder->getApiKey());
111
+
112
+ // Add the order tracking details to
113
+ // the order comments and save
114
+ $comment = $this->helper->__('Order Synced with Shippit - ' . $apiResponse->tracking_number);
115
+ $order->addStatusHistoryComment($comment)
116
+ ->setIsVisibleOnFront(false)
117
+ ->save();
118
+
119
+ // Update the order to be marked as synced
120
+ $syncOrder->setStatus(Shippit_Shippit_Model_Sync_Order::STATUS_SYNCED)
121
+ ->setTrackNumber($apiResponse->tracking_number)
122
+ ->setSyncedAt(Varien_Date::now())
123
+ ->save();
124
+
125
+ if ($displayNotifications) {
126
+ Mage::getSingleton('adminhtml/session')
127
+ ->addSuccess(
128
+ $this->helper->__('Order ' . $order->getIncrementId() . ' Synced with Shippit - ' . $apiResponse->tracking_number)
129
+ );
130
+ }
131
+ }
132
+ catch (Exception $e) {
133
+ $this->logger->log('API - Order Sync Request Failed', $e->getMessage(), Zend_Log::ERR);
134
+ $this->logger->logException($e);
135
+
136
+ // Update the sync status to failed if it's breached the max attempts
137
+ if ($syncOrder->getAttemptCount() > Shippit_Shippit_Model_Sync_Order::SYNC_MAX_ATTEMPTS) {
138
+ $syncOrder->setStatus(Shippit_Shippit_Model_Sync_Order::STATUS_FAILED);
139
+ }
140
+
141
+ // save the sync item attempt count
142
+ $syncOrder->save();
143
+
144
+ if ($displayNotifications) {
145
+ Mage::getSingleton('adminhtml/session')
146
+ ->addError(
147
+ $this->helper->__('Order ' . $syncOrder->getOrder()->getIncrementId() . ' was not Synced with Shippit - ' . $e->getMessage())
148
+ );
149
+ }
150
+
151
+ return false;
152
+ }
153
+
154
+ return true;
155
+ }
156
+ }
app/code/community/Shippit/Shippit/Model/Logger.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Logger
18
+ {
19
+ protected $helper;
20
+ protected $debugMode;
21
+
22
+ public $bugsnag = false;
23
+ protected $metaData = array();
24
+
25
+ public function __construct()
26
+ {
27
+ $this->helper = Mage::helper('shippit');
28
+ $this->debugMode = $this->helper->isDebugActive();
29
+ $this->bugsnag = Mage::helper('shippit/bugsnag')->init();
30
+ }
31
+
32
+ public function log($errorType, $message, $level = Zend_Log::DEBUG)
33
+ {
34
+ // if debug mode is disabled, only log when the level is above notice
35
+ if (!$this->debugMode && $level <= Zend_Log::NOTICE
36
+ || $this->debugMode) {
37
+ $this->bugsnagLog($errorType, $message, $level);
38
+
39
+ Mage::log($errorType . "\n" . $message, $level, 'shippit.log');
40
+
41
+ if (!empty($this->metaData)) {
42
+ Mage::log($this->metaData, $level, 'shippit.log');
43
+ }
44
+ }
45
+
46
+ return $this;
47
+ }
48
+
49
+ public function bugsnagLog($errorType, $message, $level = Zend_Log::DEBUG)
50
+ {
51
+ if (!$this->bugsnag) {
52
+ return $this;
53
+ }
54
+
55
+ $this->bugsnag->notifyError($errorType, $message, $this->metaData, $this->_getBugsnagErrorLevel($level));
56
+
57
+ return $this;
58
+ }
59
+
60
+ public function bugsnagException($exception)
61
+ {
62
+ if (!$this->bugsnag) {
63
+ return $this;
64
+ }
65
+
66
+ return $this->bugsnag->notifyException($exception, $this->metaData);
67
+ }
68
+
69
+ public function _getBugsnagErrorLevel($level)
70
+ {
71
+ if ($level <= 3) {
72
+ return 'error';
73
+ }
74
+ elseif ($level == 4) {
75
+ return 'warning';
76
+ }
77
+ else {
78
+ return 'info';
79
+ }
80
+ }
81
+
82
+ public function logException($e, $level = Zend_Log::ERR)
83
+ {
84
+ $this->bugsnagException($e);
85
+
86
+ Mage::log($e->getMessage(), $level, 'shippit.log');
87
+
88
+ if (!empty($this->metaData)) {
89
+ Mage::log($this->metaData, $level, 'shippit.log');
90
+ }
91
+
92
+ return $this;
93
+ }
94
+
95
+ public function setMetaData($metaData)
96
+ {
97
+ $this->metaData = $metaData;
98
+
99
+ return $this;
100
+ }
101
+ }
app/code/community/Shippit/Shippit/Model/Observer/Adminhtml/Sales/Order.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Observer_Adminhtml_Sales_Order
18
+ {
19
+ public function addShippitButton(Varien_Event_Observer $observer)
20
+ {
21
+ $block = $observer->getEvent()->getBlock();
22
+
23
+ if ($block instanceof Mage_Adminhtml_Block_Sales_Order_View
24
+ && $this->_isAllowed()
25
+ && Mage::helper('shippit/sync_order')->isManualSyncActive()) {
26
+ $block->addButton(
27
+ 'shippit_send_order',
28
+ array(
29
+ 'label' => Mage::helper('shippit/sync_order')->__('Send to Shippit'),
30
+ 'onclick' => "setLocation('{$block->getUrl('*/shippit_order_sync/send')}')",
31
+ 'class' => 'go'
32
+ )
33
+ );
34
+ }
35
+ }
36
+
37
+ public function addShippitMassAction(Varien_Event_Observer $observer)
38
+ {
39
+ $block = $observer->getEvent()->getBlock();
40
+
41
+ if ($block->getRequest()->getControllerName() == 'sales_order'
42
+ && $block instanceof Mage_Adminhtml_Block_Widget_Grid_Massaction
43
+ && $this->_isAllowed()
44
+ && Mage::helper('shippit/sync_order')->isManualSyncActive()) {
45
+ $block->addItem(
46
+ 'shippit_send_orders',
47
+ array(
48
+ 'label' => Mage::helper('shippit/sync_order')->__('Send to Shippit'),
49
+ 'url' => $block->getUrl('*/shippit_order_sync/massSend'),
50
+ )
51
+ );
52
+ }
53
+ }
54
+
55
+ protected function _isAllowed()
56
+ {
57
+ return Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/shippit_order_send');
58
+ }
59
+ }
app/code/community/Shippit/Shippit/Model/Observer/Order/Sync.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Observer_Order_Sync
18
+ {
19
+ // Prevents recursive requests to sync
20
+ private $_hasAttemptedSync = false;
21
+
22
+ protected $helper;
23
+
24
+ public function __construct()
25
+ {
26
+ $this->helper = Mage::helper('shippit/sync_order');
27
+ $this->logger = Mage::getModel('shippit/logger');
28
+ }
29
+
30
+ /**
31
+ * Set the order to be synced with shippit
32
+ * @param Varien_Event_Observer $observer [description]
33
+ */
34
+ public function addOrder(Varien_Event_Observer $observer)
35
+ {
36
+ // If the module is not active, stop processing
37
+ if (!$this->helper->isActive()) {
38
+ return $this;
39
+ }
40
+
41
+ // If the sync mode is custom, stop processing
42
+ if ($this->helper->getMode() == Shippit_Shippit_Helper_Data::SYNC_MODE_CUSTOM) {
43
+ return $this;
44
+ }
45
+
46
+ $order = $observer->getEvent()->getOrder();
47
+
48
+ // Ensure we have an order
49
+ if (!$order || !$order->getId()) {
50
+ return $this;
51
+ }
52
+
53
+ $shippingMethod = $order->getShippingMethod();
54
+ $shippitShippingMethod = $this->helper->getShippitShippingMethod($shippingMethod);
55
+ $shippingCountry = $order->getShippingAddress()->getCountryId();
56
+
57
+ // If send all orders,
58
+ // or shippit shipping class present
59
+ if (($this->helper->getSendAllOrders() == Shippit_Shippit_Model_System_Config_Source_Shippit_Sync_SendAllOrders::ALL
60
+ || $this->helper->getSendAllOrders() == Shippit_Shippit_Model_System_Config_Source_Shippit_Sync_SendAllOrders::ALL_AU && $shippingCountry == 'AU')
61
+ || $shippitShippingMethod !== FALSE) {
62
+
63
+ try {
64
+ $request = Mage::getModel('shippit/request_sync_order')
65
+ ->setOrderId($order->getId())
66
+ ->setItems()
67
+ ->setShippingMethod($shippitShippingMethod);
68
+
69
+ // Create a new sync order record
70
+ $syncOrder = Mage::getModel('shippit/sync_order')->addRequest($request)
71
+ ->save();
72
+ }
73
+ catch (Exception $e) {
74
+ $this->logger->log('Sync Order was unable to be created', $e->getMessage(), Zend_Log::ERR);
75
+ $this->logger->logException($e);
76
+ }
77
+
78
+ try {
79
+ // If the sync mode is realtime,
80
+ // or the shipping method is priority
81
+ // - attempt realtime sync now
82
+ if ($this->helper->getMode() == Shippit_Shippit_Helper_Data::SYNC_MODE_REALTIME
83
+ || $shippitShippingMethod == 'priority') {
84
+ $this->_syncOrder($syncOrder);
85
+ }
86
+ }
87
+ catch (Exception $e) {
88
+ $this->logger->log('Sync Order was unable to be synced realtime', $e->getMessage(), Zend_Log::ERR);
89
+ $this->logger->logException($e);
90
+ }
91
+ }
92
+
93
+ return $this;
94
+ }
95
+
96
+ private function _syncOrder($syncOrder)
97
+ {
98
+ $order = $syncOrder->getOrder();
99
+
100
+ if (!$this->_hasAttemptedSync
101
+ // ensure the order is in the processing state
102
+ && $order->getState() == Mage_Sales_Model_Order::STATE_PROCESSING
103
+ // ensure the sync order is in the pending state
104
+ && $syncOrder->getStatus() == Shippit_Shippit_Model_Sync_Order::STATUS_PENDING) {
105
+ $this->_hasAttemptedSync = true;
106
+
107
+ // attempt the sync
108
+ $syncOrderResult = Mage::getModel('shippit/api_order')->sync($syncOrder);
109
+
110
+ return $syncOrderResult;
111
+ }
112
+ else {
113
+ return false;
114
+ }
115
+ }
116
+ }
app/code/community/Shippit/Shippit/Model/Observer/Quote/AuthorityToLeave.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Observer_Quote_AuthorityToLeave
18
+ {
19
+ /**
20
+ * Check if authority to leave should be added to quote.
21
+ *
22
+ * @param Varien_Event_Observer $observer
23
+ * @return $this
24
+ */
25
+ public function addAuthorityToLeaveToQuote(Varien_Event_Observer $observer)
26
+ {
27
+ /** @var Mage_Core_Controller_Request_Http $request */
28
+ $request = Mage::app()->getRequest();
29
+
30
+ /** @var Mage_Sales_Model_Quote $quote */
31
+ $quote = $observer->getEvent()->getQuote();
32
+
33
+ $authorityToLeave = $request->getParam(
34
+ Mage::helper('shippit')->getAuthorityToLeaveId()
35
+ );
36
+
37
+ if (isset($authorityToLeave)) {
38
+ $this->_addAuthorityToLeaveToQuote($quote, true);
39
+ }
40
+ else {
41
+ $this->_addAuthorityToLeaveToQuote($quote, false);
42
+ }
43
+
44
+ return $this;
45
+ }
46
+
47
+ /**
48
+ * Add's the authority to leave to the quote data.
49
+ *
50
+ * @param Mage_Sales_Model_Quote $quote
51
+ * @param string $promiseDate
52
+ * @return $this
53
+ */
54
+ protected function _addAuthorityToLeaveToQuote($quote, $authorityToLeave)
55
+ {
56
+ $quote->setShippitAuthorityToLeave($authorityToLeave);
57
+ }
58
+ }
app/code/community/Shippit/Shippit/Model/Observer/Quote/DeliveryInstructions.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Observer_Quote_DeliveryInstructions
18
+ {
19
+ /**
20
+ * Check if customer delivery instructions should be added to quote.
21
+ *
22
+ * @param Varien_Event_Observer $observer
23
+ * @return $this
24
+ */
25
+ public function addDeliveryInstructionsToQuote(Varien_Event_Observer $observer)
26
+ {
27
+ /** @var Mage_Core_Controller_Request_Http $request */
28
+ $request = Mage::app()->getRequest();
29
+
30
+ /** @var Mage_Sales_Model_Quote $quote */
31
+ $quote = $observer->getEvent()->getQuote();
32
+
33
+ $deliveryInstructions = $request->getParam(
34
+ Mage::helper('shippit')->getDeliveryInstructionsId()
35
+ );
36
+
37
+ $this->_addDeliveryInstructionsToQuote($quote, $deliveryInstructions);
38
+
39
+ return $this;
40
+ }
41
+
42
+ /**
43
+ * Add's the order delivery instructions to the quote data.
44
+ *
45
+ * @param Mage_Sales_Model_Quote $quote
46
+ * @param string $promiseDate
47
+ * @return $this
48
+ */
49
+ protected function _addDeliveryInstructionsToQuote($quote, $deliveryInstructions)
50
+ {
51
+ $deliveryInstructions = strip_tags($deliveryInstructions);
52
+ $quote->setShippitDeliveryInstructions($deliveryInstructions);
53
+ }
54
+ }
app/code/community/Shippit/Shippit/Model/Observer/Shipping/Tracking.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Observer_Shipping_Tracking
18
+ {
19
+ /**
20
+ * Updates the order shipment email template to include
21
+ * the tracking link in the tracking details
22
+ *
23
+ * @param Varien_Event_Observer $observer
24
+ */
25
+ public function updateOrderShipmentTrackTemplate(Varien_Event_Observer $observer)
26
+ {
27
+ $block = $observer->getBlock();
28
+
29
+ if ($block->getTemplate() == 'email/order/shipment/track.phtml'
30
+ && Mage::helper('shippit/sync_shipping')->isUpdateTemplateActive()) {
31
+ $block->setTemplate('shippit/email/order/shipment/track.phtml');
32
+ }
33
+ }
34
+ }
app/code/community/Shippit/Shippit/Model/Observer/Shippit.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Observer_Shippit extends Mage_Core_Model_Abstract
18
+ {
19
+ protected $helper;
20
+
21
+ public function __construct() {
22
+ $this->helper = Mage::helper('shippit/sync_order');
23
+
24
+ return parent::__construct();
25
+ }
26
+
27
+ public function addOrder(Varien_Event_Observer $observer)
28
+ {
29
+ // Ensure the module is active
30
+ if (!$this->helper->isActive()) {
31
+ return $this;
32
+ }
33
+
34
+ // get the event parameters
35
+ $orderId = $observer->getEvent()->getEntityId();
36
+ $items = $observer->getEvent()->getItems();
37
+
38
+ if (empty($items)) {
39
+ $items = array();
40
+ }
41
+
42
+ $apiKey = $observer->getEvent()->getApiKey();
43
+ $syncMode = $observer->getEvent()->getSyncMode();
44
+ $shippingMethod = $observer->getEvent()->getShippingMethod();
45
+
46
+ $displayNotifications = $observer->getEvent()->getDisplayNotifications();
47
+
48
+ if (empty($displayNotifications)) {
49
+ $displayNotifications = false;
50
+ }
51
+
52
+ // save the request to sync the order, and sync immediately if realtime
53
+ Mage::getModel('shippit/shippit')->addOrder($orderId, $items, $shippingMethod, $apiKey, $syncMode, $displayNotifications);
54
+
55
+ return $this;
56
+ }
57
+ }
app/code/community/Shippit/Shippit/Model/Observer/System/Config.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Observer_System_Config
18
+ {
19
+ protected $helper;
20
+ protected $syncShippingHelper;
21
+ protected $api;
22
+
23
+ public function __construct()
24
+ {
25
+ $this->helper = Mage::helper('shippit');
26
+ $this->syncShippingHelper = Mage::helper('shippit/sync_shipping');
27
+ $this->api = Mage::helper('shippit/api');
28
+ }
29
+
30
+ public function checkApiKey(Varien_Event_Observer $observer)
31
+ {
32
+ $request = Mage::app()->getRequest();
33
+
34
+ if ($request->getParam('section') != 'shippit') {
35
+ return;
36
+ }
37
+
38
+ try {
39
+ $apiKeyValid = false;
40
+
41
+ $merchant = $this->api->getMerchant();
42
+
43
+ if (property_exists($merchant, 'error')) {
44
+ if ($merchant->error == 'invalid_merchant_account') {
45
+ Mage::getSingleton('adminhtml/session')->addError(
46
+ $this->helper->__('Shippit configuration error: Please check the API Key')
47
+ );
48
+ }
49
+ else {
50
+ Mage::getSingleton('adminhtml/session')->addError(
51
+ $this->helper->__('Shippit API error: ' . $merchant->error)
52
+ );
53
+ }
54
+ }
55
+ else {
56
+ Mage::getSingleton('adminhtml/session')->addSuccess(
57
+ $this->helper->__('Shippit API Key Validated')
58
+ );
59
+
60
+ $apiKeyValid = true;
61
+ }
62
+ }
63
+ catch (Exception $e) {
64
+ Mage::getSingleton('adminhtml/session')->addError('Shippit API error: An error occured while communicating with the Shippit API');
65
+ }
66
+
67
+ if ($apiKeyValid && $this->syncShippingHelper->isActive()) {
68
+ $this->registerWebhook();
69
+ }
70
+ }
71
+
72
+ public function registerWebhook()
73
+ {
74
+ try {
75
+ $apiKey = $this->helper->getApiKey();
76
+
77
+ $webhookUrl = Mage::getUrl('shippit/order/update/', array(
78
+ 'api_key' => $apiKey,
79
+ '_secure' => true,
80
+ ));
81
+
82
+ $requestData = new Varien_Object;
83
+ $requestData->setWebhookUrl($webhookUrl);
84
+ $merchant = $this->api->putMerchant($requestData, true);
85
+
86
+ if (property_exists($merchant, 'error')) {
87
+ Mage::getSingleton('adminhtml/session')->addError(
88
+ $this->helper->__('Shippit Webhook Registration Error: An error occured while registering the webhook with Shippit' . $merchant->error)
89
+ );
90
+ }
91
+ else {
92
+ Mage::getSingleton('adminhtml/session')->addSuccess(
93
+ $this->helper->__('Shippit Webhook Registered: ' . $webhookUrl)
94
+ );
95
+ }
96
+ }
97
+ catch (Exception $e) {
98
+ Mage::getSingleton('adminhtml/session')->addError(
99
+ $this->helper->__('Shippit Webhook Registration Error: An unknown error occured while registering the webhook with Shippit ' . $e->getMessage())
100
+ );
101
+ }
102
+
103
+ return;
104
+ }
105
+ }
app/code/community/Shippit/Shippit/Model/Request/Api/Order.php ADDED
@@ -0,0 +1,659 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ // Creates an API Request based on
18
+ // passed data or a sync order object
19
+
20
+ class Shippit_Shippit_Model_Request_Api_Order extends Varien_Object
21
+ {
22
+ protected $helper;
23
+ protected $api;
24
+ protected $carrierCode;
25
+ protected $itemsHelper;
26
+ protected $order;
27
+
28
+ /**
29
+ * Constants for keys of data array. Identical to the name of the getter in snake case
30
+ */
31
+ const RETAILER_INVOICE = 'retailer_invoice';
32
+ const AUTHORITY_TO_LEAVE = 'authority_to_leave';
33
+ const DELIVERY_INSTRUCTIONS = 'delivery_instructions';
34
+ const USER_ATTRIBUTES = 'user_attributes';
35
+ const COURIER_TYPE = 'courier_type';
36
+ const DELIVERY_DATE = 'delivery_date';
37
+ const DELIVERY_WINDOW = 'delivery_window';
38
+ const RECEIVER_NAME = 'receiver_name';
39
+ const RECEIVER_CONTACT_NUMBER = 'receiver_contact_number';
40
+ const DELIVERY_COMPANY = 'delivery_company';
41
+ const DELIVERY_ADDRESS = 'delivery_address';
42
+ const DELIVERY_SUBURB = 'delivery_suburb';
43
+ const DELIVERY_POSTCODE = 'delivery_postcode';
44
+ const DELIVERY_STATE = 'delivery_state';
45
+ const DELIVERY_COUNTRY = 'delivery_country_code';
46
+ const PARCEL_ATTRIBUTES = 'parcel_attributes';
47
+
48
+ // Shippit Service Class API Mappings
49
+ const SHIPPING_SERVICE_STANDARD = 'CouriersPlease';
50
+ const SHIPPING_SERVICE_EXPRESS = 'eparcelexpress';
51
+ const SHIPPING_SERVICE_PRIORITY = 'Bonds';
52
+ const SHIPPING_SERVICE_INTERNATIONAL = 'Dhl';
53
+
54
+ public function __construct() {
55
+ $this->helper = Mage::helper('shippit/sync_order');
56
+ $this->api = Mage::helper('shippit/api');
57
+ $this->carrierCode = $this->helper->getCarrierCode();
58
+ $this->itemsHelper = Mage::helper('shippit/order_items');
59
+ }
60
+
61
+ public function processSyncOrder(Shippit_Shippit_Model_Sync_Order $syncOrder)
62
+ {
63
+ // get the order attached to the syncOrder object
64
+ $order = $syncOrder->getOrder();
65
+ // get the shipping method attached to the syncOrder object
66
+ $shippingMethod = $syncOrder->getShippingMethod();
67
+ // get the order items attached to the syncOrder queue
68
+ $items = $syncOrder->getItemsCollection();
69
+
70
+ // Build the order request
71
+ $orderRequest = $this->setOrder($order)
72
+ ->setItems($items)
73
+ ->setShippingMethod($shippingMethod);
74
+
75
+ return $this;
76
+ }
77
+
78
+ /**
79
+ * Set the order to be sent to the api request
80
+ *
81
+ * @param object $order The Order Request
82
+ */
83
+ public function setOrder($order)
84
+ {
85
+ if ($order instanceof Mage_Sales_Model_Order) {
86
+ $this->order = $order;
87
+ }
88
+ else {
89
+ $order = Mage::getModel('sales/order')->load($order);
90
+ $this->order = $order;
91
+ }
92
+
93
+ $billingAddress = $order->getBillingAddress();
94
+ $shippingAddress = $order->getShippingAddress();
95
+
96
+ $this->setRetailerInvoice($order->getIncrementId())
97
+ ->setAuthorityToLeave($order->getShippitAuthorityToLeave())
98
+ ->setDeliveryInstructions($order->getShippitDeliveryInstructions())
99
+ ->setUserAttributes($order->getCustomerEmail(), $billingAddress->getFirstname(), $billingAddress->getLastname())
100
+ ->setReceiverName($shippingAddress->getName())
101
+ ->setReceiverContactNumber($shippingAddress->getTelephone())
102
+ ->setDeliveryCompany($shippingAddress->getCompany())
103
+ ->setDeliveryAddress(implode(' ', $shippingAddress->getStreet()))
104
+ ->setDeliverySuburb($shippingAddress->getCity())
105
+ ->setDeliveryPostcode($shippingAddress->getPostcode())
106
+ ->setDeliveryState($shippingAddress->getRegionCode())
107
+ ->setDeliveryCountry($shippingAddress->getCountry());
108
+
109
+ $this->setOrderAfter($order);
110
+
111
+ return $this;
112
+ }
113
+
114
+ public function setOrderAfter($order)
115
+ {
116
+ $deliveryState = $this->getDeliveryState();
117
+
118
+ // If the delivery state is empty
119
+ // Attempt to retrieve from the postcode lookup for AU Addresses
120
+ if (empty($deliveryState) && $this->getDeliveryCountry() == 'AU') {
121
+ $postcodeState = $this->helper->getStateFromPostcode($this->getDeliveryPostcode());
122
+
123
+ if ($postcodeState) {
124
+ $this->setData(self::DELIVERY_STATE, $postcodeState);
125
+ }
126
+ }
127
+
128
+ $deliveryState = $this->getDeliveryState();
129
+ $deliverySuburb = $this->getDeliverySuburb();
130
+
131
+ // If the delivery state is empty
132
+ // Copy the suburb field to the state field
133
+ if (empty($deliveryState) && !empty($deliverySuburb)) {
134
+ $this->setData(self::DELIVERY_STATE, $deliverySuburb);
135
+ }
136
+
137
+ return $this;
138
+ }
139
+
140
+ public function setItems(Shippit_Shippit_Model_Resource_Sync_Order_Item_Collection $items)
141
+ {
142
+ if (count($items) == 0) {
143
+ // If we don't have specific items in the request, build
144
+ // the request dynamically from the order object
145
+ $items = Mage::getModel('shippit/request_sync_order')
146
+ ->setOrder($this->order)
147
+ ->setItems()
148
+ ->getItems();
149
+
150
+ $this->setParcelAttributes($items);
151
+ }
152
+ else {
153
+ // Otherwise, use the data requested in the sync event
154
+ foreach ($items as $item) {
155
+ $this->addItem(
156
+ $item->getSku(),
157
+ $item->getTitle(),
158
+ $item->getQty(),
159
+ $item->getPrice(),
160
+ $item->getWeight(),
161
+ $item->getLocation()
162
+ );
163
+ }
164
+ }
165
+
166
+ return $this;
167
+ }
168
+
169
+ public function reset()
170
+ {
171
+ // reset the order reference
172
+ $this->order = null;
173
+
174
+ // reset the request data
175
+ $this->setData(self::RETAILER_INVOICE, null)
176
+ ->setData(self::AUTHORITY_TO_LEAVE, null)
177
+ ->setData(self::DELIVERY_INSTRUCTIONS, null)
178
+ ->setData(self::USER_ATTRIBUTES, null)
179
+ ->setData(self::COURIER_TYPE, null)
180
+ ->setData(self::DELIVERY_DATE, null)
181
+ ->setData(self::DELIVERY_WINDOW, null)
182
+ ->setData(self::RECEIVER_NAME, null)
183
+ ->setData(self::RECEIVER_CONTACT_NUMBER, null)
184
+ ->setData(self::DELIVERY_COMPANY, null)
185
+ ->setData(self::DELIVERY_ADDRESS, null)
186
+ ->setData(self::DELIVERY_SUBURB, null)
187
+ ->setData(self::DELIVERY_POSTCODE, null)
188
+ ->setData(self::DELIVERY_STATE, null)
189
+ ->setData(self::PARCEL_ATTRIBUTES, null);
190
+ }
191
+
192
+ /**
193
+ * Get the Retailer Invoice Referance
194
+ *
195
+ * @return string|null
196
+ */
197
+ public function getRetailerInvoice()
198
+ {
199
+ return $this->getData(self::RETAILER_INVOICE);
200
+ }
201
+
202
+ /**
203
+ * Set the Retailer Invoice Referance
204
+ *
205
+ * @param string $orderDate
206
+ * @return string
207
+ */
208
+ public function setRetailerInvoice($retailerInvoice)
209
+ {
210
+ return $this->setData(self::RETAILER_INVOICE, $retailerInvoice);
211
+ }
212
+
213
+ /**
214
+ * Get the Authority To Leave
215
+ *
216
+ * @return bool|null
217
+ */
218
+ public function getAuthorityToLeave()
219
+ {
220
+ return $this->getData(self::AUTHORITY_TO_LEAVE);
221
+ }
222
+
223
+ /**
224
+ * Set the Authority To Leave
225
+ *
226
+ * @param bool $authorityToLeave
227
+ * @return bool
228
+ */
229
+ public function setAuthorityToLeave($authorityToLeave)
230
+ {
231
+ if ($authorityToLeave) {
232
+ $authorityToLeave = "Yes";
233
+ }
234
+ else {
235
+ $authorityToLeave = "No";
236
+ }
237
+
238
+ return $this->setData(self::AUTHORITY_TO_LEAVE, $authorityToLeave);
239
+ }
240
+
241
+ /**
242
+ * Get the Delivery Instructions
243
+ *
244
+ * @return string|null
245
+ */
246
+ public function getDeliveryInstructions()
247
+ {
248
+ return $this->getData(self::DELIVERY_INSTRUCTIONS);
249
+ }
250
+
251
+ /**
252
+ * Set the Delivery Instructions
253
+ *
254
+ * @param string $deliveryInstructions
255
+ * @return string
256
+ */
257
+ public function setDeliveryInstructions($deliveryInstructions)
258
+ {
259
+ return $this->setData(self::DELIVERY_INSTRUCTIONS, $deliveryInstructions);
260
+ }
261
+
262
+ /**
263
+ * Get the User Attributes
264
+ *
265
+ * @return array|null
266
+ */
267
+ public function getUserAttributes()
268
+ {
269
+ return $this->getData(self::USER_ATTRIBUTES);
270
+ }
271
+
272
+ /**
273
+ * Set the User Attributes
274
+ *
275
+ * @param array $userAttributes
276
+ * @return array
277
+ */
278
+ public function setUserAttributes($email, $firstname, $lastname)
279
+ {
280
+ $userAttributes = array(
281
+ 'email' => $email,
282
+ 'first_name' => $firstname,
283
+ 'last_name' => $lastname,
284
+ );
285
+
286
+ return $this->setData(self::USER_ATTRIBUTES, $userAttributes);
287
+ }
288
+
289
+ /**
290
+ * Get the Courier Type
291
+ *
292
+ * @return array|null
293
+ */
294
+ public function getCourierType()
295
+ {
296
+ return $this->getData(self::COURIER_TYPE);
297
+ }
298
+
299
+ /**
300
+ * Get the Courier Type
301
+ *
302
+ * @return array|null
303
+ */
304
+ public function setCourierType($courierType)
305
+ {
306
+ return $this->setData(self::COURIER_TYPE, $courierType);
307
+ }
308
+
309
+ /**
310
+ * Get the Delivery Date
311
+ *
312
+ * @return string|null
313
+ */
314
+ public function getDeliveryDate()
315
+ {
316
+ return $this->getData(self::DELIVERY_DATE);
317
+ }
318
+
319
+ /**
320
+ * Set the Delivery Date
321
+ *
322
+ * @param string $deliveryDate Delivery Date
323
+ * @return string
324
+ */
325
+ public function setDeliveryDate($deliveryDate)
326
+ {
327
+ return $this->setData(self::DELIVERY_DATE, $deliveryDate);
328
+ }
329
+
330
+ /**
331
+ * Get the Delivery Window
332
+ *
333
+ * @return string|null
334
+ */
335
+ public function getDeliveryWindow()
336
+ {
337
+ return $this->getData(self::DELIVERY_WINDOW);
338
+ }
339
+
340
+ /**
341
+ * Set the Delivery Window
342
+ *
343
+ * @param string $deliveryWindow Delivery Window
344
+ * @return string
345
+ */
346
+ public function setDeliveryWindow($deliveryWindow)
347
+ {
348
+ return $this->setData(self::DELIVERY_WINDOW, $deliveryWindow);
349
+ }
350
+
351
+ /**
352
+ * Set the Shipping Method Values
353
+ *
354
+ * - Values may include the courier_type, delivery_date and delivery_window
355
+ *
356
+ * @param string|null $shippingMethod
357
+ * @return array
358
+ */
359
+ public function setShippingMethod($shippingMethod = null)
360
+ {
361
+ // if the order is a priority delivery,
362
+ // get the special delivery attributes
363
+ if ($shippingMethod == 'priority') {
364
+ $deliveryDate = $this->_getOrderDeliveryDate($this->order);
365
+ $deliveryWindow = $this->_getOrderDeliveryWindow($this->order);
366
+ }
367
+
368
+ // set the courier details based on the shipping method
369
+ if ($shippingMethod == 'standard') {
370
+ return $this->setCourierType(self::SHIPPING_SERVICE_STANDARD);
371
+ }
372
+ elseif ($shippingMethod == 'express') {
373
+ return $this->setCourierType(self::SHIPPING_SERVICE_EXPRESS);
374
+ }
375
+ elseif ($shippingMethod == 'priority' && isset($deliveryDate) && isset($deliveryWindow)) {
376
+ return $this->setCourierType(self::SHIPPING_SERVICE_PRIORITY)
377
+ ->setDeliveryDate($deliveryDate)
378
+ ->setDeliveryWindow($deliveryWindow);
379
+ }
380
+ elseif ($shippingMethod == 'international') {
381
+ return $this->setCourierType(self::SHIPPING_SERVICE_INTERNATIONAL);
382
+ }
383
+ else {
384
+ return $this->setData(self::COURIER_TYPE, self::SHIPPING_SERVICE_STANDARD);
385
+ }
386
+ }
387
+
388
+ private function _getOrderDeliveryDate($order)
389
+ {
390
+ $shippingMethod = $order->getShippingMethod();
391
+
392
+ // If the shipping method is a shippit method,
393
+ // processing using the selected shipping options
394
+ if (strpos($shippingMethod, $this->carrierCode) !== FALSE) {
395
+ $shippingOptions = str_replace($this->carrierCode . '_', '', $shippingMethod);
396
+ $shippingOptions = explode('_', $shippingOptions);
397
+ $courierData = array();
398
+
399
+ if (isset($shippingOptions[0])) {
400
+ if ($shippingOptions[0] == 'priority') {
401
+ return $shippingOptions[1];
402
+ }
403
+ else {
404
+ return null;
405
+ }
406
+ }
407
+ else {
408
+ return null;
409
+ }
410
+ }
411
+ else {
412
+ return null;
413
+ }
414
+ }
415
+
416
+ private function _getOrderDeliveryWindow($order)
417
+ {
418
+ $shippingMethod = $order->getShippingMethod();
419
+
420
+ // If the shipping method is a shippit method,
421
+ // processing using the selected shipping options
422
+ if (strpos($shippingMethod, $this->carrierCode) !== FALSE) {
423
+ $shippingOptions = str_replace($this->carrierCode . '_', '', $shippingMethod);
424
+ $shippingOptions = explode('_', $shippingOptions);
425
+ $courierData = array();
426
+
427
+ if (isset($shippingOptions[0])) {
428
+ if ($shippingOptions[0] == 'priority') {
429
+ return $shippingOptions[2];
430
+ }
431
+ else {
432
+ return null;
433
+ }
434
+ }
435
+ else {
436
+ return null;
437
+ }
438
+ }
439
+ else {
440
+ return null;
441
+ }
442
+ }
443
+
444
+ /**
445
+ * Get the Receiver Name
446
+ *
447
+ * @return string|null
448
+ */
449
+ public function getReceiverName()
450
+ {
451
+ return $this->getData(self::RECEIVER_NAME);
452
+ }
453
+
454
+ /**
455
+ * Set the Reciever Name
456
+ *
457
+ * @param string $receiverName Receiver Name
458
+ * @return string
459
+ */
460
+ public function setReceiverName($receiverName)
461
+ {
462
+ return $this->setData(self::RECEIVER_NAME, $receiverName);
463
+ }
464
+
465
+ /**
466
+ * Get the Receiver Contact Number
467
+ *
468
+ * @return string|null
469
+ */
470
+ public function getReceiverContactNumber()
471
+ {
472
+ return $this->getData(self::RECEIVER_CONTACT_NUMBER);
473
+ }
474
+
475
+ /**
476
+ * Set the Reciever Contact Number
477
+ *
478
+ * @param string $receiverContactNumber Receiver Contact Number
479
+ * @return string
480
+ */
481
+ public function setReceiverContactNumber($receiverContactNumber)
482
+ {
483
+ return $this->setData(self::RECEIVER_CONTACT_NUMBER, $receiverContactNumber);
484
+ }
485
+
486
+ /**
487
+ * Get the Delivery Company
488
+ *
489
+ * @return string|null
490
+ */
491
+ public function getDeliveryCompany()
492
+ {
493
+ return $this->getData(self::DELIVERY_COMPANY);
494
+ }
495
+
496
+ /**
497
+ * Set the Delivery Company
498
+ *
499
+ * @param string $deliveryCompany Delivery Company
500
+ * @return string
501
+ */
502
+ public function setDeliveryCompany($deliveryCompany)
503
+ {
504
+ return $this->setData(self::DELIVERY_COMPANY, $deliveryCompany);
505
+ }
506
+
507
+ /**
508
+ * Get the Delivery Address
509
+ *
510
+ * @return string|null
511
+ */
512
+ public function getDeliveryAddress()
513
+ {
514
+ return $this->getData(self::DELIVERY_ADDRESS);
515
+ }
516
+
517
+ /**
518
+ * Set the Delivery Address
519
+ *
520
+ * @param string $deliveryAddress Delivery Address
521
+ * @return string
522
+ */
523
+ public function setDeliveryAddress($deliveryAddress)
524
+ {
525
+ return $this->setData(self::DELIVERY_ADDRESS, $deliveryAddress);
526
+ }
527
+
528
+ /**
529
+ * Get the Delivery Suburb
530
+ *
531
+ * @return string|null
532
+ */
533
+ public function getDeliverySuburb()
534
+ {
535
+ return $this->getData(self::DELIVERY_SUBURB);
536
+ }
537
+
538
+ /**
539
+ * Set the Delivery Suburb
540
+ *
541
+ * @param string $deliverySuburb Delivery Suburb
542
+ * @return string
543
+ */
544
+ public function setDeliverySuburb($deliverySuburb)
545
+ {
546
+ return $this->setData(self::DELIVERY_SUBURB, $deliverySuburb);
547
+ }
548
+
549
+ /**
550
+ * Get the Delivery Postcode
551
+ *
552
+ * @return string|null
553
+ */
554
+ public function getDeliveryPostcode()
555
+ {
556
+ return $this->getData(self::DELIVERY_POSTCODE);
557
+ }
558
+
559
+ /**
560
+ * Set the Delivery Postcode
561
+ *
562
+ * @param string $deliveryPostcode Delivery Postcode
563
+ * @return string
564
+ */
565
+ public function setDeliveryPostcode($deliveryPostcode)
566
+ {
567
+ return $this->setData(self::DELIVERY_POSTCODE, $deliveryPostcode);
568
+ }
569
+
570
+ /**
571
+ * Get the Delivery State
572
+ *
573
+ * @return string|null
574
+ */
575
+ public function getDeliveryState()
576
+ {
577
+ return $this->getData(self::DELIVERY_STATE);
578
+ }
579
+
580
+ /**
581
+ * Set the Delivery State
582
+ *
583
+ * @param string $deliveryState Delivery State
584
+ * @return string
585
+ */
586
+ public function setDeliveryState($deliveryState)
587
+ {
588
+ return $this->setData(self::DELIVERY_STATE, $deliveryState);
589
+ }
590
+
591
+ /**
592
+ * Get the Delivery Country
593
+ *
594
+ * @return string|null
595
+ */
596
+ public function getDeliveryCountry()
597
+ {
598
+ return $this->getData(self::DELIVERY_COUNTRY);
599
+ }
600
+
601
+ /**
602
+ * Set the Delivery Country
603
+ *
604
+ * @param string $deliveryCountry Delivery Country
605
+ * @return string
606
+ */
607
+ public function setDeliveryCountry($deliveryCountry)
608
+ {
609
+ return $this->setData(self::DELIVERY_COUNTRY, $deliveryCountry);
610
+ }
611
+
612
+ /**
613
+ * Get the Parcel Attributes
614
+ *
615
+ * @return string|null
616
+ */
617
+ public function getParcelAttributes()
618
+ {
619
+ return $this->getData(self::PARCEL_ATTRIBUTES);
620
+ }
621
+
622
+ /**
623
+ * Set the Parcel Attributes
624
+ *
625
+ * @param string $parcelAttributes
626
+ * @return string|null
627
+ */
628
+ public function setParcelAttributes($parcelAttributes)
629
+ {
630
+ return $this->setData(self::PARCEL_ATTRIBUTES, $parcelAttributes);
631
+ }
632
+
633
+ /**
634
+ * Add a parcel with attributes
635
+ *
636
+ */
637
+ public function addItem($sku, $title, $qty, $price, $weight = 0, $location = null)
638
+ {
639
+ $parcelAttributes = $this->getParcelAttributes();
640
+
641
+ if (empty($parcelAttributes)) {
642
+ $parcelAttributes = array();
643
+ }
644
+
645
+ $newParcel = array(
646
+ 'sku' => $sku,
647
+ 'title' => $title,
648
+ 'qty' => $qty,
649
+ 'price' => $price,
650
+ // if a 0 weight is provided, stub the weight to 0.2kg
651
+ 'weight' => ($weight == 0 ? 0.2 : $weight),
652
+ 'location' => $location
653
+ );
654
+
655
+ $parcelAttributes[] = $newParcel;
656
+
657
+ return $this->setParcelAttributes($parcelAttributes);
658
+ }
659
+ }
app/code/community/Shippit/Shippit/Model/Request/Api/Shipment.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ // Read the Shippit webhook request and provides
18
+ // a summary of the available item actions in Magento
19
+
20
+ class Shippit_Shippit_Model_Request_Api_Shipment extends Varien_Object
21
+ {
22
+ protected $itemsHelper;
23
+ protected $items = null;
24
+
25
+ const ORDER = 'order';
26
+ const ITEMS = 'items';
27
+
28
+ const ERROR_ORDER_MISSING = 'The order id requested was not found';
29
+ const ERROR_ORDER_STATUS = 'The order id requested has an status that is not available for shipping';
30
+
31
+ public function __construct() {
32
+ $this->itemsHelper = Mage::helper('shippit/order_items');
33
+
34
+ return $this;
35
+ }
36
+
37
+ public function getOrderId()
38
+ {
39
+ return $this->getOrder()->getId();
40
+ }
41
+
42
+ public function setOrderByIncrementId($orderIncrementId)
43
+ {
44
+ $order = Mage::getModel('sales/order')->load($orderIncrementId, 'increment_id');
45
+
46
+ return $this->setOrder($order);
47
+ }
48
+
49
+ public function setOrder($order)
50
+ {
51
+ if (!$order->getId()) {
52
+ throw new Exception(self::ERROR_ORDER_MISSING);
53
+ }
54
+
55
+ if (!$order->canShip()) {
56
+ throw new Exception(self::ERROR_ORDER_STATUS);
57
+ }
58
+
59
+ return $this->setData(self::ORDER, $order);
60
+ }
61
+
62
+ /**
63
+ * Process items in the shipment request,
64
+ * - ensures only items contained in the order are present
65
+ * - ensures only qtys available for shipping are used in the shipment
66
+ *
67
+ * @param object $items The items to be included in the request
68
+ */
69
+ public function processItems($items = array())
70
+ {
71
+ // store items on the internal model property
72
+ $this->items = $items;
73
+
74
+ $itemsCollection = Mage::getResourceModel('sales/order_item_collection')
75
+ ->addFieldToFilter('order_id', $this->getOrderId());
76
+
77
+ // for the specific items that have been passed, ensure they are valid
78
+ // items for the item
79
+ if (!empty($items)) {
80
+ $itemsSkus = $this->itemsHelper->getSkus($items);
81
+
82
+ if (!empty($itemsSkus)) {
83
+ $itemsCollection->addFieldToFilter('sku', array('in' => $itemsSkus));
84
+ }
85
+ }
86
+
87
+ // For all valid items, process the quantity to be marked as shipped
88
+ foreach ($itemsCollection as $item) {
89
+ $requestedQty = $this->itemsHelper->getItemData($items, 'sku', $item->getSku(), 'quantity');
90
+
91
+ /**
92
+ * Magento marks a shipment only for the parent item in the order
93
+ * get the parent item to determine the correct qty to ship
94
+ */
95
+ $rootItem = $this->_getRootItem($item);
96
+
97
+ $itemQty = $this->itemsHelper->getQtyToShip($rootItem, $requestedQty);
98
+
99
+ if ($itemQty > 0) {
100
+ $this->addItem($item->getId(), $itemQty);
101
+ }
102
+ }
103
+
104
+ return $this;
105
+ }
106
+
107
+ private function _getRootItem($item)
108
+ {
109
+ if ($item->hasParentItem()) {
110
+ return $item->getParentItem();
111
+ }
112
+ else {
113
+ return $item;
114
+ }
115
+ }
116
+
117
+ public function getItems()
118
+ {
119
+ $items = $this->getData(self::ITEMS);
120
+
121
+ // if no items have been added, assume all items are to be marked as shipped
122
+ if (empty($items)) {
123
+ return array();
124
+ }
125
+ // otherwise, only mark the items and qtys specified as shipped
126
+ else {
127
+ return $items;
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Add a parcel with attributes
133
+ *
134
+ */
135
+ public function addItem($itemId, $qty)
136
+ {
137
+ $items = $this->getItems();
138
+
139
+ $items[$itemId] = $qty;
140
+
141
+ return $this->setItems($items);
142
+ }
143
+ }
app/code/community/Shippit/Shippit/Model/Request/Sync/Order.php ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ // Validates the request to create a sync order object
18
+ // Ensuring the order details, items and qtys requested
19
+ // to be synced are valid
20
+
21
+ class Shippit_Shippit_Model_Request_Sync_Order extends Varien_Object
22
+ {
23
+ protected $helper;
24
+ protected $itemsHelper;
25
+ protected $items;
26
+
27
+ /**
28
+ * Constants for keys of data array. Identical to the name of the getter in snake case
29
+ */
30
+ const ORDER_ID = 'order_id';
31
+ const ITEMS = 'items';
32
+ const SHIPPING_METHOD = 'shipping_method';
33
+
34
+ // const ERROR_INVALID_SHIPPING_METHOD = 'An invalid shipping method was requested, valid options include "standard" or "express"';
35
+ const ERROR_NO_ITEMS_AVAILABLE_FOR_SHIPPING = 'No items could be added to the sync order request, please ensure the items are available for shipping';
36
+
37
+ public function __construct() {
38
+ $this->helper = Mage::helper('shippit/sync_order');
39
+ $this->itemsHelper = Mage::helper('shippit/order_items');
40
+ }
41
+
42
+ /**
43
+ * Set the order to be sent to the api request
44
+ *
45
+ * @param object $order The Order Request
46
+ */
47
+ public function setOrderId($orderId)
48
+ {
49
+ return $this->setData(self::ORDER_ID, $orderId);
50
+ }
51
+
52
+ public function setOrder(Mage_Sales_Model_Order $order)
53
+ {
54
+ return $this->setOrderId($order->getId());
55
+ }
56
+
57
+ /**
58
+ * Add items from the order to the parcel details
59
+ *
60
+ * @param object $items The items to be included in the request
61
+ */
62
+ public function setItems($items = array())
63
+ {
64
+ $itemsCollection = Mage::getResourceModel('sales/order_item_collection')
65
+ ->addFieldToFilter('order_id', $this->getOrderId());
66
+
67
+ // if specific items have been passed,
68
+ // ensure that these are the only items in the request
69
+ if (!empty($items)) {
70
+ $itemsSkus = $this->itemsHelper->getSkus($items);
71
+
72
+ if (!empty($itemsSkus)) {
73
+ $itemsCollection = $itemsCollection->addFieldToFilter('sku', array('in' => $itemsSkus));
74
+ }
75
+ }
76
+
77
+ $itemsAdded = 0;
78
+
79
+ foreach ($itemsCollection as $item) {
80
+ if ($item->getHasChildren()) {
81
+ continue;
82
+ }
83
+
84
+ $requestedQty = $this->itemsHelper->getItemData($items, 'sku', $item->getSku(), 'qty');
85
+
86
+ /**
87
+ * Magento marks a shipment only for the parent item in the order
88
+ * get the parent item to determine the correct qty to ship
89
+ */
90
+ $rootItem = $this->_getRootItem($item);
91
+
92
+ $itemQty = $this->itemsHelper->getQtyToShip($rootItem, $requestedQty);
93
+ $itemWeight = $item->getWeight();
94
+
95
+ $itemLocation = $this->itemsHelper->getLocation($item);
96
+
97
+ if ($itemQty > 0) {
98
+ $this->addItem(
99
+ $item->getSku(),
100
+ $item->getName(),
101
+ $itemQty,
102
+ $rootItem->getBasePrice(),
103
+ $itemWeight,
104
+ $itemLocation
105
+ );
106
+
107
+ $itemsAdded++;
108
+ }
109
+ }
110
+
111
+ if ($itemsAdded == 0) {
112
+ throw new Exception(self::ERROR_NO_ITEMS_AVAILABLE_FOR_SHIPPING);
113
+ }
114
+
115
+ return $this;
116
+ }
117
+
118
+ private function _getRootItem($item)
119
+ {
120
+ if ($item->getParentItem()) {
121
+ return $item->getParentItem();
122
+ }
123
+ else {
124
+ return $item;
125
+ }
126
+ }
127
+
128
+ public function setShippingMethod($shippingMethod)
129
+ {
130
+ // Standard, express and priority options are available
131
+ // Priority services requires the use of live quoting to determine
132
+ // booking availability
133
+ $validShippingMethods = array(
134
+ 'standard',
135
+ 'express',
136
+ 'international',
137
+ 'priority'
138
+ );
139
+
140
+ // if the shipping method passed is not a standard shippit service class, attempt to get a service class based on the configured mapping
141
+ if (!in_array($shippingMethod, $validShippingMethods)) {
142
+ $shippingMethod = $this->helper->getShippitShippingMethod($shippingMethod);
143
+ }
144
+
145
+ if (in_array($shippingMethod, $validShippingMethods)) {
146
+ return $this->setData(self::SHIPPING_METHOD, $shippingMethod);
147
+ }
148
+ else {
149
+ return $this->setData(self::SHIPPING_METHOD, 'standard');
150
+ }
151
+ }
152
+
153
+ public function reset()
154
+ {
155
+ // reset the request data
156
+ $this->setOrderId(null)
157
+ ->setItems(null);
158
+
159
+ return $this->setData(self::SHIPPING_METHOD, null);
160
+ }
161
+
162
+ /**
163
+ * Add a parcel with attributes
164
+ *
165
+ */
166
+ public function addItem($sku, $title, $qty, $price, $weight = 0, $location = null)
167
+ {
168
+ $items = $this->getItems();
169
+
170
+ if (empty($items)) {
171
+ $items = array();
172
+ }
173
+
174
+ $newItem = array(
175
+ 'sku' => $sku,
176
+ 'title' => $title,
177
+ 'qty' => $qty,
178
+ 'price' => $price,
179
+ 'weight' => $weight,
180
+ 'location' => $location
181
+ );
182
+
183
+ $items[] = $newItem;
184
+
185
+ return $this->setData(self::ITEMS, $items);
186
+ }
187
+ }
app/code/community/Shippit/Shippit/Model/Resource/Setup.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Resource_Setup extends Mage_Eav_Model_Entity_Setup
18
+ {
19
+ // This resource model has been intentionally left blank
20
+ }
app/code/community/Shippit/Shippit/Model/Resource/Sync/Order.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Resource_Sync_Order extends Mage_Core_Model_Resource_Db_Abstract
18
+ {
19
+ protected function _construct()
20
+ {
21
+ $this->_init('shippit/sync_order', 'sync_id');
22
+ }
23
+
24
+ /**
25
+ * Perform operations before object save
26
+ *
27
+ * @param Shippit_Shippit_Model_Sync_Order $object
28
+ * @return Shippit_Shippit_Model_Resource_Sync_Order
29
+ */
30
+ protected function _beforeSave(Mage_Core_Model_Abstract $object)
31
+ {
32
+ if (!$object->getId()) {
33
+ $object->setCreatedAt(Mage::getSingleton('core/date')->gmtDate());
34
+ }
35
+
36
+ return $this;
37
+ }
38
+
39
+ /**
40
+ * Save related items to the Sync Order
41
+ *
42
+ * @param Mage_Core_Model_Abstract $customer
43
+ * @return Mage_Eav_Model_Entity_Abstract
44
+ */
45
+ protected function _afterSave(Mage_Core_Model_Abstract $syncOrder)
46
+ {
47
+ $this->_saveItems($syncOrder);
48
+
49
+ return parent::_afterSave($syncOrder);
50
+ }
51
+
52
+ /**
53
+ * Save the items attached to the sync order
54
+ *
55
+ * @param Shippit_Shippit_Model_Sync_Order $syncOrder The Sync Order Object
56
+ * @return Shippit_Shippit_Model_Sync_Order The Sync Order Object
57
+ */
58
+ protected function _saveItems(Shippit_Shippit_Model_Sync_Order $syncOrder)
59
+ {
60
+ foreach ($syncOrder->getItems() as $item) {
61
+ $item->setSyncId($syncOrder->getId())
62
+ ->save();
63
+ }
64
+
65
+ return $this;
66
+ }
67
+ }
app/code/community/Shippit/Shippit/Model/Resource/Sync/Order/Collection.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Resource_Sync_Order_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
18
+ {
19
+ protected function _construct()
20
+ {
21
+ $this->_init('shippit/sync_order');
22
+ }
23
+ }
app/code/community/Shippit/Shippit/Model/Resource/Sync/Order/Item.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Resource_Sync_Order_Item extends Mage_Core_Model_Resource_Db_Abstract
18
+ {
19
+ protected function _construct()
20
+ {
21
+ $this->_init('shippit/sync_order_item', 'sync_item_id');
22
+ }
23
+ }
app/code/community/Shippit/Shippit/Model/Resource/Sync/Order/Item/Collection.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Resource_Sync_Order_Item_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
18
+ {
19
+ protected $syncOrder;
20
+
21
+ protected function _construct()
22
+ {
23
+ $this->_init('shippit/sync_order_item');
24
+ }
25
+
26
+ /**
27
+ * Filter the items collection by the SyncOrder
28
+ * @param Shippit_Shippit_Model_Sync_Order $syncOrder The Sync Order Object
29
+ */
30
+ public function addSyncOrderFilter(Mage_Core_Model_Abstract $syncOrder)
31
+ {
32
+ $syncOrderId = $syncOrder->getSyncId();
33
+
34
+ if ($syncOrderId) {
35
+ $this->addFieldToFilter('sync_id', $syncOrderId);
36
+ }
37
+ else {
38
+ $this->addFieldToFilter('sync_id', null);
39
+ }
40
+
41
+ return $this;
42
+ }
43
+ }
app/code/community/Shippit/Shippit/Model/Shipping/Carrier/Shippit.php ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Shipping_Carrier_Shippit extends Mage_Shipping_Model_Carrier_Abstract implements Mage_Shipping_Model_Carrier_Interface
18
+ {
19
+ /**
20
+ * Carrier's code
21
+ *
22
+ * @var string
23
+ */
24
+ protected $_code = 'shippit';
25
+
26
+ /**
27
+ * Configuration Helper
28
+ * @var Shippit_Shippit_Helper_Data
29
+ */
30
+ protected $helper;
31
+ protected $api;
32
+ protected $logger;
33
+
34
+ /**
35
+ * Attach the helper as a class variable
36
+ */
37
+ public function __construct()
38
+ {
39
+ $this->helper = Mage::helper('shippit/carrier');
40
+ $this->api = Mage::helper('shippit/api');
41
+ $this->logger = Mage::getModel('shippit/logger');
42
+
43
+ return parent::__construct();
44
+ }
45
+
46
+ /**
47
+ * Collect and get rates
48
+ *
49
+ * @abstract
50
+ * @param Mage_Shipping_Model_Rate_Request $request
51
+ * @return Mage_Shipping_Model_Rate_Result|bool|null
52
+ */
53
+ public function collectRates(Mage_Shipping_Model_Rate_Request $request)
54
+ {
55
+ if (!$this->helper->isActive()) {
56
+ return false;
57
+ }
58
+
59
+ // check if we have any methods allowed before proceeding
60
+ $allowedMethods = $this->helper->getAllowedMethods();
61
+ if (count($allowedMethods) == 0) {
62
+ return false;
63
+ }
64
+
65
+ // check the products are eligible for shippit shipping
66
+ if (!$this->_canShipProducts($request)) {
67
+ return false;
68
+ }
69
+
70
+ $rateResult = Mage::getModel('shipping/rate_result');
71
+ $quoteRequest = new Varien_Object;
72
+
73
+ // Get the first available dates based on the customer's shippit profile settings
74
+ $quoteRequest->setOrderDate('');
75
+
76
+ if ($request->getDestCity()) {
77
+ $quoteRequest->setDropoffSuburb($request->getDestCity());
78
+ }
79
+
80
+ if ($request->getDestPostcode()) {
81
+ $quoteRequest->setDropoffPostcode($request->getDestPostcode());
82
+ }
83
+
84
+ if ($request->getDestRegionCode()) {
85
+ $quoteRequest->setDropoffState($request->getDestRegionCode());
86
+ }
87
+ elseif ($request->getDestPostcode()
88
+ && $regionCodeFallback = $this->helper->getStateFromPostcode($request->getDestPostcode())) {
89
+ $quoteRequest->setDropoffState($regionCodeFallback);
90
+ }
91
+
92
+ $quoteRequest->setParcelAttributes($this->_getParcelAttributes($request));
93
+
94
+ try {
95
+ // Call the api and retrieve the quote
96
+ $shippingQuotes = $this->api->getQuote($quoteRequest);
97
+ }
98
+ catch (Exception $e) {
99
+ return false;
100
+ }
101
+
102
+ $this->_processShippingQuotes($rateResult, $shippingQuotes);
103
+
104
+ return $rateResult;
105
+ }
106
+
107
+ private function _processShippingQuotes(&$rateResult, $shippingQuotes)
108
+ {
109
+ $allowedMethods = $this->helper->getAllowedMethods();
110
+
111
+ $isPriorityAvailable = in_array('priority', $allowedMethods);
112
+ $isExpressAvailable = in_array('express', $allowedMethods);
113
+ $isStandardAvailable = in_array('standard', $allowedMethods);
114
+
115
+ // Process the response and return available options
116
+ foreach ($shippingQuotes as $shippingQuoteKey => $shippingQuote) {
117
+ if ($shippingQuote->success) {
118
+ if ($shippingQuote->courier_type == 'Bonds'
119
+ && $isPriorityAvailable) {
120
+ $this->_addPriorityQuote($rateResult, $shippingQuote);
121
+ }
122
+ elseif ($shippingQuote->courier_type == 'eparcelexpress'
123
+ && $isExpressAvailable) {
124
+ $this->_addExpressQuote($rateResult, $shippingQuote);
125
+ }
126
+ elseif ($isStandardAvailable) {
127
+ $this->_addStandardQuote($rateResult, $shippingQuote);
128
+ }
129
+ }
130
+ }
131
+
132
+ return $rateResult;
133
+ }
134
+
135
+ private function _addStandardQuote(&$rateResult, $shippingQuote)
136
+ {
137
+ foreach ($shippingQuote->quotes as $shippingQuoteQuote) {
138
+ $rateResultMethod = Mage::getModel('shipping/rate_result_method');
139
+ $rateResultMethod->setCarrier($this->_code)
140
+ ->setCarrierTitle($this->helper->getTitle())
141
+ ->setMethod('standard')
142
+ ->setMethodTitle('Standard')
143
+ ->setCost($shippingQuoteQuote->price)
144
+ ->setPrice($shippingQuoteQuote->price);
145
+
146
+ $rateResult->append($rateResultMethod);
147
+ }
148
+ }
149
+
150
+ private function _addExpressQuote(&$rateResult, $shippingQuote)
151
+ {
152
+ foreach ($shippingQuote->quotes as $shippingQuoteQuote) {
153
+ $rateResultMethod = Mage::getModel('shipping/rate_result_method');
154
+ $rateResultMethod->setCarrier($this->_code)
155
+ ->setCarrierTitle($this->helper->getTitle())
156
+ ->setMethod('express')
157
+ ->setMethodTitle('Express')
158
+ ->setCost($shippingQuoteQuote->price)
159
+ ->setPrice($shippingQuoteQuote->price);
160
+
161
+ $rateResult->append($rateResultMethod);
162
+ }
163
+ }
164
+
165
+ private function _addPriorityQuote(&$rateResult, $shippingQuote)
166
+ {
167
+ $maxTimeslots = $this->helper->getMaxTimeslots();
168
+ $timeslotCount = 0;
169
+
170
+ foreach ($shippingQuote->quotes as $shippingQuoteQuote) {
171
+ if (!empty($maxTimeslots) && $maxTimeslots <= $timeslotCount) {
172
+ break;
173
+ }
174
+
175
+ $rateResultMethod = Mage::getModel('shipping/rate_result_method');
176
+
177
+ if (property_exists($shippingQuoteQuote, 'delivery_date')
178
+ && property_exists($shippingQuoteQuote, 'delivery_window')
179
+ && property_exists($shippingQuoteQuote, 'delivery_window_desc')) {
180
+ $timeslotCount++;
181
+ $carrierTitle = $this->helper->getTitle();
182
+ $method = 'priority_' . $shippingQuoteQuote->delivery_date . '_' . $shippingQuoteQuote->delivery_window;
183
+ $methodTitle = 'Priority' . ' - Delivered ' . $shippingQuoteQuote->delivery_date. ', Between ' . $shippingQuoteQuote->delivery_window_desc;
184
+ }
185
+ else {
186
+ $carrierTitle = $this->helper->getTitle();
187
+ $method = 'priority';
188
+ $methodTitle = 'Priority';
189
+ }
190
+
191
+ $rateResultMethod->setCarrier($this->_code)
192
+ ->setCarrierTitle($carrierTitle)
193
+ ->setMethod($method)
194
+ ->setMethodTitle($methodTitle)
195
+ ->setCost($shippingQuoteQuote->price)
196
+ ->setPrice($shippingQuoteQuote->price);
197
+
198
+ $rateResult->append($rateResultMethod);
199
+ }
200
+ }
201
+
202
+ public function isTrackingAvailable()
203
+ {
204
+ return true;
205
+ }
206
+
207
+ public function getTrackingInfo($tracking)
208
+ {
209
+ $track = Mage::getModel('shipping/tracking_result_status');
210
+ $track->setUrl('https://www.shippit.com/track/' . $tracking)
211
+ ->setTracking($tracking)
212
+ ->setCarrierTitle($this->getConfigData('name'));
213
+
214
+ return $track;
215
+ }
216
+
217
+ public function getAllowedMethods()
218
+ {
219
+ $configAllowedMethods = $this->helper->getAllowedMethods();
220
+ $availableMethods = Mage::getModel('shippit/system_config_source_shippit_methods')->getMethods();
221
+
222
+ $allowedMethods = array();
223
+
224
+ foreach ($availableMethods as $methodValue => $methodLabel) {
225
+ if (in_array($methodValue, $configAllowedMethods)) {
226
+ $allowedMethods[$methodValue] = $this->helper->getTitle() . ' ' . $methodLabel;
227
+ }
228
+ }
229
+
230
+ return $allowedMethods;
231
+ }
232
+
233
+ public function isStateProvinceRequired()
234
+ {
235
+ return true;
236
+ }
237
+
238
+ public function isCityRequired()
239
+ {
240
+ return true;
241
+ }
242
+
243
+ public function isZipCodeRequired($countryId = null)
244
+ {
245
+ if ($countryId == 'AU') {
246
+ return true;
247
+ }
248
+ else {
249
+ return parent::isZipCodeRequired($countryId);
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Checks the request and ensures all products are either enabled, or part of the attributes elidgable
255
+ *
256
+ * @param [type] $request The shipment request
257
+ * @return boolean True or false
258
+ */
259
+ private function _canShipProducts($request)
260
+ {
261
+ $items = $request->getAllItems();
262
+ $productIds = array();
263
+
264
+ foreach ($items as $item) {
265
+ // Skip special product types
266
+ if ($item->getProduct()->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE
267
+ || $item->getProduct()->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE
268
+ || $item->getProduct()->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_GROUPED
269
+ || $item->getProduct()->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_VIRTUAL) {
270
+ continue;
271
+ }
272
+
273
+ $productIds[] = $item->getProduct()->getId();
274
+ }
275
+
276
+ $canShipEnabledProducts = $this->_canShipEnabledProducts($productIds);
277
+ $canShipEnabledProductAttributes = $this->_canShipEnabledProductAttributes($productIds);
278
+
279
+ if ($canShipEnabledProducts && $canShipEnabledProductAttributes) {
280
+ return true;
281
+ }
282
+ else {
283
+ return false;
284
+ }
285
+ }
286
+
287
+ private function _canShipEnabledProducts($productIds)
288
+ {
289
+ if (!$this->helper->isEnabledProductActive()) {
290
+ return true;
291
+ }
292
+
293
+ $enabledProductIds = $this->helper->getEnabledProductIds();
294
+
295
+ // if we have enabled products, check that all
296
+ // items in the shipping request are enabled
297
+ if (count($enabledProductIds) > 0) {
298
+ if ($productIds != array_intersect($productIds, $enabledProductIds)) {
299
+ return false;
300
+ }
301
+ }
302
+
303
+ return true;
304
+ }
305
+
306
+ private function _canShipEnabledProductAttributes($productIds)
307
+ {
308
+ if (!$this->helper->isEnabledProductAttributeActive()) {
309
+ return true;
310
+ }
311
+
312
+ $attributeCode = $this->helper->getEnabledProductAttributeCode();
313
+ $attributeValue = $this->helper->getEnabledProductAttributeValue();
314
+
315
+ if (!empty($attributeCode) && !empty($attributeValue)) {
316
+ $attributeProductCount = Mage::getModel('catalog/product')
317
+ ->getCollection()
318
+ ->addAttributeToFilter('entity_id', array('in' => $productIds));
319
+
320
+ // When filtering by attribute value, allow for * as a wildcard
321
+ if (strpos($attributeValue, '*') !== FALSE) {
322
+ $attributeValue = str_replace('*', '%', $attributeValue);
323
+
324
+ $attributeProductCount = $attributeProductCount->addAttributeToFilter($attributeCode, array('like' => $attributeValue))
325
+ ->getSize();
326
+ }
327
+ // Otherwise, use the exact match
328
+ else {
329
+ $attributeProductCount = $attributeProductCount->addAttributeToFilter($attributeCode, array('eq' => $attributeValue))
330
+ ->getSize();
331
+ }
332
+
333
+ // If the number of filtered products is not
334
+ // equal to the products in the cart, return false
335
+ if ($attributeProductCount != count($productIds)) {
336
+ return false;
337
+ }
338
+ }
339
+
340
+ // All checks have passed, return true
341
+ return true;
342
+ }
343
+
344
+ private function _getParcelAttributes($request)
345
+ {
346
+ $parcelAttributes = array(
347
+ array(
348
+ 'qty' => $request->getPackageQty(),
349
+ 'weight' => ($request->getPackageWeight() / $request->getPackageQty())
350
+ )
351
+ );
352
+
353
+ return $parcelAttributes;
354
+ }
355
+ }
app/code/community/Shippit/Shippit/Model/Shippit.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Shippit extends Mage_Core_Model_Abstract
18
+ {
19
+ protected $helper;
20
+
21
+ public function __construct() {
22
+ $this->helper = Mage::helper('shippit');
23
+
24
+ return parent::__construct();
25
+ }
26
+
27
+ /**
28
+ * Adds the order to the request queue, and if the mode is requested as realtime,
29
+ * attempts to sync the record immediately.
30
+ *
31
+ * Note: Priority shipping services are only available via live quoting
32
+ *
33
+ * @param integer $entityId The order entity_id
34
+ * @param array $items An array of the items to be included
35
+ * @param string $shippingMethod The shipping method service class to be used (standard, express)
36
+ * @param string $apiKey The API Key to be used in the request
37
+ * @param string $syncMode The sync mode ot be used for the request
38
+ * @param boolean $displayNotifications Flag to indiciate if notifications should be shown to the user
39
+ */
40
+ public function addOrder($entityId, $items = array(), $shippingMethod = null, $apiKey = null, $syncMode = null, $displayNotifications = false)
41
+ {
42
+ // Ensure the module is active
43
+ if (!$this->helper->isActive()) {
44
+ return $this;
45
+ }
46
+
47
+ $request = Mage::getModel('shippit/request_sync_order')
48
+ ->setOrderId($entityId)
49
+ ->setItems($items)
50
+ ->setApiKey($apiKey)
51
+ ->setShippingMethod($shippingMethod);
52
+
53
+ // Create a new sync order record
54
+ $syncOrder = Mage::getModel('shippit/sync_order')->addRequest($request)
55
+ ->save();
56
+
57
+ // sync immediately if sync mode is realtime,
58
+ if ($syncMode == Shippit_Shippit_Helper_Data::SYNC_MODE_REALTIME) {
59
+ // return the result of the sync
60
+ return Mage::getModel('shippit/api_order')->sync($syncOrder, $displayNotifications);
61
+ }
62
+
63
+ // return the sync order object
64
+ return $syncOrder;
65
+ }
66
+ }
app/code/community/Shippit/Shippit/Model/Sync/Order.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Sync_Order extends Mage_Core_Model_Abstract
18
+ {
19
+ const STATUS_PENDING = 0;
20
+ const STATUS_PENDING_TEXT = 'Pending';
21
+ const STATUS_SYNCED = 1;
22
+ const STATUS_SYNCED_TEXT = 'Synced';
23
+ const STATUS_FAILED = 2;
24
+ const STATUS_FAILED_TEXT = 'Failed';
25
+
26
+ const SYNC_MAX_ATTEMPTS = 5;
27
+
28
+ protected $_itemsCollection = null;
29
+ protected $_items = null;
30
+
31
+ protected function _construct()
32
+ {
33
+ $this->_init('shippit/sync_order');
34
+ }
35
+
36
+ public function addRequest($request)
37
+ {
38
+ $this->setOrderId($request->getOrderId())
39
+ ->addItems($request->getItems())
40
+ ->setShippingMethod($request->getShippingMethod())
41
+ ->setApiKey($request->getApiKey());
42
+
43
+ return $this;
44
+ }
45
+
46
+ /**
47
+ * Add the order details to the sync event
48
+ *
49
+ * @param Mage_Sales_Model_Order|String $order The Magento Order object or Order id
50
+ */
51
+ public function addOrder(Mage_Sales_Model_Order $order)
52
+ {
53
+ $this->setOrderId($order->getEntityId());
54
+
55
+ return $this;
56
+ }
57
+
58
+ /**
59
+ * Get the Order Object attached to the Sync Order Entry
60
+ *
61
+ * @return [type] [description]
62
+ */
63
+ public function getOrder()
64
+ {
65
+ $orderId = $this->getOrderId();
66
+
67
+ return Mage::getModel('sales/order')->load($orderId);
68
+ }
69
+
70
+ /**
71
+ * Retrieve sync order items collection
72
+ *
73
+ * @param bool $useCache
74
+ * @return Mage_Eav_Model_Entity_Collection_Abstract
75
+ */
76
+ public function getItemsCollection($useCache = true)
77
+ {
78
+ if (is_null($this->_itemsCollection) || !$useCache) {
79
+ $this->_itemsCollection = Mage::getResourceModel('shippit/sync_order_item_collection');
80
+ $this->_itemsCollection->addSyncOrderFilter($this);
81
+ }
82
+
83
+ return $this->_itemsCollection;
84
+ }
85
+
86
+ /**
87
+ * Retrieve customer address array
88
+ *
89
+ * @return array
90
+ */
91
+ public function getItems()
92
+ {
93
+ $this->_items = $this->getItemsCollection()->getItems();
94
+
95
+ return $this->_items;
96
+ }
97
+
98
+ /**
99
+ * Add a new item to the sync order request
100
+ *
101
+ * @param Shippit_Shippit_Model_Sync_Order_Item $item
102
+ */
103
+ public function addItem(Shippit_Shippit_Model_Sync_Order_Item $item)
104
+ {
105
+ if (!$item->getSyncItemId()) {
106
+ $this->getItemsCollection()->addItem($item);
107
+ $this->_items[] = $item;
108
+ }
109
+
110
+ return $this;
111
+ }
112
+
113
+ /**
114
+ * Add a new item to the sync order request
115
+ *
116
+ * @param Array $item
117
+ */
118
+ public function addItems($items)
119
+ {
120
+ foreach ($items as $item) {
121
+ $itemObject = Mage::getModel('shippit/sync_order_item')->addItem($item);
122
+ $this->addItem($itemObject);
123
+ }
124
+
125
+ return $this;
126
+ }
127
+ }
app/code/community/Shippit/Shippit/Model/Sync/Order/Config.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Sync_Order_Config extends Mage_Core_Model_Abstract
18
+ {
19
+ public function getStatus()
20
+ {
21
+ return array(
22
+ Shippit_Shippit_Model_Sync_Order::STATUS_PENDING => Shippit_Shippit_Model_Sync_Order::STATUS_PENDING_TEXT,
23
+ Shippit_Shippit_Model_Sync_Order::STATUS_SYNCED => Shippit_Shippit_Model_Sync_Order::STATUS_SYNCED_TEXT,
24
+ Shippit_Shippit_Model_Sync_Order::STATUS_FAILED => Shippit_Shippit_Model_Sync_Order::STATUS_FAILED_TEXT,
25
+ );
26
+ }
27
+ }
app/code/community/Shippit/Shippit/Model/Sync/Order/Item.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_Sync_Order_Item extends Mage_Core_Model_Abstract
18
+ {
19
+ protected function _construct()
20
+ {
21
+ $this->_init('shippit/sync_order_item');
22
+ }
23
+
24
+ public function addItem($item)
25
+ {
26
+ return $this->setData($item);
27
+ }
28
+ }
app/code/community/Shippit/Shippit/Model/System/Config/Source/Catalog/Attributes.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_System_Config_Source_Catalog_Attributes
18
+ {
19
+ /**
20
+ * Returns code => code pairs of attributes for all product attributes
21
+ *
22
+ * @return array
23
+ */
24
+ public function toOptionArray()
25
+ {
26
+ $entityType = Mage::getModel('eav/entity_type')
27
+ ->loadByCode(Mage_Catalog_Model_Product::ENTITY);
28
+
29
+ $attributes = Mage::getModel('eav/entity_attribute')
30
+ ->getCollection()
31
+ ->addFieldToSelect('attribute_code')
32
+ ->setEntityTypeFilter($entityType)
33
+ ->setOrder('attribute_code', 'ASC');
34
+
35
+ $attributeArray[] = array(
36
+ 'label' => ' -- Please Select -- ',
37
+ 'value' => ''
38
+ );
39
+
40
+ foreach ($attributes as $attribute)
41
+ {
42
+ $attributeArray[] = array(
43
+ 'label' => $attribute->getAttributeCode(),
44
+ 'value' => $attribute->getAttributeCode()
45
+ );
46
+ }
47
+
48
+ return $attributeArray;
49
+ }
50
+ }
app/code/community/Shippit/Shippit/Model/System/Config/Source/Catalog/Attributes/Location.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_System_Config_Source_Catalog_Attributes_Location
18
+ {
19
+ /**
20
+ * Returns code => code pairs of attributes for all product attributes
21
+ *
22
+ * @return array
23
+ */
24
+ public function toOptionArray()
25
+ {
26
+ $entityType = Mage::getModel('eav/entity_type')
27
+ ->loadByCode(Mage_Catalog_Model_Product::ENTITY);
28
+
29
+ $attributes = Mage::getModel('eav/entity_attribute')
30
+ ->getCollection()
31
+ ->addFieldToSelect('attribute_code')
32
+ ->setEntityTypeFilter($entityType)
33
+ ->setOrder('attribute_code', 'ASC');
34
+
35
+ $attributeArray[] = array(
36
+ 'label' => ' -- Leave Blank -- ',
37
+ 'value' => ''
38
+ );
39
+
40
+ foreach ($attributes as $attribute)
41
+ {
42
+ $attributeArray[] = array(
43
+ 'label' => $attribute->getAttributeCode(),
44
+ 'value' => $attribute->getAttributeCode()
45
+ );
46
+ }
47
+
48
+ return $attributeArray;
49
+ }
50
+ }
app/code/community/Shippit/Shippit/Model/System/Config/Source/Catalog/Products.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_System_Config_Source_Catalog_Products
18
+ {
19
+ /**
20
+ * Returns code => code pairs of attributes for all product attributes
21
+ *
22
+ * @return array
23
+ */
24
+ public function toOptionArray()
25
+ {
26
+ $products = Mage::getModel('catalog/product')
27
+ ->getCollection()
28
+ ->addAttributeToSelect('name')
29
+ ->setOrder('name', 'ASC');
30
+
31
+ foreach ($products as $product)
32
+ {
33
+ $productArray[] = array(
34
+ 'label' => $product->getName(),
35
+ 'value' => $product->getId()
36
+ );
37
+ }
38
+
39
+ return $productArray;
40
+ }
41
+ }
app/code/community/Shippit/Shippit/Model/System/Config/Source/Shipping/Methods.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_System_Config_Source_Shipping_Methods
18
+ {
19
+ public function toOptionArray($excludeShippit = false)
20
+ {
21
+ $optionsArray = array();
22
+ $carriers = Mage::getSingleton('shipping/config')->getAllCarriers();
23
+
24
+ foreach ($carriers as $carrierCode => $carrier) {
25
+ // if the carrier is shippit, exclude it from the
26
+ // returned results
27
+ if ($excludeShippit && $carrierCode == 'shippit') {
28
+ continue;
29
+ }
30
+
31
+ if ($methods = $carrier->getAllowedMethods()) {
32
+ if (!$methodTitle = Mage::getStoreConfig("carriers/$carrierCode/title")) {
33
+ $methodTitle = $carrierCode;
34
+ }
35
+
36
+ foreach ($methods as $methodCode => $method) {
37
+ $carrierMethodCode = $carrierCode . '_' . $methodCode;
38
+ $optionsArray[] = array(
39
+ 'label' => $methodTitle . ' (' . $methodCode . ')',
40
+ 'value' => $carrierMethodCode
41
+ );
42
+ }
43
+ }
44
+ }
45
+
46
+ return $optionsArray;
47
+ }
48
+ }
app/code/community/Shippit/Shippit/Model/System/Config/Source/Shippit/Environment.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_System_Config_Source_Shippit_Environment
18
+ {
19
+ public function toOptionArray()
20
+ {
21
+ $optionsArray = array(
22
+ array(
23
+ 'label' => 'Live',
24
+ 'value' => 'production'
25
+ ),
26
+ array(
27
+ 'label' => 'Sandbox',
28
+ 'value' => 'staging'
29
+ )
30
+ );
31
+
32
+ return $optionsArray;
33
+ }
34
+ }
app/code/community/Shippit/Shippit/Model/System/Config/Source/Shippit/MaxTimeslots.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_System_Config_Source_Shippit_MaxTimeslots
18
+ {
19
+ const TIMESLOTS_MIN = 1;
20
+ const TIMESLOTS_MAX = 20;
21
+
22
+ public function toOptionArray()
23
+ {
24
+ $timeslots = range(self::TIMESLOTS_MIN, self::TIMESLOTS_MAX);
25
+
26
+ $optionsArray = array();
27
+ $optionsArray[] = array(
28
+ 'label' => '-- No Max Timeslots --',
29
+ 'value' => ''
30
+ );
31
+
32
+ foreach ($timeslots as $timeslot)
33
+ {
34
+ $optionsArray[] = array(
35
+ 'label' => $timeslot . ' Timeslots',
36
+ 'value' => $timeslot
37
+ );
38
+ }
39
+
40
+ return $optionsArray;
41
+ }
42
+ }
app/code/community/Shippit/Shippit/Model/System/Config/Source/Shippit/Methods.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_System_Config_Source_Shippit_Methods
18
+ {
19
+ /**
20
+ * Returns code => code pairs of attributes for all product attributes
21
+ *
22
+ * @return array
23
+ */
24
+ public function toOptionArray($includePriority = true)
25
+ {
26
+ $methods = $this->getMethods($includePriority);
27
+ $methodOptions = array();
28
+
29
+ foreach ($methods as $methodValue => $methodLabel) {
30
+ $methodOptions[] = array(
31
+ 'label' => $methodLabel,
32
+ 'value' => $methodValue
33
+ );
34
+ }
35
+
36
+ return $methodOptions;
37
+ }
38
+
39
+ public function getMethods($includePriority = true)
40
+ {
41
+ $methods = array(
42
+ 'standard' => 'Standard',
43
+ 'express' => 'Express',
44
+ );
45
+
46
+ if ($includePriority) {
47
+ $methods['priority'] = 'Priority';
48
+ }
49
+
50
+ $methods['international'] = 'International';
51
+
52
+ return $methods;
53
+ }
54
+ }
app/code/community/Shippit/Shippit/Model/System/Config/Source/Shippit/Sync/Mode.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_System_Config_Source_Shippit_Sync_Mode
18
+ {
19
+ public function toOptionArray()
20
+ {
21
+ $optionsArray = array(
22
+ array(
23
+ 'label' => 'Realtime',
24
+ 'value' => Shippit_Shippit_Helper_Data::SYNC_MODE_REALTIME
25
+ ),
26
+ array(
27
+ 'label' => 'Scheduled',
28
+ 'value' => Shippit_Shippit_Helper_Data::SYNC_MODE_CRON
29
+ ),
30
+ array(
31
+ 'label' => 'Custom',
32
+ 'value' => Shippit_Shippit_Helper_Data::SYNC_MODE_CUSTOM
33
+ )
34
+ );
35
+
36
+ return $optionsArray;
37
+ }
38
+ }
app/code/community/Shippit/Shippit/Model/System/Config/Source/Shippit/Sync/SendAllOrders.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Model_System_Config_Source_Shippit_Sync_SendAllOrders
18
+ {
19
+ const ALL = 'all';
20
+ const ALL_LABEL = 'Yes - All Orders';
21
+
22
+ const ALL_AU = 'all_au';
23
+ const ALL_AU_LABEL = 'Yes - All Australian Orders';
24
+
25
+ const NO = 'no';
26
+ const NO_LABEL = 'No';
27
+
28
+ /**
29
+ * Options getter
30
+ *
31
+ * @return array
32
+ */
33
+ public function toOptionArray()
34
+ {
35
+ $optionsArray = array(
36
+ array(
37
+ 'label' => self::ALL_LABEL,
38
+ 'value' => self::ALL
39
+ ),
40
+ array(
41
+ 'label' => self::ALL_AU_LABEL,
42
+ 'value' => self::ALL_AU
43
+ ),
44
+ array(
45
+ 'label' => self::NO_LABEL,
46
+ 'value' => self::NO
47
+ )
48
+ );
49
+
50
+ return $optionsArray;
51
+ }
52
+ }
app/code/community/Shippit/Shippit/controllers/Adminhtml/Shippit/Order/SyncController.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Adminhtml_Shippit_Order_SyncController extends Mage_Adminhtml_Controller_Action
18
+ {
19
+ public function sendAction()
20
+ {
21
+ $orderId = $this->getRequest()->getParam('order_id', null);
22
+
23
+ if (empty($orderId)) {
24
+ $this->_getSession()->addError($this->__('The order could not be found'));
25
+ $this->_redirect('adminhtml/sales_order');
26
+
27
+ return;
28
+ }
29
+
30
+ $order = Mage::getModel('sales/order')->load($orderId);
31
+
32
+ if (!$order) {
33
+ $this->_getSession()->addError($this->__('The order could not be found'));
34
+ $this->_redirect('adminhtml/sales_order');
35
+
36
+ return;
37
+ }
38
+
39
+ try {
40
+ Mage::dispatchEvent(
41
+ 'shippit_add_order',
42
+ array(
43
+ 'entity_id' => $orderId,
44
+ 'sync_mode' => 'realtime',
45
+ 'display_notifications' => true,
46
+ 'shipping_method' => $order->getShippingMethod()
47
+ )
48
+ );
49
+
50
+ $this->_redirect(
51
+ 'adminhtml/sales_order/view',
52
+ array(
53
+ 'order_id' => $orderId
54
+ )
55
+ );
56
+
57
+ return;
58
+ }
59
+ catch (Exception $e) {
60
+ $this->_getSession()->addError($this->__('An error occured while send the order to Shippit') . ' - ' . $e->getMessage());
61
+
62
+ $this->_redirect(
63
+ 'adminhtml/sales_order/view',
64
+ array(
65
+ 'order_id' => $orderId
66
+ )
67
+ );
68
+
69
+ return;
70
+ }
71
+ }
72
+
73
+ public function massSendAction()
74
+ {
75
+ $orderIds = $this->getRequest()->getParam('order_ids', null);
76
+
77
+ if (empty($orderIds)) {
78
+ $this->_getSession()->addError($this->__('The orders could not be found'));
79
+ $this->_redirect('adminhtml/sales_order');
80
+
81
+ return;
82
+ }
83
+
84
+ $orders = Mage::getModel('sales/order')
85
+ ->getCollection()
86
+ ->addAttributeToSelect('entity_id')
87
+ ->addAttributeToSelect('shipping_method')
88
+ ->addAttributeToFilter('entity_id', array('in' => $orderIds));
89
+
90
+ try {
91
+ foreach ($orders as $order) {
92
+ Mage::dispatchEvent(
93
+ 'shippit_add_order',
94
+ array(
95
+ 'entity_id' => $order->getId(),
96
+ 'shipping_method' => $order->getShippingMethod()
97
+ )
98
+ );
99
+ }
100
+
101
+ $this->_getSession()->addSuccess($this->__('The orders have been scheduled to sync with Shippit'));
102
+
103
+ $this->_redirect('adminhtml/sales_order');
104
+
105
+ return;
106
+ }
107
+ catch (Exception $e) {
108
+ $this->_getSession()->addError($this->__('An error occured while scheduling the orders to sync with Shippit') . ' - ' . $e->getMessage());
109
+
110
+ $this->_redirect('adminhtml/sales_order');
111
+
112
+ return;
113
+ }
114
+ }
115
+
116
+ protected function _isAllowed()
117
+ {
118
+ return Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/shippit_order_send');
119
+ }
120
+ }
app/code/community/Shippit/Shippit/controllers/Adminhtml/Shippit/OrderController.php ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_Adminhtml_Shippit_OrderController extends Mage_Adminhtml_Controller_Action
18
+ {
19
+ public function indexAction()
20
+ {
21
+ $this->_title($this->__('Sales'))->_title($this->__('Shippit Orders'));
22
+
23
+ $this->loadLayout();
24
+ $this->_setActiveMenu('sales/shippit_orders');
25
+
26
+ $this->_addContent($this->getLayout()->createBlock('shippit/adminhtml_sales_order'));
27
+ $this->renderLayout();
28
+ }
29
+
30
+ public function gridAction()
31
+ {
32
+ $this->loadLayout(false);
33
+ $this->renderLayout();
34
+ }
35
+
36
+ public function massSyncAction()
37
+ {
38
+ $syncIds = $this->getRequest()->getPost('sync_ids', array());
39
+ $this->_syncOrders($syncIds);
40
+ }
41
+
42
+ public function syncAction()
43
+ {
44
+ $syncId = $this->getRequest()->getParam('id', null);
45
+
46
+ if (empty($syncId)) {
47
+ $this->_getSession()->addError($this->__('You must select at least 1 order to sync'));
48
+
49
+ $this->_redirect('*/*/index');
50
+
51
+ return;
52
+ }
53
+
54
+ $this->_syncOrders(array($syncId));
55
+ }
56
+
57
+ private function _syncOrders($syncIds)
58
+ {
59
+ if (empty($syncIds)) {
60
+ $this->_getSession()->addError($this->__('You must select at least 1 order to sync'));
61
+
62
+ $this->_redirect('*/*/index');
63
+
64
+ return;
65
+ }
66
+
67
+ // get a list of all pending sync in the sync queue
68
+ $syncOrders = Mage::getModel('shippit/sync_order')
69
+ ->getCollection()
70
+ ->addFieldToFilter('sync_id', array('in', $syncIds));
71
+
72
+ if ($syncOrders->getSize() == 0) {
73
+ $this->_getSession()->addError($this->__('No valid orders were found'));
74
+
75
+ $this->_redirect('*/*/index');
76
+
77
+ return;
78
+ }
79
+
80
+ $apiOrder = Mage::getSingleton('shippit/api_order');
81
+
82
+ // reset the status of all items and attempts
83
+ foreach ($syncOrders as $syncOrder) {
84
+ $syncOrder->setStatus(Shippit_Shippit_Model_Sync_Order::STATUS_PENDING)
85
+ ->setTrackNumber(null)
86
+ ->setSyncedAt(null)
87
+ ->save();
88
+ }
89
+
90
+ foreach ($syncOrders as $syncOrder) {
91
+ $apiOrder->sync($syncOrder, true);
92
+ }
93
+
94
+ $this->_redirect('*/*/index');
95
+
96
+ return;
97
+ }
98
+
99
+ public function removeAction()
100
+ {
101
+ $syncId = $this->getRequest()->getParam('id', null);
102
+
103
+ if (empty($syncId)) {
104
+ $this->_getSession()->addError($this->__('You must select at least 1 order to remove'));
105
+
106
+ $this->_redirect('*/*/index');
107
+
108
+ return;
109
+ }
110
+
111
+ $this->_removeItems(array($syncId));
112
+ }
113
+
114
+ public function massRemoveAction()
115
+ {
116
+ $syncIds = $this->getRequest()->getPost('sync_ids', null);
117
+
118
+ $this->_removeItems($syncIds);
119
+ }
120
+
121
+ private function _removeItems($syncIds)
122
+ {
123
+ if (empty($syncIds)) {
124
+ $this->_getSession()->addError($this->__('You must select at least 1 order to remove'));
125
+
126
+ $this->_redirect('*/*/index');
127
+
128
+ return;
129
+ }
130
+
131
+ // get a list of all pending sync in the sync queue
132
+ $syncItems = Mage::getModel('shippit/sync_order')
133
+ ->getCollection()
134
+ ->addFieldToFilter('sync_id', array('in', $syncIds));
135
+
136
+ foreach ($syncItems as $syncItem) {
137
+ $syncItem->delete();
138
+ }
139
+
140
+ if (count($syncItems) > 1) {
141
+ $this->_getSession()->addSuccess($this->__('The orders have been removed from the sync queue'));
142
+ }
143
+ else {
144
+ $this->_getSession()->addSuccess($this->__('The order has been removed from the sync queue'));
145
+ }
146
+
147
+ $this->_redirect('*/*/index');
148
+
149
+ return;
150
+ }
151
+
152
+ public function scheduleAction()
153
+ {
154
+ $syncId = $this->getRequest()->getParam('id', null);
155
+
156
+ if (empty($syncId)) {
157
+ $this->_getSession()->addError($this->__('You must select at least 1 order to schedule'));
158
+
159
+ $this->_redirect('*/*/index');
160
+
161
+ return;
162
+ }
163
+
164
+ $this->_scheduleItems(array($syncId));
165
+ }
166
+
167
+ public function massScheduleAction()
168
+ {
169
+ $syncIds = $this->getRequest()->getParam('sync_ids', array());
170
+ $this->_scheduleItems($syncIds);
171
+ }
172
+
173
+ private function _scheduleItems($syncIds)
174
+ {
175
+ if (empty($syncIds)) {
176
+ $this->_getSession()->addError($this->__('You must select at least 1 order to schedule'));
177
+
178
+ $this->_redirect('*/*/index');
179
+
180
+ return;
181
+ }
182
+
183
+ // get a list of all pending sync in the sync queue
184
+ $syncItems = Mage::getModel('shippit/sync_order')
185
+ ->getCollection()
186
+ ->addFieldToFilter('sync_id', array('in', $syncIds));
187
+
188
+ foreach ($syncItems as $syncItem) {
189
+ $syncItem->setStatus(Shippit_Shippit_Model_Sync_Order::STATUS_PENDING)
190
+ ->setAttemptCount(0)
191
+ ->setTrackNumber(null)
192
+ ->setSyncedAt(null)
193
+ ->save();
194
+ }
195
+
196
+ if (count($syncItems) > 1) {
197
+ $this->_getSession()->addSuccess($this->__('The orders have been successfully reset and will sync with Shippit again shortly'));
198
+ }
199
+ else {
200
+ $this->_getSession()->addSuccess($this->__('The order has been successfully reset and will sync with Shippit again shortly'));
201
+ }
202
+
203
+ $this->_redirect('*/*/index');
204
+
205
+ return;
206
+ }
207
+
208
+ protected function _isAllowed()
209
+ {
210
+ return Mage::getSingleton('admin/session')->isAllowed('sales/shippit_orders');
211
+ }
212
+ }
app/code/community/Shippit/Shippit/controllers/OrderController.php ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ class Shippit_Shippit_OrderController extends Mage_Core_Controller_Front_Action
18
+ {
19
+ const ERROR_SYNC_DISABLED = 'Shipping Sync is Disabled';
20
+ const ERROR_API_KEY_MISSING = 'An API Key is required';
21
+ const ERROR_API_KEY_MISMATCH = 'The API Key provided does not match the configured API Key';
22
+ const ERROR_BAD_REQUEST = 'An invalid request was recieved';
23
+ const ERROR_ORDER_MISSING = 'The order id requested was not found';
24
+ const ERROR_ORDER_STATUS = 'The order id requested has an status that is not available for shipping';
25
+ const NOTICE_SHIPMENT_STATUS = 'Ignoring the order status update, as we only respond to ready_for_pickup state';
26
+ const ERROR_SHIPMENT_FAILED = 'The shipment record was not able to be created at this time, please try again.';
27
+ const SUCCESS_SHIPMENT_CREATED = 'The shipment record was created successfully.';
28
+
29
+ protected $helper;
30
+ protected $logger;
31
+
32
+ public function _construct()
33
+ {
34
+ $this->helper = Mage::helper('shippit/sync_shipping');
35
+ $this->logger = Mage::getModel('shippit/logger');
36
+
37
+ return parent::_construct();
38
+ }
39
+
40
+ public function updateAction()
41
+ {
42
+ $request = json_decode(file_get_contents('php://input'), true);
43
+
44
+ $metaData = array(
45
+ 'api_request' => array(
46
+ 'request_body' => $request
47
+ )
48
+ );
49
+
50
+ $this->logger->setMetaData($metaData);
51
+ $this->logger->log('Shipment Sync Request Recieved');
52
+
53
+ if (!$this->helper->isActive()) {
54
+ $this->logger->log('Shipping Sync is not active');
55
+ $response = $this->_prepareResponse(false, self::ERROR_SYNC_DISABLED);
56
+
57
+ return $this->getResponse()->setBody($response);
58
+ }
59
+
60
+ $apiKey = $this->getRequest()->getParam('api_key');
61
+ $orderIncrementId = $request['retailer_order_number'];
62
+ $orderShipmentState = $request['current_state'];
63
+
64
+ $courierName = $request['courier_name'];
65
+ $trackingNumber = $request['tracking_number'];
66
+
67
+ if (isset($request['products'])) {
68
+ $products = $request['products'];
69
+ }
70
+ else {
71
+ $products = array();
72
+ }
73
+
74
+ if (empty($apiKey)) {
75
+ $response = $this->_prepareResponse(false, self::ERROR_API_KEY_MISSING);
76
+ $this->logger->log('Shipment Sync Error - ' . self::ERROR_API_KEY_MISSING, Zend_Log::WARN);
77
+
78
+ return $this->getResponse()->setBody($response);
79
+ }
80
+
81
+ if (!$this->_checkApiKey($apiKey)) {
82
+ $response = $this->_prepareResponse(false, self::ERROR_API_KEY_MISMATCH);
83
+ $this->logger->log('Shipment Sync Error - ' . self::ERROR_API_KEY_MISMATCH, Zend_Log::WARN);
84
+
85
+ return $this->getResponse()->setBody($response);
86
+ }
87
+
88
+ if (empty($request)) {
89
+ $response = $this->_prepareResponse(false, self::ERROR_BAD_REQUEST);
90
+ $this->logger->log('Shipment Sync Error - ' . self::ERROR_BAD_REQUEST, Zend_Log::WARN);
91
+
92
+ return $this->getResponse()->setBody($response);
93
+ }
94
+
95
+ if (empty($orderShipmentState) || $orderShipmentState != 'ready_for_pickup') {
96
+ $response = $this->_prepareResponse(true, self::NOTICE_SHIPMENT_STATUS);
97
+ $this->logger->log('Shipment Sync Error - ' . self::NOTICE_SHIPMENT_STATUS);
98
+
99
+ return $this->getResponse()->setBody($response);
100
+ }
101
+
102
+ // attempt to get the order using the reference provided
103
+ $order = $this->_getOrder($orderIncrementId);
104
+
105
+ if (!$order->getId()) {
106
+ $response = $this->_prepareResponse(false, self::ERROR_ORDER_MISSING);
107
+
108
+ return $this->getResponse()->setBody($response);
109
+ }
110
+
111
+ if (!$order->canShip()) {
112
+ $response = $this->_prepareResponse(false, self::ERROR_ORDER_STATUS);
113
+
114
+ return $this->getResponse()->setBody($response);
115
+ }
116
+
117
+ try {
118
+ $shipmentRequest = Mage::getModel('shippit/request_api_shipment')
119
+ ->setOrder($order)
120
+ ->processItems($products);
121
+
122
+ // create the shipment
123
+ $response = $this->_createShipment(
124
+ $shipmentRequest->getOrder(),
125
+ $shipmentRequest->getItems(),
126
+ $courierName,
127
+ $trackingNumber
128
+ );
129
+
130
+ return $this->getResponse()->setBody($response);
131
+ }
132
+ catch (Exception $e)
133
+ {
134
+ $response = $this->_prepareResponse(false, $e->getMessage());
135
+ $this->logger->logException($e);
136
+
137
+ return $this->getResponse()->setBody($response);
138
+ }
139
+ }
140
+
141
+ private function _prepareResponse($success, $message)
142
+ {
143
+ $response = array(
144
+ 'success' => $success,
145
+ 'message' => $message,
146
+ );
147
+
148
+ $metaData = array(
149
+ 'api_request' => array(
150
+ 'request_body' => json_decode(file_get_contents('php://input'), true),
151
+ 'response_body' => $response
152
+ )
153
+ );
154
+
155
+ $this->logger->setMetaData($metaData);
156
+
157
+ return Mage::helper('core')->jsonEncode($response);
158
+ }
159
+
160
+ private function _checkApiKey($apiKey)
161
+ {
162
+ $configuredApiKey = Mage::helper('shippit')->getApiKey();
163
+
164
+ if ($configuredApiKey != $apiKey) {
165
+ return false;
166
+ }
167
+
168
+ return true;
169
+ }
170
+
171
+ private function _getOrder($orderIncrementId)
172
+ {
173
+ return Mage::getModel('sales/order')->load($orderIncrementId, 'increment_id');
174
+ }
175
+
176
+ private function _createShipment($order, $items, $courierName, $trackingNumber)
177
+ {
178
+ $shipment = $order->prepareShipment($items);
179
+
180
+ $shipment = Mage::getModel('sales/service_order', $order)
181
+ ->prepareShipment($items);
182
+
183
+ if ($shipment) {
184
+ $comment = 'Your order has been shipped - your tracking number is ' . $trackingNumber;
185
+
186
+ $track = Mage::getModel('sales/order_shipment_track')
187
+ ->setNumber($trackingNumber)
188
+ ->setCarrierCode(Shippit_Shippit_Helper_Data::CARRIER_CODE)
189
+ ->setTitle('Shippit - ' . $courierName);
190
+
191
+ $shipment->addTrack($track)
192
+ ->register()
193
+ ->addComment($comment, true)
194
+ ->setEmailSent(true);
195
+
196
+ $shipment->getOrder()->setIsInProcess(true);
197
+
198
+ try {
199
+ $transactionSave = Mage::getModel('core/resource_transaction')
200
+ ->addObject($shipment)
201
+ ->addObject($shipment->getOrder())
202
+ ->save();
203
+
204
+ $shipment->sendEmail(true, $comment);
205
+ }
206
+ catch (Mage_Core_Exception $e) {
207
+ $this->logger->log('Shipment Sync Error - ' . self::ERROR_SHIPMENT_FAILED);
208
+
209
+ return $this->_prepareResponse(false, self::ERROR_SHIPMENT_FAILED);
210
+ }
211
+
212
+ $this->logger->log('Shipment Sync Successful - ' . self::SUCCESS_SHIPMENT_CREATED);
213
+
214
+ return $this->_prepareResponse(true, self::SUCCESS_SHIPMENT_CREATED);
215
+ }
216
+
217
+ $this->logger->log('Shipment Sync Error - ' . self::ERROR_SHIPMENT_FAILED);
218
+
219
+ return $this->_prepareResponse(false, self::ERROR_SHIPMENT_FAILED);
220
+ }
221
+ }
app/code/community/Shippit/Shippit/data/shippit_setup/data-install-4.0.0.php ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ $installer = $this;
18
+ $installer->startSetup();
19
+
20
+ /**
21
+ * Add Australian States and Territories if they are not present
22
+ */
23
+ $regions = array(
24
+ array(
25
+ 'country_id' => 'AU',
26
+ 'code' => 'VIC',
27
+ 'default_name' => 'Victoria'
28
+ ),
29
+ array(
30
+ 'country_id' => 'AU',
31
+ 'code' => 'NSW',
32
+ 'default_name' => 'New South Wales'
33
+ ),
34
+ array(
35
+ 'country_id' => 'AU',
36
+ 'code' => 'ACT',
37
+ 'default_name' => 'Australian Capital Territory'
38
+ ),
39
+ array(
40
+ 'country_id' => 'AU',
41
+ 'code' => 'QLD',
42
+ 'default_name' => 'Queensland'
43
+ ),
44
+ array(
45
+ 'country_id' => 'AU',
46
+ 'code' => 'TAS',
47
+ 'default_name' => 'Tasmania'
48
+ ),
49
+ array(
50
+ 'country_id' => 'AU',
51
+ 'code' => 'SA',
52
+ 'default_name' => 'South Australia'
53
+ ),
54
+ array(
55
+ 'country_id' => 'AU',
56
+ 'code' => 'NT',
57
+ 'default_name' => 'Northern Territory'
58
+ ),
59
+ array(
60
+ 'country_id' => 'AU',
61
+ 'code' => 'WA',
62
+ 'default_name' => 'Western Australia'
63
+ ),
64
+ );
65
+
66
+ foreach ($regions as $region) {
67
+ // Attempt to load the region, checking if it already exists
68
+ $hasRegion = Mage::getModel('directory/region')->loadByCode($region['code'], $region['country_id'])
69
+ ->hasData();
70
+
71
+ if (!$hasRegion) {
72
+ // Insert the region data
73
+ $installer->getConnection()->insert(
74
+ $installer->getTable('directory/country_region'),
75
+ $region
76
+ );
77
+
78
+ // Get the newly created region
79
+ $regionId = $installer->getConnection()->lastInsertId(
80
+ $installer->getTable('directory/country_region')
81
+ );
82
+
83
+ // Setup the region name data
84
+ $regionName = array(
85
+ 'locale' => 'en_US',
86
+ 'region_id' => $regionId,
87
+ 'name' => $region['default_name'],
88
+ );
89
+
90
+ // Add the region name data
91
+ $installer->getConnection()->insert(
92
+ $installer->getTable('directory/country_region_name'),
93
+ $regionName
94
+ );
95
+ }
96
+ }
97
+
98
+ // retrieve all orders with a shippit sync event
99
+ $orders = Mage::getModel('sales/order')->getCollection()
100
+ ->addAttributeToFilter('shippit_sync', array('eq' => false));
101
+
102
+ $orderSyncs = array();
103
+
104
+ // migrate these orders + sync status to the shippit sync table
105
+ foreach ($orders as $order) {
106
+ $orderSyncs[] = array(
107
+ 'store_id' => $order->getStoreId(),
108
+ 'order_id' => $order->getEntityId(),
109
+ 'status' => Shippit_Shippit_Model_Sync_Order::STATUS_PENDING,
110
+ );
111
+ }
112
+
113
+ foreach ($orderSyncs as $orderSync) {
114
+ // Insert the order sync data
115
+ $installer->getConnection()->insert(
116
+ $installer->getTable('shippit/sync_order'),
117
+ $orderSync
118
+ );
119
+ }
120
+
121
+ // Migrate from v3 to v4 (default settings only)
122
+ $configKeys = array(
123
+ 'mamis_shippit',
124
+ 'mindarc_shippit'
125
+ );
126
+
127
+ $configOptions = array(
128
+ 'active',
129
+ 'api_key',
130
+ 'debug_active',
131
+ 'sync_mode',
132
+ 'send_all_orders_active',
133
+ 'title',
134
+ 'allowed_methods',
135
+ 'max_timeslots',
136
+ 'enabled_product_active',
137
+ 'enabled_product_ids',
138
+ 'enabled_product_attribute_active',
139
+ 'enabled_product_attribute_code',
140
+ 'enabled_product_attribute_value',
141
+ 'sallowspecific',
142
+ 'specificcountry',
143
+ 'showmethod',
144
+ 'sort_order'
145
+ );
146
+
147
+ foreach ($configKeys as $configKey) {
148
+ foreach ($configOptions as $configOption) {
149
+ $configValue = Mage::getStoreConfig('carriers/' . $configKey . '/' . $configOption);
150
+
151
+ if (!is_null($configValue)) {
152
+ Mage::getConfig()->saveConfig('carriers/shippit/' . $configOption, $configValue, 'default', 0);
153
+ }
154
+ }
155
+ }
156
+
157
+ $installer->endSetup();
app/code/community/Shippit/Shippit/data/shippit_setup/data-upgrade-4.1.0-4.1.1.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ $installer = $this;
18
+ $installer->startSetup();
19
+
20
+ /**
21
+ * Migrate settings data from v4.1.0 to v4.1.1
22
+ */
23
+ $configKeys = array(
24
+ 'carriers/shippit',
25
+ 'shippit'
26
+ );
27
+
28
+ $configOptions = array(
29
+ 'active' => array(
30
+ 'shippit/general/active',
31
+ 'shippit/sync_order/active',
32
+ 'shippit/checkout/authority_to_leave_active',
33
+ 'shippit/checkout/delivery_instructions_active',
34
+ 'shippit/sync_shipping/active',
35
+ 'shippit/sync_shipping/update_template_active'
36
+ ),
37
+ 'api_key' => 'shippit/general/api_key',
38
+ 'environment' => 'shippit/general/environment',
39
+ 'debug_active' => 'shippit/general/debug_active',
40
+ 'sync_mode' => 'shippit/sync_order/mode',
41
+ 'send_all_orders_active' => 'shippit/sync_order/send_all_orders_active',
42
+ 'product_location_active' => 'shippit/sync_order/product_location_active',
43
+ 'product_location_attribute_code' => 'shippit/sync_order/product_location_attribute_code'
44
+ );
45
+
46
+ foreach ($configOptions as $configOptionOldKey => $configOptionNewKey) {
47
+ $configOptionValue = Mage::getStoreConfig('carriers/shippit/' . $configOptionOldKey);
48
+
49
+ if (!is_null($configOptionValue)) {
50
+ if (is_array($configOptionNewKey)) {
51
+ foreach ($configOptionNewKey as $configOptionNewKeyItem) {
52
+ Mage::getConfig()->saveConfig(
53
+ $configOptionNewKeyItem,
54
+ $configOptionValue,
55
+ 'default',
56
+ 0
57
+ );
58
+ }
59
+ }
60
+ else {
61
+ Mage::getConfig()->saveConfig(
62
+ $configOptionNewKey,
63
+ $configOptionValue,
64
+ 'default',
65
+ 0
66
+ );
67
+ }
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Update sync order records to include the shipping method class
73
+ */
74
+ $syncOrders = Mage::getModel('shippit/sync_order')->getCollection()
75
+ ->addFieldToFilter('shipping_method', array('null' => true));
76
+
77
+ foreach ($syncOrders as $syncOrder) {
78
+ $order = $syncOrder->getOrder();
79
+
80
+ if (!$order->getId()) {
81
+ continue;
82
+ }
83
+
84
+ $shippingMethod = $order->getShippingMethod();
85
+
86
+ // If the shipping method is a shippit method,
87
+ // processing using the selected shipping options
88
+ if (strpos($shippingMethod, 'shippit') !== FALSE) {
89
+ $shippingOptions = str_replace('shippit' . '_', '', $shippingMethod);
90
+ $shippingOptions = explode('_', $shippingOptions);
91
+ $courierData = array();
92
+
93
+ if (isset($shippingOptions[0])) {
94
+ if ($shippingOptions[0] == 'Bonds') {
95
+ $shippitShippingMethod = 'premium';
96
+ }
97
+ elseif ($shippingOptions[0] == 'eparcelexpress') {
98
+ $shippitShippingMethod = 'express';
99
+ }
100
+ elseif ($shippingOptions[0] == 'CouriersPlease'
101
+ || $shippingOptions[0] == 'Fastway') {
102
+ $shippitShippingMethod = 'standard';
103
+ }
104
+ else {
105
+ $shippitShippingMethod = 'standard';
106
+ }
107
+ }
108
+ else {
109
+ $shippitShippingMethod = 'standard';
110
+ }
111
+ }
112
+ else {
113
+ $shippitShippingMethod = 'standard';
114
+ }
115
+
116
+ $syncOrder->setShippingMethod($shippitShippingMethod)
117
+ ->save();
118
+ }
119
+
120
+ $installer->endSetup();
app/code/community/Shippit/Shippit/data/shippit_setup/data-upgrade-4.1.6-4.1.7.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ $installer = $this;
18
+ $installer->startSetup();
19
+
20
+ /**
21
+ * Migrate settings data from v4.1.6 to v4.1.7
22
+ */
23
+
24
+ $allowedMethods = Mage::getStoreConfig('carriers/shippit/allowed_methods');
25
+
26
+ $allowedMethods = strtolower($allowedMethods);
27
+ $allowedMethods = str_replace('premium', 'priority', $allowedMethods);
28
+
29
+ Mage::getConfig()->saveConfig(
30
+ 'carriers/shippit/allowed_methods',
31
+ $allowedMethods,
32
+ 'default',
33
+ 0
34
+ );
35
+
36
+ /**
37
+ * Migrate sync orders data from v4.1.6 to v4.1.7
38
+ */
39
+
40
+ $syncOrders = Mage::getModel('shippit/sync_order')->getCollection()
41
+ ->addFieldToFilter('shipping_method', array('eq' => 'premium'));
42
+
43
+ foreach ($syncOrders as $syncOrder) {
44
+ $syncOrder->setShippingMethod('priority')
45
+ ->save();
46
+ }
47
+
48
+ $installer->endSetup();
app/code/community/Shippit/Shippit/data/shippit_setup/data-upgrade-4.2.3-4.2.4.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ $installer = $this;
18
+ $installer->startSetup();
19
+
20
+ /**
21
+ * Migrate settings data from v4.2.3 to v4.2.4
22
+ */
23
+
24
+ $configOptions = array(
25
+ 'shippit/sync_order/all_orders' => 'shippit/sync_order/send_all_orders_active'
26
+ );
27
+
28
+ foreach ($configOptions as $configOptionOldKey => $configOptionNewKey) {
29
+ $configOptionValue = Mage::getStoreConfig($configOptionOldKey);
30
+
31
+ if (!is_null($configOptionValue)) {
32
+ if (is_array($configOptionNewKey)) {
33
+ foreach ($configOptionNewKey as $configOptionNewKeyItem) {
34
+ Mage::getConfig()->saveConfig(
35
+ $configOptionNewKeyItem,
36
+ $configOptionValue,
37
+ 'default',
38
+ 0
39
+ );
40
+ }
41
+ }
42
+ else {
43
+ Mage::getConfig()->saveConfig(
44
+ $configOptionNewKey,
45
+ $configOptionValue,
46
+ 'default',
47
+ 0
48
+ );
49
+ }
50
+ }
51
+ }
52
+
53
+ $installer->endSetup();
app/code/community/Shippit/Shippit/data/shippit_setup/data-upgrade-4.3.2-4.3.3.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ $installer = $this;
18
+ $installer->startSetup();
19
+
20
+ /**
21
+ * Migrate settings data from v4.3.2 to v4.3.3
22
+ */
23
+ $sendAllOrders = Mage::getStoreConfigFlag('shippit/sync_order/send_all_orders_active');
24
+
25
+ // If send all orders is set to true, update to all_au
26
+ if ($sendAllOrders) {
27
+ Mage::getConfig()->saveConfig(
28
+ 'shippit/sync_order/send_all_orders',
29
+ 'all_au',
30
+ 'default',
31
+ 0
32
+ );
33
+ }
34
+
35
+ $installer->endSetup();
app/code/community/Shippit/Shippit/etc/adminhtml.xml ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Shippit Pty Ltd
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the terms
9
+ * that is available through the world-wide-web at this URL:
10
+ * http://www.shippit.com/terms
11
+ *
12
+ * @category Shippit
13
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
14
+ * @author Matthew Muscat <matthew@mamis.com.au>
15
+ * @license http://www.shippit.com/terms
16
+ */
17
+ -->
18
+ <config>
19
+ <menu>
20
+ <sales>
21
+ <children>
22
+ <shippit_orders translate="title" module="shippit">
23
+ <sort_order>10</sort_order>
24
+ <title>Shippit Orders</title>
25
+ <action>adminhtml/shippit_order</action>
26
+ </shippit_orders>
27
+ </children>
28
+ </sales>
29
+ </menu>
30
+
31
+ <acl>
32
+ <resources>
33
+ <admin>
34
+ <children>
35
+ <sales>
36
+ <children>
37
+ <shippit_orders>
38
+ <title>Shippit Orders</title>
39
+ <sort_order>10</sort_order>
40
+ </shippit_orders>
41
+
42
+ <order>
43
+ <children>
44
+ <actions>
45
+ <children>
46
+ <shippit_order_send>
47
+ <title>Send Order to Shippit</title>
48
+ <sort_order>100</sort_order>
49
+ </shippit_order_send>
50
+ </children>
51
+ </actions>
52
+ </children>
53
+ </order>
54
+ </children>
55
+ </sales>
56
+
57
+ <system>
58
+ <children>
59
+ <config>
60
+ <children>
61
+ <shippit>
62
+ <title>Shippit</title>
63
+ </shippit>
64
+ </children>
65
+ </config>
66
+ </children>
67
+ </system>
68
+ </children>
69
+ </admin>
70
+ </resources>
71
+ </acl>
72
+ </config>
app/code/community/Shippit/Shippit/etc/config.xml ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Shippit Pty Ltd
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the terms
9
+ * that is available through the world-wide-web at this URL:
10
+ * http://www.shippit.com/terms
11
+ *
12
+ * @category Shippit
13
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
14
+ * @author Matthew Muscat <matthew@mamis.com.au>
15
+ * @license http://www.shippit.com/terms
16
+ */
17
+ -->
18
+ <config>
19
+ <modules>
20
+ <Shippit_Shippit>
21
+ <version>4.3.4</version>
22
+ </Shippit_Shippit>
23
+ </modules>
24
+
25
+ <global>
26
+ <blocks>
27
+ <shippit>
28
+ <class>Shippit_Shippit_Block</class>
29
+ </shippit>
30
+ <checkout>
31
+ <rewrite>
32
+ <cart_shipping>Shippit_Shippit_Block_Checkout_Cart_Shipping</cart_shipping>
33
+ </rewrite>
34
+ </checkout>
35
+ </blocks>
36
+
37
+ <models>
38
+ <shippit>
39
+ <class>Shippit_Shippit_Model</class>
40
+ <resourceModel>shippit_resource</resourceModel>
41
+ </shippit>
42
+
43
+ <shippit_resource>
44
+ <class>Shippit_Shippit_Model_Resource</class>
45
+
46
+ <entities>
47
+ <!-- Depreciated Node as of v4.1.0 -->
48
+ <order_sync>
49
+ <table>shippit_order_sync</table>
50
+ </order_sync>
51
+ <sync_order>
52
+ <table>shippit_sync_order</table>
53
+ </sync_order>
54
+ <sync_order_item>
55
+ <table>shippit_sync_order_item</table>
56
+ </sync_order_item>
57
+ </entities>
58
+ </shippit_resource>
59
+ </models>
60
+
61
+ <resources>
62
+ <shippit_setup>
63
+ <setup>
64
+ <module>Shippit_Shippit</module>
65
+ <class>Shippit_Shippit_Model_Resource_Setup</class>
66
+ </setup>
67
+
68
+ <connection>
69
+ <use>core_setup</use>
70
+ </connection>
71
+ </shippit_setup>
72
+
73
+ <shippit_write>
74
+ <connection>
75
+ <use>core_write</use>
76
+ </connection>
77
+ </shippit_write>
78
+
79
+ <shippit_read>
80
+ <connection>
81
+ <use>core_read</use>
82
+ </connection>
83
+ </shippit_read>
84
+
85
+ <shippit_delete>
86
+ <connection>
87
+ <use>core_delete</use>
88
+ </connection>
89
+ </shippit_delete>
90
+ </resources>
91
+
92
+ <helpers>
93
+ <shippit>
94
+ <class>Shippit_Shippit_Helper</class>
95
+ </shippit>
96
+ </helpers>
97
+
98
+ <events>
99
+ <sales_order_place_after>
100
+ <observers>
101
+ <shippit_add_order_to_sync>
102
+ <class>shippit/observer_order_sync</class>
103
+ <method>addOrder</method>
104
+ </shippit_add_order_to_sync>
105
+ </observers>
106
+ </sales_order_place_after>
107
+
108
+ <core_block_abstract_to_html_before>
109
+ <observers>
110
+ <shippit_update_order_shipment_track_template>
111
+ <type>singleton</type>
112
+ <class>shippit/observer_shipping_tracking</class>
113
+ <method>updateOrderShipmentTrackTemplate</method>
114
+ </shippit_update_order_shipment_track_template>
115
+ </observers>
116
+ </core_block_abstract_to_html_before>
117
+
118
+ <shippit_add_order>
119
+ <observers>
120
+ <shippit_add_order>
121
+ <class>shippit/observer_shippit</class>
122
+ <method>addOrder</method>
123
+ </shippit_add_order>
124
+ </observers>
125
+ </shippit_add_order>
126
+ </events>
127
+
128
+ <fieldsets>
129
+ <sales_convert_quote>
130
+ <shippit_authority_to_leave>
131
+ <to_order>*</to_order>
132
+ </shippit_authority_to_leave>
133
+
134
+ <shippit_delivery_instructions>
135
+ <to_order>*</to_order>
136
+ </shippit_delivery_instructions>
137
+ </sales_convert_quote>
138
+ </fieldsets>
139
+ </global>
140
+
141
+ <frontend>
142
+ <routers>
143
+ <shippit>
144
+ <use>standard</use>
145
+ <args>
146
+ <module>Shippit_Shippit</module>
147
+ <frontName>shippit</frontName>
148
+ </args>
149
+ </shippit>
150
+ </routers>
151
+
152
+ <translate>
153
+ <modules>
154
+ <shippit>
155
+ <files>
156
+ <default>shippit.csv</default>
157
+ </files>
158
+ </shippit>
159
+ </modules>
160
+ </translate>
161
+
162
+ <layout>
163
+ <updates>
164
+ <shippit>
165
+ <file>shippit.xml</file>
166
+ </shippit>
167
+ </updates>
168
+ </layout>
169
+
170
+ <events>
171
+ <checkout_controller_onepage_save_shipping_method>
172
+ <observers>
173
+ <shippit_add_delivery_instructions_to_quote>
174
+ <class>shippit/observer_quote_deliveryInstructions</class>
175
+ <method>addDeliveryInstructionsToQuote</method>
176
+ </shippit_add_delivery_instructions_to_quote>
177
+
178
+ <shippit_add_authority_to_leave_to_quote>
179
+ <class>shippit/observer_quote_authorityToLeave</class>
180
+ <method>addAuthorityToLeaveToQuote</method>
181
+ </shippit_add_authority_to_leave_to_quote>
182
+ </observers>
183
+ </checkout_controller_onepage_save_shipping_method>
184
+ </events>
185
+ </frontend>
186
+
187
+ <admin>
188
+ <routers>
189
+ <adminhtml>
190
+ <args>
191
+ <modules>
192
+ <shippit before="Mage_Adminhtml">Shippit_Shippit_Adminhtml</shippit>
193
+ </modules>
194
+ </args>
195
+ </adminhtml>
196
+ </routers>
197
+ </admin>
198
+
199
+ <adminhtml>
200
+ <layout>
201
+ <updates>
202
+ <shippit>
203
+ <file>shippit.xml</file>
204
+ </shippit>
205
+ </updates>
206
+ </layout>
207
+
208
+ <events>
209
+ <admin_system_config_changed_section_shippit>
210
+ <observers>
211
+ <shippit_check_api_key>
212
+ <class>shippit/observer_system_config</class>
213
+ <method>checkApiKey</method>
214
+ </shippit_check_api_key>
215
+ </observers>
216
+ </admin_system_config_changed_section_shippit>
217
+
218
+ <adminhtml_widget_container_html_before>
219
+ <observers>
220
+ <shippit_add_button>
221
+ <class>shippit/observer_adminhtml_sales_order</class>
222
+ <type>singleton</type>
223
+ <method>addShippitButton</method>
224
+ </shippit_add_button>
225
+ </observers>
226
+ </adminhtml_widget_container_html_before>
227
+
228
+ <core_block_abstract_prepare_layout_before>
229
+ <observers>
230
+ <shippit_add_mass_action>
231
+ <class>shippit/observer_adminhtml_sales_order</class>
232
+ <type>singleton</type>
233
+ <method>addShippitMassAction</method>
234
+ </shippit_add_mass_action>
235
+ </observers>
236
+ </core_block_abstract_prepare_layout_before>
237
+ </events>
238
+ </adminhtml>
239
+
240
+ <crontab>
241
+ <jobs>
242
+ <shippit_order_sync>
243
+ <schedule>
244
+ <cron_expr>*/5 * * * *</cron_expr>
245
+ </schedule>
246
+ <run>
247
+ <model>shippit/api_order::run</model>
248
+ </run>
249
+ </shippit_order_sync>
250
+ </jobs>
251
+ </crontab>
252
+
253
+ <default>
254
+ <!-- Shippit Core Module Configuration -->
255
+ <shippit>
256
+ <general>
257
+ <active>0</active>
258
+ <api_key/>
259
+ <environment>production</environment>
260
+ <debug_active>0</debug_active>
261
+ </general>
262
+
263
+ <checkout>
264
+ <authority_to_leave_active>1</authority_to_leave_active>
265
+ <delivery_instructions_active>1</delivery_instructions_active>
266
+ </checkout>
267
+
268
+ <sync_order>
269
+ <active>0</active>
270
+ <manual_sync_active>0</manual_sync_active>
271
+ <mode>realtime</mode>
272
+ <send_all_orders>no</send_all_orders>
273
+ <product_location_active>0</product_location_active>
274
+ <product_location_attribute_code></product_location_attribute_code>
275
+ </sync_order>
276
+
277
+ <sync_shipping>
278
+ <active>0</active>
279
+ <update_template_active>0</update_template_active>
280
+ </sync_shipping>
281
+ </shippit>
282
+
283
+ <!-- Shippit Carrier Module Configuration -->
284
+ <carriers>
285
+ <shippit>
286
+ <model>shippit/shipping_carrier_shippit</model>
287
+ <active>0</active>
288
+ <debug_active>0</debug_active>
289
+ <allowed_methods>standard,express,priority</allowed_methods>
290
+ <title>Shippit</title>
291
+ <max_timeslots/>
292
+ <enabled_product_active>0</enabled_product_active>
293
+ <enabled_product_ids/>
294
+ <enabled_product_attribute_active>0</enabled_product_attribute_active>
295
+ <enabled_product_attribute_code/>
296
+ <enabled_product_attribute_value/>
297
+ <sallowspecific/>
298
+ <specificcountry/>
299
+ <showmethod/>
300
+ <sort_order>10</sort_order>
301
+ </shippit>
302
+ </carriers>
303
+ </default>
304
+ </config>
app/code/community/Shippit/Shippit/etc/system.xml ADDED
@@ -0,0 +1,367 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ /**
4
+ * Shippit Pty Ltd
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the terms
9
+ * that is available through the world-wide-web at this URL:
10
+ * http://www.shippit.com/terms
11
+ *
12
+ * @category Shippit
13
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
14
+ * @author Matthew Muscat <matthew@mamis.com.au>
15
+ * @license http://www.shippit.com/terms
16
+ */
17
+ -->
18
+ <config>
19
+ <sections>
20
+ <shippit translate="label" module="shippit">
21
+ <label>Shippit</label>
22
+ <tab>sales</tab>
23
+ <frontend_type>text</frontend_type>
24
+ <sort_order>340</sort_order>
25
+ <show_in_default>1</show_in_default>
26
+ <show_in_website>1</show_in_website>
27
+ <show_in_store>1</show_in_store>
28
+ <groups>
29
+ <general translate="label" module="shippit">
30
+ <label>General Settings</label>
31
+ <sort_order>10</sort_order>
32
+ <show_in_default>1</show_in_default>
33
+ <show_in_website>1</show_in_website>
34
+ <show_in_store>1</show_in_store>
35
+ <fields>
36
+ <version translate="label">
37
+ <label>Version</label>
38
+ <frontend_type>text</frontend_type>
39
+ <frontend_model>shippit/adminhtml_system_config_form_fieldset_version</frontend_model>
40
+ <sort_order>1</sort_order>
41
+ <show_in_default>1</show_in_default>
42
+ <show_in_website>1</show_in_website>
43
+ <show_in_store>1</show_in_store>
44
+ </version>
45
+ <active translate="label">
46
+ <label>Enabled</label>
47
+ <frontend_type>select</frontend_type>
48
+ <source_model>adminhtml/system_config_source_yesno</source_model>
49
+ <sort_order>10</sort_order>
50
+ <show_in_default>1</show_in_default>
51
+ <show_in_website>1</show_in_website>
52
+ <show_in_store>0</show_in_store>
53
+ </active>
54
+ <api_key translate="label">
55
+ <label>API Key</label>
56
+ <frontend_type>text</frontend_type>
57
+ <sort_order>20</sort_order>
58
+ <show_in_default>1</show_in_default>
59
+ <show_in_website>1</show_in_website>
60
+ <show_in_store>0</show_in_store>
61
+ </api_key>
62
+ <environment translate="label">
63
+ <label>Environment</label>
64
+ <frontend_type>select</frontend_type>
65
+ <source_model>shippit/system_config_source_shippit_environment</source_model>
66
+ <sort_order>30</sort_order>
67
+ <show_in_default>1</show_in_default>
68
+ <show_in_website>1</show_in_website>
69
+ <show_in_store>0</show_in_store>
70
+ </environment>
71
+ <debug_active translate="label">
72
+ <label>Debug Mode</label>
73
+ <frontend_type>select</frontend_type>
74
+ <source_model>adminhtml/system_config_source_yesno</source_model>
75
+ <sort_order>40</sort_order>
76
+ <show_in_default>1</show_in_default>
77
+ <show_in_website>1</show_in_website>
78
+ <show_in_store>0</show_in_store>
79
+ </debug_active>
80
+ </fields>
81
+ </general>
82
+ <checkout>
83
+ <label>Checkout Options</label>
84
+ <sort_order>20</sort_order>
85
+ <show_in_default>1</show_in_default>
86
+ <show_in_website>1</show_in_website>
87
+ <show_in_store>1</show_in_store>
88
+ <fields>
89
+ <authority_to_leave_active translate="label">
90
+ <label>Display Authority To Leave</label>
91
+ <frontend_type>select</frontend_type>
92
+ <source_model>adminhtml/system_config_source_yesno</source_model>
93
+ <sort_order>10</sort_order>
94
+ <show_in_default>1</show_in_default>
95
+ <show_in_website>1</show_in_website>
96
+ <show_in_store>0</show_in_store>
97
+ </authority_to_leave_active>
98
+ <delivery_instructions_active>
99
+ <label>Display Delivery Instructions</label>
100
+ <frontend_type>select</frontend_type>
101
+ <source_model>adminhtml/system_config_source_yesno</source_model>
102
+ <sort_order>20</sort_order>
103
+ <show_in_default>1</show_in_default>
104
+ <show_in_website>1</show_in_website>
105
+ <show_in_store>0</show_in_store>
106
+ </delivery_instructions_active>
107
+ </fields>
108
+ </checkout>
109
+ <sync_order translate="label" module="shippit">
110
+ <label>Order Sync</label>
111
+ <sort_order>30</sort_order>
112
+ <show_in_default>1</show_in_default>
113
+ <show_in_website>1</show_in_website>
114
+ <show_in_store>1</show_in_store>
115
+ <fields>
116
+ <active translate="label">
117
+ <label>Enabled</label>
118
+ <frontend_type>select</frontend_type>
119
+ <source_model>adminhtml/system_config_source_yesno</source_model>
120
+ <sort_order>10</sort_order>
121
+ <show_in_default>1</show_in_default>
122
+ <show_in_website>1</show_in_website>
123
+ <show_in_store>0</show_in_store>
124
+ </active>
125
+ <manual_sync_active translate="label comment">
126
+ <label>Manual Sync Enabled</label>
127
+ <frontend_type>select</frontend_type>
128
+ <source_model>adminhtml/system_config_source_yesno</source_model>
129
+ <sort_order>20</sort_order>
130
+ <show_in_default>1</show_in_default>
131
+ <show_in_website>1</show_in_website>
132
+ <show_in_store>0</show_in_store>
133
+ <comment>Add a button on the order view and a mass action on the order grid to enable a manual sync of orders with Shippit</comment>
134
+ </manual_sync_active>
135
+ <mode translate="label">
136
+ <label>Mode</label>
137
+ <frontend_type>select</frontend_type>
138
+ <source_model>shippit/system_config_source_shippit_sync_mode</source_model>
139
+ <sort_order>30</sort_order>
140
+ <show_in_default>1</show_in_default>
141
+ <show_in_website>1</show_in_website>
142
+ <show_in_store>0</show_in_store>
143
+ </mode>
144
+ <send_all_orders translate="label comment">
145
+ <label>Send All Orders to Shippit</label>
146
+ <frontend_type>select</frontend_type>
147
+ <source_model>shippit/system_config_source_shippit_sync_sendAllOrders</source_model>
148
+ <sort_order>40</sort_order>
149
+ <show_in_default>1</show_in_default>
150
+ <show_in_website>1</show_in_website>
151
+ <show_in_store>0</show_in_store>
152
+ <comment>By Default, only orders with a Shippit Shipping method, or a Shipping Method Mapping (below) are sent to Shippit</comment>
153
+ </send_all_orders>
154
+ <product_location_active translate="label comment">
155
+ <label>Send Product Location to Shippit</label>
156
+ <frontend_type>select</frontend_type>
157
+ <source_model>adminhtml/system_config_source_yesno</source_model>
158
+ <sort_order>50</sort_order>
159
+ <show_in_default>1</show_in_default>
160
+ <show_in_website>1</show_in_website>
161
+ <show_in_store>0</show_in_store>
162
+ <comment>Send the product stock location to Shippit</comment>
163
+ </product_location_active>
164
+ <product_location_attribute_code translate="label comment">
165
+ <label>Product Location Attribute Code</label>
166
+ <frontend_type>select</frontend_type>
167
+ <source_model>shippit/system_config_source_catalog_attributes</source_model>
168
+ <sort_order>60</sort_order>
169
+ <show_in_default>1</show_in_default>
170
+ <show_in_website>1</show_in_website>
171
+ <show_in_store>0</show_in_store>
172
+ <comment>The Product Attribute to be used for location information on Shippit Pick Slips</comment>
173
+ <depends>
174
+ <product_location_active>1</product_location_active>
175
+ </depends>
176
+ </product_location_attribute_code>
177
+ <shipping_method_mapping translate="label comment">
178
+ <label>Shipping Method Mapping</label>
179
+ <frontend_model>shippit/adminhtml_system_config_form_field_sync_order_shippingMethodMapping</frontend_model>
180
+ <backend_model>adminhtml/system_config_backend_serialized_array</backend_model>
181
+ <sort_order>70</sort_order>
182
+ <show_in_default>1</show_in_default>
183
+ <show_in_website>1</show_in_website>
184
+ <show_in_store>1</show_in_store>
185
+ <comment>A mapping of the Magento Shipping Methods to Shippit Services classes</comment>
186
+ </shipping_method_mapping>
187
+ </fields>
188
+ </sync_order>
189
+ <sync_shipping>
190
+ <label>Shipping Sync</label>
191
+ <sort_order>40</sort_order>
192
+ <show_in_default>1</show_in_default>
193
+ <show_in_website>1</show_in_website>
194
+ <show_in_store>1</show_in_store>
195
+ <fields>
196
+ <active translate="label">
197
+ <label>Enabled</label>
198
+ <frontend_type>select</frontend_type>
199
+ <source_model>adminhtml/system_config_source_yesno</source_model>
200
+ <sort_order>10</sort_order>
201
+ <show_in_default>1</show_in_default>
202
+ <show_in_website>1</show_in_website>
203
+ <show_in_store>0</show_in_store>
204
+ </active>
205
+ <update_template_active>
206
+ <label>Update Shipping Template</label>
207
+ <frontend_type>select</frontend_type>
208
+ <source_model>adminhtml/system_config_source_yesno</source_model>
209
+ <sort_order>20</sort_order>
210
+ <show_in_default>1</show_in_default>
211
+ <show_in_website>1</show_in_website>
212
+ <show_in_store>0</show_in_store>
213
+ <comments>Updates the shipping template to include the tracking link to Shippit</comments>
214
+ </update_template_active>
215
+ </fields>
216
+ </sync_shipping>
217
+ </groups>
218
+ </shippit>
219
+
220
+ <carriers>
221
+ <groups>
222
+ <shippit translate="label" module="shippit">
223
+ <label>Shippit</label>
224
+ <sort_order>1</sort_order>
225
+ <show_in_default>1</show_in_default>
226
+ <show_in_website>1</show_in_website>
227
+ <show_in_store>1</show_in_store>
228
+ <fields>
229
+ <active translate="label">
230
+ <label>Enabled</label>
231
+ <frontend_type>select</frontend_type>
232
+ <source_model>adminhtml/system_config_source_yesno</source_model>
233
+ <sort_order>10</sort_order>
234
+ <show_in_default>1</show_in_default>
235
+ <show_in_website>1</show_in_website>
236
+ <show_in_store>0</show_in_store>
237
+ </active>
238
+ <title translate="label">
239
+ <label>Title</label>
240
+ <frontend_type>text</frontend_type>
241
+ <sort_order>70</sort_order>
242
+ <show_in_default>1</show_in_default>
243
+ <show_in_website>1</show_in_website>
244
+ <show_in_store>0</show_in_store>
245
+ </title>
246
+ <allowed_methods translate="label">
247
+ <label>Allowed Methods</label>
248
+ <frontend_type>multiselect</frontend_type>
249
+ <source_model>shippit/system_config_source_shippit_methods</source_model>
250
+ <sort_order>80</sort_order>
251
+ <show_in_default>1</show_in_default>
252
+ <show_in_website>1</show_in_website>
253
+ <show_in_store>0</show_in_store>
254
+ <can_be_empty>1</can_be_empty>
255
+ </allowed_methods>
256
+ <max_timeslots translate="label">
257
+ <label>Maximum Timeslots</label>
258
+ <frontend_type>select</frontend_type>
259
+ <source_model>shippit/system_config_source_shippit_maxTimeslots</source_model>
260
+ <sort_order>90</sort_order>
261
+ <show_in_default>1</show_in_default>
262
+ <show_in_website>1</show_in_website>
263
+ <show_in_store>0</show_in_store>
264
+ </max_timeslots>
265
+ <enabled_product_active translate="label comment">
266
+ <label>Filter by Enabled Products</label>
267
+ <frontend_type>select</frontend_type>
268
+ <source_model>adminhtml/system_config_source_yesno</source_model>
269
+ <sort_order>120</sort_order>
270
+ <show_in_default>1</show_in_default>
271
+ <show_in_website>1</show_in_website>
272
+ <show_in_store>0</show_in_store>
273
+ <comment>Filter by products for items that are available for shipping via Shippit.</comment>
274
+ </enabled_product_active>
275
+ <enabled_product_ids translate="label comment">
276
+ <label>Enabled Products</label>
277
+ <frontend_type>multiselect</frontend_type>
278
+ <source_model>shippit/system_config_source_catalog_products</source_model>
279
+ <sort_order>130</sort_order>
280
+ <show_in_default>1</show_in_default>
281
+ <show_in_website>1</show_in_website>
282
+ <show_in_store>0</show_in_store>
283
+ <can_be_empty>1</can_be_empty>
284
+ <comment>Select the Products for which you want this method to be available.</comment>
285
+ <depends>
286
+ <enabled_product_active>1</enabled_product_active>
287
+ </depends>
288
+ </enabled_product_ids>
289
+ <enabled_product_attribute_active translate="label comment">
290
+ <label>Filter by Product Attribute</label>
291
+ <frontend_type>select</frontend_type>
292
+ <source_model>adminhtml/system_config_source_yesno</source_model>
293
+ <sort_order>140</sort_order>
294
+ <show_in_default>1</show_in_default>
295
+ <show_in_website>1</show_in_website>
296
+ <show_in_store>0</show_in_store>
297
+ <comment>Filter by product attribute for items that are available for shipping via Shippit.</comment>
298
+ </enabled_product_attribute_active>
299
+ <enabled_product_attribute_code translate="label comment">
300
+ <label>Product Attribute Code</label>
301
+ <frontend_type>select</frontend_type>
302
+ <source_model>shippit/system_config_source_catalog_attributes</source_model>
303
+ <sort_order>150</sort_order>
304
+ <show_in_default>1</show_in_default>
305
+ <show_in_website>1</show_in_website>
306
+ <show_in_store>0</show_in_store>
307
+ <comment>Select the attribute code to filter by</comment>
308
+ <depends>
309
+ <enabled_product_attribute_active>1</enabled_product_attribute_active>
310
+ </depends>
311
+ </enabled_product_attribute_code>
312
+ <enabled_product_attribute_value translate="label comment">
313
+ <label>Product Attribute Value</label>
314
+ <frontend_type>text</frontend_type>
315
+ <sort_order>160</sort_order>
316
+ <show_in_default>1</show_in_default>
317
+ <show_in_website>1</show_in_website>
318
+ <show_in_store>0</show_in_store>
319
+ <comment>Enter the attribute value to filter by. The * character indicates a wildcard.</comment>
320
+ <depends>
321
+ <enabled_product_attribute_active>1</enabled_product_attribute_active>
322
+ </depends>
323
+ </enabled_product_attribute_value>
324
+ <sallowspecific translate="label">
325
+ <label>Ship to Applicable Countries</label>
326
+ <frontend_type>select</frontend_type>
327
+ <frontend_class>shipping-applicable-country</frontend_class>
328
+ <source_model>adminhtml/system_config_source_shipping_allspecificcountries</source_model>
329
+ <sort_order>170</sort_order>
330
+ <show_in_default>1</show_in_default>
331
+ <show_in_website>1</show_in_website>
332
+ <show_in_store>0</show_in_store>
333
+ </sallowspecific>
334
+ <specificcountry translate="label">
335
+ <label>Ship to Specific Countries</label>
336
+ <frontend_type>multiselect</frontend_type>
337
+ <sort_order>180</sort_order>
338
+ <source_model>adminhtml/system_config_source_country</source_model>
339
+ <show_in_default>1</show_in_default>
340
+ <show_in_website>1</show_in_website>
341
+ <show_in_store>0</show_in_store>
342
+ <can_be_empty>1</can_be_empty>
343
+ </specificcountry>
344
+ <showmethod translate="label">
345
+ <label>Show Method if Not Applicable</label>
346
+ <frontend_type>select</frontend_type>
347
+ <sort_order>190</sort_order>
348
+ <frontend_class>shipping-skip-hide</frontend_class>
349
+ <source_model>adminhtml/system_config_source_yesno</source_model>
350
+ <show_in_default>1</show_in_default>
351
+ <show_in_website>1</show_in_website>
352
+ <show_in_store>0</show_in_store>
353
+ </showmethod>
354
+ <sort_order translate="label">
355
+ <label>Sort Order</label>
356
+ <frontend_type>text</frontend_type>
357
+ <sort_order>200</sort_order>
358
+ <show_in_default>1</show_in_default>
359
+ <show_in_website>1</show_in_website>
360
+ <show_in_store>0</show_in_store>
361
+ </sort_order>
362
+ </fields>
363
+ </shippit>
364
+ </groups>
365
+ </carriers>
366
+ </sections>
367
+ </config>
app/code/community/Shippit/Shippit/sql/shippit_setup/install-4.0.0.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ $installer = $this;
18
+ $installer->startSetup();
19
+
20
+ $orderTable = $installer->getConnection()
21
+ ->describeTable($installer->getTable('sales/order'));
22
+
23
+ $quoteTable = $installer->getConnection()
24
+ ->describeTable($installer->getTable('sales/order'));
25
+
26
+ if (!isset($orderTable['shippit_sync'])) {
27
+ $installer->getConnection()->addColumn(
28
+ $installer->getTable('sales/order'),
29
+ 'shippit_sync',
30
+ array(
31
+ 'type' => Varien_Db_Ddl_Table::TYPE_BOOLEAN,
32
+ 'nullable' => true,
33
+ 'default' => null,
34
+ 'comment' => 'Shippit - Sync with Shippit'
35
+ )
36
+ );
37
+ }
38
+
39
+ if (!isset($quoteTable['shippit_delivery_instructions'])) {
40
+ $installer->getConnection()->addColumn(
41
+ $installer->getTable('sales/quote'),
42
+ 'shippit_delivery_instructions',
43
+ array(
44
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
45
+ 'length' => 256,
46
+ 'comment' => 'Shippit - Customer Delivery Instructions'
47
+ )
48
+ );
49
+ }
50
+
51
+ if (!isset($orderTable['shippit_delivery_instructions'])) {
52
+ $installer->getConnection()->addColumn(
53
+ $installer->getTable('sales/order'),
54
+ 'shippit_delivery_instructions',
55
+ array(
56
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
57
+ 'length' => 256,
58
+ 'comment' => 'Shippit - Customer Delivery Instructions'
59
+ )
60
+ );
61
+ }
62
+
63
+ if (!isset($quoteTable['shippit_authority_to_leave'])) {
64
+ $installer->getConnection()->addColumn(
65
+ $installer->getTable('sales/quote'),
66
+ 'shippit_authority_to_leave',
67
+ array(
68
+ 'type' => Varien_Db_Ddl_Table::TYPE_BOOLEAN,
69
+ 'default' => null,
70
+ 'comment' => 'Shippit - Customer Authority To Leave'
71
+ )
72
+ );
73
+ }
74
+
75
+ if (!isset($orderTable['shippit_authority_to_leave'])) {
76
+ $installer->getConnection()->addColumn(
77
+ $installer->getTable('sales/order'),
78
+ 'shippit_authority_to_leave',
79
+ array(
80
+ 'type' => Varien_Db_Ddl_Table::TYPE_BOOLEAN,
81
+ 'default' => null,
82
+ 'comment' => 'Shippit - Customer Authority To Leave'
83
+ )
84
+ );
85
+ }
86
+
87
+ $table = $installer->getConnection()
88
+ ->newTable($installer->getTable('shippit/order_sync'))
89
+ ->addColumn(
90
+ 'sync_id',
91
+ Varien_Db_Ddl_Table::TYPE_INTEGER,
92
+ null,
93
+ array(
94
+ 'identity' => true,
95
+ 'unsigned' => true,
96
+ 'nullable' => false,
97
+ 'primary' => true,
98
+ ),
99
+ 'Id'
100
+ )
101
+ ->addColumn(
102
+ 'store_id',
103
+ Varien_Db_Ddl_Table::TYPE_SMALLINT,
104
+ null,
105
+ array(
106
+ 'unsigned' => true,
107
+ ),
108
+ 'Store Id'
109
+ )
110
+ ->addColumn(
111
+ 'order_id',
112
+ Varien_Db_Ddl_Table::TYPE_INTEGER,
113
+ null,
114
+ array(
115
+ 'unsigned' => true,
116
+ 'nullable' => false,
117
+ ),
118
+ 'Order Id'
119
+ )
120
+ ->addColumn(
121
+ 'status',
122
+ Varien_Db_Ddl_Table::TYPE_TINYINT,
123
+ null,
124
+ array(
125
+ 'unsigned' => true,
126
+ 'nullable' => false,
127
+ ),
128
+ 'Status'
129
+ )
130
+ ->addColumn(
131
+ 'attempt_count',
132
+ Varien_Db_Ddl_Table::TYPE_TINYINT,
133
+ null,
134
+ array(
135
+ 'unsigned' => true,
136
+ 'nullable' => false,
137
+ ),
138
+ 'Attempt Count'
139
+ )
140
+ ->addColumn('track_number',
141
+ Varien_Db_Ddl_Table::TYPE_TEXT,
142
+ '64k',
143
+ array(),
144
+ 'Tracking Number'
145
+ )
146
+ ->addColumn(
147
+ 'synced_at',
148
+ Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
149
+ null,
150
+ array(),
151
+ 'Synced At'
152
+ )
153
+ ->addIndex(
154
+ $installer->getIdxName(
155
+ 'shippit/order_sync',
156
+ array('store_id')
157
+ ),
158
+ array('store_id')
159
+ )
160
+ ->addIndex(
161
+ $installer->getIdxName(
162
+ 'shippit/order_sync',
163
+ array('order_id')
164
+ ),
165
+ array('order_id')
166
+ )
167
+ ->addForeignKey(
168
+ $installer->getFkName(
169
+ 'shippit/order_sync',
170
+ 'order_id',
171
+ 'sales/order',
172
+ 'entity_id'
173
+ ),
174
+ 'order_id',
175
+ $installer->getTable('sales/order'),
176
+ 'entity_id',
177
+ Varien_Db_Ddl_Table::ACTION_CASCADE,
178
+ Varien_Db_Ddl_Table::ACTION_CASCADE
179
+ )
180
+ ->addForeignKey(
181
+ $installer->getFkName(
182
+ 'shippit/order_sync',
183
+ 'store_id',
184
+ 'core/store',
185
+ 'store_id'
186
+ ),
187
+ 'store_id',
188
+ $installer->getTable('core/store'),
189
+ 'store_id',
190
+ Varien_Db_Ddl_Table::ACTION_SET_NULL,
191
+ Varien_Db_Ddl_Table::ACTION_CASCADE
192
+ )
193
+ ->setComment('Sales Flat Shipment');
194
+
195
+ $installer->getConnection()->createTable($table);
196
+
197
+ $installer->endSetup();
app/code/community/Shippit/Shippit/sql/shippit_setup/upgrade-4.0.9-4.1.0.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ $installer = $this;
18
+ $installer->startSetup();
19
+
20
+ $installer->getConnection()
21
+ ->dropColumn(
22
+ $installer->getTable('shippit/order_sync'),
23
+ 'shippit_sync'
24
+ );
25
+
26
+ // Rename the order sync table
27
+ $installer->getConnection()
28
+ ->renameTable(
29
+ $installer->getTable('shippit/order_sync'),
30
+ $installer->getTable('shippit/sync_order')
31
+ );
32
+
33
+ // Remove the store_id column
34
+ $installer->getConnection()
35
+ ->dropColumn(
36
+ $installer->getTable('shippit/sync_order'),
37
+ 'store_id'
38
+ );
39
+
40
+ $installer->getConnection()
41
+ ->addColumn(
42
+ $installer->getTable('shippit/sync_order'),
43
+ 'api_key',
44
+ array(
45
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
46
+ 'length' => 255,
47
+ 'nullable' => true,
48
+ 'default' => null,
49
+ 'after' => 'sync_id',
50
+ 'comment' => 'Shippit - API Key Override for the request'
51
+ )
52
+ );
53
+
54
+ $installer->getConnection()
55
+ ->addColumn(
56
+ $installer->getTable('shippit/sync_order'),
57
+ 'created_at',
58
+ array(
59
+ 'type' => Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
60
+ 'default' => null,
61
+ 'after' => 'track_number',
62
+ 'comment' => 'Shippit - Order Sync Created At Date'
63
+ )
64
+ );
65
+
66
+ $table = $installer->getConnection()
67
+ ->newTable($installer->getTable('shippit/sync_order_item'))
68
+ ->addColumn(
69
+ 'sync_item_id',
70
+ Varien_Db_Ddl_Table::TYPE_INTEGER,
71
+ null,
72
+ array(
73
+ 'identity' => true,
74
+ 'unsigned' => true,
75
+ 'nullable' => false,
76
+ 'primary' => true,
77
+ ),
78
+ 'Id'
79
+ )
80
+ ->addColumn(
81
+ 'sync_id',
82
+ Varien_Db_Ddl_Table::TYPE_INTEGER,
83
+ null,
84
+ array(
85
+ 'unsigned' => true,
86
+ 'nullable' => false,
87
+ ),
88
+ 'Id'
89
+ )
90
+ ->addColumn(
91
+ 'sku',
92
+ Varien_Db_Ddl_Table::TYPE_VARCHAR,
93
+ 255,
94
+ array(
95
+ 'nullable' => false,
96
+ ),
97
+ 'Item SKU'
98
+ )
99
+ ->addColumn(
100
+ 'title',
101
+ Varien_Db_Ddl_Table::TYPE_TEXT,
102
+ '64k',
103
+ array(),
104
+ 'Item Name'
105
+ )
106
+ ->addColumn(
107
+ 'qty',
108
+ Varien_Db_Ddl_Table::TYPE_INTEGER,
109
+ null,
110
+ array(
111
+ 'unsigned' => true,
112
+ 'nullable' => false,
113
+ ),
114
+ 'Item Qty'
115
+ )
116
+ ->addColumn(
117
+ 'weight',
118
+ Varien_Db_Ddl_Table::TYPE_INTEGER,
119
+ null,
120
+ array(
121
+ 'nullable' => false,
122
+ ),
123
+ 'Item Weight'
124
+ )
125
+ ->addColumn(
126
+ 'location',
127
+ Varien_Db_Ddl_Table::TYPE_VARCHAR,
128
+ 255,
129
+ array(
130
+ 'nullable' => false,
131
+ ),
132
+ 'Item Location'
133
+ )
134
+ ->addIndex(
135
+ $installer->getIdxName(
136
+ 'shippit/sync_order_item',
137
+ array('sync_id')
138
+ ),
139
+ array('sync_id')
140
+ )
141
+ ->addIndex(
142
+ $installer->getIdxName(
143
+ 'shippit/sync_order_item',
144
+ array('sku')
145
+ ),
146
+ array('sku')
147
+ )
148
+ ->addForeignKey(
149
+ $installer->getFkName(
150
+ 'shippit/sync_order_item',
151
+ 'sync_id',
152
+ 'shippit/sync_order',
153
+ 'sync_id'
154
+ ),
155
+ 'sync_id',
156
+ $installer->getTable('shippit/sync_order'),
157
+ 'sync_id',
158
+ Varien_Db_Ddl_Table::ACTION_CASCADE,
159
+ Varien_Db_Ddl_Table::ACTION_CASCADE
160
+ )
161
+ ->setComment('Shippit Order Sync Items');
162
+
163
+ $installer->getConnection()->createTable($table);
164
+
165
+ $installer->endSetup();
app/code/community/Shippit/Shippit/sql/shippit_setup/upgrade-4.1.0-4.1.1.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ $installer = $this;
18
+ $installer->startSetup();
19
+
20
+ $installer->getConnection()
21
+ ->addColumn(
22
+ $installer->getTable('shippit/sync_order'),
23
+ 'shipping_method',
24
+ array(
25
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
26
+ 'length' => 255,
27
+ 'nullable' => true,
28
+ 'after' => 'order_id',
29
+ 'comment' => 'Shippit - Shipping Method Selection'
30
+ )
31
+ );
32
+
33
+ $installer->endSetup();
app/code/community/Shippit/Shippit/sql/shippit_setup/upgrade-4.2.5-4.2.6.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ $installer = $this;
18
+ $installer->startSetup();
19
+
20
+ // Update the weight column to be casted as a float
21
+ $installer->getConnection()->changeColumn(
22
+ $installer->getTable('shippit/sync_order_item'),
23
+ 'weight',
24
+ 'weight',
25
+ array(
26
+ 'type' => Varien_Db_Ddl_Table::TYPE_DECIMAL,
27
+ 'length' => '12,4',
28
+ 'default' => '0.0000',
29
+ 'comment' => 'Item Weight'
30
+ )
31
+ );
32
+
33
+ // Update the item qty column to be casted as a float
34
+ $installer->getConnection()->changeColumn(
35
+ $installer->getTable('shippit/sync_order_item'),
36
+ 'qty',
37
+ 'qty',
38
+ array(
39
+ 'type' => Varien_Db_Ddl_Table::TYPE_DECIMAL,
40
+ 'length' => '12,4',
41
+ 'default' => '0.0000',
42
+ 'comment' => 'Item Qty'
43
+ )
44
+ );
45
+
46
+ $installer->endSetup();
app/code/community/Shippit/Shippit/sql/shippit_setup/upgrade-4.2.6-4.3.0.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+
17
+ $installer = $this;
18
+ $installer->startSetup();
19
+
20
+ $installer->getConnection()
21
+ ->addColumn(
22
+ $installer->getTable('shippit/sync_order_item'),
23
+ 'price',
24
+ array(
25
+ 'type' => Varien_Db_Ddl_Table::TYPE_DECIMAL,
26
+ 'scale' => 4,
27
+ 'precision' => 12,
28
+ 'nullable' => true,
29
+ 'default' => null,
30
+ 'after' => 'qty',
31
+ 'comment' => 'Item Price'
32
+ )
33
+ );
34
+
35
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/shippit.xml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout>
3
+ <adminhtml_shippit_order_grid>
4
+ <update handle="formkey"/>
5
+
6
+ <block type="shippit/adminhtml_sales_order_grid" name="shippit.sales.order.grid" output="toHtml" />
7
+ </adminhtml_shippit_order_grid>
8
+ </layout>
app/design/adminhtml/default/default/template/shippit/system/config/form/field/array.phtml ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Academic Free License (AFL 3.0)
8
+ * that is bundled with this package in the file LICENSE_AFL.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/afl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
18
+ * versions in the future. If you wish to customize Magento for your
19
+ * needs please refer to http://www.magentocommerce.com for more information.
20
+ *
21
+ * @category design
22
+ * @package default_default
23
+ * @copyright Copyright (c) 2014 Magento Inc. (http://www.magentocommerce.com)
24
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
25
+ */
26
+ ?>
27
+
28
+ <?php
29
+ $_htmlId = $this->getHtmlId() ? $this->getHtmlId() : '_' . uniqid();
30
+
31
+ $_colspan = 2;
32
+ if (!$this->_addAfter) {
33
+ $_colspan -= 1;
34
+ }
35
+ $_colspan = $_colspan > 1 ? 'colspan="' . $_colspan . '"' : '';
36
+ ?>
37
+
38
+ <div class="grid" id="grid<?php echo $_htmlId ?>">
39
+ <table cellpadding="0" cellspacing="0" class="border">
40
+ <tbody>
41
+
42
+ <tr class="headings" id="headings<?php echo $_htmlId ?>">
43
+ <?php foreach ($this->_columns as $columnName => $column):?>
44
+ <th><?php echo $column['label'] ?></th>
45
+ <?php endforeach;?>
46
+ <th <?php echo $_colspan?>></th>
47
+ </tr>
48
+
49
+ <tr id="addRow<?php echo $_htmlId ?>">
50
+ <td colspan="<?php echo count($this->_columns) ?>"></td>
51
+ <td <?php echo $_colspan?>>
52
+ <button style="" onclick="" class="scalable add" type="button" id="addToEndBtn<?php echo $_htmlId ?>">
53
+ <span><span><span><?php echo $this->_addButtonLabel ?></span></span></span>
54
+ </button>
55
+ </td>
56
+ </tr>
57
+
58
+ </tbody>
59
+ </table>
60
+ <input type="hidden" name="<?php echo $this->getElement()->getName() ?>[__empty]" value="" />
61
+ </div>
62
+ <div id="empty<?php echo $_htmlId ?>">
63
+ <button style="" onclick="" class="scalable add" type="button" id="emptyAddBtn<?php echo $_htmlId ?>">
64
+ <span><span><span><?php echo $this->_addButtonLabel ?></span></span></span>
65
+ </button>
66
+ </div>
67
+
68
+ <script type="text/javascript">
69
+ //<![CDATA[
70
+ // create row creator
71
+ var arrayRow<?php echo $_htmlId ?> = {
72
+ // define row prototypeJS template
73
+ template : new Template(
74
+ '<tr id="#{_id}">'
75
+ <?php foreach ($this->_columns as $columnName => $column):?>
76
+ +'<td class="#{_id}-<?php echo $columnName?>">'
77
+ +'<?php echo $this->_renderCellTemplate($columnName)?>'
78
+ +'<\/td>'
79
+ <?php endforeach;?>
80
+ <?php if ($this->_addAfter):?>
81
+ +'<td><button onclick="" class="scalable add" type="button" id="addAfterBtn#{_id}"><span><span><span><?php echo Mage::helper('adminhtml')->__('Add after') ?><\/span><\/span><\/span><\/button><\/td>'
82
+ <?php endif;?>
83
+ +'<td><button onclick="arrayRow<?php echo $_htmlId ?>.del(\'#{_id}\')" class="scalable delete" type="button"><span><span><span><?php echo Mage::helper('adminhtml')->__('Delete') ?><\/span><\/span><\/span><\/button><\/td>'
84
+ +'<\/tr>'
85
+ ),
86
+
87
+ rowsCount : 0,
88
+
89
+ add : function(templateData, insertAfterId)
90
+ {
91
+ // generate default template data
92
+ if ('' == templateData) {
93
+ var d = new Date();
94
+ var templateData = {
95
+ <?php foreach ($this->_columns as $columnName => $column):?>
96
+ <?php echo $columnName ?> : '',
97
+ <?php endforeach;?>
98
+ _id : '_' + d.getTime() + '_' + d.getMilliseconds()
99
+ };
100
+ }
101
+
102
+ // insert before last row
103
+ if ('' == insertAfterId) {
104
+ Element.insert($('addRow<?php echo $_htmlId ?>'), {before: this.template.evaluate(templateData)});
105
+ }
106
+ // insert after specified row
107
+ else {
108
+ Element.insert($(insertAfterId), {after: this.template.evaluate(templateData)});
109
+ }
110
+
111
+ // set the selected drop-down list item
112
+ <?php foreach ($this->_columns as $columnName => $column):?>
113
+ var options = $$('td.' + templateData._id + '-' + '<?php echo $columnName?>' + ' option')
114
+ for (var index = 0; index < options.length; ++index)
115
+ {
116
+ var option = options[index]
117
+ if (option.getAttribute('value') == templateData.<?php echo $columnName?>)
118
+ {
119
+ option.selected = true
120
+ }
121
+ }
122
+ <?php endforeach;?>
123
+
124
+ <?php if ($this->_addAfter):?>
125
+ Event.observe('addAfterBtn' + templateData._id, 'click', this.add.bind(this, '', templateData._id));
126
+ <?php endif;?>
127
+
128
+ this.rowsCount += 1;
129
+ },
130
+
131
+ del : function(rowId)
132
+ {
133
+ $(rowId).remove();
134
+ this.rowsCount -= 1;
135
+ if (0 == this.rowsCount) {
136
+ this.showButtonOnly();
137
+ }
138
+ },
139
+
140
+ showButtonOnly : function()
141
+ {
142
+ $('grid<?php echo $_htmlId ?>').hide();
143
+ $('empty<?php echo $_htmlId ?>').show();
144
+ }
145
+ }
146
+
147
+ // bind add action to "Add" button in last row
148
+ Event.observe('addToEndBtn<?php echo $_htmlId ?>', 'click', arrayRow<?php echo $_htmlId ?>.add.bind(arrayRow<?php echo $_htmlId ?>, '', ''));
149
+
150
+ // add existing rows
151
+ <?php
152
+ $_addAfterId = "headings{$_htmlId}";
153
+ foreach ($this->getArrayRows() as $_rowId => $_row) {
154
+ echo "arrayRow{$_htmlId}.add(" . $_row->toJson() . ", '{$_addAfterId}');\n";
155
+ $_addAfterId = $_rowId;
156
+ }
157
+ ?>
158
+
159
+ // initialize standalone button
160
+ $('empty<?php echo $_htmlId ?>').hide();
161
+ Event.observe('emptyAddBtn<?php echo $_htmlId ?>', 'click', function () {
162
+ $('grid<?php echo $_htmlId ?>').show();
163
+ $('empty<?php echo $_htmlId ?>').hide();
164
+ arrayRow<?php echo $_htmlId ?>.add('', '');
165
+ });
166
+
167
+ // if no rows, hide grid and show button only
168
+ <?php if (!$this->getArrayRows()):?>
169
+ arrayRow<?php echo $_htmlId ?>.showButtonOnly();
170
+ <?php endif;?>
171
+
172
+ // toggle the grid, if element is disabled (depending on scope)
173
+ <?php if ($this->getElement()->getDisabled()):?>
174
+ toggleValueElements({checked:true}, $('grid<?php echo $_htmlId ?>').parentNode);
175
+ <?php endif;?>
176
+ //]]>
177
+ </script>
app/design/frontend/base/default/layout/shippit.xml ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+
3
+ <!--
4
+ /**
5
+ * Shippit Pty Ltd
6
+ *
7
+ * NOTICE OF LICENSE
8
+ *
9
+ * This source file is subject to the terms
10
+ * that is available through the world-wide-web at this URL:
11
+ * http://www.shippit.com/terms
12
+ *
13
+ * @category Shippit
14
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
15
+ * @author Matthew Muscat <matthew@mamis.com.au>
16
+ * @license http://www.shippit.com/terms
17
+ */
18
+ -->
19
+
20
+ <layout version="0.1.0">
21
+ <checkout_onepage_index>
22
+ <reference name="checkout.onepage.shipping_method">
23
+ <action method="setTemplate">
24
+ <template>shippit/checkout/onepage/shipping_method.phtml</template>
25
+ </action>
26
+
27
+ <block type="shippit/checkout_shipping_deliveryInstructions" name="shippit.shipping_comment" as="shippit_delivery_instructions" template="shippit/checkout/onepage/shipping_method/deliveryinstructions.phtml" />
28
+
29
+ <block type="shippit/checkout_shipping_authorityToLeave" name="shippit.authority_to_leave" as="shippit_authority_to_leave" template="shippit/checkout/onepage/shipping_method/authoritytoleave.phtml" />
30
+ </reference>
31
+ </checkout_onepage_index>
32
+ </layout>
app/design/frontend/base/default/template/shippit/checkout/onepage/shipping_method.phtml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+ ?>
17
+ <form id="co-shipping-method-form" action="">
18
+ <div id="checkout-shipping-method-load">
19
+ <!-- Content loaded dynamically -->
20
+ </div>
21
+ <script type="text/javascript">
22
+ //<![CDATA[
23
+ var shippingMethod = new ShippingMethod('co-shipping-method-form', "<?php echo $this->getUrl('checkout/onepage/saveShippingMethod') ?>");
24
+ //]]>
25
+ </script>
26
+
27
+ <?php if (Mage::helper('core')->isModuleEnabled('Shippit_Shippit')): ?>
28
+ <div id="onepage-checkout-shipping-method-shippit">
29
+ <?php echo $this->getChildHtml('shippit_authority_to_leave') ?>
30
+ <?php echo $this->getChildHtml('shippit_delivery_instructions') ?>
31
+ </div>
32
+ <?php endif ?>
33
+
34
+ <div id="onepage-checkout-shipping-method-additional-load">
35
+ <?php echo $this->getChildHtml('additional') ?>
36
+ </div>
37
+ <div class="buttons-set" id="shipping-method-buttons-container">
38
+ <p class="back-link"><a href="#" onclick="checkout.back(); return false;"><small>&laquo; </small><?php echo $this->__('Back') ?></a></p>
39
+ <button type="button" class="button" onclick="shippingMethod.save()"><span><span><?php echo $this->__('Continue') ?></span></span></button>
40
+ <span id="shipping-method-please-wait" class="please-wait" style="display:none;">
41
+ <img src="<?php echo $this->getSkinUrl('images/opc-ajax-loader.gif') ?>" alt="<?php echo $this->__('Loading next step...') ?>" title="<?php echo $this->__('Loading next step...') ?>" class="v-middle" /> <?php echo $this->__('Loading next step...') ?>
42
+ </span>
43
+ </div>
44
+ </form>
app/design/frontend/base/default/template/shippit/checkout/onepage/shipping_method/authoritytoleave.phtml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+ ?>
17
+
18
+ <div id="onepage-checkout-shipping-method-shippit-authoritytoleave">
19
+ <ul class="form-list">
20
+ <li class="control">
21
+ <!-- Shippit Authority To Leave Checkbox -->
22
+ <input name="<?php echo $this->getFieldId() ?>" type="checkbox" title="<?php echo $this->getLabelText() ?>" class="checkbox" id="<?php echo $this->getFieldId() ?>" <?php echo ($this->getValue() ? 'checked' : '') ?> />
23
+ <label for="<?php echo $this->getFieldId() ?>">
24
+ <?php echo $this->getLabelText() ?>
25
+ </label>
26
+ </li>
27
+ </ul>
28
+ </div>
app/design/frontend/base/default/template/shippit/checkout/onepage/shipping_method/deliveryinstructions.phtml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+ ?>
17
+
18
+ <div id="onepage-checkout-shipping-method-shippit-deliveryinstructions">
19
+ <ul class="form-list">
20
+ <li class="wide">
21
+ <!-- Shippit Delivery Instructions Textarea -->
22
+ <label for="<?php echo $this->getFieldId(); ?>">
23
+ <?php echo $this->getLabelText() ?>
24
+ </label>
25
+ <div class="input-box">
26
+ <textarea id="<?php echo $this->getFieldId() ?>" name="<?php echo $this->getFieldId() ?>" style="min-height: 145px;"><?php echo $this->getValue() ?></textarea>
27
+ </div>
28
+ </li>
29
+ </ul>
30
+ </div>
app/design/frontend/base/default/template/shippit/email/order/shipment/track.phtml ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shippit Pty Ltd
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the terms
8
+ * that is available through the world-wide-web at this URL:
9
+ * http://www.shippit.com/terms
10
+ *
11
+ * @category Shippit
12
+ * @copyright Copyright (c) 2016 by Shippit Pty Ltd (http://www.shippit.com)
13
+ * @author Matthew Muscat <matthew@mamis.com.au>
14
+ * @license http://www.shippit.com/terms
15
+ */
16
+ ?>
17
+ <?php $_shipment = $this->getShipment() ?>
18
+ <?php $_order = $this->getOrder() ?>
19
+ <?php if ($_shipment && $_order && $_shipment->getAllTracks()): ?>
20
+ <table cellspacing="0" cellpadding="0" border="0" width="650" style="border: 1px solid #EAEAEA;">
21
+ <thead>
22
+ <tr>
23
+ <th align="left" bgcolor="#EAEAEA" style="font-size: 13px; padding: 3px 9px"><?php echo $this->__('Shipped By') ?></th>
24
+ <th align="center" bgcolor="#EAEAEA" style="font-size: 13px; padding: 3px 9px"><?php echo $this->__('Tracking Number') ?></th>
25
+ </tr>
26
+ </thead>
27
+ <tbody>
28
+ <?php $i = 0 ?>
29
+ <?php foreach ($_shipment->getAllTracks() as $_item): ?>
30
+ <?php
31
+ $i++;
32
+ $_trackingNumberDetail = $_item->getNumberDetail();
33
+
34
+ if ($_trackingNumberDetail && $_trackingNumberDetail instanceof Mage_Shipping_Model_Tracking_Result_Status) {
35
+ $_trackingUrl = $_trackingNumberDetail->getUrl();
36
+ }
37
+ else {
38
+ $_trackingUrl = false;
39
+ }
40
+ ?>
41
+ <tr <?php echo $i%2?'bgcolor="#F6F6F6"':'' ?>>
42
+ <td align="left" valign="top" style="padding: 3px 9px"><?php echo $this->escapeHtml($_item->getTitle()) ?></td>
43
+ <td align="center" valign="top" style="padding: 3px 9px">
44
+ <?php if ($_trackingUrl): ?>
45
+ <a href="<?php echo $_trackingUrl ?>"><?php echo $this->escapeHtml($_item->getNumber()) ?></a>
46
+ <?php else: ?>
47
+ <?php echo $this->escapeHtml($_item->getNumber()) ?>
48
+ <?php endif ?>
49
+ </td>
50
+ </tr>
51
+ <?php endforeach ?>
52
+ </tbody>
53
+ </table>
54
+ <?php endif ?>
app/etc/modules/Shippit_Shippit.xml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Shippit_Shippit>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends>
8
+ <Mage_Shipping/>
9
+ <Mage_Checkout/>
10
+ </depends>
11
+ </Shippit_Shippit>
12
+ </modules>
13
+ </config>
lib/shippit-bugsnag/Autoload.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ # We used to have an autoloader, but it caused problems in some
4
+ # environments. So now we manually load the entire library upfront.
5
+ #
6
+ # The file is still called Autoload so that existing integration
7
+ # instructions continue to work.
8
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Client.php";
9
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Configuration.php";
10
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Diagnostics.php";
11
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Error.php";
12
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR."ErrorTypes.php";
13
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Notification.php";
14
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Request.php";
15
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Stacktrace.php";
lib/shippit-bugsnag/Client.php ADDED
@@ -0,0 +1,557 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bugsnag_Client
4
+ {
5
+ private $config;
6
+ /** @var Bugsnag_Notification|null */
7
+ private $notification;
8
+
9
+ /**
10
+ * Initialize Bugsnag
11
+ *
12
+ * @param String $apiKey your Bugsnag API key
13
+ * @throws Exception
14
+ */
15
+ public function __construct($apiKey)
16
+ {
17
+ // Check API key has been passed
18
+ if (!is_string($apiKey)) {
19
+ throw new Exception('Bugsnag Error: Invalid API key');
20
+ }
21
+
22
+ // Create a configuration object
23
+ $this->config = new Bugsnag_Configuration();
24
+ $this->config->apiKey = $apiKey;
25
+
26
+ // Build a Diagnostics object
27
+ $this->diagnostics = new Bugsnag_Diagnostics($this->config);
28
+
29
+ // Register a shutdown function to check for fatal errors
30
+ // and flush any buffered errors
31
+ register_shutdown_function(array($this, 'shutdownHandler'));
32
+ }
33
+
34
+ /**
35
+ * Set your release stage, eg "production" or "development"
36
+ *
37
+ * @param String $releaseStage the app's current release stage
38
+ * @return $this
39
+ */
40
+ public function setReleaseStage($releaseStage)
41
+ {
42
+ $this->config->releaseStage = $releaseStage;
43
+
44
+ return $this;
45
+ }
46
+
47
+ /**
48
+ * Set your app's semantic version, eg "1.2.3"
49
+ *
50
+ * @param String $appVersion the app's version
51
+ * @return $this
52
+ */
53
+ public function setAppVersion($appVersion)
54
+ {
55
+ $this->config->appVersion = $appVersion;
56
+
57
+ return $this;
58
+ }
59
+
60
+ /**
61
+ * Set the host name
62
+ *
63
+ * @param String $hostname the host name
64
+ * @return $this
65
+ */
66
+ public function setHostname($hostname)
67
+ {
68
+ $this->config->hostname = $hostname;
69
+
70
+ return $this;
71
+ }
72
+
73
+ /**
74
+ * Set which release stages should be allowed to notify Bugsnag
75
+ * eg array("production", "development")
76
+ *
77
+ * @param Array $notifyReleaseStages array of release stages to notify for
78
+ * @return $this
79
+ */
80
+ public function setNotifyReleaseStages(array $notifyReleaseStages)
81
+ {
82
+ $this->config->notifyReleaseStages = $notifyReleaseStages;
83
+
84
+ return $this;
85
+ }
86
+
87
+ /**
88
+ * Set which Bugsnag endpoint to send errors to.
89
+ *
90
+ * @param String $endpoint endpoint URL
91
+ * @return $this
92
+ */
93
+ public function setEndpoint($endpoint)
94
+ {
95
+ $this->config->endpoint = $endpoint;
96
+
97
+ return $this;
98
+ }
99
+
100
+ /**
101
+ * Enable debug mode to help diagnose problems.
102
+ *
103
+ * @param Boolean $debug whether to enable debug mode
104
+ * @return $this
105
+ */
106
+ public function setDebug($debug)
107
+ {
108
+ $this->config->debug = $debug;
109
+
110
+ return $this;
111
+ }
112
+
113
+ /**
114
+ * Set whether or not to use SSL when notifying bugsnag
115
+ *
116
+ * @param Boolean $useSSL whether to use SSL
117
+ * @deprecated you can now pass full URLs to setEndpoint
118
+ * @return $this
119
+ */
120
+ public function setUseSSL($useSSL)
121
+ {
122
+ $this->config->useSSL = $useSSL;
123
+
124
+ return $this;
125
+ }
126
+
127
+ /**
128
+ * Set the desired timeout for cURL connection when notifying bugsnag
129
+ *
130
+ * @param Integer $timeout the desired timeout in seconds
131
+ * @return $this
132
+ */
133
+ public function setTimeout($timeout)
134
+ {
135
+ $this->config->timeout = $timeout;
136
+
137
+ return $this;
138
+ }
139
+
140
+ /**
141
+ * Set the absolute path to the root of your application.
142
+ * We use this to help with error grouping and to highlight "in project"
143
+ * stacktrace lines.
144
+ *
145
+ * @param String $projectRoot the root path for your application
146
+ * @return $this
147
+ */
148
+ public function setProjectRoot($projectRoot)
149
+ {
150
+ $this->config->setProjectRoot($projectRoot);
151
+
152
+ return $this;
153
+ }
154
+
155
+ /**
156
+ * Set the path that should be stripped from the beginning of
157
+ * any stacktrace file line. This helps to normalise filenames
158
+ * for grouping and reduces the noise in stack traces.
159
+ *
160
+ * @param String $stripPath the path to strip from filenames
161
+ * @return $this
162
+ */
163
+ public function setStripPath($stripPath)
164
+ {
165
+ $this->config->setStripPath($stripPath);
166
+
167
+ return $this;
168
+ }
169
+
170
+ /**
171
+ * Set the a regular expression for matching filenames in stacktrace lines
172
+ * that are part of your application.
173
+ *
174
+ * @param String $projectRootRegex regex matching paths belong to your project
175
+ * @return $this
176
+ */
177
+ public function setProjectRootRegex($projectRootRegex)
178
+ {
179
+ $this->config->projectRootRegex = $projectRootRegex;
180
+
181
+ return $this;
182
+ }
183
+
184
+ /**
185
+ * Set the strings to filter out from metaData arrays before sending then
186
+ * to Bugsnag. Eg. array("password", "credit_card")
187
+ *
188
+ * @param Array $filters an array of metaData filters
189
+ * @return $this
190
+ */
191
+ public function setFilters(array $filters)
192
+ {
193
+ $this->config->filters = $filters;
194
+
195
+ return $this;
196
+ }
197
+
198
+ /**
199
+ * Set information about the current user of your app, including
200
+ * id, name and email.
201
+ *
202
+ * @param Array $user an array of user information. Eg:
203
+ * array(
204
+ * 'name' => 'Bob Hoskins',
205
+ * 'email' => 'bob@hoskins.com'
206
+ * )
207
+ * @return $this
208
+ */
209
+ public function setUser(array $user)
210
+ {
211
+ $this->config->user = $user;
212
+
213
+ return $this;
214
+ }
215
+
216
+ /**
217
+ * @deprecated deprecated since version 2.1
218
+ * @param $userId
219
+ * @return $this
220
+ */
221
+ public function setUserId($userId)
222
+ {
223
+ if (!is_array($this->config->user)) {
224
+ $this->config->user = array();
225
+ }
226
+
227
+ $this->config->user['id'] = $userId;
228
+
229
+ return $this;
230
+ }
231
+
232
+ /**
233
+ * Set a context representing the current type of request, or location in code.
234
+ *
235
+ * @param String $context the current context
236
+ * @return $this
237
+ */
238
+ public function setContext($context)
239
+ {
240
+ $this->config->context = $context;
241
+
242
+ return $this;
243
+ }
244
+
245
+ /**
246
+ * Set the type of application executing the code. This is usually used to
247
+ * represent if you are running plain PHP code "php", via a framework,
248
+ * eg "laravel", or executing through delayed worker code, eg "resque".
249
+ *
250
+ * @param String $type the current type
251
+ * @return $this
252
+ */
253
+ public function setType($type)
254
+ {
255
+ $this->config->type = $type;
256
+
257
+ return $this;
258
+ }
259
+
260
+ /**
261
+ * Set custom metadata to send to Bugsnag with every error. You can use
262
+ * this to add custom tabs of data to each error on your Bugsnag dashboard
263
+ *
264
+ * @param Array $metaData an array of arrays of custom data. Eg:
265
+ * array(
266
+ * "user" => array(
267
+ * "name" => "James",
268
+ * "email" => "james@example.com"
269
+ * )
270
+ * )
271
+ * @return $this
272
+ */
273
+ public function setMetaData(array $metaData)
274
+ {
275
+ $this->config->metaData = $metaData;
276
+
277
+ return $this;
278
+ }
279
+
280
+ /**
281
+ * Set proxy configuration
282
+ *
283
+ * @param Array $proxySettings an array with proxy settings. Eg:
284
+ * array(
285
+ * 'host' => "bugsnag.com",
286
+ * 'port' => 42,
287
+ * 'user' => "username"
288
+ * 'password' => "password123"
289
+ * )
290
+ * @return $this
291
+ */
292
+ public function setProxySettings(array $proxySettings)
293
+ {
294
+ $this->config->proxySettings = $proxySettings;
295
+
296
+ return $this;
297
+ }
298
+
299
+ /**
300
+ * Set custom curl options
301
+ *
302
+ * @param Array $curlOptions an array with curl options. Eg:
303
+ * array(
304
+ * CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4
305
+ * )
306
+ * @return $this
307
+ */
308
+ public function setCurlOptions(array $curlOptions)
309
+ {
310
+ $this->config->curlOptions = $curlOptions;
311
+
312
+ return $this;
313
+ }
314
+
315
+ /**
316
+ * Set a custom function to call before notifying Bugsnag of an error.
317
+ * You can use this to call your own error handling functions, or to add
318
+ * custom tabs of data to each error on your Bugsnag dashboard.
319
+ *
320
+ * // Adding meta-data example
321
+ * function before_bugsnag_notify($error) {
322
+ * $error->addMetaData(array(
323
+ * "user" => array(
324
+ * "name" => "James"
325
+ * )
326
+ * ));
327
+ * }
328
+ * $bugsnag->setBeforeNotifyFunction("before_bugsnag_notify");
329
+ * @param callable $beforeNotifyFunction
330
+ * @return $this
331
+ */
332
+ public function setBeforeNotifyFunction($beforeNotifyFunction)
333
+ {
334
+ $this->config->beforeNotifyFunction = $beforeNotifyFunction;
335
+
336
+ return $this;
337
+ }
338
+
339
+ /**
340
+ * Set Bugsnag's error reporting level.
341
+ * If this is not set, we'll use your current PHP error_reporting value
342
+ * from your ini file or error_reporting(...) calls.
343
+ *
344
+ * @param Integer $errorReportingLevel the error reporting level integer
345
+ * exactly as you would pass to PHP's error_reporting
346
+ * @return $this
347
+ */
348
+ public function setErrorReportingLevel($errorReportingLevel)
349
+ {
350
+ $this->config->errorReportingLevel = $errorReportingLevel;
351
+
352
+ return $this;
353
+ }
354
+
355
+ /**
356
+ * Sets whether Bugsnag should be automatically notified of unhandled
357
+ * exceptions and errors.
358
+ *
359
+ * @param Boolean $autoNotify whether to auto notify or not
360
+ * @return $this
361
+ */
362
+ public function setAutoNotify($autoNotify)
363
+ {
364
+ $this->config->autoNotify = $autoNotify;
365
+
366
+ return $this;
367
+ }
368
+
369
+ /**
370
+ * Sets whether errors should be batched together and send at the end of
371
+ * each request.
372
+ *
373
+ * @param Boolean $batchSending whether to batch together errors
374
+ * @return $this
375
+ */
376
+ public function setBatchSending($batchSending)
377
+ {
378
+ $this->config->batchSending = $batchSending;
379
+
380
+ return $this;
381
+ }
382
+
383
+ /**
384
+ * Sets the notifier to report as to Bugsnag. This should only be
385
+ * set by other notifier libraries.
386
+ *
387
+ * @param Array $notifier an array of name, version, url.
388
+ * @return $this
389
+ */
390
+ public function setNotifier($notifier)
391
+ {
392
+ $this->config->notifier = $notifier;
393
+
394
+ return $this;
395
+ }
396
+
397
+ /**
398
+ * Sets whether Bugsnag should send $_ENV with each error.
399
+ *
400
+ * @param Boolean $sendEnvironment whether to send the environment
401
+ * @return $this
402
+ */
403
+ public function setSendEnvironment($sendEnvironment)
404
+ {
405
+ $this->config->sendEnvironment = $sendEnvironment;
406
+
407
+ return $this;
408
+ }
409
+
410
+ /**
411
+ * Sets whether Bugsnag should send $_COOKIE with each error.
412
+ *
413
+ * @param Boolean $sendCookies whether to send the environment
414
+ * @return $this
415
+ */
416
+ public function setSendCookies($sendCookies)
417
+ {
418
+ $this->config->sendCookies = $sendCookies;
419
+
420
+ return $this;
421
+ }
422
+
423
+ /**
424
+ * Sets whether Bugsnag should send $_SESSION with each error.
425
+ *
426
+ * @param Boolean $sendSession whether to send the environment
427
+ * @return $this
428
+ */
429
+ public function setSendSession($sendSession)
430
+ {
431
+ $this->config->sendSession = $sendSession;
432
+
433
+ return $this;
434
+ }
435
+
436
+ /**
437
+ * Should we send a small snippet of the code that crashed to help you
438
+ * diagnose even faster from within your dashboard.
439
+ *
440
+ * @param Boolean $sendCode whether to send code to Bugsnag
441
+ * @return $this
442
+ */
443
+ public function setSendCode($sendCode)
444
+ {
445
+ $this->config->sendCode = $sendCode;
446
+
447
+ return $this;
448
+ }
449
+
450
+ /**
451
+ * Notify Bugsnag of a non-fatal/handled throwable
452
+ *
453
+ * @param Throwable $throwable the throwable to notify Bugsnag about
454
+ * @param Array $metaData optional metaData to send with this error
455
+ * @param String $severity optional severity of this error (fatal/error/warning/info)
456
+ */
457
+ public function notifyException($throwable, array $metaData = null, $severity = null)
458
+ {
459
+ if (is_subclass_of($throwable, 'Throwable') || is_subclass_of($throwable, 'Exception') || get_class($throwable) == 'Exception') {
460
+ $error = Bugsnag_Error::fromPHPThrowable($this->config, $this->diagnostics, $throwable);
461
+ $error->setSeverity($severity);
462
+
463
+ $this->notify($error, $metaData);
464
+ }
465
+ }
466
+
467
+ /**
468
+ * Notify Bugsnag of a non-fatal/handled error
469
+ *
470
+ * @param String $name the name of the error, a short (1 word) string
471
+ * @param String $message the error message
472
+ * @param Array $metaData optional metaData to send with this error
473
+ * @param String $severity optional severity of this error (fatal/error/warning/info)
474
+ */
475
+ public function notifyError($name, $message, array $metaData = null, $severity = null)
476
+ {
477
+ $error = Bugsnag_Error::fromNamedError($this->config, $this->diagnostics, $name, $message);
478
+ $error->setSeverity($severity);
479
+
480
+ $this->notify($error, $metaData);
481
+ }
482
+
483
+ // Exception handler callback, should only be called internally by PHP's set_exception_handler
484
+ public function exceptionHandler($throwable)
485
+ {
486
+ if(!$this->config->autoNotify) {
487
+ return;
488
+ }
489
+
490
+ $error = Bugsnag_Error::fromPHPThrowable($this->config, $this->diagnostics, $throwable);
491
+ $error->setSeverity("error");
492
+ $this->notify($error);
493
+ }
494
+
495
+ // Exception handler callback, should only be called internally by PHP's set_error_handler
496
+ public function errorHandler($errno, $errstr, $errfile = '', $errline = 0)
497
+ {
498
+ if(!$this->config->autoNotify || $this->config->shouldIgnoreErrorCode($errno)) {
499
+ return;
500
+ }
501
+
502
+ $error = Bugsnag_Error::fromPHPError($this->config, $this->diagnostics, $errno, $errstr, $errfile, $errline);
503
+ $this->notify($error);
504
+ }
505
+
506
+ // Shutdown handler callback, called when the PHP process has finished running
507
+ // Should only be called internally by PHP's register_shutdown_function
508
+ public function shutdownHandler()
509
+ {
510
+ // Get last error
511
+ $lastError = error_get_last();
512
+
513
+ // Check if a fatal error caused this shutdown
514
+ if (!is_null($lastError) && Bugsnag_ErrorTypes::isFatal($lastError['type']) && $this->config->autoNotify && !$this->config->shouldIgnoreErrorCode($lastError['type'])) {
515
+ $error = Bugsnag_Error::fromPHPError($this->config, $this->diagnostics, $lastError['type'], $lastError['message'], $lastError['file'], $lastError['line'], true);
516
+ $error->setSeverity("error");
517
+ $this->notify($error);
518
+ }
519
+
520
+ // Flush any buffered errors
521
+ if ($this->notification) {
522
+ $this->notification->deliver();
523
+ $this->notification = null;
524
+ }
525
+ }
526
+
527
+ /**
528
+ * Batches up errors into notifications for later sending
529
+ *
530
+ * @param Bugsnag_Error $error the error to batch up
531
+ * @param array $metaData optional meta data to send with the error
532
+ */
533
+ public function notify(Bugsnag_Error $error, $metaData = array())
534
+ {
535
+ // Queue or send the error
536
+ if ($this->sendErrorsOnShutdown()) {
537
+ // Create a batch notification unless we already have one
538
+ if (is_null($this->notification)) {
539
+ $this->notification = new Bugsnag_Notification($this->config);
540
+ }
541
+
542
+ // Add this error to the notification
543
+ $this->notification->addError($error, $metaData);
544
+ } else {
545
+ // Create and deliver notification immediately
546
+ $notif = new Bugsnag_Notification($this->config);
547
+ $notif->addError($error, $metaData);
548
+ $notif->deliver();
549
+ }
550
+ }
551
+
552
+ // Should we send errors immediately or on shutdown
553
+ private function sendErrorsOnShutdown()
554
+ {
555
+ return $this->config->batchSending && Bugsnag_Request::isRequest();
556
+ }
557
+ }
lib/shippit-bugsnag/Configuration.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bugsnag_Configuration
4
+ {
5
+ public static $DEFAULT_TIMEOUT = 10;
6
+ public static $DEFAULT_ENDPOINT = 'https://notify.bugsnag.com';
7
+ public static $DEFAULT_NON_SSL_ENDPOINT = 'http://notify.bugsnag.com';
8
+
9
+ public $apiKey;
10
+ public $autoNotify = true;
11
+ public $batchSending = true;
12
+ public $useSSL = true;
13
+ public $endpoint;
14
+ public $notifyReleaseStages;
15
+ public $filters = array('password');
16
+ public $projectRoot;
17
+ public $projectRootRegex;
18
+ public $proxySettings = array();
19
+ public $notifier = array(
20
+ 'name' => 'Bugsnag PHP (Official)',
21
+ 'version' => '2.7.0',
22
+ 'url' => 'https://bugsnag.com',
23
+ );
24
+ public $sendEnvironment = false;
25
+ public $sendCookies = true;
26
+ public $sendSession = true;
27
+ public $sendCode = true;
28
+ public $stripPath;
29
+ public $stripPathRegex;
30
+
31
+ public $context;
32
+ public $type;
33
+ public $user;
34
+ public $releaseStage = 'production';
35
+ public $appVersion;
36
+ public $hostname;
37
+
38
+ public $metaData;
39
+ public $beforeNotifyFunction;
40
+ public $errorReportingLevel;
41
+
42
+ public $curlOptions = array();
43
+
44
+ public $debug = false;
45
+
46
+ public function __construct()
47
+ {
48
+ $this->timeout = Bugsnag_Configuration::$DEFAULT_TIMEOUT;
49
+ }
50
+
51
+ public function getNotifyEndpoint()
52
+ {
53
+ if (is_null($this->endpoint)) {
54
+ return $this->useSSL ? Bugsnag_Configuration::$DEFAULT_ENDPOINT : Bugsnag_Configuration::$DEFAULT_NON_SSL_ENDPOINT;
55
+ } elseif (preg_match('/^(http:\/\/|https:\/\/)/', $this->endpoint)) {
56
+ return $this->endpoint;
57
+ } else {
58
+ return ($this->useSSL ? "https" : "http")."://".$this->endpoint;
59
+ }
60
+ }
61
+
62
+ public function shouldNotify()
63
+ {
64
+ return is_null($this->notifyReleaseStages) || (is_array($this->notifyReleaseStages) && in_array($this->releaseStage, $this->notifyReleaseStages));
65
+ }
66
+
67
+ public function shouldIgnoreErrorCode($code)
68
+ {
69
+ if (isset($this->errorReportingLevel)) {
70
+ return !($this->errorReportingLevel & $code);
71
+ } else {
72
+ return !(error_reporting() & $code);
73
+ }
74
+ }
75
+
76
+ public function setProjectRoot($projectRoot)
77
+ {
78
+ $this->projectRoot = $projectRoot;
79
+ $this->projectRootRegex = '/'.preg_quote($projectRoot, '/')."[\\/]?/i";
80
+ if (is_null($this->stripPath)) {
81
+ $this->setStripPath($projectRoot);
82
+ }
83
+ }
84
+
85
+ public function setStripPath($stripPath)
86
+ {
87
+ $this->stripPath = $stripPath;
88
+ $this->stripPathRegex = '/'.preg_quote($stripPath, '/')."[\\/]?/i";
89
+ }
90
+
91
+ public function get($prop, $default = null)
92
+ {
93
+ $configured = $this->$prop;
94
+
95
+ if (is_array($configured) && is_array($default)) {
96
+ return array_merge($default, $configured);
97
+ } else {
98
+ return $configured ? $configured : $default;
99
+ }
100
+ }
101
+ }
lib/shippit-bugsnag/Diagnostics.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bugsnag_Diagnostics
4
+ {
5
+ private $config;
6
+
7
+ public function __construct(Bugsnag_Configuration $config)
8
+ {
9
+ $this->config = $config;
10
+ }
11
+
12
+ public function getAppData()
13
+ {
14
+ $appData = array();
15
+
16
+ if (!is_null($this->config->appVersion)) {
17
+ $appData['version'] = $this->config->appVersion;
18
+ }
19
+
20
+ if (!is_null($this->config->releaseStage)) {
21
+ $appData['releaseStage'] = $this->config->releaseStage;
22
+ }
23
+
24
+ if (!is_null($this->config->type)) {
25
+ $appData['type'] = $this->config->type;
26
+ }
27
+
28
+ return $appData;
29
+ }
30
+
31
+ public function getDeviceData()
32
+ {
33
+ return array(
34
+ 'hostname' => $this->config->get('hostname', php_uname('n')),
35
+ );
36
+ }
37
+
38
+ public function getContext()
39
+ {
40
+ return $this->config->get('context', Bugsnag_Request::getContext());
41
+ }
42
+
43
+ public function getUser()
44
+ {
45
+ $defaultUser = array();
46
+ $userId = Bugsnag_Request::getUserId();
47
+
48
+ if (!is_null($userId)) {
49
+ $defaultUser['id'] = $userId;
50
+ }
51
+
52
+ return $this->config->get('user', $defaultUser);
53
+ }
54
+ }
lib/shippit-bugsnag/Error.php ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bugsnag_Error
4
+ {
5
+ private static $VALID_SEVERITIES = array(
6
+ 'error',
7
+ 'warning',
8
+ 'info',
9
+ );
10
+
11
+ public $name;
12
+ public $payloadVersion = "2";
13
+ public $message;
14
+ public $severity = "warning";
15
+ /** @var Bugsnag_Stacktrace */
16
+ public $stacktrace;
17
+ public $metaData = array();
18
+ public $config;
19
+ public $diagnostics;
20
+ /** @var Bugsnag_Error|null */
21
+ public $previous;
22
+ public $groupingHash;
23
+
24
+ // Static error creation methods, to ensure that Error object is always complete
25
+ public static function fromPHPError(Bugsnag_Configuration $config, Bugsnag_Diagnostics $diagnostics, $code, $message, $file, $line, $fatal = false)
26
+ {
27
+ $error = new Bugsnag_Error($config, $diagnostics);
28
+ $error->setPHPError($code, $message, $file, $line, $fatal);
29
+
30
+ return $error;
31
+ }
32
+
33
+ public static function fromPHPThrowable(Bugsnag_Configuration $config, Bugsnag_Diagnostics $diagnostics, $throwable)
34
+ {
35
+ $error = new Bugsnag_Error($config, $diagnostics);
36
+ $error->setPHPException($throwable);
37
+
38
+ return $error;
39
+ }
40
+
41
+ public static function fromNamedError(Bugsnag_Configuration $config, Bugsnag_Diagnostics $diagnostics, $name, $message = null)
42
+ {
43
+ $error = new Bugsnag_Error($config, $diagnostics);
44
+ $error->setName($name)
45
+ ->setMessage($message)
46
+ ->setStacktrace(Bugsnag_Stacktrace::generate($config));
47
+
48
+ return $error;
49
+ }
50
+
51
+ // Private constructor (for use only by the static methods above)
52
+ private function __construct(Bugsnag_Configuration $config, Bugsnag_Diagnostics $diagnostics)
53
+ {
54
+ $this->config = $config;
55
+ $this->diagnostics = $diagnostics;
56
+ }
57
+
58
+ public function setName($name)
59
+ {
60
+ $this->name = $name;
61
+
62
+ return $this;
63
+ }
64
+
65
+ public function setMessage($message)
66
+ {
67
+ $this->message = $message;
68
+
69
+ return $this;
70
+ }
71
+
72
+ public function setGroupingHash($groupingHash)
73
+ {
74
+ $this->groupingHash = $groupingHash;
75
+
76
+ return $this;
77
+ }
78
+
79
+ public function setStacktrace(Bugsnag_Stacktrace $stacktrace)
80
+ {
81
+ $this->stacktrace = $stacktrace;
82
+
83
+ return $this;
84
+ }
85
+
86
+ public function setSeverity($severity)
87
+ {
88
+ if (!is_null($severity)) {
89
+ if (in_array($severity, Bugsnag_Error::$VALID_SEVERITIES)) {
90
+ $this->severity = $severity;
91
+ } else {
92
+ error_log('Bugsnag Warning: Tried to set error severity to '.$severity.' which is not allowed.');
93
+ }
94
+ }
95
+
96
+ return $this;
97
+ }
98
+
99
+ public function setPHPException($exception)
100
+ {
101
+ if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
102
+ if (!$exception instanceof \Throwable) {
103
+ error_log('Bugsnag Warning: Exception must implement interface \Throwable.');
104
+ return;
105
+ }
106
+ } else {
107
+ if (!$exception instanceof \Exception) {
108
+ error_log('Bugsnag Warning: Exception must be instance of \Exception.');
109
+ return;
110
+ }
111
+ }
112
+
113
+ $this->setName(get_class($exception))
114
+ ->setMessage($exception->getMessage())
115
+ ->setStacktrace(Bugsnag_Stacktrace::fromBacktrace($this->config, $exception->getTrace(), $exception->getFile(), $exception->getLine()));
116
+
117
+ if (method_exists($exception, 'getPrevious')) {
118
+ $this->setPrevious($exception->getPrevious());
119
+ }
120
+
121
+ return $this;
122
+ }
123
+
124
+ public function setPHPError($code, $message, $file, $line, $fatal = false)
125
+ {
126
+ if ($fatal) {
127
+ // Generating stacktrace for PHP fatal errors is not possible,
128
+ // since this code executes when the PHP process shuts down,
129
+ // rather than at the time of the crash.
130
+ //
131
+ // In these situations, we generate a "stacktrace" containing only
132
+ // the line and file number where the crash occurred.
133
+ $stacktrace = Bugsnag_Stacktrace::fromFrame($this->config, $file, $line);
134
+ } else {
135
+ $stacktrace = Bugsnag_Stacktrace::generate($this->config);
136
+ }
137
+
138
+ $this->setName(Bugsnag_ErrorTypes::getName($code))
139
+ ->setMessage($message)
140
+ ->setSeverity(Bugsnag_ErrorTypes::getSeverity($code))
141
+ ->setStacktrace($stacktrace);
142
+
143
+ return $this;
144
+ }
145
+
146
+ public function setMetaData($metaData)
147
+ {
148
+ if (is_array($metaData)) {
149
+ $this->metaData = array_merge_recursive($this->metaData, $metaData);
150
+ }
151
+
152
+ return $this;
153
+ }
154
+
155
+ public function setPrevious($exception)
156
+ {
157
+ if ($exception) {
158
+ $this->previous = Bugsnag_Error::fromPHPThrowable($this->config, $this->diagnostics, $exception);
159
+ }
160
+
161
+ return $this;
162
+ }
163
+
164
+ public function toArray()
165
+ {
166
+ $errorArray = array(
167
+ 'app' => $this->diagnostics->getAppData(),
168
+ 'device' => $this->diagnostics->getDeviceData(),
169
+ 'user' => $this->diagnostics->getUser(),
170
+ 'context' => $this->diagnostics->getContext(),
171
+ 'payloadVersion' => $this->payloadVersion,
172
+ 'severity' => $this->severity,
173
+ 'exceptions' => $this->exceptionArray(),
174
+ 'metaData' => $this->cleanupObj($this->metaData, true),
175
+ );
176
+
177
+ if (isset($this->groupingHash)) {
178
+ $errorArray['groupingHash'] = $this->groupingHash;
179
+ }
180
+
181
+ return $errorArray;
182
+ }
183
+
184
+ public function exceptionArray()
185
+ {
186
+ if ($this->previous) {
187
+ $exceptionArray = $this->previous->exceptionArray();
188
+ } else {
189
+ $exceptionArray = array();
190
+ }
191
+
192
+ $exceptionArray[] = array(
193
+ 'errorClass' => $this->name,
194
+ 'message' => $this->message,
195
+ 'stacktrace' => $this->stacktrace->toArray(),
196
+ );
197
+
198
+ return $this->cleanupObj($exceptionArray, false);
199
+ }
200
+
201
+ private function cleanupObj($obj, $isMetaData)
202
+ {
203
+ if (is_null($obj)) {
204
+ return null;
205
+ }
206
+
207
+ if (is_array($obj)) {
208
+ $cleanArray = array();
209
+ foreach ($obj as $key => $value) {
210
+ // Check if this key should be filtered
211
+ $shouldFilter = false;
212
+
213
+ // Apply filters to metadata if required
214
+ if ($isMetaData && is_array($this->config->filters)) {
215
+ foreach ($this->config->filters as $filter) {
216
+ if (strpos($key, $filter) !== false) {
217
+ $shouldFilter = true;
218
+ break;
219
+ }
220
+ }
221
+ }
222
+ // Apply filter
223
+ if ($shouldFilter) {
224
+ $cleanArray[$key] = '[FILTERED]';
225
+ } else {
226
+ $cleanArray[$key] = $this->cleanupObj($value, $isMetaData);
227
+ }
228
+ }
229
+
230
+ return $cleanArray;
231
+ } elseif (is_string($obj)) {
232
+ // UTF8-encode if not already encoded
233
+ if (function_exists('mb_detect_encoding') && !mb_detect_encoding($obj, 'UTF-8', true)) {
234
+ return utf8_encode($obj);
235
+ } else {
236
+ return $obj;
237
+ }
238
+ } elseif (is_object($obj)) {
239
+ // json_encode -> json_decode trick turns an object into an array
240
+ return $this->cleanupObj(json_decode(json_encode($obj), true), $isMetaData);
241
+ } else {
242
+ return $obj;
243
+ }
244
+ }
245
+ }
lib/shippit-bugsnag/ErrorTypes.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bugsnag_ErrorTypes
4
+ {
5
+ private static $ERROR_TYPES = array(
6
+ E_ERROR => array(
7
+ 'name' => 'PHP Fatal Error',
8
+ 'severity' => 'error',
9
+ ),
10
+
11
+ E_WARNING => array(
12
+ 'name' => 'PHP Warning',
13
+ 'severity' => 'warning',
14
+ ),
15
+
16
+ E_PARSE => array(
17
+ 'name' => 'PHP Parse Error',
18
+ 'severity' => 'error',
19
+ ),
20
+
21
+ E_NOTICE => array(
22
+ 'name' => 'PHP Notice',
23
+ 'severity' => 'info',
24
+ ),
25
+
26
+ E_CORE_ERROR => array(
27
+ 'name' => 'PHP Core Error',
28
+ 'severity' => 'error',
29
+ ),
30
+
31
+ E_CORE_WARNING => array(
32
+ 'name' => 'PHP Core Warning',
33
+ 'severity' => 'warning',
34
+ ),
35
+
36
+ E_COMPILE_ERROR => array(
37
+ 'name' => 'PHP Compile Error',
38
+ 'severity' => 'error',
39
+ ),
40
+
41
+ E_COMPILE_WARNING => array(
42
+ 'name' => 'PHP Compile Warning',
43
+ 'severity' => 'warning',
44
+ ),
45
+
46
+ E_USER_ERROR => array(
47
+ 'name' => 'User Error',
48
+ 'severity' => 'error',
49
+ ),
50
+
51
+ E_USER_WARNING => array(
52
+ 'name' => 'User Warning',
53
+ 'severity' => 'warning',
54
+ ),
55
+
56
+ E_USER_NOTICE => array(
57
+ 'name' => 'User Notice',
58
+ 'severity' => 'info',
59
+ ),
60
+
61
+ E_STRICT => array(
62
+ 'name' => 'PHP Strict',
63
+ 'severity' => 'info',
64
+ ),
65
+
66
+ E_RECOVERABLE_ERROR => array(
67
+ 'name' => 'PHP Recoverable Error',
68
+ 'severity' => 'error',
69
+ ),
70
+
71
+ // E_DEPRECATED (Since PHP 5.3.0)
72
+ 8192 => array(
73
+ 'name' => 'PHP Deprecated',
74
+ 'severity' => 'info',
75
+ ),
76
+
77
+ // E_USER_DEPRECATED (Since PHP 5.3.0)
78
+ 16384 => array(
79
+ 'name' => 'User Deprecated',
80
+ 'severity' => 'info',
81
+ ),
82
+ );
83
+
84
+ public static function isFatal($code)
85
+ {
86
+ return self::getSeverity($code) == 'error';
87
+ }
88
+
89
+ public static function getName($code)
90
+ {
91
+ if (array_key_exists($code, self::$ERROR_TYPES)) {
92
+ return self::$ERROR_TYPES[$code]['name'];
93
+ } else {
94
+ return "Unknown";
95
+ }
96
+ }
97
+
98
+ public static function getSeverity($code)
99
+ {
100
+ if (array_key_exists($code, self::$ERROR_TYPES)) {
101
+ return self::$ERROR_TYPES[$code]['severity'];
102
+ } else {
103
+ return "error";
104
+ }
105
+ }
106
+
107
+ public static function getLevelsForSeverity($severity)
108
+ {
109
+ $levels = 0;
110
+ foreach (Bugsnag_ErrorTypes::$ERROR_TYPES as $level => $info) {
111
+ if ($info['severity'] == $severity) {
112
+ $levels |= $level;
113
+ }
114
+ }
115
+
116
+ return $levels;
117
+ }
118
+ }
lib/shippit-bugsnag/Notification.php ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bugsnag_Notification
4
+ {
5
+ private static $CONTENT_TYPE_HEADER = 'Content-type: application/json';
6
+
7
+ private $config;
8
+ /** @var Bugsnag_Error[] */
9
+ private $errorQueue = array();
10
+
11
+ public function __construct(Bugsnag_Configuration $config)
12
+ {
13
+ $this->config = $config;
14
+ }
15
+
16
+ public function addError(Bugsnag_Error $error, $passedMetaData = array())
17
+ {
18
+ // Check if this error should be sent to Bugsnag
19
+ if (!$this->config->shouldNotify()) {
20
+ return false;
21
+ }
22
+
23
+ // Add global meta-data to error
24
+ $error->setMetaData($this->config->metaData);
25
+
26
+ // Add request meta-data to error
27
+ if (Bugsnag_Request::isRequest()) {
28
+ $error->setMetaData(Bugsnag_Request::getRequestMetaData());
29
+ }
30
+
31
+ // Session Tab
32
+ if ($this->config->sendSession && !empty($_SESSION)) {
33
+ $error->setMetaData(array('session' => $_SESSION));
34
+ }
35
+
36
+ // Cookies Tab
37
+ if ($this->config->sendCookies && !empty($_COOKIE)) {
38
+ $error->setMetaData(array('cookies' => $_COOKIE));
39
+ }
40
+
41
+ // Add environment meta-data to error
42
+ if ($this->config->sendEnvironment && !empty($_ENV)) {
43
+ $error->setMetaData(array("Environment" => $_ENV));
44
+ }
45
+
46
+ // Add user-specified meta-data to error
47
+ $error->setMetaData($passedMetaData);
48
+
49
+ // Run beforeNotify function (can cause more meta-data to be merged)
50
+ if (isset($this->config->beforeNotifyFunction) && is_callable($this->config->beforeNotifyFunction)) {
51
+ $beforeNotifyReturn = call_user_func($this->config->beforeNotifyFunction, $error);
52
+ }
53
+
54
+ // Skip this error if the beforeNotify function returned FALSE
55
+ if (!isset($beforeNotifyReturn) || $beforeNotifyReturn !== false) {
56
+ $this->errorQueue[] = $error;
57
+
58
+ return true;
59
+ } else {
60
+ return false;
61
+ }
62
+ }
63
+
64
+ public function toArray()
65
+ {
66
+ $events = array();
67
+ foreach ($this->errorQueue as $error) {
68
+ $errorArray = $error->toArray();
69
+
70
+ if (!is_null($errorArray)) {
71
+ $events[] = $errorArray;
72
+ }
73
+ }
74
+
75
+ return array(
76
+ 'apiKey' => $this->config->apiKey,
77
+ 'notifier' => $this->config->notifier,
78
+ 'events' => $events,
79
+ );
80
+ }
81
+
82
+ public function deliver()
83
+ {
84
+ if (!empty($this->errorQueue)) {
85
+ // Post the request to bugsnag
86
+ $this->postJSON($this->config->getNotifyEndpoint(), $this->toArray());
87
+
88
+ // Clear the error queue
89
+ $this->errorQueue = array();
90
+ }
91
+ }
92
+
93
+ public function postJSON($url, $data)
94
+ {
95
+ $body = json_encode($data);
96
+
97
+ // Prefer cURL if it is installed, otherwise fall back to fopen()
98
+ // cURL supports both timeouts and proxies
99
+ if (function_exists('curl_version')) {
100
+ $this->postWithCurl($url, $body);
101
+ } elseif (ini_get('allow_url_fopen')) {
102
+ $this->postWithFopen($url, $body);
103
+ } else {
104
+ error_log('Bugsnag Warning: Couldn\'t notify (neither cURL or allow_url_fopen are available on your PHP installation)');
105
+ }
106
+ }
107
+
108
+ private function postWithCurl($url, $body)
109
+ {
110
+ $http = curl_init($url);
111
+
112
+ // Default curl settings
113
+ curl_setopt($http, CURLOPT_HEADER, false);
114
+ curl_setopt($http, CURLOPT_RETURNTRANSFER, true);
115
+ curl_setopt($http, CURLOPT_POST, true);
116
+ curl_setopt($http, CURLOPT_HTTPHEADER, array(Bugsnag_Notification::$CONTENT_TYPE_HEADER));
117
+ curl_setopt($http, CURLOPT_POSTFIELDS, $body);
118
+ curl_setopt($http, CURLOPT_CONNECTTIMEOUT, $this->config->timeout);
119
+ curl_setopt($http, CURLOPT_SSL_VERIFYPEER, false);
120
+ curl_setopt($http, CURLOPT_VERBOSE, false);
121
+ if (defined('HHVM_VERSION')) {
122
+ curl_setopt($http, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
123
+ } else {
124
+ curl_setopt($http, CURL_IPRESOLVE_V4, true);
125
+ }
126
+
127
+ if (!empty($this->config->curlOptions)) {
128
+ foreach ($this->config->curlOptions as $option => $value) {
129
+ curl_setopt($http, $option, $value);
130
+ }
131
+ }
132
+ // Apply proxy settings (if present)
133
+ if (count($this->config->proxySettings)) {
134
+ if (isset($this->config->proxySettings['host'])) {
135
+ curl_setopt($http, CURLOPT_PROXY, $this->config->proxySettings['host']);
136
+ }
137
+ if (isset($this->config->proxySettings['port'])) {
138
+ curl_setopt($http, CURLOPT_PROXYPORT, $this->config->proxySettings['port']);
139
+ }
140
+ if (isset($this->config->proxySettings['user'])) {
141
+ $userPassword = $this->config->proxySettings['user'].':';
142
+ $userPassword .= isset($this->config->proxySettings['password']) ? $this->config->proxySettings['password'] : '';
143
+ curl_setopt($http, CURLOPT_PROXYUSERPWD, $userPassword);
144
+ }
145
+ }
146
+
147
+ // Execute the request and fetch the response
148
+ $responseBody = curl_exec($http);
149
+ $statusCode = curl_getinfo($http, CURLINFO_HTTP_CODE);
150
+
151
+ if ($statusCode > 200) {
152
+ error_log('Bugsnag Warning: Couldn\'t notify ('.$responseBody.')');
153
+
154
+ if($this->config->debug) {
155
+ error_log('Bugsnag Debug: Attempted to post to URL - "'.$url.'"');
156
+ error_log('Bugsnag Debug: Attempted to post payload - "'.$body.'"');
157
+ }
158
+ }
159
+
160
+ if (curl_errno($http)) {
161
+ error_log('Bugsnag Warning: Couldn\'t notify ('.curl_error($http).')');
162
+ }
163
+
164
+ curl_close($http);
165
+ }
166
+
167
+ private function postWithFopen($url, $body)
168
+ {
169
+ // Warn about lack of proxy support if we are using fopen()
170
+ if (count($this->config->proxySettings)) {
171
+ error_log('Bugsnag Warning: Can\'t use proxy settings unless cURL is installed');
172
+ }
173
+
174
+ // Create the request context
175
+ $context = stream_context_create(array(
176
+ 'http' => array(
177
+ 'method' => 'POST',
178
+ 'header' => Bugsnag_Notification::$CONTENT_TYPE_HEADER.'\r\n',
179
+ 'content' => $body,
180
+ 'timeout' => $this->config->timeout
181
+ ),
182
+ 'ssl' => array(
183
+ 'verify_peer' => false,
184
+ ),
185
+ ));
186
+
187
+ // Execute the request and fetch the response
188
+ if ($stream = fopen($url, 'rb', false, $context)) {
189
+ $response = stream_get_contents($stream);
190
+
191
+ if (!$response) {
192
+ error_log('Bugsnag Warning: Couldn\'t notify (no response)');
193
+ }
194
+ } else {
195
+ error_log('Bugsnag Warning: Couldn\'t notify (fopen failed)');
196
+ }
197
+ }
198
+ }
lib/shippit-bugsnag/Request.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bugsnag_Request
4
+ {
5
+ public static function isRequest()
6
+ {
7
+ return isset($_SERVER['REQUEST_METHOD']);
8
+ }
9
+
10
+ public static function getRequestMetaData()
11
+ {
12
+ $requestData = array();
13
+
14
+ $methodsWithPayload = array('PUT');
15
+
16
+ // Request Tab
17
+ $requestData['request'] = array();
18
+ $requestData['request']['url'] = self::getCurrentUrl();
19
+ if (isset($_SERVER['REQUEST_METHOD'])) {
20
+ $requestData['request']['httpMethod'] = $_SERVER['REQUEST_METHOD'];
21
+ }
22
+
23
+ if (!empty($_POST)) {
24
+ $requestData['request']['params'] = $_POST;
25
+ } else {
26
+
27
+ if (isset($_SERVER['CONTENT_TYPE']) && stripos($_SERVER['CONTENT_TYPE'], 'application/json') === 0) {
28
+ $requestData['request']['params'] = json_decode(file_get_contents('php://input'));
29
+ }
30
+
31
+ if (isset($_SERVER['REQUEST_METHOD']) && in_array(strtoupper($_SERVER['REQUEST_METHOD']), $methodsWithPayload)) {
32
+ parse_str(file_get_contents('php://input'),$params);
33
+ if(isset($requestData['request']['params']))
34
+ {
35
+ $requestData['request']['params'] = array_merge($requestData['request']['params'],$params);
36
+ }
37
+ else
38
+ {
39
+ $requestData['request']['params'] = $params;
40
+ }
41
+ }
42
+ }
43
+
44
+ $requestData['request']['ip'] = self::getRequestIp();
45
+ if (isset($_SERVER['HTTP_USER_AGENT'])) {
46
+ $requestData['request']['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
47
+ }
48
+
49
+ $headers = self::getRequestHeaders();
50
+ if (!empty($headers)) {
51
+ $requestData['request']['headers'] = $headers;
52
+ }
53
+
54
+ return $requestData;
55
+ }
56
+
57
+ public static function getContext()
58
+ {
59
+ if (self::isRequest() && isset($_SERVER['REQUEST_METHOD']) && isset($_SERVER["REQUEST_URI"])) {
60
+ return $_SERVER['REQUEST_METHOD'].' '.strtok($_SERVER["REQUEST_URI"], '?');
61
+ } else {
62
+ return null;
63
+ }
64
+ }
65
+
66
+ public static function getUserId()
67
+ {
68
+ if (self::isRequest()) {
69
+ return self::getRequestIp();
70
+ } else {
71
+ return null;
72
+ }
73
+ }
74
+
75
+ public static function getCurrentUrl()
76
+ {
77
+ $schema = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443)) ? 'https://' : 'http://';
78
+
79
+ return $schema.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
80
+ }
81
+
82
+ public static function getRequestIp()
83
+ {
84
+ return isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
85
+ }
86
+
87
+ public static function getRequestHeaders()
88
+ {
89
+ if (function_exists('getallheaders')) {
90
+ return getallheaders();
91
+ }
92
+
93
+ $headers = array();
94
+
95
+ foreach ($_SERVER as $name => $value) {
96
+ if (substr($name, 0, 5) == 'HTTP_') {
97
+ $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
98
+ }
99
+ }
100
+
101
+ return $headers;
102
+ }
103
+ }
lib/shippit-bugsnag/Stacktrace.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Bugsnag_Stacktrace
4
+ {
5
+ private static $DEFAULT_NUM_LINES = 7;
6
+ private static $MAX_LINE_LENGTH = 200;
7
+
8
+ public $frames = array();
9
+ private $config;
10
+
11
+ public static function generate($config)
12
+ {
13
+ // Reduce memory usage by omitting args and objects from backtrace
14
+ if (version_compare(PHP_VERSION, '5.3.6') >= 0) {
15
+ $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS & ~DEBUG_BACKTRACE_PROVIDE_OBJECT);
16
+ } elseif (version_compare(PHP_VERSION, '5.2.5') >= 0) {
17
+ $backtrace = debug_backtrace(false);
18
+ } else {
19
+ $backtrace = debug_backtrace();
20
+ }
21
+
22
+ return self::fromBacktrace($config, $backtrace, "[generator]", 0);
23
+ }
24
+
25
+ public static function fromFrame($config, $file, $line)
26
+ {
27
+ $stacktrace = new Bugsnag_Stacktrace($config);
28
+ $stacktrace->addFrame($file, $line, "[unknown]");
29
+
30
+ return $stacktrace;
31
+ }
32
+
33
+ public static function fromBacktrace($config, $backtrace, $topFile, $topLine)
34
+ {
35
+ $stacktrace = new Bugsnag_Stacktrace($config);
36
+
37
+ // PHP backtrace's are misaligned, we need to shift the file/line down a frame
38
+ foreach ($backtrace as $frame) {
39
+ if (!self::frameInsideBugsnag($frame)) {
40
+ $stacktrace->addFrame(
41
+ $topFile,
42
+ $topLine,
43
+ isset($frame['function']) ? $frame['function'] : null,
44
+ isset($frame['class']) ? $frame['class'] : null
45
+ );
46
+ }
47
+
48
+ if (isset($frame['file']) && isset($frame['line'])) {
49
+ $topFile = $frame['file'];
50
+ $topLine = $frame['line'];
51
+ } else {
52
+ $topFile = "[internal]";
53
+ $topLine = 0;
54
+ }
55
+ }
56
+
57
+ // Add a final stackframe for the "main" method
58
+ $stacktrace->addFrame($topFile, $topLine, '[main]');
59
+
60
+ return $stacktrace;
61
+ }
62
+
63
+ public static function frameInsideBugsnag($frame)
64
+ {
65
+ return isset($frame['class']) && strpos($frame['class'], 'Bugsnag_') === 0;
66
+ }
67
+
68
+ public function __construct($config)
69
+ {
70
+ $this->config = $config;
71
+ }
72
+
73
+ public function toArray()
74
+ {
75
+ return $this->frames;
76
+ }
77
+
78
+ public function addFrame($file, $line, $method, $class = null)
79
+ {
80
+ // Account for special "filenames" in eval'd code
81
+ $matches = array();
82
+ if (preg_match("/^(.*?)\((\d+)\) : (?:eval\(\)'d code|runtime-created function)$/", $file, $matches)) {
83
+ $file = $matches[1];
84
+ $line = $matches[2];
85
+ }
86
+
87
+ // Construct the frame
88
+ $frame = array(
89
+ 'lineNumber' => $line,
90
+ 'method' => $class ? "$class::$method" : $method,
91
+ );
92
+
93
+ // Attach some lines of code for context
94
+ if($this->config->sendCode) {
95
+ $frame['code'] = $this->getCode($file, $line, Bugsnag_Stacktrace::$DEFAULT_NUM_LINES);
96
+ }
97
+
98
+ // Check if this frame is inProject
99
+ $frame['inProject'] = !is_null($this->config->projectRootRegex) && preg_match($this->config->projectRootRegex, $file);
100
+
101
+ // Strip out projectRoot from start of file path
102
+ if (is_null($this->config->stripPathRegex)) {
103
+ $frame['file'] = $file;
104
+ } else {
105
+ $frame['file'] = preg_replace($this->config->stripPathRegex, '', $file);
106
+ }
107
+
108
+ $this->frames[] = $frame;
109
+ }
110
+
111
+ private function getCode($path, $line, $numLines)
112
+ {
113
+ if (empty($path) || empty($line) || !file_exists($path)) {
114
+ return NULL;
115
+ }
116
+
117
+ try {
118
+ // Get the number of lines in the file
119
+ $file = new SplFileObject($path);
120
+ $file->seek(PHP_INT_MAX);
121
+ $totalLines = $file->key() + 1;
122
+
123
+ // Work out which lines we should fetch
124
+ $start = max($line - floor($numLines / 2), 1);
125
+ $end = $start + ($numLines - 1);
126
+ if ($end > $totalLines) {
127
+ $end = $totalLines;
128
+ $start = max($end - ($numLines - 1), 1);
129
+ }
130
+
131
+ // Get the code for this range
132
+ $code = array();
133
+
134
+ $file->seek($start - 1);
135
+ while ($file->key() < $end) {
136
+ $code[$file->key() + 1] = rtrim(substr($file->current(), 0, Bugsnag_Stacktrace::$MAX_LINE_LENGTH));
137
+ $file->next();
138
+ }
139
+
140
+ return $code;
141
+ } catch (RuntimeException $ex) {
142
+ return null;
143
+ }
144
+ }
145
+ }
package.xml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Shippit_Shippit</name>
4
+ <version>4.3.4</version>
5
+ <stability>stable</stability>
6
+ <license>Open Software Licence</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Shippit Magento Integration Module</summary>
10
+ <description>Shipping Integration Module with Shippit.com&#xD;
11
+ &#xD;
12
+ Features:&#xD;
13
+ - Adds a "Shippit" carrier method, enabling quotes on orders from a number of Australian Couriers&#xD;
14
+ - Syncs order details with Shippit when a customer selects a shippit method, enabling easy label printing and customer notification.</description>
15
+ <notes>Shippit Magento Integration module, using the Shippit v3 API.&#xD;
16
+ &#xD;
17
+ Allows for retrieving shipping quotes during checkout and sending orders to Shippit.&#xD;
18
+ &#xD;
19
+ Also adds Australian States and Territories to the available region options and Authority to Leave and Delivery Comments to the checkout process.</notes>
20
+ <authors><author><name>Matthew Muscat</name><user>matthewmuscat</user><email>matthew@mamis.com.au</email></author><author><name>William On</name><user>williamon</user><email>will@shippit.com</email></author></authors>
21
+ <date>2016-07-13</date>
22
+ <time>03:53:24</time>
23
+ <contents><target name="magelib"><dir name="shippit-bugsnag"><file name="Autoload.php" hash="141a845b8baaebee4232b30540d5cda5"/><file name="Client.php" hash="1899cce9e4e05aa200c5c05ef2c0f52d"/><file name="Configuration.php" hash="c4a28bb83e49dfb24ff15e3daebbe156"/><file name="Diagnostics.php" hash="ee57a579dec73e922465d417cfecccf6"/><file name="Error.php" hash="f8d179e9406a6c0a958d06367b9e64e0"/><file name="ErrorTypes.php" hash="d52493e689517f479abb21599e9c1989"/><file name="Notification.php" hash="98ac2f24e77a96fe8f274e9694a33dd4"/><file name="Request.php" hash="ff8dbf358238351801518bad62138491"/><file name="Stacktrace.php" hash="2f7b8e1172f04071ce70b5b53cfe55ee"/></dir></target><target name="magecommunity"><dir name="Shippit"><dir name="Shippit"><dir name="Block"><dir name="Adminhtml"><dir name="Sales"><dir name="Order"><file name="Grid.php" hash="9208ed6e0b222590610f6a3e2a3ac254"/><file name="Items.php" hash="275116a2c42700de7a65fc9e0a6568c6"/></dir><file name="Order.php" hash="665a08b5f3f6432ba49327ad0d320572"/></dir><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><dir name="Renderer"><dir name="Shipping"><file name="Methods.php" hash="26428642657de1a0f0d22140fd84174d"/></dir><dir name="Shippit"><file name="ServiceClass.php" hash="190d62627bbf749bdd326f3384563ca8"/></dir></dir><dir name="Sync"><dir name="Order"><file name="ShippingMethodMapping.php" hash="7296f3ac577b89c36c68693ab1a84a32"/></dir></dir></dir><dir name="Fieldset"><file name="Version.php" hash="6cbff78c307a14e3eed4219f180901b1"/></dir></dir></dir></dir></dir><dir name="Checkout"><dir name="Cart"><file name="Shipping.php" hash="dd5dc61d665da4746e5c2a4fc6df089f"/></dir><dir name="Shipping"><file name="AuthorityToLeave.php" hash="241ff5d226c8f848b9895b767883dc30"/><file name="DeliveryInstructions.php" hash="77b5fb807d9dfdd8b5b6bfab6f8df9a6"/></dir></dir></dir><file name="Exception.php" hash="909594393898823a108bab9c6a2e77ed"/><dir name="Helper"><file name="Api.php" hash="4b786e0b9857caf468730f7cd3b74f9b"/><file name="Bugsnag.php" hash="ae4f276ee853abaf75ffbaf9de08cc08"/><file name="Carrier.php" hash="f7d031b67b5c9beec38214236ff30b5a"/><file name="Checkout.php" hash="004418f9ee0de6ba090faa32e540d8a3"/><file name="Data.php" hash="df6ea2d54c389f91721dc28c72b1dea1"/><dir name="Order"><file name="Items.php" hash="76b3de4116a35bad7a9b555d570c3e0a"/></dir><dir name="Sync"><file name="Order.php" hash="49c06a4593fd5facbe9179e7e6c7d772"/><file name="Shipping.php" hash="c19889222cffbddf178a6236f78ae41c"/></dir></dir><dir name="Model"><dir name="Api"><file name="Order.php" hash="da43b34915cf919fc2efb46f3f11dc07"/></dir><file name="Logger.php" hash="64ed33a2d7554a9da58a080e3462504e"/><dir name="Observer"><dir name="Adminhtml"><dir name="Sales"><file name="Order.php" hash="44393a4d02ea135f68d74ca8ec37394a"/></dir></dir><dir name="Order"><file name="Sync.php" hash="963898714f719827a507a914e23d99c5"/></dir><dir name="Quote"><file name="AuthorityToLeave.php" hash="c675772dcb25d6a35372f46060b3a8e4"/><file name="DeliveryInstructions.php" hash="8cf1353e6406710208a5312c9cd68c7d"/></dir><dir name="Shipping"><file name="Tracking.php" hash="988cffc30e8d606ba6a2754ba4b2d3a3"/></dir><file name="Shippit.php" hash="3625385600a8e3f0c64492bfaac9c681"/><dir name="System"><file name="Config.php" hash="e5515b7d0cccde3ad7bb70fbe33a3f0b"/></dir></dir><dir name="Request"><dir name="Api"><file name="Order.php" hash="cb4ef62cdafedadf330e7d2f2db3686c"/><file name="Shipment.php" hash="ddd370c2c9ddc107108bab26af0e99ce"/></dir><dir name="Sync"><file name="Order.php" hash="60ee300b5581d12d3ea48493d7ef2c20"/></dir></dir><dir name="Resource"><file name="Setup.php" hash="8eb28f6cf5f637597d5f0ad668b64269"/><dir name="Sync"><dir name="Order"><file name="Collection.php" hash="b6fc680edfd57d6cbf810290799dad2c"/><dir name="Item"><file name="Collection.php" hash="935dd5847558e6629ea671b91ad9a1df"/></dir><file name="Item.php" hash="1ba227660a2d1ad09283c312e7e88a98"/></dir><file name="Order.php" hash="4808f4501b760ac09af24fba0df7494d"/></dir></dir><dir name="Shipping"><dir name="Carrier"><file name="Shippit.php" hash="eaf1fc6ec3a58fc1a3adecf07ec5bd8b"/></dir></dir><file name="Shippit.php" hash="d85a257bda0253ef41e2a062bb4a223b"/><dir name="Sync"><dir name="Order"><file name="Config.php" hash="f52faaf68213e313746abde13781350e"/><file name="Item.php" hash="dee4de2286845cdaed924f81dfeeab51"/></dir><file name="Order.php" hash="460b020cd0a44d8f956e415fbccae620"/></dir><dir name="System"><dir name="Config"><dir name="Source"><dir name="Catalog"><dir name="Attributes"><file name="Location.php" hash="80af2e3d897d52a4f840feb37341b6ea"/></dir><file name="Attributes.php" hash="1f051ddfcea5034c3b0f299ed35d2c7c"/><file name="Products.php" hash="6e78a631987441e8228ee410fe5addd2"/></dir><dir name="Shipping"><file name="Methods.php" hash="683dd6c9d412d52be6941ec1aec0e1eb"/></dir><dir name="Shippit"><file name="Environment.php" hash="a71561807ce05052a678a5d8d0656695"/><file name="MaxTimeslots.php" hash="a87f36fb06a9e9b79c1ffdc5ff1c42c0"/><file name="Methods.php" hash="8ac2d4a18fd249259ef05ba406acc846"/><dir name="Sync"><file name="Mode.php" hash="64ff642d93ad9505f160f48b5061efae"/><file name="SendAllOrders.php" hash="99fc5b1dcb2d49768025194cd02aba0e"/></dir></dir></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Shippit"><dir name="Order"><file name="SyncController.php" hash="d5a22ab5fe1346e68d7967e9cad20402"/></dir><file name="OrderController.php" hash="7d4e2c615b524c211d75b4b7c4edc0e7"/></dir></dir><file name="OrderController.php" hash="6d5fe674fd570b6d7b8acc761e450de6"/></dir><dir name="data"><dir name="shippit_setup"><file name="data-install-4.0.0.php" hash="fcc2ad84912ffaf9dc07b866f5fd7460"/><file name="data-upgrade-4.1.0-4.1.1.php" hash="aebc8c802bf8af45219500526da944fa"/><file name="data-upgrade-4.1.6-4.1.7.php" hash="2b2fe61d97645521516728a329cba9ad"/><file name="data-upgrade-4.2.3-4.2.4.php" hash="bd3ed5e70b9349d830fa789e0b394d83"/><file name="data-upgrade-4.3.2-4.3.3.php" hash="3699a8b74b0898f48ec1b9daeb3fcfcc"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="fb2576b73bea6a323cfd157e95c25e90"/><file name="config.xml" hash="ea2571b81276ff80c25bd78370b27ff3"/><file name="system.xml" hash="9db0c4db9094b978db5c7b3ddd3266c9"/></dir><dir name="sql"><dir name="shippit_setup"><file name="install-4.0.0.php" hash="19a0a09b6a10c89b73edc7f0a744fe5a"/><file name="upgrade-4.0.9-4.1.0.php" hash="35e56aeea2b78bba82e845d4c4c16fc1"/><file name="upgrade-4.1.0-4.1.1.php" hash="5c675c05272472cdd7c585aa6db750d9"/><file name="upgrade-4.2.5-4.2.6.php" hash="15dd734c1f7797d8cd0ff5b91a2dda55"/><file name="upgrade-4.2.6-4.3.0.php" hash="635d87318271636ed348a41834c70081"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="shippit.xml" hash="18fa39b7eae780fe993e5140270ffefe"/></dir><dir name="template"><dir name="shippit"><dir name="checkout"><dir name="onepage"><dir name="shipping_method"><file name="authoritytoleave.phtml" hash="7a138531233734c55f97de3cb1641a18"/><file name="deliveryinstructions.phtml" hash="cc64f104584b7be4de3e5de3f2c047c0"/></dir><file name="shipping_method.phtml" hash="c7d804a639749b3c7b21e5e228463f88"/></dir></dir><dir name="email"><dir name="order"><dir name="shipment"><file name="track.phtml" hash="c1450ff14e566880d421799852df4014"/></dir></dir></dir></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="shippit.xml" hash="c0ae616038936a98b9e87124fb1c3127"/></dir><dir name="template"><dir name="shippit"><dir name="system"><dir name="config"><dir name="form"><dir name="field"><file name="array.phtml" hash="46d02a4a01af0e14cb2d0d91665ca03e"/></dir></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Shippit_Shippit.xml" hash="401f33d7db491808587c51209d8d6a8b"/></dir></target></contents>
24
+ <compatible/>
25
+ <dependencies><required><php><min>5.2.0</min><max>8.0.0</max></php></required></dependencies>
26
+ </package>