Wallmob_Wallmob - Version 0.1.2

Version Notes

Initial stable release. Imports the following entities from the Wallmob POS:
- Categories
- Products
- Stock

In addition, placed orders will be reported to the Wallmob POS.

Download this release

Release Info

Developer Wallmob
Extension Wallmob_Wallmob
Version 0.1.2
Comparing to
See all releases


Version 0.1.2

Files changed (24) hide show
  1. app/code/community/Wallmob/Wallmob/Block/Adminhtml/Datetimelabel.php +37 -0
  2. app/code/community/Wallmob/Wallmob/Block/Adminhtml/Resetbutton.php +39 -0
  3. app/code/community/Wallmob/Wallmob/Block/Adminhtml/Scheduledlabel.php +41 -0
  4. app/code/community/Wallmob/Wallmob/Block/Adminhtml/Statuslabel.php +54 -0
  5. app/code/community/Wallmob/Wallmob/Helper/Data.php +58 -0
  6. app/code/community/Wallmob/Wallmob/Model/Api.php +172 -0
  7. app/code/community/Wallmob/Wallmob/Model/Import.php +146 -0
  8. app/code/community/Wallmob/Wallmob/Model/Observer.php +201 -0
  9. app/code/community/Wallmob/Wallmob/Model/Processor/Abstract.php +31 -0
  10. app/code/community/Wallmob/Wallmob/Model/Processor/Category.php +145 -0
  11. app/code/community/Wallmob/Wallmob/Model/Processor/Interface.php +29 -0
  12. app/code/community/Wallmob/Wallmob/Model/Processor/Product.php +413 -0
  13. app/code/community/Wallmob/Wallmob/Model/Processor/Stock.php +158 -0
  14. app/code/community/Wallmob/Wallmob/Model/Processor/Vat.php +36 -0
  15. app/code/community/Wallmob/Wallmob/Model/System/Config/Source/Wallmob/Store.php +43 -0
  16. app/code/community/Wallmob/Wallmob/controllers/Adminhtml/WallmobController.php +36 -0
  17. app/code/community/Wallmob/Wallmob/data/wallmob_setup/data-install-0.1.0.php +40 -0
  18. app/code/community/Wallmob/Wallmob/data/wallmob_setup/data-upgrade-0.1.0-0.1.1.php +33 -0
  19. app/code/community/Wallmob/Wallmob/data/wallmob_setup/data-upgrade-0.1.1-0.1.2.php +36 -0
  20. app/code/community/Wallmob/Wallmob/etc/adminhtml.xml +22 -0
  21. app/code/community/Wallmob/Wallmob/etc/config.xml +100 -0
  22. app/code/community/Wallmob/Wallmob/etc/system.xml +157 -0
  23. app/etc/modules/Wallmob_Wallmob.xml +12 -0
  24. package.xml +23 -0
app/code/community/Wallmob/Wallmob/Block/Adminhtml/Datetimelabel.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Block_Adminhtml_Datetimelabel
19
+ extends Mage_Adminhtml_Block_System_Config_Form_Field
20
+ {
21
+
22
+ /**
23
+ * Retrieve Element HTML
24
+ *
25
+ * @param Varien_Data_Form_Element_Abstract $element
26
+ * @return string
27
+ */
28
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
29
+ {
30
+ $timestamp = (int)parent::_getElementHtml($element);
31
+ if ($timestamp) {
32
+ return date('Y-m-d h:i:s', $timestamp);
33
+ }
34
+ return '<i>' . $this->__('Not Available') . '</i>';
35
+ }
36
+
37
+ }
app/code/community/Wallmob/Wallmob/Block/Adminhtml/Resetbutton.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Block_Adminhtml_Resetbutton
19
+ extends Mage_Adminhtml_Block_System_Config_Form_Field
20
+ {
21
+
22
+ /**
23
+ * Returns the URL for resetting last updated timer.
24
+ *
25
+ * @param Varien_Data_Form_Element_Abstract $element
26
+ * @return string
27
+ */
28
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
29
+ {
30
+ $this->setElement($element);
31
+ return $this->getLayout()->createBlock('adminhtml/widget_button')
32
+ ->setType('button')
33
+ ->setClass('scalable')
34
+ ->setLabel($this->__('Force Update'))
35
+ ->setOnClick("setLocation('" . $this->getUrl('*/wallmob/reset') . "')")
36
+ ->toHtml();
37
+ }
38
+
39
+ }
app/code/community/Wallmob/Wallmob/Block/Adminhtml/Scheduledlabel.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Block_Adminhtml_Scheduledlabel
19
+ extends Mage_Adminhtml_Block_System_Config_Form_Field
20
+ {
21
+
22
+ /**
23
+ * Retrieve Element HTML
24
+ *
25
+ * @param Varien_Data_Form_Element_Abstract $element
26
+ * @return string
27
+ */
28
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
29
+ {
30
+ $schedule = Mage::getModel('cron/schedule')->getCollection()
31
+ ->addFieldToFilter('job_code', array('eq' => 'wallmob_import_all'))
32
+ ->addFieldToFilter('executed_at', array('null' => true))
33
+ ->addOrder('scheduled_at', 'asc');
34
+ if ($schedule->count()) {
35
+ return $schedule->getFirstItem()->getScheduledAt();
36
+ } else {
37
+ return '<i>Not scheduled</i>';
38
+ }
39
+ }
40
+
41
+ }
app/code/community/Wallmob/Wallmob/Block/Adminhtml/Statuslabel.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Block_Adminhtml_Statuslabel
19
+ extends Mage_Adminhtml_Block_System_Config_Form_Field
20
+ {
21
+
22
+ /**
23
+ * Gets a formatted message.
24
+ *
25
+ * @param string $message
26
+ * @param string $color
27
+ * @return string
28
+ */
29
+ protected function _getMessage($message, $color)
30
+ {
31
+ return sprintf('<span style="color: #%s">%s</span>', $color, $message);
32
+ }
33
+
34
+ /**
35
+ * Retrieve Element HTML
36
+ *
37
+ * @param Varien_Data_Form_Element_Abstract $element
38
+ * @return string
39
+ */
40
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
41
+ {
42
+ try {
43
+ $reachability = Mage::getModel('wallmob/api')->getReachability();
44
+ if ($reachability) {
45
+ return $this->_getMessage('Reachable', '00CD00');
46
+ } else {
47
+ return $this->_getMessage('Unreachable', 'CD0000');
48
+ }
49
+ } catch (Exception $e) {
50
+ return $this->_getMessage(sprintf('Error: %s', $e->getMessage()), 'CD0000');
51
+ }
52
+ }
53
+
54
+ }
app/code/community/Wallmob/Wallmob/Helper/Data.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Helper_Data
19
+ extends Mage_Core_Helper_Abstract
20
+ {
21
+
22
+ /**
23
+ * XML configuration constants.
24
+ */
25
+ const XML_PATH_DEBUG_MODE = 'wallmob/import_settings/debug_mode';
26
+
27
+ /**
28
+ * Cached debug mode configuration.
29
+ *
30
+ * @var null|bool
31
+ */
32
+ protected $_isDebugMode = null;
33
+
34
+ /**
35
+ * Whether or not we are running in debug mode.
36
+ *
37
+ * @return bool
38
+ */
39
+ protected function _getIsDebugMode()
40
+ {
41
+ if ($this->_isDebugMode === null) {
42
+ $this->_isDebugMode = (bool)Mage::getStoreConfig(self::XML_PATH_DEBUG_MODE);
43
+ }
44
+ return $this->_isDebugMode;
45
+ }
46
+
47
+ /**
48
+ * Logs a message to the wallmob log file.
49
+ *
50
+ * @param string $message
51
+ * @return void
52
+ */
53
+ public function logMessage($message)
54
+ {
55
+ Mage::log($message, null, 'wallmob.log', $this->_getIsDebugMode());
56
+ }
57
+
58
+ }
app/code/community/Wallmob/Wallmob/Model/Api.php ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Model_Api
19
+ {
20
+
21
+ /**
22
+ * API config nodes.
23
+ */
24
+ const XML_PATH_API_URL = 'wallmob/api_settings/url';
25
+ const XML_PATH_API_USERNAME = 'wallmob/api_settings/username';
26
+ const XML_PATH_API_PASSWORD = 'wallmob/api_settings/password';
27
+ const XML_PATH_API_STORE = 'wallmob/api_settings/store';
28
+
29
+ /**
30
+ * Cached HTTP client instance.
31
+ *
32
+ * @var null|Zend_Http_Client
33
+ */
34
+ protected $_client = null;
35
+
36
+ /**
37
+ * Returns the HTTP client.
38
+ *
39
+ * @return Zend_Http_Client
40
+ */
41
+ protected function _getClient()
42
+ {
43
+ if ($this->_client === null) {
44
+ $this->_client = new Zend_Http_Client();
45
+ $this->_client->setAuth(
46
+ Mage::getStoreConfig(self::XML_PATH_API_USERNAME),
47
+ Mage::getStoreConfig(self::XML_PATH_API_PASSWORD)
48
+ );
49
+ }
50
+ return $this->_client;
51
+ }
52
+
53
+ /**
54
+ * Gets URI for specific endpoint.
55
+ *
56
+ * @param string $endpoint
57
+ * @return string
58
+ */
59
+ protected function _getUri($endpoint)
60
+ {
61
+ return Mage::getStoreConfig(self::XML_PATH_API_URL) . $endpoint;
62
+ }
63
+
64
+ /**
65
+ * Make a GET request to a specific endpoint and return the decoded body.
66
+ *
67
+ * @param string $endpoint
68
+ * @param array $parameters
69
+ * @return array
70
+ */
71
+ protected function _get($endpoint, $parameters = array())
72
+ {
73
+ $client = $this->_getClient()->setUri($this->_getUri($endpoint));
74
+ $client->setParameterGet($parameters);
75
+ try {
76
+ $response = $client->request();
77
+ $body = json_decode($response->getBody(), true);
78
+ if (isset($body['error'])) {
79
+ Mage::throwException($body['error']);
80
+ }
81
+ return $body;
82
+ } catch (Exception $ex) {
83
+ Mage::throwException($ex->getMessage());
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Make a POST request to a specific endpoint and return the decoded body.
89
+ *
90
+ * @param string $endpoint
91
+ * @param array $parameters
92
+ * @return array
93
+ */
94
+ protected function _post($endpoint, $parameters = array())
95
+ {
96
+ $client = $this->_getClient()->setUri($this->_getUri($endpoint));
97
+ $client->setParameterPost($parameters);
98
+ $client->setMethod(Zend_Http_Client::POST);
99
+ try {
100
+ $response = $client->request();
101
+ $body = json_decode($response->getBody(), true);
102
+ if (isset($body['error'])) {
103
+ Mage::throwException(sprintf('%s (%s)', $body['error'], json_encode($body['data'])));
104
+ }
105
+ return $body;
106
+ } catch (Exception $ex) {
107
+ Mage::throwException($ex->getMessage());
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Gets changes from the API, limited by timestamp and/or excludes/includes.
113
+ *
114
+ * @param int $timestamp
115
+ * @param array $exclude
116
+ * @param array $include
117
+ * @return array
118
+ */
119
+ public function getChanges($timestamp = 0, $exclude = array(), $include = array())
120
+ {
121
+ $shop = Mage::getStoreConfig(self::XML_PATH_API_STORE);
122
+ $endpoint = $shop ? sprintf('/shops/%s/changes', $shop) : '/changes';
123
+ return $this->_get($endpoint, array(
124
+ 'from' => $timestamp,
125
+ 'exclude' => json_encode($exclude),
126
+ 'include' => json_encode($include)
127
+ ));
128
+ }
129
+
130
+ /**
131
+ * Gets the server reachability.
132
+ *
133
+ * @return int
134
+ */
135
+ public function getReachability()
136
+ {
137
+ return $this->_get('/reachability');
138
+ }
139
+
140
+ /**
141
+ * Gets shops.
142
+ *
143
+ * @return array
144
+ */
145
+ public function getShops()
146
+ {
147
+ return $this->_get('/shops');
148
+ }
149
+
150
+ /**
151
+ * Gets the current shop.
152
+ *
153
+ * @return array|false
154
+ */
155
+ public function getCurrentShop()
156
+ {
157
+ $shop = Mage::getStoreConfig(self::XML_PATH_API_STORE);
158
+ return $shop ? $this->_get(sprintf('/shops/%s', $shop)) : false;
159
+ }
160
+
161
+ /**
162
+ * Posts an order.
163
+ *
164
+ * @param array $data
165
+ * @return array
166
+ */
167
+ public function postOrder($data)
168
+ {
169
+ return $this->_post('/orders', $data);
170
+ }
171
+
172
+ }
app/code/community/Wallmob/Wallmob/Model/Import.php ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Model_Import
19
+ {
20
+
21
+ /**
22
+ * Import config nodes.
23
+ */
24
+ const XML_PATH_IMPORT_ENTITIES = 'wallmob/import_settings/entities';
25
+ const XML_PATH_IMPORT_LAST_UPDATED = 'wallmob/import_settings/last_updated';
26
+
27
+ /**
28
+ * ID used to lock the import process.
29
+ */
30
+ const PROCESS_ID = 'wallmob_import';
31
+
32
+ /**
33
+ * Cached API instance.
34
+ *
35
+ * @var null|Wallmob_Wallmob_Model_Api
36
+ */
37
+ protected $_api = null;
38
+
39
+ /**
40
+ * Cached index process.
41
+ *
42
+ * @var null|Mage_Index_Model_Process
43
+ */
44
+ protected $_indexProcess = null;
45
+
46
+ /**
47
+ * Gets the API instance.
48
+ *
49
+ * @return Wallmob_Wallmob_Model_Api
50
+ */
51
+ protected function _getApi()
52
+ {
53
+ if ($this->_api === null) {
54
+ $this->_api = Mage::getSingleton('wallmob/api');
55
+ }
56
+ return $this->_api;
57
+ }
58
+
59
+ /**
60
+ * Gets the import entities as an associative array.
61
+ *
62
+ * @return array
63
+ */
64
+ public function getEntities()
65
+ {
66
+ return (array)Mage::getStoreConfig(self::XML_PATH_IMPORT_ENTITIES);
67
+ }
68
+
69
+ /**
70
+ * Gets the index process.
71
+ *
72
+ * @return Mage_Index_Model_Process
73
+ */
74
+ protected function _getIndexProcess()
75
+ {
76
+ if ($this->_indexProcess === null) {
77
+ $this->_indexProcess = new Mage_Index_Model_Process();
78
+ $this->_indexProcess->setId(self::PROCESS_ID);
79
+ }
80
+ return $this->_indexProcess;
81
+ }
82
+
83
+ /**
84
+ * Imports all entities.
85
+ *
86
+ * @return void
87
+ */
88
+ public function importAll()
89
+ {
90
+ $helper = Mage::helper('wallmob');
91
+ if ($this->_getIndexProcess()->isLocked()) {
92
+ $helper->logMessage('Import already running, skipping.');
93
+ return;
94
+ }
95
+
96
+ // Grab changes for our entities.
97
+ $entities = $this->getEntities();
98
+ try {
99
+ $lastUpdated = Mage::getStoreConfig(self::XML_PATH_IMPORT_LAST_UPDATED);
100
+ $helper->logMessage(sprintf('Last updated: %s', date('c', $lastUpdated)));
101
+ $changes = $this->_getApi()->getChanges(
102
+ $lastUpdated,
103
+ array(),
104
+ array_keys($entities)
105
+ );
106
+ } catch (Exception $ex) {
107
+ $helper->logMessage(sprintf('Failed to get changes: %s', $ex->getMessage()));
108
+ return;
109
+ }
110
+
111
+ // Grab a timestamp before we start the import.
112
+ $time = time();
113
+
114
+ // Import data for all entities.
115
+ $this->_getIndexProcess()->lockAndBlock();
116
+ if ($changes['changes_found'] !== false) {
117
+ foreach ($entities as $type => $model) {
118
+ try {
119
+ $data = $changes[$type];
120
+ if (count($data)) {
121
+ $helper->logMessage(sprintf('Processing %d changes for %s', count($data), $type));
122
+ $processor = Mage::getModel($model);
123
+ $processor->importData($data);
124
+ }
125
+ } catch (Exception $ex) {
126
+ $helper->logMessage(sprintf('An error occurred during the import: %s', $ex->getMessage()));
127
+ $this->_getIndexProcess()->unlock();
128
+ return;
129
+ }
130
+ $helper->logMessage('Update succesfully finished.');
131
+
132
+ // But only update the timestamp when we had no errors.
133
+ $config = Mage::getConfig();
134
+ $config->saveConfig(self::XML_PATH_IMPORT_LAST_UPDATED, $time);
135
+ $config->removeCache();
136
+
137
+ // In case we're still in the same request, let's update the local cache too.
138
+ Mage::app()->getStore()->setConfig(self::XML_PATH_IMPORT_LAST_UPDATED, $time);
139
+ }
140
+ } else {
141
+ $helper->logMessage('No changes found since last update.');
142
+ }
143
+ $this->_getIndexProcess()->unlock();
144
+ }
145
+
146
+ }
app/code/community/Wallmob/Wallmob/Model/Observer.php ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Model_Observer
19
+ {
20
+
21
+ /**
22
+ * Transaction constants.
23
+ */
24
+ const WALLMOB_TRANSACTION_TYPE = 'WM_TRANSACTION_TYPE_CARD_EXTERNAL';
25
+ const WALLMOB_TRANSACTION_STATE = 'WM_TRANSACTION_STATE_CAPTURED';
26
+ const WALLMOB_USER_NAME = 'MAGENTO';
27
+
28
+ /**
29
+ * Configuration constants.
30
+ */
31
+ const XML_PATH_SEND_EMAIL = 'wallmob/order_settings/send_email';
32
+
33
+ /**
34
+ * Gets the base data for an order.
35
+ *
36
+ * @param Mage_Sales_Model_Order $order
37
+ * @param array|bool $shop
38
+ * @param string $id
39
+ * @return array
40
+ */
41
+ protected function _getBaseOrder($order, $shop, $id)
42
+ {
43
+ $data = array(
44
+ 'id' => $id,
45
+ 'user_name' => self::WALLMOB_USER_NAME,
46
+ 'customer_id' => $order->getCustomerName(),
47
+ 'shop_name' => Mage::app()->getStore()->getName(),
48
+ 'timestamp' => time()
49
+ );
50
+ if (Mage::getStoreConfig(self::XML_PATH_SEND_EMAIL)) {
51
+ $data['email'] = $order->getCustomerEmail();
52
+ }
53
+ if ($shop) {
54
+ $data['shop_id'] = $shop['id'];
55
+ }
56
+
57
+ if ($order->getDiscountAmount() > 0) {
58
+ $data['discounts'] = array(array(
59
+ 'amount' => -($order->getDiscountAmount() * 100),
60
+ 'description' => $order->getDiscountDescription()
61
+ ));
62
+ }
63
+ return $data;
64
+ }
65
+
66
+ /**
67
+ * Gets the line items for an order.
68
+ *
69
+ * @param Mage_Sales_Model_Order $order
70
+ * @param array|bool $shop
71
+ * @return array
72
+ */
73
+ protected function _getLineItems($order, $shop)
74
+ {
75
+ $lineItems = array();
76
+ foreach ($order->getAllVisibleItems() as $item) {
77
+ // Set line item defaults.
78
+ $lineItem = array(
79
+ 'product_id' => $item->getProduct()->getWallmobId(),
80
+ 'product_name' => $item->getName(),
81
+ 'sku' => $item->getSku(),
82
+ 'retail_price' => $item->getPriceInclTax() * 100,
83
+ 'total_line_amount' => $item->getRowTotalInclTax() * 100,
84
+ 'quantity' => (int)$item->getQtyOrdered()
85
+ );
86
+
87
+ // See if we need to override any settings from variants.
88
+ $childrenItems = $item->getChildrenItems();
89
+ if (count($childrenItems)) {
90
+ $variant = current($childrenItems);
91
+ $lineItem['product_variant_name'] = $variant->getName();
92
+ $lineItem['sku'] = $variant->getSku();
93
+ $lineItem['product_variant_id'] = $variant->getProduct()->getWallmobId();
94
+ }
95
+
96
+ // Copy the stock location from the current shop.
97
+ if ($shop) {
98
+ $lineItem['stock_location_id'] = $shop['stock_location_id'];
99
+ }
100
+
101
+ $lineItems[] = $lineItem;
102
+ }
103
+ return $lineItems;
104
+ }
105
+
106
+ /**
107
+ * Gets a unique guid.
108
+ *
109
+ * @return string
110
+ */
111
+ protected function _getGuid()
112
+ {
113
+ $str = md5(uniqid());
114
+ return sprintf('%s-%s-%s-%s-%s',
115
+ substr($str, 0, 8),
116
+ substr($str, 8, 4),
117
+ substr($str, 12, 4),
118
+ substr($str, 16, 4),
119
+ substr($str, 20, 12)
120
+ );
121
+ }
122
+
123
+ /**
124
+ * Gets the shipping item for an order.
125
+ *
126
+ * @param Mage_Sales_Model_Order $order
127
+ * @return array
128
+ */
129
+ protected function _getShippingItem($order)
130
+ {
131
+ return array(
132
+ 'product_name' => $order->getShippingDescription(),
133
+ 'retail_price' => $order->getShippingInclTax() * 100,
134
+ 'quantity' => 1
135
+ );
136
+ }
137
+
138
+ /**
139
+ * Gets the transaction for an order.
140
+ *
141
+ * @param Mage_Sales_Model_Order $order
142
+ * @param string $orderId
143
+ * @return array
144
+ */
145
+ protected function _getTransaction($order, $orderId)
146
+ {
147
+ return array(
148
+ 'order_id' => $orderId,
149
+ 'type' => self::WALLMOB_TRANSACTION_TYPE,
150
+ 'state' => self::WALLMOB_TRANSACTION_STATE,
151
+ 'base_currency' => $order->getBaseCurrencyCode(),
152
+ 'currency' => $order->getOrderCurrencyCode(),
153
+ 'base_currency_amount' => $order->getBaseGrandTotal() * 100,
154
+ 'currency_amount' => $order->getGrandTotal() * 100
155
+ );
156
+ }
157
+
158
+ /**
159
+ * Creates a wallmob order through the API.
160
+ *
161
+ * @param Varien_Event_Observer $observer
162
+ * @return void
163
+ */
164
+ public function createWallmobOrder($observer)
165
+ {
166
+ $helper = Mage::helper('wallmob');
167
+ try {
168
+ $order = Mage::getModel('sales/order')->load(current($observer->getOrderIds()));
169
+ $api = Mage::getSingleton('wallmob/api');
170
+ $shop = $api->getCurrentShop();
171
+
172
+ // Construct the order.
173
+ $orderId = $this->_getGuid();
174
+ $data = $this->_getBaseOrder($order, $shop, $orderId);
175
+ $data['order_line_items'] = $this->_getLineItems($order, $shop);
176
+ $data['order_line_items'][] = $this->_getShippingItem($order);
177
+ $data['transactions'][] = $this->_getTransaction($order, $orderId);
178
+
179
+ // Attempt to post it.
180
+ // $helper->logMessage(sprintf('Sending order: %s', print_r($data, true)));
181
+ $return = $api->postOrder($data);
182
+ $helper->logMessage(sprintf('Succesfully posted order: %s', $return['id']));
183
+ } catch (Exception $e) {
184
+ $helper->logMessage(sprintf('Failed to post order: %s', $e->getMessage()));
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Adds the wallmob ID attribute to the item collection.
190
+ *
191
+ * @param Varien_Event_Observer $observer
192
+ * @return void
193
+ */
194
+ public function addWallmobAttribute($observer)
195
+ {
196
+ $observer->getEvent()
197
+ ->getAttributes()
198
+ ->setData(Wallmob_Wallmob_Model_Processor_Product::ID_ATTRIBUTE_CODE, true);
199
+ }
200
+
201
+ }
app/code/community/Wallmob/Wallmob/Model/Processor/Abstract.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Model_Processor_Abstract
19
+ {
20
+
21
+ /**
22
+ * Gets the wallmob helper.
23
+ *
24
+ * @return Wallmob_Wallmob_Helper_Data
25
+ */
26
+ protected function _getHelper()
27
+ {
28
+ return Mage::helper('wallmob');
29
+ }
30
+
31
+ }
app/code/community/Wallmob/Wallmob/Model/Processor/Category.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Model_Processor_Category
19
+ extends Wallmob_Wallmob_Model_Processor_Abstract
20
+ implements Wallmob_Wallmob_Model_Processor_Interface
21
+ {
22
+
23
+ /**
24
+ * Category processor constants.
25
+ */
26
+ const ROOT_CATEGORY_NAME = 'Wallmob';
27
+ const ID_ATTRIBUTE_CODE = 'wallmob_id';
28
+
29
+ /**
30
+ * Cache wallmob category instance.
31
+ *
32
+ * @var null|Mage_Catalog_Model_Category
33
+ */
34
+ protected $_wallmobCategory = null;
35
+
36
+ /**
37
+ * Return the wallmob root category.
38
+ *
39
+ * @return Mage_Catalog_Model_Category
40
+ */
41
+ protected function _getWallmobCategory()
42
+ {
43
+ if ($this->_wallmobCategory === null) {
44
+ $categoryCollection = Mage::getModel('catalog/category')->getCollection()
45
+ ->addAttributeToSelect('*')
46
+ ->addAttributeToFilter('name', array('eq' => self::ROOT_CATEGORY_NAME))
47
+ ->addAttributeToFilter('parent_id', array('eq' => Mage_Catalog_Model_Category::TREE_ROOT_ID));
48
+ if (!$categoryCollection->count()) {
49
+ Mage::throwException('Wallmob root category did not exist.');
50
+ }
51
+ $this->_wallmobCategory = $categoryCollection->getFirstItem();
52
+ }
53
+ return $this->_wallmobCategory;
54
+ }
55
+
56
+ /**
57
+ * Imports a category.
58
+ *
59
+ * @param array $data
60
+ * @return void
61
+ */
62
+ protected function _importCategory($data)
63
+ {
64
+ // Get our parent category.
65
+ if ($data['parent_id'] !== null) {
66
+ $parentCategory = Mage::getModel('catalog/category')->loadByAttribute(self::ID_ATTRIBUTE_CODE, $data['parent_id']);
67
+ if ($parentCategory === false) {
68
+ Mage::throwException('Attempted to import into a non-existent parent.');
69
+ }
70
+ } else {
71
+ $parentCategory = $this->_getWallmobCategory();
72
+ }
73
+
74
+ // If the category already exists, grab it. Otherwise create a new one.
75
+ $helper = $this->_getHelper();
76
+ $category = Mage::getModel('catalog/category')->loadByAttribute(self::ID_ATTRIBUTE_CODE, $data['id']);
77
+ if ($category === false) {
78
+ $helper->logMessage(sprintf('Category does not exist yet, creating...'));
79
+ $category = Mage::getModel('catalog/category');
80
+ } else {
81
+ $helper->logMessage('Updating category...');
82
+ }
83
+
84
+ if (isset($data['deleted'])) {
85
+ // Delete the category.
86
+ $helper->logMessage(sprintf('Deleting category: %s', $data['id']));
87
+ $category->delete();
88
+ } else {
89
+ // Save the category.
90
+ $helper->logMessage(sprintf('Saving category: %s (parent: %s)', $data['name'], $parentCategory->getName()));
91
+ $category->addData(array(
92
+ 'wallmob_id' => $data['id'],
93
+ 'name' => $data['name'],
94
+ 'store_id' => Mage_Core_Model_App::ADMIN_STORE_ID,
95
+ 'parent_id' => $parentCategory->getId(),
96
+ 'attribute_set_id' => $category->getDefaultAttributeSetId(),
97
+ 'is_active' => true
98
+ ));
99
+ if (!$category->getPath()) {
100
+ $category->setPath($parentCategory->getPath());
101
+ }
102
+ $category->save();
103
+
104
+ // We need to specifically move it, Magento doesn't do that when we update parent id.
105
+ $category->move($parentCategory->getId(), null);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Import categories based on their hierarchical tree.
111
+ *
112
+ * @param array $tree
113
+ * @param string $root
114
+ * @return void
115
+ */
116
+ protected function _importCategories(&$tree, $root = null)
117
+ {
118
+ foreach ($tree as $child => $data) {
119
+ if ($data['parent_id'] == $root) {
120
+ $this->_importCategory($data);
121
+ unset($tree[$child]);
122
+ $this->_importCategories($tree, $data['id']);
123
+ }
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Imports categories.
129
+ *
130
+ * @param array $data
131
+ * @return void
132
+ */
133
+ public function importData($data)
134
+ {
135
+ // First base it on hierarchy.
136
+ $this->_importCategories($data);
137
+
138
+ // Then import what's left on top level (no relationship found).
139
+ // We assume this is an update and the parent hasn't updated.
140
+ foreach ($data as $category) {
141
+ $this->_importCategory($category);
142
+ }
143
+ }
144
+
145
+ }
app/code/community/Wallmob/Wallmob/Model/Processor/Interface.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ interface Wallmob_Wallmob_Model_Processor_Interface
19
+ {
20
+
21
+ /**
22
+ * Imports data for the specific entity.
23
+ * Error messages must be thrown as exceptions.
24
+ *
25
+ * @return void
26
+ */
27
+ public function importData($data);
28
+
29
+ }
app/code/community/Wallmob/Wallmob/Model/Processor/Product.php ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Model_Processor_Product
19
+ extends Wallmob_Wallmob_Model_Processor_Abstract
20
+ implements Wallmob_Wallmob_Model_Processor_Interface
21
+ {
22
+
23
+ /**
24
+ * Product processor constants.
25
+ */
26
+ const ID_ATTRIBUTE_CODE = 'wallmob_id';
27
+
28
+ /**
29
+ * Product processor config nodes.
30
+ */
31
+ const XML_PATH_DEFAULT_TAX_CLASS = 'wallmob/import_settings/default_tax_class';
32
+ const XML_PATH_ASSIGN_TO_WEBSITES = 'wallmob/import_settings/assign_to_websites';
33
+
34
+ /**
35
+ * Cached taxclass configuration value.
36
+ *
37
+ * @var null|int
38
+ */
39
+ protected $_defaultTaxClass = null;
40
+
41
+ /**
42
+ * Cached assign to websites configuration value.
43
+ *
44
+ * @var null|array
45
+ */
46
+ protected $_assignToWebsites = null;
47
+
48
+ /**
49
+ * Cached default attribute set id value.
50
+ *
51
+ * @var null|int
52
+ */
53
+ protected $_defaultAttributeSetId = null;
54
+
55
+ /**
56
+ * Gets the default attribute set ID.
57
+ *
58
+ * @return int
59
+ */
60
+ protected function _getDefaultAttributeSetId()
61
+ {
62
+ if ($this->_defaultAttributeSetId === null) {
63
+ $this->_defaultAttributeSetId = Mage::getModel('catalog/product')->getDefaultAttributeSetId();
64
+ }
65
+ return $this->_defaultAttributeSetId;
66
+ }
67
+
68
+ /**
69
+ * Gets the default tax class from config.
70
+ *
71
+ * @return int
72
+ */
73
+ protected function _getDefaultTaxClass()
74
+ {
75
+ if ($this->_defaultTaxClass === null) {
76
+ $this->_defaultTaxClass = (int)Mage::getStoreConfig(self::XML_PATH_DEFAULT_TAX_CLASS);
77
+ }
78
+ return $this->_defaultTaxClass;
79
+ }
80
+
81
+ /**
82
+ * Returns the sites we assign to the product from config.
83
+ *
84
+ * @return array
85
+ */
86
+ protected function _getAssignToWebsites()
87
+ {
88
+ if ($this->_assignToWebsites === null) {
89
+ $allWebsites = array_keys(Mage::app()->getWebsites());
90
+ $selectedWebsites = Mage::getStoreConfig(self::XML_PATH_ASSIGN_TO_WEBSITES);
91
+ if (!empty($selectedWebsites)) {
92
+ $this->_assignToWebsites = array_intersect(explode(',', $selectedWebsites), $allWebsites);
93
+ } else {
94
+ $this->_assignToWebsites = $allWebsites;
95
+ }
96
+ }
97
+ return $this->_assignToWebsites;
98
+ }
99
+
100
+ /**
101
+ * Loads and optionally creates a product from sku.
102
+ *
103
+ * @param string $sku
104
+ * @param int $productType
105
+ * @return Mage_Catalog_Model_Product
106
+ */
107
+ protected function _getProductFromSku($sku, $productType)
108
+ {
109
+ $helper = $this->_getHelper();
110
+ $product = Mage::getModel('catalog/product');
111
+ $productId = $product->getIdBySku($sku);
112
+ if (!$productId) {
113
+ $helper->logMessage(sprintf('Product does not exist yet, creating...'));
114
+ } else {
115
+ $product->load($productId);
116
+ if ($product->getTypeId() != $productType) {
117
+ $helper->logMessage('Product already exists but of wrong type, deleting original...');
118
+ $product->delete();
119
+ } else {
120
+ $helper->logMessage('Updating product.');
121
+ }
122
+ }
123
+ return $product;
124
+ }
125
+
126
+ /**
127
+ * Get a product with base fields filled.
128
+ *
129
+ * @param array $data
130
+ * @param string $name
131
+ * @param string $productType
132
+ * @param int $visibility
133
+ * @param float $price
134
+ * @return Mage_Catalog_Model_Product
135
+ */
136
+ protected function _getBaseProduct($data, $name, $productType, $visibility, $price)
137
+ {
138
+ $product = $this->_getProductFromSku($data['sku'], $productType);
139
+ $product->addData(array(
140
+ 'name' => $name,
141
+ 'type_id' => $productType,
142
+ 'visibility' => $visibility,
143
+ 'sku' => $data['sku'],
144
+ 'wallmob_id' => $data['id'],
145
+ 'is_active' => isset($data['active']) ? $data['active'] : 1,
146
+ 'attribute_set_id' => $this->_getDefaultAttributeSetId(),
147
+ 'website_ids' => $this->_getAssignToWebsites(),
148
+ 'status' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED,
149
+ 'price' => $price,
150
+ 'tax_class_id' => $this->_getDefaultTaxClass()
151
+ ));
152
+ return $product;
153
+ }
154
+
155
+ /**
156
+ * Gets the variant URL key.
157
+ *
158
+ * @param string $parentName
159
+ * @param string $variantName
160
+ * @return string
161
+ */
162
+ protected function _getVariantUrlKey($parentName, $variantName)
163
+ {
164
+ $urlKey = strtolower($parentName . ' ' . $variantName);
165
+ $urlKey = preg_replace('/[^[:print:]]/', '', $urlKey);
166
+ $urlKey = str_replace(' ', ' ', $urlKey);
167
+ $urlKey = str_replace(' ', '-', $urlKey);
168
+ return $urlKey;
169
+ }
170
+
171
+ /**
172
+ * Imports variants, returns their product IDs.
173
+ *
174
+ * @param array $variants
175
+ * @param float $basePrice
176
+ * @return array
177
+ */
178
+ protected function _importVariants($variants, $basePrice, $parentName)
179
+ {
180
+ $productIds = array();
181
+ foreach ($variants as $variant) {
182
+ $this->_getHelper()->logMessage(sprintf('Processing variant: %s', $variant['product_variant_name']));
183
+
184
+ // If we can't find a price for this child, assume it's the same as parent.
185
+ $childPrice = $variant['product_data'][0]['retail_price'];
186
+ if (!is_numeric($childPrice) || $childPrice == 0) {
187
+ $childPrice = $basePrice;
188
+ } else {
189
+ $childPrice /= 100;
190
+ }
191
+
192
+ // Get child base product.
193
+ $childProduct = $this->_getBaseProduct(
194
+ $variant,
195
+ $variant['product_variant_name'],
196
+ 'simple',
197
+ Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE,
198
+ $childPrice
199
+ );
200
+
201
+ // Set a specific URL path to avoid duplicates.
202
+ $childProduct->setUrlKey($this->_getVariantUrlKey($parentName, $variant['product_variant_name']));
203
+
204
+ // Save the child product.
205
+ $childProduct->save();
206
+ $productIds[] = $childProduct->getId();
207
+ }
208
+ return $productIds;
209
+ }
210
+
211
+ /**
212
+ * Assign categories to the product.
213
+ *
214
+ * @param Mage_Catalog_Model_Product $product
215
+ * @param array $categories
216
+ * @return void
217
+ */
218
+ protected function _assignCategories($product, $categories)
219
+ {
220
+ $categoryCollection = Mage::getModel('catalog/category')->getCollection()
221
+ ->addAttributeToSelect('*')
222
+ ->addFieldToFilter(
223
+ Wallmob_Wallmob_Model_Processor_Category::ID_ATTRIBUTE_CODE,
224
+ array('in' => $categories)
225
+ );
226
+ if ($categoryCollection->count()) {
227
+ $categoryIds = $categoryCollection->getColumnValues('entity_id');
228
+ $this->_getHelper()->logMessage(sprintf('Assigning product to %d categories.', count($categoryIds)));
229
+ $product->setCategoryIds($categoryIds);
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Assign image to the product.
235
+ *
236
+ * @param Mage_Catalog_Model_Product $product
237
+ * @param string $image
238
+ * @return void
239
+ */
240
+ protected function _assignImage($product, $image)
241
+ {
242
+ $helper = $this->_getHelper();
243
+ $helper->logMessage(sprintf('Downloading asset: %s', $image));
244
+ $filePath = $this->_getImportDirectory() . DS . end(explode('/', $image));
245
+ file_put_contents($filePath, file_get_contents($image));
246
+ if (!file_exists($filePath)) {
247
+ $helper->logMessage('Was unable to download asset.');
248
+ } else {
249
+ $helper->logMessage('Assigning asset to product.');
250
+ $product->addImageToMediaGallery($filePath, array('thumbnail', 'small_image', 'image'));
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Get import directory and create it when it doesn't exist.
256
+ *
257
+ * @return string
258
+ */
259
+ protected function _getImportDirectory()
260
+ {
261
+ $directory = Mage::getBaseDir('media') . DS . 'import';
262
+ if (!is_dir($directory)) {
263
+ @mkdir($directory);
264
+ }
265
+ return $directory;
266
+ }
267
+
268
+ /**
269
+ * Insert variant relations.
270
+ *
271
+ * @param Mage_Catalog_Model_Product $product
272
+ * @param array $variantProductIds
273
+ */
274
+ protected function _insertVariantRelations($product, $variantProductIds)
275
+ {
276
+ // If we're updating, delete existing options.
277
+ if ($product->getId()) {
278
+ Mage::getModel('bundle/option')->getCollection()
279
+ ->addFieldToFilter('parent_id', array('eq' => $product->getId()))
280
+ ->walk('delete');
281
+ }
282
+
283
+ // Create variant option.
284
+ $product->setBundleOptionsData(array(array(
285
+ 'title' => 'Select option',
286
+ 'type' => 'select',
287
+ 'required' => 1,
288
+ 'position' => 0,
289
+ 'delete' => false
290
+ )));
291
+
292
+ // Create variant selections.
293
+ $position = 0;
294
+ $selections = array();
295
+ foreach ($variantProductIds as $variantProductId) {
296
+ $selections[] = array(
297
+ 'product_id' => $variantProductId,
298
+ 'is_default' => false,
299
+ 'delete' => false,
300
+ 'selection_qty' => 1,
301
+ 'position' => $position++
302
+ );
303
+ }
304
+
305
+ // Make sure our variants get saved.
306
+ $product->setPriceType(Mage_Bundle_Model_Product_Price::PRICE_TYPE_DYNAMIC);
307
+ $product->setBundleSelectionsData(array($selections));
308
+ $product->setCanSaveBundleSelections(true);
309
+ }
310
+
311
+ /**
312
+ * Deletes a product and optionally its variants.
313
+ *
314
+ * @param array $data
315
+ * @return void
316
+ */
317
+ protected function _deleteProduct($data)
318
+ {
319
+ $helper = $this->_getHelper();
320
+ $product = Mage::getModel('catalog/product')->loadByAttribute(self::ID_ATTRIBUTE_CODE, $data['id']);
321
+ if (!$product) {
322
+ $helper->logMessage(sprintf('Attempted to delete product that does not exist: %s', $data['id']));
323
+ return;
324
+ }
325
+
326
+ // If we're a bundle, delete our variants.
327
+ if ($product->getTypeId() == 'bundle') {
328
+ $selectionCollection = $product->getTypeInstance(true)->getSelectionsCollection(
329
+ $product->getTypeInstance(true)->getOptionsIds($product), $product
330
+ );
331
+ foreach ($selectionCollection as $option) {
332
+ $variant = Mage::getModel('catalog/product')->load($option->getProductId());
333
+ if ($variant->getId()) {
334
+ $helper->logMessage(sprintf('Deleting variant: %s', $variant->getName()));
335
+ $variant->delete();
336
+ }
337
+ }
338
+ }
339
+ $helper->logMessage(sprintf('Deleting product: %s', $product->getName()));
340
+ $product->delete();
341
+ }
342
+
343
+ /**
344
+ * Imports a single product.
345
+ *
346
+ * @param array $data
347
+ * @return void
348
+ */
349
+ protected function _importProduct($data)
350
+ {
351
+ $this->_getHelper()->logMessage(sprintf('Processing product: %s', $data['id']));
352
+
353
+ // If a product has variants, it's a bundle.
354
+ $productType = count($data['product_variants']) ? 'bundle' : 'simple';
355
+
356
+ // For now it's safe to just grab the first product data node.
357
+ $productPrice = $data['product_data'][0]['retail_price'] / 100;
358
+
359
+ if (isset($data['deleted'])) {
360
+ $this->_deleteProduct($data);
361
+ return;
362
+ }
363
+
364
+ // Get parent base product.
365
+ $parentProduct = $this->_getBaseProduct(
366
+ $data,
367
+ $data['name'],
368
+ $productType,
369
+ Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
370
+ $productPrice
371
+ );
372
+
373
+ // We need to register the product for bundle saves.
374
+ Mage::register('product', $parentProduct);
375
+
376
+ // Assign to categories.
377
+ if (count($data['product_categories'])) {
378
+ $this->_assignCategories($parentProduct, $data['product_categories']);
379
+ }
380
+
381
+ // Import images.
382
+ if (isset($data['image'])) {
383
+ $this->_assignImage($parentProduct, $data['image']);
384
+ }
385
+
386
+ // Create and assign variants.
387
+ if ($productType == 'bundle') {
388
+ $variantProductIds = $this->_importVariants($data['product_variants'], $productPrice, $data['name']);
389
+ $this->_insertVariantRelations($parentProduct, $variantProductIds);
390
+ }
391
+ $parentProduct->save();
392
+
393
+ // Unregister it for next iteration.
394
+ Mage::unregister('product');
395
+ }
396
+
397
+ /**
398
+ * Imports products.
399
+ *
400
+ * @param array $data
401
+ * @return void
402
+ */
403
+ public function importData($data)
404
+ {
405
+ foreach ($data as $product) {
406
+ $this->_importProduct($product);
407
+ }
408
+
409
+ // Forcibly clear the block cache.
410
+ Mage::app()->getCacheInstance()->cleanType(Mage_Core_Block_Abstract::CACHE_GROUP);
411
+ }
412
+
413
+ }
app/code/community/Wallmob/Wallmob/Model/Processor/Stock.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Model_Processor_Stock
19
+ extends Wallmob_Wallmob_Model_Processor_Abstract
20
+ implements Wallmob_Wallmob_Model_Processor_Interface
21
+ {
22
+
23
+ /**
24
+ * Determines if any of the bundle's variants is in stock.
25
+ *
26
+ * @param Mage_Catalog_Model_Product $productIds
27
+ * @return boolean
28
+ */
29
+ protected function _anyProductInStock($product)
30
+ {
31
+ // Get all variants from this bundle.
32
+ $productIds = $product->getTypeInstance()->getSelectionsCollection(
33
+ $product->getTypeInstance()->getOptionsCollection($product)->getAllIds(), $product
34
+ )->getColumnValues('product_id');
35
+
36
+ // Then if any of them have stock, the bundle is in stock too.
37
+ $stockItemCollection = Mage::getModel('cataloginventory/stock_item')->getCollection()
38
+ ->addProductsFilter($productIds);
39
+ foreach ($stockItemCollection as $stockItem) {
40
+ if ((int)$stockItem->getQty() > 0) return true;
41
+ }
42
+ return false;
43
+ }
44
+
45
+ /**
46
+ * Updates stock for the parents of specified variants.
47
+ *
48
+ * @param array $stockData
49
+ * @return Wallmob_Wallmob_Model_Processor_Stock
50
+ */
51
+ protected function _updateBundleStock($stockData)
52
+ {
53
+ // Grab all variant product IDs.
54
+ $variantIds = $this->_getProductCollectionFromWallmobIds(array_keys($stockData))
55
+ ->getColumnValues('entity_id');
56
+
57
+ // Then use them to get our parent products.
58
+ $bundleCollection = Mage::getModel('catalog/product')->getCollection()
59
+ ->addAttributeToSelect('*')
60
+ ->addFieldToFilter('entity_id', array('in' =>
61
+ array_unique(Mage::getResourceSingleton('bundle/selection')->getParentIdsByChild($variantIds))
62
+ ));
63
+
64
+ // If we're salable, we're in stock.
65
+ $this->_getHelper()->logMessage(sprintf('Updating %d bundle stock status.', $bundleCollection->count()));
66
+ foreach ($bundleCollection as $bundle) {
67
+ $this->_updateStock($bundle->getId(), (int)$this->_anyProductInStock($bundle));
68
+ }
69
+ return $this;
70
+ }
71
+
72
+ /**
73
+ * Updates normal product stock.
74
+ *
75
+ * @param array $stockData
76
+ * @return Wallmob_Wallmob_Model_Processor_Stock
77
+ */
78
+ protected function _updateProductStock($stockData)
79
+ {
80
+ $productCollection = $this->_getProductCollectionFromWallmobIds(array_keys($stockData));
81
+ $this->_getHelper()->logMessage(sprintf('Found %d products that can be updated.', $productCollection->count()));
82
+ foreach ($productCollection as $_product) {
83
+ $productId = $_product->getData(Wallmob_Wallmob_Model_Processor_Product::ID_ATTRIBUTE_CODE);
84
+ if (isset($stockData[$productId])) {
85
+ $this->_updateStock($_product->getId(), $stockData[$productId]);
86
+ }
87
+ }
88
+ return $this;
89
+ }
90
+
91
+ /**
92
+ * Gets a Magento product collection from wallmob product IDs.
93
+ *
94
+ * @param array $wallmobIds
95
+ * @return Mage_Catalog_Model_Resource_Collection
96
+ */
97
+ protected function _getProductCollectionFromWallmobIds($wallmobIds)
98
+ {
99
+ return Mage::getModel('catalog/product')->getCollection()
100
+ ->addAttributeToSelect('*')
101
+ ->addFieldToFilter(Wallmob_Wallmob_Model_Processor_Product::ID_ATTRIBUTE_CODE, array(
102
+ 'in' => $wallmobIds
103
+ ));
104
+ }
105
+
106
+ /**
107
+ * Updates stock for a specified product ID.
108
+ *
109
+ * @param int $productId
110
+ * @param int $qty
111
+ * @return Wallmob_Wallmob_Model_Processor_Stock
112
+ */
113
+ protected function _updateStock($productId, $qty)
114
+ {
115
+ $product = Mage::getModel('catalog/product')->load($productId);
116
+ if ($product->getId()) {
117
+ $this->_getHelper()->logMessage(sprintf('Updating inventory: %s -> %s', $product->getName(), $qty));
118
+ $product->setStockData(array(
119
+ 'is_in_stock' => $qty > 0,
120
+ 'manage_stock' => 1,
121
+ 'qty' => $qty
122
+ ));
123
+ $product->save();
124
+ }
125
+ return $this;
126
+ }
127
+
128
+ /**
129
+ * Import stock data.
130
+ *
131
+ * @param array $data
132
+ * @return void
133
+ */
134
+ public function importData($data)
135
+ {
136
+ $this->_getHelper()->logMessage(sprintf('Updating stock for %d products.', count($data)));
137
+
138
+ // Make stock data digestible.
139
+ $stockUpdates = array();
140
+ $variantUpdates = array();
141
+ foreach ($data as $stock) {
142
+ if (isset($stock['product_variant_id'])) {
143
+ $stockUpdates[$stock['product_variant_id']] = $stock['quantity'];
144
+ $variantUpdates[$stock['product_variant_id']] = $stock['quantity'];
145
+ }
146
+ if (isset($stock['product_id'])) {
147
+ $stockUpdates[$stock['product_id']] = $stock['quantity'];
148
+ }
149
+ }
150
+
151
+ // Update normal product stock.
152
+ $this->_updateProductStock($stockUpdates);
153
+
154
+ // Update bundle stock.
155
+ $this->_updateBundleStock($variantUpdates);
156
+ }
157
+
158
+ }
app/code/community/Wallmob/Wallmob/Model/Processor/Vat.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Model_Processor_Vat
19
+ extends Wallmob_Wallmob_Model_Processor_Abstract
20
+ implements Wallmob_Wallmob_Model_Processor_Interface
21
+ {
22
+
23
+ /**
24
+ * Imports vat rates.
25
+ *
26
+ * @param array $data
27
+ * @return void
28
+ */
29
+ public function importData($data)
30
+ {
31
+ $helper = $this->_getHelper();
32
+ $helper->logMessage(sprintf('Processing %d VAT rates.', count($data)));
33
+ $helper->logMessage('VAT import is not implemented yet.');
34
+ }
35
+
36
+ }
app/code/community/Wallmob/Wallmob/Model/System/Config/Source/Wallmob/Store.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Model_System_Config_Source_Wallmob_Store
19
+ {
20
+
21
+ /**
22
+ * Returns an array of wallmob shops.
23
+ *
24
+ * @return array
25
+ */
26
+ public function toOptionArray()
27
+ {
28
+ $stops = array();
29
+ try {
30
+ $shops = Mage::getModel('wallmob/api')->getShops();
31
+ } catch (Exception $e) {}
32
+ $options = array();
33
+ $options[] = array('label' => 'All shops', 'value' => 0);
34
+ foreach ($shops as $shop) {
35
+ $options[] = array(
36
+ 'label' => $shop['name'],
37
+ 'value' => $shop['id']
38
+ );
39
+ }
40
+ return $options;
41
+ }
42
+
43
+ }
app/code/community/Wallmob/Wallmob/controllers/Adminhtml/WallmobController.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Wallmob_Wallmob_Adminhtml_WallmobController
19
+ extends Mage_Adminhtml_Controller_Action
20
+ {
21
+
22
+ /**
23
+ * Resets the last updated timer.
24
+ *
25
+ * @return void
26
+ */
27
+ public function resetAction()
28
+ {
29
+ $config = Mage::getConfig();
30
+ $config->saveConfig(Wallmob_Wallmob_Model_Import::XML_PATH_IMPORT_LAST_UPDATED, 0);
31
+ $config->removeCache();
32
+ Mage::getSingleton('core/session')->addSuccess('Succesfully updated import timer.');
33
+ $this->getResponse()->setRedirect($this->_getRefererUrl());
34
+ }
35
+
36
+ }
app/code/community/Wallmob/Wallmob/data/wallmob_setup/data-install-0.1.0.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /* @var $installer Mage_Catalog_Model_Resource_Setup */
19
+ $installer = $this;
20
+ $installer->startSetup();
21
+
22
+ // Fake an admin environment.
23
+ $currentStoreId = Mage::app()->getStore()->getId();
24
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
25
+
26
+ // Create the wallmob root category.
27
+ $category = Mage::getModel('catalog/category');
28
+ $category
29
+ ->setStoreId(Mage_Core_Model_App::ADMIN_STORE_ID)
30
+ ->setName(Wallmob_Wallmob_Model_Processor_Category::ROOT_CATEGORY_NAME)
31
+ ->setParentId(Mage_Catalog_Model_Category::TREE_ROOT_ID)
32
+ ->setPath(Mage_Catalog_Model_Category::TREE_ROOT_ID)
33
+ ->setAttributeSetId($category->getDefaultAttributeSetId())
34
+ ->setIsActive(true)
35
+ ->save();
36
+
37
+ // Restore the original store.
38
+ Mage::app()->setCurrentStore($currentStoreId);
39
+
40
+ $installer->endSetup();
app/code/community/Wallmob/Wallmob/data/wallmob_setup/data-upgrade-0.1.0-0.1.1.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /* @var $installer Mage_Catalog_Model_Resource_Setup */
19
+ $installer = $this;
20
+ $installer->startSetup();
21
+
22
+ // Add the wallmob category ID attribute.
23
+ $installer->addAttribute(
24
+ 'catalog_category',
25
+ Wallmob_Wallmob_Model_Processor_Category::ID_ATTRIBUTE_CODE,
26
+ array(
27
+ 'visible' => 0,
28
+ 'required' => 0,
29
+ 'user_defined' => 1
30
+ )
31
+ );
32
+
33
+ $installer->endSetup();
app/code/community/Wallmob/Wallmob/data/wallmob_setup/data-upgrade-0.1.1-0.1.2.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Daniel Sloof <daniel@rubic.nl>
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /* @var $installer Mage_Catalog_Model_Resource_Setup */
19
+ $installer = $this;
20
+ $installer->startSetup();
21
+
22
+ // Add the wallmob ID attribute.
23
+ $installer->addAttribute(
24
+ 'catalog_product',
25
+ Wallmob_Wallmob_Model_Processor_Product::ID_ATTRIBUTE_CODE,
26
+ array(
27
+ 'group' => 'General',
28
+ 'label' => 'Wallmob ID',
29
+ 'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
30
+ 'required' => false,
31
+ 'input' => 'text',
32
+ 'user_defined' => true
33
+ )
34
+ );
35
+
36
+ $installer->endSetup();
app/code/community/Wallmob/Wallmob/etc/adminhtml.xml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <acl>
4
+ <resources>
5
+ <admin>
6
+ <children>
7
+ <system>
8
+ <children>
9
+ <config>
10
+ <children>
11
+ <wallmob translate="title" module="wallmob">
12
+ <title>Wallmob Settings Section</title>
13
+ </wallmob>
14
+ </children>
15
+ </config>
16
+ </children>
17
+ </system>
18
+ </children>
19
+ </admin>
20
+ </resources>
21
+ </acl>
22
+ </config>
app/code/community/Wallmob/Wallmob/etc/config.xml ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <modules>
4
+ <Wallmob_Wallmob>
5
+ <version>0.1.2</version>
6
+ </Wallmob_Wallmob>
7
+ </modules>
8
+ <global>
9
+ <models>
10
+ <wallmob>
11
+ <class>Wallmob_Wallmob_Model</class>
12
+ </wallmob>
13
+ </models>
14
+ <helpers>
15
+ <wallmob>
16
+ <class>Wallmob_Wallmob_Helper</class>
17
+ </wallmob>
18
+ </helpers>
19
+ <blocks>
20
+ <wallmob>
21
+ <class>Wallmob_Wallmob_Block</class>
22
+ </wallmob>
23
+ </blocks>
24
+ <resources>
25
+ <wallmob_setup>
26
+ <setup>
27
+ <module>Wallmob_Wallmob</module>
28
+ <class>Mage_Catalog_Model_Resource_Setup</class>
29
+ </setup>
30
+ </wallmob_setup>
31
+ </resources>
32
+ <events>
33
+ <checkout_onepage_controller_success_action>
34
+ <observers>
35
+ <create_wallmob_order>
36
+ <type>singleton</type>
37
+ <class>wallmob/observer</class>
38
+ <method>createWallmobOrder</method>
39
+ </create_wallmob_order>
40
+ </observers>
41
+ </checkout_onepage_controller_success_action>
42
+ <sales_quote_config_get_product_attributes>
43
+ <observers>
44
+ <add_wallmob_attribute>
45
+ <type>singleton</type>
46
+ <class>wallmob/observer</class>
47
+ <method>addWallmobAttribute</method>
48
+ </add_wallmob_attribute>
49
+ </observers>
50
+ </sales_quote_config_get_product_attributes>
51
+ </events>
52
+ </global>
53
+ <admin>
54
+ <routers>
55
+ <adminhtml>
56
+ <args>
57
+ <modules>
58
+ <wallmob before="Mage_Adminhtml">Wallmob_Wallmob_Adminhtml</wallmob>
59
+ </modules>
60
+ </args>
61
+ </adminhtml>
62
+ </routers>
63
+ </admin>
64
+ <default>
65
+ <wallmob>
66
+ <api_settings>
67
+ <url>https://www.wallmob.com/api_v2/</url>
68
+ <username></username>
69
+ <password></password>
70
+ <store>0</store>
71
+ </api_settings>
72
+ <import_settings>
73
+ <entities>
74
+ <vat_rates>wallmob/processor_vat</vat_rates>
75
+ <product_categories>wallmob/processor_category</product_categories>
76
+ <products>wallmob/processor_product</products>
77
+ <stock_values>wallmob/processor_stock</stock_values>
78
+ </entities>
79
+ <default_tax_class>0</default_tax_class>
80
+ <last_updated>0</last_updated>
81
+ <debug_mode>0</debug_mode>
82
+ </import_settings>
83
+ <order_settings>
84
+ <send_email>0</send_email>
85
+ </order_settings>
86
+ </wallmob>
87
+ </default>
88
+ <crontab>
89
+ <jobs>
90
+ <wallmob_import_all>
91
+ <schedule>
92
+ <cron_expr>* * * * *</cron_expr>
93
+ </schedule>
94
+ <run>
95
+ <model>wallmob/import::importAll</model>
96
+ </run>
97
+ </wallmob_import_all>
98
+ </jobs>
99
+ </crontab>
100
+ </config>
app/code/community/Wallmob/Wallmob/etc/system.xml ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <sections>
4
+ <wallmob translate="label" module="wallmob">
5
+ <label>Wallmob</label>
6
+ <tab>service</tab>
7
+ <frontend_type>text</frontend_type>
8
+ <sort_order>500</sort_order>
9
+ <show_in_default>1</show_in_default>
10
+ <show_in_website>1</show_in_website>
11
+ <show_in_store>1</show_in_store>
12
+ <groups>
13
+ <api_settings translate="label">
14
+ <label>API Settings</label>
15
+ <frontend_type>text</frontend_type>
16
+ <sort_order>100</sort_order>
17
+ <show_in_default>1</show_in_default>
18
+ <show_in_website>0</show_in_website>
19
+ <show_in_store>0</show_in_store>
20
+ <fields>
21
+ <status translate="label">
22
+ <label>API Status</label>
23
+ <frontend_type>label</frontend_type>
24
+ <frontend_model>wallmob/adminhtml_statuslabel</frontend_model>
25
+ <comment>Determines whether or not the API is reachable. This does not imply that your credentials are correct.</comment>
26
+ <sort_order>5</sort_order>
27
+ <show_in_default>1</show_in_default>
28
+ <show_in_website>0</show_in_website>
29
+ <show_in_store>0</show_in_store>
30
+ </status>
31
+ <url translate="label">
32
+ <label>URL</label>
33
+ <frontend_type>text</frontend_type>
34
+ <sort_order>10</sort_order>
35
+ <show_in_default>1</show_in_default>
36
+ <show_in_website>0</show_in_website>
37
+ <show_in_store>0</show_in_store>
38
+ </url>
39
+ <username translate="label">
40
+ <label>Username</label>
41
+ <frontend_type>text</frontend_type>
42
+ <sort_order>20</sort_order>
43
+ <show_in_default>1</show_in_default>
44
+ <show_in_website>0</show_in_website>
45
+ <show_in_store>0</show_in_store>
46
+ </username>
47
+ <password translate="label">
48
+ <label>Password</label>
49
+ <frontend_type>text</frontend_type>
50
+ <sort_order>30</sort_order>
51
+ <show_in_default>1</show_in_default>
52
+ <show_in_website>0</show_in_website>
53
+ <show_in_store>0</show_in_store>
54
+ </password>
55
+ <store translate="label">
56
+ <label>Store</label>
57
+ <frontend_type>select</frontend_type>
58
+ <comment>If no store is selected, will get changes for all stores. This means the import will use the first store for its prices.</comment>
59
+ <source_model>wallmob/system_config_source_wallmob_store</source_model>
60
+ <sort_order>40</sort_order>
61
+ <show_in_default>1</show_in_default>
62
+ <show_in_website>0</show_in_website>
63
+ <show_in_store>0</show_in_store>
64
+ </store>
65
+ </fields>
66
+ </api_settings>
67
+ <import_settings translate="label">
68
+ <label>Import Settings</label>
69
+ <frontend_type>text</frontend_type>
70
+ <sort_order>200</sort_order>
71
+ <show_in_default>1</show_in_default>
72
+ <show_in_website>0</show_in_website>
73
+ <show_in_store>0</show_in_store>
74
+ <fields>
75
+ <last_updated translate="label">
76
+ <label>Last Update Finished At</label>
77
+ <frontend_type>label</frontend_type>
78
+ <frontend_model>wallmob/adminhtml_datetimelabel</frontend_model>
79
+ <sort_order>10</sort_order>
80
+ <show_in_default>1</show_in_default>
81
+ <show_in_website>0</show_in_website>
82
+ <show_in_store>0</show_in_store>
83
+ </last_updated>
84
+ <last_scheduled translate="label">
85
+ <label>Next Update Scheduled For</label>
86
+ <frontend_type>label</frontend_type>
87
+ <frontend_model>wallmob/adminhtml_scheduledlabel</frontend_model>
88
+ <sort_order>10</sort_order>
89
+ <show_in_default>1</show_in_default>
90
+ <show_in_website>0</show_in_website>
91
+ <show_in_store>0</show_in_store>
92
+ </last_scheduled>
93
+ <run translate="label">
94
+ <label>Force Full Update</label>
95
+ <frontend_type>button</frontend_type>
96
+ <frontend_model>wallmob/adminhtml_resetbutton</frontend_model>
97
+ <comment>Will cause all product changes to be updated on the next import run.</comment>
98
+ <sort_order>20</sort_order>
99
+ <show_in_default>1</show_in_default>
100
+ <show_in_website>0</show_in_website>
101
+ <show_in_store>0</show_in_store>
102
+ </run>
103
+ <default_tax_class translate="label">
104
+ <label>Default Product Tax Class</label>
105
+ <frontend_type>select</frontend_type>
106
+ <source_model>tax/class_source_product</source_model>
107
+ <sort_order>30</sort_order>
108
+ <show_in_default>1</show_in_default>
109
+ <show_in_website>0</show_in_website>
110
+ <show_in_store>0</show_in_store>
111
+ </default_tax_class>
112
+ <assign_to_websites translate="label">
113
+ <label>Assign to Websites</label>
114
+ <frontend_type>multiselect</frontend_type>
115
+ <source_model>adminhtml/system_config_source_website</source_model>
116
+ <comment>If nothing is selected, the product will be assigned to all existing websites.</comment>
117
+ <sort_order>50</sort_order>
118
+ <show_in_default>1</show_in_default>
119
+ <show_in_website>0</show_in_website>
120
+ <show_in_store>0</show_in_store>
121
+ </assign_to_websites>
122
+ <debug_mode translate="label">
123
+ <label>Debug Mode</label>
124
+ <frontend_type>select</frontend_type>
125
+ <source_model>adminhtml/system_config_source_yesno</source_model>
126
+ <comment>If this is enabled, debug information is written to var/log/wallmob.log.</comment>
127
+ <sort_order>60</sort_order>
128
+ <show_in_default>1</show_in_default>
129
+ <show_in_website>0</show_in_website>
130
+ <show_in_store>0</show_in_store>
131
+ </debug_mode>
132
+ </fields>
133
+ </import_settings>
134
+ <order_settings>
135
+ <label>Order Settings</label>
136
+ <frontend_type>text</frontend_type>
137
+ <sort_order>300</sort_order>
138
+ <show_in_default>1</show_in_default>
139
+ <show_in_website>0</show_in_website>
140
+ <show_in_store>0</show_in_store>
141
+ <fields>
142
+ <send_email translate="label">
143
+ <label>Send e-mail</label>
144
+ <frontend_type>select</frontend_type>
145
+ <source_model>adminhtml/system_config_source_yesno</source_model>
146
+ <comment>If this is enabled, Wallmob will send the customer an e-mail with an order confirmation. Only enable this if you don't send Magento order confirmations.</comment>
147
+ <sort_order>10</sort_order>
148
+ <show_in_default>1</show_in_default>
149
+ <show_in_website>0</show_in_website>
150
+ <show_in_store>0</show_in_store>
151
+ </send_email>
152
+ </fields>
153
+ </order_settings>
154
+ </groups>
155
+ </wallmob>
156
+ </sections>
157
+ </config>
app/etc/modules/Wallmob_Wallmob.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <modules>
4
+ <Wallmob_Wallmob>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends>
8
+ <Mage_Catalog />
9
+ </depends>
10
+ </Wallmob_Wallmob>
11
+ </modules>
12
+ </config>
package.xml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Wallmob_Wallmob</name>
4
+ <version>0.1.2</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.apache.org/licenses/LICENSE-2.0">ASL</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Integration between the Wallmob Point of Sale and Magento.</summary>
10
+ <description>Increased multichannel competition and changes in buying behavior has created a need for rethinking the Point of Sale. WALLMOB's POS is build on a new platform that has been developed to meet business demands to optimize sales and earnings, and at the same time improve the shopping experience as well as customer loyalty. Furthermore, the WALLMOB POS integrates with multiple payment methods such as mobile payments, numerous wallets, apps and e-Commerce.</description>
11
+ <notes>Initial stable release. Imports the following entities from the Wallmob POS:&#xD;
12
+ - Categories&#xD;
13
+ - Products&#xD;
14
+ - Stock&#xD;
15
+ &#xD;
16
+ In addition, placed orders will be reported to the Wallmob POS.</notes>
17
+ <authors><author><name>Wallmob</name><user>TeamWallmob</user><email>integrations@wallmob.com</email></author></authors>
18
+ <date>2014-05-23</date>
19
+ <time>11:03:42</time>
20
+ <contents><target name="mageetc"><dir name="modules"><file name="Wallmob_Wallmob.xml" hash="3811e24a9d103ac8b0eed96bde6310fe"/></dir></target><target name="magecommunity"><dir name="Wallmob"><dir name="Wallmob"><dir name="Block"><dir name="Adminhtml"><file name="Datetimelabel.php" hash="c5e99d5f6571771195e0ad13d519bd98"/><file name="Resetbutton.php" hash="f8ab93eeb8a0dd864a78f7aa48519b26"/><file name="Scheduledlabel.php" hash="aa9f70431aaa41c5ba060436850d59a7"/><file name="Statuslabel.php" hash="9ee45dcd770fe5ea965300a1147a226a"/></dir></dir><dir name="Helper"><file name="Data.php" hash="6ee25acc097196cfcc0914042430daaf"/></dir><dir name="Model"><file name="Api.php" hash="70b8fe9964ab5dfd38bc36591944d781"/><file name="Import.php" hash="5207a486d5c51d82c3ed9d3452ecc005"/><file name="Observer.php" hash="a06f16deb9c0665f9f196a3fd285ef9f"/><dir name="Processor"><file name="Abstract.php" hash="231eb22734fb810833fb603c0c233589"/><file name="Category.php" hash="783982993f14da3085a13f023676e0c5"/><file name="Interface.php" hash="4262a60a55c2125485291d8b963c3002"/><file name="Product.php" hash="9890d9382b898a61a87a656bf9fd8429"/><file name="Stock.php" hash="d6349e81d7913aad1ae8929dab036a45"/><file name="Vat.php" hash="bf860ab6e5ad9a142cfb20352d442beb"/></dir><dir name="System"><dir name="Config"><dir name="Source"><dir name="Wallmob"><file name="Store.php" hash="67cb2c223cb591c4c835520fa7116fb7"/></dir></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="WallmobController.php" hash="5689ce92ace815946caf984cfbc11744"/></dir></dir><dir name="data"><dir name="wallmob_setup"><file name="data-install-0.1.0.php" hash="88cb129cd970802ff24fdb56bc12938b"/><file name="data-upgrade-0.1.0-0.1.1.php" hash="e87f031a6ea5fb9fcf60abe4eda9f639"/><file name="data-upgrade-0.1.1-0.1.2.php" hash="113b227925f9e990d6df6984be1e844b"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="101e69312f130aef2a9fb72b9d0e6e13"/><file name="config.xml" hash="f291eab2f9545fc295755e3d5a72d430"/><file name="system.xml" hash="2fd28d0243a8ac1d662d4f9fa8f66f16"/></dir></dir></dir></target></contents>
21
+ <compatible/>
22
+ <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php><package><name>Mage_Core_Modules</name><channel>community</channel><min>1.6.0.0</min><max>1.9.0.1</max></package></required></dependencies>
23
+ </package>