YeahCommerce_Catalog_Sync_Extension - Version 1.0.18

Version Notes

Version: 1.0.18
Stability: Stable
Notes: This module allows you to synchronize your product catalog with your Yeah!Commerce account.
Integration includes synchronization between your shop and your Yeah!Commerce apps:

- Categories
- Category Images
- Products
- Products availability
- Product Images
- Product Info
- Product Prices
New in version 1.0.18:
- Synchronization for deleted products

Download this release

Release Info

Developer Boris Udachin
Extension YeahCommerce_Catalog_Sync_Extension
Version 1.0.18
Comparing to
See all releases


Code changes from version 1.0.17 to 1.0.18

app/code/community/YeahCommerce/Sync/Model/Observer.php CHANGED
@@ -1,194 +1,192 @@
1
- <?php
2
-
3
- require_once "Mobile_Detect.php";
4
-
5
- class YeahCommerce_Sync_Model_Observer {
6
-
7
- private static $_type;
8
-
9
- const YEAH_HOST = 'https://yeahcommerce.com/api/v01/';
10
- const TYPE_PRODUCT = 'product';
11
- const TYPE_CATEGORY = 'category';
12
- const TYPE_SITE = 'site';
13
- const YEAH_TEMP_DIR = 'yeah_data_dir';
14
- const DELETED_PRODUCTS_INFO = 'Deleted_Products_Info.gz';
15
-
16
- /**
17
- * @param $observer
18
- */
19
- public function redirectToMobile($observer){
20
- $do_redirect = Mage::getStoreConfig('yeah_sync_section/yeah_sync_group/redirect_check');
21
- if ($this->_detectMobile() && $do_redirect){
22
- $product = $observer->getData('product');
23
- if (!$product || empty($product)){
24
- $category = $observer->getData('category');
25
- if (!$category || empty($category)){
26
- if (!isset(self::$_type)){
27
- if ($this->_getIsHomePage()){
28
- $this->_redirect('');
29
- }
30
- }
31
- } else {
32
- if (!isset(self::$_type)){
33
- $this->_setType(self::TYPE_CATEGORY);
34
- $this->_redirectToMobileVersionCategory($category);
35
- }
36
- }
37
- } else {
38
- if (!isset(self::$_type)){
39
- $this->_setType(self::TYPE_PRODUCT);
40
- $this->_redirectToMobileVersionProduct($product);
41
- }
42
- }
43
- }
44
- }
45
-
46
- /**
47
- * Saves an ID of deleted product to an archive DELETED_PRODUCTS_INFO
48
- * @param $observer
49
- */
50
- public function saveOnDelete($observer){
51
- try{
52
- $id = $observer->getData('product')->getId();
53
- $path = self::_getVarFolder().self::DELETED_PRODUCTS_INFO;
54
- $f = gzopen($path, 'a');
55
- gzwrite($f, $id.',');
56
- gzclose($f);
57
- } catch (Exception $e){
58
- print_r($e->getMessage());
59
- exit;
60
- }
61
- return;
62
- }
63
-
64
- private static function _getVarFolder(){
65
- return Mage::getBaseDir() . DS . 'var' . DS . self::YEAH_TEMP_DIR . DS;
66
- }
67
- /**
68
- * @return bool
69
- */
70
- private function _getIsHomePage()
71
- {
72
- $page = Mage::app()->getFrontController()->getRequest()->getRouteName();
73
- $homePage = false;
74
-
75
- if($page =='cms'){
76
- $cmsSingletonIdentifier = Mage::getSingleton('cms/page')->getIdentifier();
77
- $homeIdentifier = Mage::app()->getStore()->getConfig('web/default/cms_home_page');
78
- if($cmsSingletonIdentifier === $homeIdentifier){
79
- $homePage = true;
80
- }
81
- }
82
-
83
- return $homePage;
84
- }
85
-
86
- /**
87
- * @return bool
88
- */
89
- private function _detectMobile(){
90
- $detect = new Mobile_Detect;
91
- return $detect->isMobile();
92
- }
93
-
94
- /**
95
- * @param $type
96
- */
97
- private function _setType($type){
98
- if (!isset(self::$_type)){
99
- self::$_type = $type;
100
- }
101
- }
102
-
103
- /**
104
- * @param $product
105
- */
106
- private function _redirectToMobileVersionProduct($product)
107
- {
108
- $url = $this->_constructUrl(self::TYPE_PRODUCT, $product->getId());
109
- $app_id = $this->_makeRequest($url);
110
- if (is_int($app_id)){
111
- $this->_redirect('#product/'.$app_id);
112
- }
113
- }
114
-
115
- /**
116
- * @param $category
117
- */
118
- private function _redirectToMobileVersionCategory($category){
119
- $url = $this->_constructUrl(self::TYPE_CATEGORY, $category->getId());
120
- $app_id = $this->_makeRequest($url);
121
- if (is_int($app_id)){
122
- if ($this->_hasSubCategories($category)){
123
- $url = '#category_cat/'.$app_id;
124
- } else {
125
- $url = '#category_prod/'.$app_id;
126
- }
127
- $this->_redirect($url);
128
- }
129
- }
130
-
131
- /**
132
- * @param $url
133
- */
134
- private function _redirect($url){
135
- $key = Mage::getStoreConfig('yeah_sync_section/yeah_sync_group/secret_key');
136
- $request = self::YEAH_HOST.$key.'/get_url';
137
- $domain = $this->_makeRequest($request);
138
- $targetUrl = $domain.$url;
139
- Mage::app()->getFrontController()->getResponse()->setRedirect($targetUrl);
140
- }
141
-
142
- /**
143
- * Compose a string to make request to mobile API
144
- * @param $type
145
- * @param $id
146
- * @return string
147
- */
148
- private function _constructUrl($type, $id){
149
- $key = Mage::getStoreConfig('yeah_sync_section/yeah_sync_group/secret_key');
150
- $url = self::YEAH_HOST.$key.'/'.$type.'/get_id/'.$id;
151
- return $url;
152
- }
153
-
154
- /**
155
- * Check if category has subcategories
156
- * @param $category
157
- * @return bool
158
- */
159
- private function _hasSubCategories($category){
160
- $cat = Mage::getModel('catalog/category')->load($category->getId());
161
- $subcats = $cat->getChildren();
162
- if (empty($subcats)){
163
- return false;
164
- } else {
165
- return true;
166
- }
167
- }
168
-
169
- /**
170
- * Get id of a product or category in mobile version
171
- * @param $url
172
- * @return mixed
173
- */
174
- private function _makeRequest($url){
175
- $process = curl_init($url);
176
- curl_setopt($process, CURLOPT_TIMEOUT, 30);
177
- curl_setopt($process, CURLOPT_RETURNTRANSFER, true);
178
- curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);
179
- curl_setopt($process, CURLOPT_SSL_VERIFYHOST, false);
180
- var_dump($url);
181
- $return = curl_exec($process);
182
- $data = json_decode($return);
183
- var_dump($data);
184
- curl_close($process);
185
- if ($data->id){
186
- return $data->id;
187
- }elseif($data->url){
188
- return $data->url;
189
- }else{
190
- return NULL;
191
- }
192
- }
193
-
194
  }
1
+ <?php
2
+
3
+ require_once "Mobile_Detect.php";
4
+
5
+ class YeahCommerce_Sync_Model_Observer {
6
+
7
+ private static $_type;
8
+
9
+ const YEAH_HOST = 'https://yeahcommerce.com/api/v01/';
10
+ const TYPE_PRODUCT = 'product';
11
+ const TYPE_CATEGORY = 'category';
12
+ const TYPE_SITE = 'site';
13
+ const YEAH_TEMP_DIR = 'yeah_data_dir';
14
+ const DELETED_PRODUCTS_INFO = 'Deleted_Products_Info.gz';
15
+
16
+ /**
17
+ * @param $observer
18
+ */
19
+ public function redirectToMobile($observer){
20
+ $do_redirect = Mage::getStoreConfig('yeah_sync_section/yeah_sync_group/redirect_check');
21
+ if ($this->_detectMobile() && $do_redirect){
22
+ $product = $observer->getData('product');
23
+ if (!$product || empty($product)){
24
+ $category = $observer->getData('category');
25
+ if (!$category || empty($category)){
26
+ if (!isset(self::$_type)){
27
+ if ($this->_getIsHomePage()){
28
+ $this->_redirect('');
29
+ }
30
+ }
31
+ } else {
32
+ if (!isset(self::$_type)){
33
+ $this->_setType(self::TYPE_CATEGORY);
34
+ $this->_redirectToMobileVersionCategory($category);
35
+ }
36
+ }
37
+ } else {
38
+ if (!isset(self::$_type)){
39
+ $this->_setType(self::TYPE_PRODUCT);
40
+ $this->_redirectToMobileVersionProduct($product);
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Saves an ID of deleted product to an archive DELETED_PRODUCTS_INFO
48
+ * @param $observer
49
+ */
50
+ public function saveOnDelete($observer){
51
+ try{
52
+ $id = $observer->getData('product')->getId();
53
+ $path = self::_getVarFolder().self::DELETED_PRODUCTS_INFO;
54
+ $f = gzopen($path, 'a');
55
+ gzwrite($f, $id.',');
56
+ gzclose($f);
57
+ } catch (Exception $e){
58
+ print_r($e->getMessage());
59
+ exit;
60
+ }
61
+ return;
62
+ }
63
+
64
+ private static function _getVarFolder(){
65
+ return Mage::getBaseDir() . DS . 'var' . DS . self::YEAH_TEMP_DIR . DS;
66
+ }
67
+ /**
68
+ * @return bool
69
+ */
70
+ private function _getIsHomePage()
71
+ {
72
+ $page = Mage::app()->getFrontController()->getRequest()->getRouteName();
73
+ $homePage = false;
74
+
75
+ if($page =='cms'){
76
+ $cmsSingletonIdentifier = Mage::getSingleton('cms/page')->getIdentifier();
77
+ $homeIdentifier = Mage::app()->getStore()->getConfig('web/default/cms_home_page');
78
+ if($cmsSingletonIdentifier === $homeIdentifier){
79
+ $homePage = true;
80
+ }
81
+ }
82
+
83
+ return $homePage;
84
+ }
85
+
86
+ /**
87
+ * @return bool
88
+ */
89
+ private function _detectMobile(){
90
+ $detect = new Mobile_Detect;
91
+ return $detect->isMobile();
92
+ }
93
+
94
+ /**
95
+ * @param $type
96
+ */
97
+ private function _setType($type){
98
+ if (!isset(self::$_type)){
99
+ self::$_type = $type;
100
+ }
101
+ }
102
+
103
+ /**
104
+ * @param $product
105
+ */
106
+ private function _redirectToMobileVersionProduct($product)
107
+ {
108
+ $url = $this->_constructUrl(self::TYPE_PRODUCT, $product->getId());
109
+ $app_id = $this->_makeRequest($url);
110
+ if (is_int($app_id)){
111
+ $this->_redirect('#product/'.$app_id);
112
+ }
113
+ }
114
+
115
+ /**
116
+ * @param $category
117
+ */
118
+ private function _redirectToMobileVersionCategory($category){
119
+ $url = $this->_constructUrl(self::TYPE_CATEGORY, $category->getId());
120
+ $app_id = $this->_makeRequest($url);
121
+ if (is_int($app_id)){
122
+ if ($this->_hasSubCategories($category)){
123
+ $url = '#category_cat/'.$app_id;
124
+ } else {
125
+ $url = '#category_prod/'.$app_id;
126
+ }
127
+ $this->_redirect($url);
128
+ }
129
+ }
130
+
131
+ /**
132
+ * @param $url
133
+ */
134
+ private function _redirect($url){
135
+ $key = Mage::getStoreConfig('yeah_sync_section/yeah_sync_group/secret_key');
136
+ $request = self::YEAH_HOST.$key.'/get_url';
137
+ $domain = $this->_makeRequest($request);
138
+ $targetUrl = $domain.$url;
139
+ Mage::app()->getFrontController()->getResponse()->setRedirect($targetUrl);
140
+ }
141
+
142
+ /**
143
+ * Compose a string to make request to mobile API
144
+ * @param $type
145
+ * @param $id
146
+ * @return string
147
+ */
148
+ private function _constructUrl($type, $id){
149
+ $key = Mage::getStoreConfig('yeah_sync_section/yeah_sync_group/secret_key');
150
+ $url = self::YEAH_HOST.$key.'/'.$type.'/get_id/'.$id;
151
+ return $url;
152
+ }
153
+
154
+ /**
155
+ * Check if category has subcategories
156
+ * @param $category
157
+ * @return bool
158
+ */
159
+ private function _hasSubCategories($category){
160
+ $cat = Mage::getModel('catalog/category')->load($category->getId());
161
+ $subcats = $cat->getChildren();
162
+ if (empty($subcats)){
163
+ return false;
164
+ } else {
165
+ return true;
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Get id of a product or category in mobile version
171
+ * @param $url
172
+ * @return mixed
173
+ */
174
+ private function _makeRequest($url){
175
+ $process = curl_init($url);
176
+ curl_setopt($process, CURLOPT_TIMEOUT, 30);
177
+ curl_setopt($process, CURLOPT_RETURNTRANSFER, true);
178
+ curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);
179
+ curl_setopt($process, CURLOPT_SSL_VERIFYHOST, false);
180
+ $return = curl_exec($process);
181
+ $data = json_decode($return);
182
+ curl_close($process);
183
+ if ($data->id){
184
+ return $data->id;
185
+ }elseif($data->url){
186
+ return $data->url;
187
+ }else{
188
+ return NULL;
189
+ }
190
+ }
191
+
 
 
192
  }
app/code/community/YeahCommerce/Sync/controllers/IndexController.php CHANGED
@@ -1,563 +1,920 @@
1
- <?php
2
- class YeahCommerce_Sync_IndexController extends Mage_Core_Controller_Front_Action{
3
- const YEAH_TEMP_DIR = 'yeah_data_dir';
4
- const LAST_UPDATE = '14.12.2012';
5
- const MODULE_TYPE = 'magento';
6
- const DELETED_PRODUCTS_INFO = 'Deleted_Products_Info.gz';
7
-
8
- /**
9
- * Checking KEY
10
- * @return Mage_Core_Controller_Front_Action|void
11
- */
12
- public function preDispatch(){
13
- parent::preDispatch();
14
- $this->_sessionNamespace = 'frontend';
15
-
16
- $key = Mage::getStoreConfig('yeah_sync_section/yeah_sync_group/secret_key');
17
-
18
- if(isset($_GET['createOrder'])){
19
- return;
20
- }
21
-
22
- if(empty($key)){
23
- header("HTTP/1.0 400 Bad Request");
24
- die('{error:400}');
25
- }
26
-
27
- if(Mage::app()->getRequest()->get('key') !== $key){
28
- header("HTTP/1.0 401 Unauthorized");
29
- die('{error:401}');
30
- }
31
- }
32
-
33
- /**
34
- * Default action
35
- * Just info about the module
36
- */
37
- public function indexAction(){
38
- if(isset($_GET['createOrder'])){
39
- $this->createOrderAction();
40
- return;
41
- }elseif(isset($_GET['products'])){
42
- $this->productsAction();
43
- return;
44
- }elseif(isset($_GET['categories'])){
45
- $this->categoriesAction();
46
- }elseif(isset($_GET['order'])){
47
- $this->orderAction();
48
- return;
49
- }else{
50
- $response = array(
51
- 'module' => self::MODULE_TYPE,
52
- 'ver' => Mage::getConfig()->getModuleConfig('YeahCommerce_Sync')->version->__toString(),
53
- 'last_update' => self::LAST_UPDATE,
54
- 'changes' => false,
55
- );
56
- echo json_encode($response);
57
- }
58
- }
59
-
60
- public function orderAction(){
61
- $order = $_POST['order'];
62
- echo Mage::getUrl('sync') .'?createOrder&orderData='.urlencode($order);
63
- }
64
-
65
- /**
66
- * Gets a product associated with given configurable product by given params
67
- * @param integer $id
68
- * @param array $params
69
- */
70
- private function _getAssociatedProductByAttributes($id,$params){
71
- $productModel = Mage::getModel('catalog/product');
72
- $product = $productModel->load($id);
73
- $instance = $product->getTypeInstance(true);
74
- $associated_products = $instance->getUsedProducts(null, $product); // Получаем продукты
75
- foreach($params as $key => $value){
76
- $attr = $productModel->getResource()->getAttribute($key);
77
- if ($attr->usesSource()) {
78
- $params_ids[$key] = $attr->getSource()->getOptionId($value);
79
- }
80
- }
81
- foreach($associated_products as $prod){
82
- $flag = true;
83
- foreach($params_ids as $key => $value){
84
- if ($prod->getData()[$key] != $params_ids[$key]){
85
- $flag = false;
86
- }
87
- }
88
- if ($flag == true){
89
- $result = $prod;
90
- }
91
- }
92
- return $result;
93
- }
94
-
95
- public function createOrderAction(){
96
- $order = json_decode($_GET['orderData']);
97
- try{
98
- $this->_createOrder($order);
99
- }catch (Exception $e){
100
- print_r($e->getMessage());
101
- }
102
-
103
- $this->_redirect('checkout/cart');
104
- }
105
-
106
- /**
107
- * Adds order into guest user cart and returns SID=session pair for login into the cart
108
- * @param array $products
109
- * @return string "SID=sessionid"
110
- */
111
- private function _createOrder($products){
112
- $cart = Mage::getSingleton('checkout/cart', array('name' => 'frontend'));
113
- $cart->init();
114
-
115
- foreach($products as $one){
116
- $productModel = Mage::getModel('catalog/product');
117
- $id = $productModel->getIdBySku($one->sku);
118
- $product = $productModel->load($id);
119
- $qty = Mage::getModel('cataloginventory/stock_item')->loadByProduct($id)->getQty();
120
- $options = array();
121
- $type = $product->getTypeId();
122
- var_dump($type);
123
- switch($type){
124
- case Mage_Catalog_Model_Product_Type::TYPE_SIMPLE: // Simple product (with attributes)
125
- echo "SIMPLE!!!";
126
- if($one->options){
127
- foreach ($one->options as $opt => $value) {
128
- $option_id = $this->_getCustomOptionId($product, $opt);
129
- $option_value_id = $this->_getCustomOptionTypeId($product, $option_id, $value);
130
- $options[$option_id] = $option_value_id;
131
- }
132
- }
133
- break;
134
- case Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE:
135
- echo "CONF!!!";
136
- $conf = $this->_getAssociatedProductByAttributes($id,$one->options);
137
- $id = $conf->getEntityId();
138
- $product = $conf;
139
- break;
140
- }
141
- try{
142
- $params = new Varien_Object(array(
143
- 'product' => $id,
144
- 'qty' => min($one->count, $qty),
145
- 'options' => $options
146
- ));
147
- $cart->addProduct($product, $params);
148
- }catch (Exception $e){
149
- print_r($e->getMessage());
150
- exit;
151
- }
152
- }
153
- $cart->save();
154
-
155
- /** @var $session Mage_Checkout_Model_Session */
156
- $session = Mage::getSingleton('core/session', array('name' => 'frontend'));
157
- $session->setCartWasUpdated(true);
158
- return $session->getSessionIdQueryParam() .'='. $session->getSessionId();
159
- }
160
-
161
- /**
162
- * Gets option_id value for given product using option title
163
- * @param $product
164
- * @param string $title
165
- * @return integer
166
- */
167
- private function _getCustomOptionId($product, $title){
168
- foreach ($product->getOptions() as $option) {
169
- if ($option["title"] == $title){
170
- return $option["option_id"];
171
- }
172
- }
173
- return 0;
174
- }
175
-
176
- /**
177
- * Gets option_type_id value for given option and product
178
- * @param $product
179
- * @param $option_id
180
- * @param string $title
181
- * @return integer
182
- */
183
- private function _getCustomOptionTypeId($product, $option_id, $title){
184
- foreach ($product->getOptions() as $option) {
185
- if ($option["option_id"] == $option_id){
186
- foreach ($option->getValues() as $value) {
187
- if ($value["title"] == $title){
188
- return $value["option_type_id"];
189
- }
190
- }
191
- }
192
- }
193
- return 0;
194
- }
195
- /**
196
- * Gets bundle product
197
- * @param $current_product
198
- * @return array
199
- */
200
- private function _getBundleProduct($current_product){
201
- $components = array();
202
- $bundle_items = Mage::getBlockSingleton('bundle/catalog_product_view_type_bundle')->setProduct($current_product)->getOptions();
203
- foreach($bundle_items as $bundle){
204
- $products = array();
205
- $options = $bundle->getData();
206
- $items = $options['selections'];
207
-
208
- foreach($items as $i){
209
- $product = $i->getData();
210
- $tmp_product['id'] = $product['entity_id']; // Id продукта
211
- $tmp_product['default_qty'] = $product['selection_qty']; // Дефолтное количество
212
- $tmp_product['user_qty'] = (bool)$product['selection_can_change_qty']; // Может ли пользователь менять количество
213
- $tmp_product['default'] = (bool)$product['is_default'];
214
- $products[] = $tmp_product;
215
- }
216
-
217
- $components[] = array(
218
- 'title' => $options['title'],
219
- 'required' => (bool)$options['required'],
220
- 'type' => $options['type'], // select, radio, checkbox, multi
221
- 'products' => $products
222
- );
223
- }
224
-
225
- return $components;
226
- }
227
-
228
- /**
229
- * Get configurable product with its options
230
- * @param $current_product
231
- * @return array
232
- */
233
- private function _getConfigurableProduct($current_product){
234
- $components = array();
235
- $instance = $current_product->getTypeInstance(true);
236
- $associated_products = $instance->getUsedProducts(null, $current_product); // Retrieves associated products
237
- $product_attributes = $instance->getConfigurableAttributesAsArray($current_product); // Retrieves products attributes
238
-
239
- $attributes = array();
240
- $attributes_name = array();
241
- $options = array();
242
- foreach($product_attributes as $attribute){
243
- $i = 0;
244
- foreach($attribute['values'] as $v){
245
- // Creating an array: array(attribute title => array(value id => array())
246
- $options[ $attribute['attribute_code'] ][$i++] = array(
247
- 'value' => $v['label'], // attribute label
248
- 'pricing_value' => is_null($v['pricing_value']) ? "0" : $v['pricing_value'], // price
249
- 'is_percent' => (bool)$v['is_percent'] // True - price is percentage, false - fixed
250
- );
251
- }
252
- }
253
- return $options;
254
- }
255
-
256
- /**
257
- * Gets Custom options
258
- * @param $current_product
259
- * @return array
260
- */
261
- private function _getOptions($current_product){
262
- $options = array();
263
-
264
- return $options;
265
- }
266
-
267
- /**
268
- * Retrievies all (or recently updated) products,
269
- * creates gzip-archive with json-encoded info and returns the link
270
- */
271
- public function productsAction(){
272
- $collection = Mage::getModel('catalog/product')->getCollection() /** @var $collection */
273
- ->joinField('stock_status','cataloginventory/stock_status','stock_status',
274
- 'product_id=entity_id', array(
275
- 'stock_status' => Mage_CatalogInventory_Model_Stock_Status::STATUS_IN_STOCK,
276
- 'website_id' => Mage::app()->getWebsite()->getWebsiteId(),
277
- ))
278
- ->addAttributeToFilter('status', 1)
279
- ->addAttributeToSelect('name')
280
- ->addAttributeToSelect('description')
281
- ->addAttributeToSelect('price')
282
- ->addAttributeToSelect('image')
283
- ->addAttributeToSelect('category')
284
- ->addAttributeToSelect('category_ids')
285
- ->addAttributeToSelect('url_path');
286
- if(!empty($_REQUEST['from_ts'])){
287
- $from_ts = (int)$_REQUEST['from_ts'];
288
- if($from_ts > mktime(0, 0, 0, 0, 0, 2000) && $from_ts < time()){
289
- $collection = $collection->addAttributeToFilter('updated_at', array('gt' => date('Y.m.d H:i:s', $from_ts)));
290
- }
291
- }
292
- if(count($collection)){
293
- addMediaGalleryAttributeToCollection($collection);
294
- }
295
- $products = array();
296
- foreach($collection as $one){ /** @var $one Mage_Catalog_Model_Product */
297
- $categories = $one->getCategoryIds();
298
- if ($categories){
299
- //making images array
300
- $images = array();
301
- if($imgCollection = $one->getMediaGalleryImages()){
302
- $baseImage = $one->image;
303
- foreach($imgCollection as $img){
304
- if($img->file == $baseImage){
305
- $images[] = array('path' => $img->url, 'status' => 1);
306
- }else{
307
- $images[] = array('path' => $img->url, 'status' => 0);
308
- }
309
- }
310
- }
311
- //info about the product
312
- $options = array();
313
-
314
- $type = $one->getTypeId();
315
- switch($type){
316
- case Mage_Catalog_Model_Product_Type::TYPE_BUNDLE: // Product type is Bundle
317
- $options = $this->_getBundleProduct($one);
318
- break;
319
- case Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE: // Product type is Configurable
320
- $options = $this->_getConfigurableProduct($one);
321
- break;
322
- }
323
-
324
- $products[$one->getEntityId()] = array(
325
- 'name' => $one->name,
326
- 'sku' => $one->getSku(),
327
- 'desc' => $one->description,
328
- 'images' => $images,
329
- 'price' => $one->getPrice(), //may be high load caused by "calculatePrice"
330
- 'category' => $categories,
331
- 'type' => $type, // simple, bundle, configurable
332
- 'options' => $options,
333
- 'components' => array()
334
- );
335
- }
336
-
337
- }
338
-
339
- // Gathering option values
340
- $optionId2values = array();
341
- $collection = Mage::getResourceModel('catalog/product_option_value_collection')->getValues(0);
342
- foreach($collection as $one){
343
- $data = $one->getData();
344
- $optionId2values[ $data['option_id'] ][$data['option_type_id']] = array(
345
- 'value' => $data['title'],
346
- 'pricing_value' => $data['price'],
347
- 'is_percent' => ($data['price_type'] == 'fixed') ? false : true, // fixed, percent
348
- 'sku' => $data['sku'],
349
- 'order' => $data['sort_order']
350
- );
351
- }
352
-
353
- //Gathering custom options
354
- $collection = Mage::getModel('catalog/product_option')
355
- ->getCollection()
356
- ->addTitleToResult(0)
357
- ->addPriceToResult(0);
358
- foreach($collection as $one){
359
- $data = $one->getData();
360
- $oid = $data['option_id'];
361
- $oname = $data['title'];
362
- $pid = $data['product_id'];
363
- if(isset($products[$pid])){
364
- $params = array(
365
- 'option_id' => $oid,
366
- 'type' => $data['type'],
367
- 'required' => (bool)$data['is_require'],
368
- 'order' => $data['sort_order']
369
- );
370
- $products[$pid]['options'][$oname]['_params'] = $params;
371
- if (!empty($optionId2values[$oid])){
372
- $products[$pid]['options'][$oname] += array_values($optionId2values[$oid]);
373
- }
374
- }
375
- }
376
-
377
- if ($data = self::_openArchive(self::DELETED_PRODUCTS_INFO)){
378
- $deleted = preg_split('/,/', $data);
379
- foreach ($deleted as $deleted_id) {
380
- $products[$deleted_id]['type'] = "deleted";
381
- }
382
- unset($data);
383
- unset($deleted);
384
- }
385
-
386
- unset($collection);
387
- unset($optionId2values);
388
- //dumping all
389
- $archive = self::_createArchive('products', json_encode($products));
390
- $response = array('link' => Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB) . 'var/'.self::YEAH_TEMP_DIR.'/'.$archive);
391
- echo json_encode($response);
392
- }
393
-
394
- /**
395
- * Retrievies all the categories, creates gzip-archive and returns the link
396
- */
397
- public function categoriesAction(){
398
- $collection = Mage::getModel('catalog/category')->getCollection()
399
- ->addAttributeToSelect('name')
400
- ->addAttributeToSelect('image')
401
- ->addAttributeToSelect('url_path')
402
- ->addAttributeToSelect('is_active');
403
-
404
- if(!empty($_REQUEST['from_ts'])){
405
- $from_ts = (int)$_REQUEST['from_ts'];
406
- if($from_ts > mktime(0, 0, 0, 0, 0, 2000) && $from_ts < time()){
407
- $collection = $collection->addAttributeToFilter('updated_at', array('gt' => date('Y.m.d H:i:s', $from_ts)));
408
- }
409
- }
410
-
411
- $cats = array();
412
- $root_cat_id = Mage::app()->getStore()->getRootCategoryId();
413
- $root_parent = null;
414
- foreach($collection as $cat){
415
- $cat_id = $cat->getEntityId();
416
- //we memorize parent of root category in order to delete it in future
417
- //we don't write the root category also
418
- if($cat_id == $root_cat_id){
419
- $root_parent = $cat->parent_id;
420
- continue;
421
- }
422
- $parent_id = $cat->parent_id == $root_cat_id ? 0 : $cat->parent_id;
423
- $cats[$cat_id] = array(
424
- 'path' => '/'.$cat->url_path,
425
- 'name' => $cat->name,
426
- 'pid' => $parent_id,
427
- 'img' => $cat->getImageUrl(),
428
- 'isActive' => (bool)$cat->is_active,
429
- );
430
- }
431
- //deleting parent of root category
432
- if(!is_null($root_parent)){
433
- unset($cats[$root_parent]);
434
- }
435
-
436
- $archive = self::_createArchive('category', json_encode($cats));
437
- $response = array('link' => Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB) . 'var/'.self::YEAH_TEMP_DIR.'/'.$archive);
438
- echo json_encode($response);
439
- }
440
-
441
- /**
442
- * @param string $type
443
- * @param string $data
444
- * @throws Exception
445
- * @return string File name
446
- */
447
- private static function _createArchive($type, $data){
448
- if($type != 'category' && $type != 'products'){
449
- throw new Exception('Wrong type: '.$type);
450
- }
451
-
452
- self::_cleanOldFiles();
453
-
454
- $fname = $type."_".date('Y_m_d_H_i_s') . '.gz';
455
- $path = self::_getVarFolder() . $fname;
456
- $f = gzopen($path, 'w9');
457
- gzwrite($f, $data);
458
- gzclose($f);
459
- return $fname;
460
- }
461
-
462
- /**
463
- * @param string $fname
464
- * @return string File content
465
- */
466
- private static function _openArchive($fname){
467
- $path = self::_getVarFolder() . $fname;
468
- $f = gzopen($path,'r');
469
- $data = gzread($f, 10000);
470
- gzclose($f);
471
- return substr($data, 0, -1);
472
- }
473
-
474
- /**
475
- * Clean old files
476
- */
477
- private function _cleanOldFiles(){
478
- $path = self::_getVarFolder();
479
- $files = scandir($path);
480
- $prods = array_filter($files, function($v){ return preg_match('/^products_\d\d\d\d(_\d\d){5}\.gz$/', $v); });
481
- $cats = array_filter($files, function($v){ return preg_match('/^category_\d\d\d\d(_\d\d){5}\.gz$/', $v); });
482
- unset($files);
483
- sort($prods);
484
- sort($cats);
485
- while(count($prods) > 2){
486
- $file = array_shift($prods);
487
- unlink($path.$file);
488
- }
489
- while(count($cats) > 2){
490
- $file = array_shift($cats);
491
- unlink($path.$file);
492
- }
493
- unlink($path.self::DELETED_PRODUCTS_INFO);
494
- }
495
-
496
- /**
497
- * Checks that data folder in "var" is created and "htaccess" is set up
498
- * @return string
499
- */
500
- private static function _getVarFolder(){
501
- $var_dir = Mage::getBaseDir() . DS . 'var' . DS . self::YEAH_TEMP_DIR . DS;
502
- if(!file_exists($var_dir)){
503
- mkdir($var_dir, 0777);
504
- //create htaccess file
505
- $htaccess = $var_dir . '.htaccess';
506
- $hf = fopen($htaccess, 'w');
507
- fwrite($hf, "Order allow,deny\nAllow from all");
508
- fclose($hf);
509
- }
510
- return $var_dir;
511
- }
512
- }
513
-
514
- /**
515
- * A really magic function. But there is no better way to load gallery images
516
- * along with product collection
517
- * @link http://www.magentocommerce.com/boards/viewthread/17414/#t141830
518
- * @param $_productCollection
519
- * @return
520
- */
521
- function addMediaGalleryAttributeToCollection($_productCollection) {
522
- $_mediaGalleryAttributeId = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'media_gallery')->getAttributeId();
523
- $_read = Mage::getSingleton('core/resource')->getConnection('catalog_read');
524
-
525
- $_mediaGalleryData = $_read->fetchAll('
526
- SELECT
527
- main.entity_id, `main`.`value_id`, `main`.`value` AS `file`,
528
- `value`.`label`, `value`.`position`, `value`.`disabled`, `default_value`.`label` AS `label_default`,
529
- `default_value`.`position` AS `position_default`,
530
- `default_value`.`disabled` AS `disabled_default`
531
- FROM `catalog_product_entity_media_gallery` AS `main`
532
- LEFT JOIN `catalog_product_entity_media_gallery_value` AS `value`
533
- ON main.value_id=value.value_id AND value.store_id=' . Mage::app()->getStore()->getId() . '
534
- LEFT JOIN `catalog_product_entity_media_gallery_value` AS `default_value`
535
- ON main.value_id=default_value.value_id AND default_value.store_id=0
536
- WHERE (
537
- main.attribute_id = ' . $_read->quote($_mediaGalleryAttributeId) . ')
538
- AND (main.entity_id IN (' . $_read->quote($_productCollection->getAllIds()) . '))
539
- ORDER BY IF(value.position IS NULL, default_value.position, value.position) ASC
540
- ');
541
-
542
-
543
- $_mediaGalleryByProductId = array();
544
- foreach ($_mediaGalleryData as $_galleryImage) {
545
- $k = $_galleryImage['entity_id'];
546
- unset($_galleryImage['entity_id']);
547
- if (!isset($_mediaGalleryByProductId[$k])) {
548
- $_mediaGalleryByProductId[$k] = array();
549
- }
550
- $_mediaGalleryByProductId[$k][] = $_galleryImage;
551
- }
552
- unset($_mediaGalleryData);
553
- foreach ($_productCollection as &$_product) {
554
- $_productId = $_product->getData('entity_id');
555
- if (isset($_mediaGalleryByProductId[$_productId])) {
556
- $_product->setData('media_gallery', array('images' => $_mediaGalleryByProductId[$_productId]));
557
- }
558
- }
559
- unset($_mediaGalleryByProductId);
560
-
561
- return $_productCollection;
562
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
563
  ?>
1
+ <?php
2
+ class YeahCommerce_Sync_IndexController extends Mage_Core_Controller_Front_Action{
3
+ const YEAH_TEMP_DIR = 'yeah_data_dir';
4
+ const LAST_UPDATE = '14.12.2012';
5
+ const MODULE_TYPE = 'magento';
6
+ const DELETED_PRODUCTS_INFO = 'Deleted_Products_Info.gz';
7
+
8
+ var $quoteId;
9
+
10
+ /**
11
+ * Checking KEY
12
+ * @return Mage_Core_Controller_Front_Action|void
13
+ */
14
+ public function preDispatch(){
15
+ parent::preDispatch();
16
+ $this->_sessionNamespace = 'frontend';
17
+
18
+ $key = Mage::getStoreConfig('yeah_sync_section/yeah_sync_group/secret_key');
19
+
20
+ if(isset($_GET['createOrder'])){
21
+ return;
22
+ }
23
+
24
+ if(empty($key)){
25
+ header("HTTP/1.0 400 Bad Request");
26
+ die('{error:400}');
27
+ }
28
+
29
+ if(Mage::app()->getRequest()->get('key') !== $key){
30
+ header("HTTP/1.0 401 Unauthorized");
31
+ die('{error:401}');
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Default action
37
+ * Just info about the module
38
+ */
39
+ public function indexAction(){
40
+ if(isset($_GET['createOrder'])){
41
+ $this->createOrderAction();
42
+ return;
43
+ }elseif(isset($_GET['products'])){
44
+ $this->productsAction();
45
+ return;
46
+ }elseif(isset($_GET['categories'])){
47
+ $this->categoriesAction();
48
+ }elseif(isset($_GET['order'])){
49
+ // $this->prepareAction();
50
+ $this->orderAction();
51
+ return;
52
+ }elseif(isset($_GET['shippings'])){
53
+ $this->getShippingMethodsAction();
54
+ }elseif(isset($_GET['countries'])){
55
+ $this->getCountries();
56
+ }elseif(isset($_GET['paypal'])){
57
+ $this->paypalRedirect();
58
+ }else{
59
+ $response = array(
60
+ 'module' => self::MODULE_TYPE,
61
+ 'ver' => Mage::getConfig()->getModuleConfig('YeahCommerce_Sync')->version->__toString(),
62
+ 'last_update' => self::LAST_UPDATE,
63
+ 'changes' => false,
64
+ );
65
+ echo json_encode($response);
66
+ }
67
+ }
68
+
69
+ public function orderAction(){
70
+ $order = $_POST['order'];
71
+ echo Mage::getUrl('sync') .'?createOrder&orderData='.urlencode($order);
72
+ }
73
+
74
+ public function createOrderAction(){
75
+ $order = json_decode($_GET['orderData']);
76
+ try{
77
+ $this->_addProductsToCart($order);
78
+ }catch (Exception $e){
79
+ print_r($e->getMessage());
80
+ }
81
+
82
+ $this->_redirect('checkout/cart');
83
+ }
84
+
85
+ /**
86
+ * Adds order into guest user cart and returns SID=session pair for login into the cart
87
+ * @param array $products
88
+ * @return string "SID=sessionid"
89
+ */
90
+ private function _createOrder($products){
91
+ $cart = Mage::getSingleton('checkout/cart', array('name' => 'frontend'));
92
+ $cart->init();
93
+ /*foreach( $session->getQuote()->getItemsCollection() as $item ){
94
+ $cart->removeItem($item->getId());
95
+ }*/
96
+
97
+ foreach($products as $one){
98
+ $product = Mage::getModel('catalog/product');
99
+ //$product->setStoreId(Mage::app()->getStore()->getId());
100
+ $id = $product->getIdBySku($one->sku);
101
+ $product->load($id);
102
+ $qty = Mage::getModel('cataloginventory/stock_item')->loadByProduct($id)->getQty();
103
+ try{
104
+ $cart->addProduct($product, array(
105
+ 'product' => $id,
106
+ 'qty' => min($one->count, $qty),
107
+ ));
108
+ }catch (Exception $e){
109
+ //print_r($e->getMessage());
110
+ //exit;
111
+ }
112
+ }
113
+ $cart->save();
114
+
115
+ /** @var $session Mage_Checkout_Model_Session */
116
+ $session = Mage::getSingleton('core/session', array('name' => 'frontend'));
117
+ $session->setCartWasUpdated(true);
118
+ return $session->getSessionIdQueryParam() .'='. $session->getSessionId();
119
+ }
120
+ public function prepareAction(){
121
+ $data = json_decode($_REQUEST['order']);
122
+ // var_dump($data);
123
+
124
+ if(!$data){
125
+ header("HTTP/1.0 400 Bad Request");
126
+ die('{error:400}');
127
+ }
128
+
129
+ $billing_address = $data[0]->billing;
130
+ $shippings = $data['shipping_methods'];
131
+ $payments = $data['payments_methods'];
132
+ $ccsave = ($data['method_id'] == 'ccsave') ? $data['ccsave'] : null;
133
+ $items = $data[0]->items;
134
+ $session = $this->_addProductsToCart($items);
135
+ $quoteId = $this->prepareOrder($billing_address, '');
136
+ if (!$quoteId){
137
+ header("HTTP/1.0 400 Bad Request");
138
+ die('{error:400}');
139
+ }
140
+ $orderId = $this->createOrder($quoteId, '','');
141
+
142
+ if (!$orderId){
143
+ header("HTTP/1.0 400 Bad Request");
144
+ die('{error:400}');
145
+ }
146
+ }
147
+
148
+ public function paypalRedirect(){
149
+ if (!$_REQUEST['return'] || !$_REQUEST['cancel_return']){
150
+ header("HTTP/1.0 400 Bad Request");
151
+ die('{error:400}');
152
+ }
153
+ $standard = Mage::getModel('paypal/standard');
154
+ $form = new Varien_Data_Form();
155
+ $form->setAction($standard->getConfig()->getPaypalUrl())
156
+ ->setId('paypal_standard_checkout')
157
+ ->setName('paypal_standard_checkout')
158
+ ->setMethod('POST')
159
+ ->setUseContainer(true);
160
+ foreach ($standard->getStandardCheckoutFormFields() as $field=>$v) {
161
+ switch ($field) {
162
+ case 'return':
163
+ $value = $_REQUEST['return'];
164
+ break;
165
+ case 'cancel_return':
166
+ $value = $_REQUEST['cancel_return'];
167
+ break;
168
+
169
+ default:
170
+ $value = $v;
171
+ break;
172
+ }
173
+ $form->addField($field, 'hidden', array('name'=>$field, 'value'=>$value));
174
+ }
175
+ $idSuffix = Mage::helper('core')->uniqHash();
176
+ $submitButton = new Varien_Data_Form_Element_Submit(array(
177
+ 'value' => $this->__('Click here if you are not redirected within 10 seconds...'),
178
+ ));
179
+ $id = "submit_to_paypal_button_{$idSuffix}";
180
+ $submitButton->setId($id);
181
+ $form->addElement($submitButton);
182
+ $html = '<html><body>';
183
+ $html.= $this->__('You will be redirected to the PayPal website in a few seconds.');
184
+ $html.= $form->toHtml();
185
+ $html.= '<script type="text/javascript">document.getElementById("paypal_standard_checkout").submit();</script>';
186
+ $html.= '</body></html>';
187
+
188
+ echo $html;
189
+ }
190
+
191
+ // $email, $billing_address, $shipping_address, $shipping_method
192
+ /**
193
+ * @todo Shipping rate for configurable
194
+ */
195
+ public function prepareOrder($addressData, $shipping){
196
+ $shippingAddress = array(
197
+ 'firstname' => $addressData->firstName,
198
+ 'lastname' => $addressData->lastName,
199
+ 'email' => $addressData->email,
200
+ 'street' => array(
201
+ '0' => $addressData->addressLine1,
202
+ '1' => $addressData->addressLine2,
203
+ ),
204
+ 'city' => $addressData->city,
205
+ // 'region_id' => $addressData->regionId,
206
+ 'region' => $addressData->region,
207
+ 'postcode' => $addressData->zipcode,
208
+ 'country_id' => $addressData->country,
209
+ 'telephone' => $addressData->phone,
210
+ );
211
+ // create quote
212
+ $quoteObj = Mage::getModel('sales/quote');
213
+ $quoteObj->setIsMultiShipping(false);
214
+ $quoteObj->setCheckoutMethod('guest');
215
+ $quoteObj->setCustomerId(null);
216
+ $quoteObj->setCustomerEmail($email);
217
+ $quoteObj->setCustomerIsGuest(true);
218
+ $quoteObj->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID);
219
+
220
+ // set store
221
+ $quoteObj->setStore(Mage::app()->getStore());
222
+ // add products to quote
223
+ $quoteItem = null;
224
+ $cart_items = Mage::getSingleton('checkout/cart')->getQuote()->getAllVisibleItems();
225
+ foreach($cart_items as $item) {
226
+ $newItem = clone $item;
227
+ $quoteObj->addItem($newItem);
228
+ if ($item->getHasChildren()) {
229
+ foreach ($item->getChildren() as $child) {
230
+ $newChild = clone $child;
231
+ $newChild->setParentItem($newItem);
232
+ $quoteObj->addItem($newChild);
233
+ }
234
+ }
235
+ }
236
+ // addresses
237
+ $quoteShippingAddress = new Mage_Sales_Model_Quote_Address();
238
+ $quoteShippingAddress->setData($shippingAddress);
239
+ $quoteBillingAddress = new Mage_Sales_Model_Quote_Address();
240
+ $quoteBillingAddress->setData($shippingAddress);
241
+ $quoteObj->setShippingAddress($quoteShippingAddress);
242
+ $quoteObj->setBillingAddress($quoteBillingAddress);
243
+ // shipping method an collect
244
+ $quoteObj->getShippingAddress()->setShippingMethod('flatrate_flatrate');
245
+ $quoteObj->getShippingAddress()->setCollectShippingRates(true);
246
+ $quoteObj->collectTotals(); // calls $address->collectTotals();
247
+ $quoteObj->save();
248
+ $this->quoteId = $quoteObj->getId();
249
+ return $quoteObj->getId();
250
+ }
251
+
252
+ /**
253
+ * Gets a product associated with given configurable product by given params
254
+ * @param integer $id
255
+ * @param array $params
256
+ */
257
+ private function _getAssociatedProductByAttributes($id,$params){
258
+ $productModel = Mage::getModel('catalog/product');
259
+ $product = $productModel->load($id);
260
+ $instance = $product->getTypeInstance(true);
261
+ $associated_products = $instance->getUsedProducts(null, $product); // Получаем продукты
262
+ foreach($params as $key => $value){
263
+ $attr = $productModel->getResource()->getAttribute($key);
264
+ if ($attr->usesSource()) {
265
+ $params_ids[$key] = $attr->getSource()->getOptionId($value);
266
+ }
267
+ }
268
+ foreach($associated_products as $prod){
269
+ $flag = true;
270
+ foreach($params_ids as $key => $value){
271
+ if ($prod->getData()[$key] != $params_ids[$key]){
272
+ $flag = false;
273
+ }
274
+ }
275
+ if ($flag == true){
276
+ $result = $prod;
277
+ }
278
+ }
279
+ return $result;
280
+ }
281
+
282
+ public function createOrder($quoteId, $paymentMethod, $paymentData)
283
+ {
284
+ $quoteObj = Mage::getModel('sales/quote')->load($quoteId); // Mage_Sales_Model_Quote
285
+ $items = $quoteObj->getAllItems();
286
+ $quoteObj->reserveOrderId();
287
+
288
+ $paymentMethod = 'checkmo';
289
+ // set payment method
290
+ $quotePaymentObj = $quoteObj->getPayment(); // Mage_Sales_Model_Quote_Payment
291
+ $quotePaymentObj->setMethod($paymentMethod);
292
+ $quoteObj->setPayment($quotePaymentObj);
293
+
294
+ // convert quote to order
295
+ $convertQuoteObj = Mage::getSingleton('sales/convert_quote');
296
+
297
+ if($quoteObj->isVirtual() == 0) {
298
+ $orderObj = $convertQuoteObj->addressToOrder($quoteObj->getShippingAddress());
299
+ } else {
300
+ $orderObj = $convertQuoteObj->addressToOrder($quoteObj->getBillingAddress());
301
+ }
302
+
303
+ $orderPaymentObj = $convertQuoteObj->paymentToOrderPayment($quotePaymentObj);
304
+
305
+ // convert quote addresses
306
+ $orderObj->setBillingAddress($convertQuoteObj->addressToOrderAddress($quoteObj->getBillingAddress()));
307
+ if($quoteObj->isVirtual() == 0) {
308
+ $orderObj->setShippingAddress($convertQuoteObj->addressToOrderAddress($quoteObj->getShippingAddress()));
309
+ }
310
+ // set payment options
311
+ $orderObj->setPayment($convertQuoteObj->paymentToOrderPayment($quoteObj->getPayment()));
312
+ if ($paymentData) {
313
+ $orderObj->getPayment()->setCcNumber($paymentData->ccNumber);
314
+ $orderObj->getPayment()->setCcType($paymentData->ccType);
315
+ $orderObj->getPayment()->setCcExpMonth($paymentData->ccExpMonth);
316
+ $orderObj->getPayment()->setCcExpYear($paymentData->ccExpYear);
317
+ $orderObj->getPayment()->setCcLast4(substr($paymentData->ccNumber,-4));
318
+ }
319
+ // convert quote items
320
+ foreach ($items as $item) {
321
+ // @var $item Mage_Sales_Model_Quote_Item
322
+ $orderItem = $convertQuoteObj->itemToOrderItem($item);
323
+ if ($item->getParentItem()) {
324
+ $orderItem->setParentItem($orderObj->getItemByQuoteItemId($item->getParentItem()->getId()));
325
+ }
326
+ $orderObj->addItem($orderItem);
327
+ }
328
+
329
+ $orderObj->setCanShipPartiallyItem(false);
330
+
331
+ try {
332
+ $orderObj->place();
333
+ } catch (Exception $e){
334
+ Mage::log($e->getMessage());
335
+ Mage::log($e->getTraceAsString());
336
+ }
337
+
338
+ $orderObj->save();
339
+ $orderObj->sendNewOrderEmail();
340
+ Mage::getSingleton('checkout/session')->setLastOrderId($orderObj->getId())
341
+ ->setLastRealOrderId($orderObj->getIncrementId());
342
+ return $orderObj->getId();
343
+ unset ($orderObj, $quoteObj);
344
+ }
345
+
346
+ public function getCountries(){
347
+ $countries = Mage::getSingleton('directory/country')->getResourceCollection()
348
+ ->loadByStore()->toOptionArray();
349
+ array_shift($countries);
350
+ foreach ($countries as $key => $country) {
351
+ $regions = Mage::getModel('directory/region')->getResourceCollection()
352
+ ->addCountryFilter($country['value'])
353
+ ->load()->toOptionArray();
354
+ if ($regions){
355
+ array_shift($regions);
356
+ foreach ($regions as $i => $region) {
357
+ $countries[$key]['regions'][$i]['value'] = $region['value'];
358
+ $countries[$key]['regions'][$i]['label'] = $region['label'];
359
+ }
360
+ }else{
361
+ $countries[$key]['regions'] = array();
362
+ }
363
+ }
364
+ echo json_encode($countries);
365
+ }
366
+ /**
367
+ * Returns json-encoded array of available shipping methods with prices
368
+ * @param array $addressData
369
+ * @return string
370
+ */
371
+ public function getShippingMethodsAction(){
372
+ if (!$_POST['zipcode'] || !$_POST['country']){
373
+ header("HTTP/1.0 400 Bad Request");
374
+ die('{error:400}');
375
+ }
376
+ $addressData['zipcode'] = $_POST['zipcode'];
377
+ $addressData['region'] = $_POST['region'];
378
+ $addressData['city'] = $_POST['city'];
379
+ $addressData['country_id'] = $_POST['country'];
380
+
381
+ $session = Mage::getSingleton('checkout/session');
382
+ $address = $session->getQuote()->getShippingAddress()->addData($addressData);
383
+
384
+ $currencySym = Mage::app()->getLocale()->currency(Mage::app()->getStore()->getCurrentCurrencyCode())->getSymbol();
385
+
386
+ $rates = $address->setCollectShippingRates(true)->collectShippingRates()->getGroupedAllShippingRates();
387
+ $i = 0;
388
+ foreach ($rates as $code => $carrier) {
389
+ $title = Mage::getStoreConfig('carriers/'.$code.'/title');
390
+ $shipMethods[$i]["label"] = $title;
391
+ $shipMethods[$i]["id"] = $code;
392
+ $j = 0;
393
+ foreach ($carrier as $rate) {
394
+ // $shipMethods[$i]["rates"][] = array(
395
+ // "cost" => $currencySym.$rate->getPrice(),
396
+ // "label" => $rate->getMethodTitle()
397
+ // );
398
+ $shipMethods[$i]["rates"][$j]["cost"] = $currencySym.$rate->getPrice();
399
+ $shipMethods[$i]["rates"][$j]["label"] = $rate->getMethodTitle();
400
+ $j++;
401
+ }
402
+ $i++;
403
+ }
404
+ $paymentObj = Mage::getSingleton('payment/config');
405
+ $payments = $paymentObj->getActiveMethods();
406
+ $payMethods = array();
407
+ $i = 0;
408
+ foreach ($payments as $paymentCode => $paymentModel) {
409
+ if($paymentModel->canUseCheckout() == 1
410
+ && $paymentCode != 'free'
411
+ && $paymentCode != 'checkmo'
412
+ && $paymentCode != 'banktransfer'
413
+ && $paymentCode != 'cashondelivery'
414
+ && $paymentCode != 'googlecheckout'){
415
+
416
+ $cctypes = $paymentObj->getCcTypes();
417
+ $cardTypes = array();
418
+ $availableTypes = $paymentModel->getConfigData('cctypes');
419
+ if ($availableTypes) {
420
+ $availableTypes = explode(',', $availableTypes);
421
+ foreach ($cctypes as $code => $name) {
422
+ if (in_array($code, $availableTypes)) {
423
+ $cardTypes[] = array(
424
+ 'id' => $code,
425
+ 'label' => $name
426
+ );
427
+ }
428
+ }
429
+ }
430
+
431
+ $paymentTitle = Mage::getStoreConfig('payment/'.$paymentCode.'/title');
432
+ $useccv = Mage::getStoreConfig('payment/'.$paymentCode.'/useccv');
433
+ $payMethods[$i++] = array(
434
+ 'id' => $paymentCode,
435
+ 'label' => $paymentTitle,
436
+ 'useccv' => ($useccv) ? true : false,
437
+ 'cctypes' => $cardTypes
438
+ );
439
+ }
440
+ }
441
+ $result = array();
442
+ if (!$shipMethods || !$payMethods){
443
+ header("HTTP/1.0 400 Bad Request");
444
+ die('{error:400}');
445
+ }
446
+ else{
447
+ $result['shippings'] = $shipMethods;
448
+ $result['payments'] = $payMethods;
449
+ }
450
+ echo json_encode($result);
451
+ }
452
+
453
+ public function testAction(){
454
+ $this->prepareOrder();
455
+ $this->createOrder($this->quoteId);
456
+ }
457
+
458
+ /**
459
+ * Adds order into guest user cart and returns SID=session pair for login into the cart
460
+ * @param array $products
461
+ * @return string "SID=sessionid"
462
+ */
463
+ private function _addProductsToCart($products){
464
+ $cart = Mage::getSingleton('checkout/cart', array('name' => 'frontend'));
465
+ $cart->init();
466
+
467
+ if ($cart->getItemsCount()){
468
+ $cart->truncate();
469
+ }
470
+ foreach($products as $one){
471
+ $productModel = Mage::getModel('catalog/product');
472
+ $id = $productModel->getIdBySku($one->sku);
473
+ $product = $productModel->load($id);
474
+ $qty = Mage::getModel('cataloginventory/stock_item')->loadByProduct($id)->getQty();
475
+ $options = array();
476
+ $type = $product->getTypeId();
477
+ // var_dump($type);
478
+ switch($type){
479
+ case Mage_Catalog_Model_Product_Type::TYPE_SIMPLE: // Simple product (with attributes)
480
+ // if($one->options){
481
+ // foreach ($one->options as $opt => $value) {
482
+ // $option_id = $this->_getCustomOptionId($product, $opt);
483
+ // $option_value_id = $this->_getCustomOptionTypeId($product, $option_id, $value);
484
+ // $options[$option_id] = $option_value_id;
485
+ // }
486
+ // }
487
+ break;
488
+ case Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE:
489
+ $instance = $product->getTypeInstance(true);
490
+ $associated_products = $instance->getUsedProducts(null, $product);
491
+ $product = array_shift($associated_products);
492
+ // $conf = $this->_getAssociatedProductByAttributes($id,$one->options);
493
+ // $id = $conf->getEntityId();
494
+ // $product = $conf;
495
+ break;
496
+ }
497
+ try{
498
+ // $params = new Varien_Object(array(
499
+ // 'product' => $id,
500
+ // 'qty' => min($one->count, $qty),
501
+ // 'options' => $options
502
+ // ));
503
+ // $cart->addProduct($product, $params);
504
+ $cart->addProduct($product);
505
+ }catch (Exception $e){
506
+ print_r($e->getMessage());
507
+ exit;
508
+ }
509
+ }
510
+ $cart->save();
511
+
512
+ /** @var $session Mage_Checkout_Model_Session */
513
+ $session = Mage::getSingleton('core/session', array('name' => 'frontend'));
514
+ $session->setCartWasUpdated(true);
515
+ return $session->getSessionIdQueryParam() .'='. $session->getSessionId();
516
+ }
517
+
518
+ /**
519
+ * Gets option_id value for given product using option title
520
+ * @param $product
521
+ * @param string $title
522
+ * @return integer
523
+ */
524
+ private function _getCustomOptionId($product, $title){
525
+ foreach ($product->getOptions() as $option) {
526
+ if ($option["title"] == $title){
527
+ return $option["option_id"];
528
+ }
529
+ }
530
+ return 0;
531
+ }
532
+
533
+ /**
534
+ * Gets option_type_id value for given option and product
535
+ * @param $product
536
+ * @param $option_id
537
+ * @param string $title
538
+ * @return integer
539
+ */
540
+ private function _getCustomOptionTypeId($product, $option_id, $title){
541
+ foreach ($product->getOptions() as $option) {
542
+ if ($option["option_id"] == $option_id){
543
+ foreach ($option->getValues() as $value) {
544
+ if ($value["title"] == $title){
545
+ return $value["option_type_id"];
546
+ }
547
+ }
548
+ }
549
+ }
550
+ return 0;
551
+ }
552
+ /**
553
+ * Gets bundle product
554
+ * @param $current_product
555
+ * @return array
556
+ */
557
+ private function _getBundleProduct($current_product){
558
+ $components = array();
559
+ $bundle_items = Mage::getBlockSingleton('bundle/catalog_product_view_type_bundle')->setProduct($current_product)->getOptions();
560
+ foreach($bundle_items as $bundle){
561
+ $products = array();
562
+ $options = $bundle->getData();
563
+ $items = $options['selections'];
564
+
565
+ foreach($items as $i){
566
+ $product = $i->getData();
567
+ $tmp_product['id'] = $product['entity_id']; // Id продукта
568
+ $tmp_product['default_qty'] = $product['selection_qty']; // Дефолтное количество
569
+ $tmp_product['user_qty'] = (bool)$product['selection_can_change_qty']; // Может ли пользователь менять количество
570
+ $tmp_product['default'] = (bool)$product['is_default'];
571
+ $products[] = $tmp_product;
572
+ }
573
+
574
+ $components[] = array(
575
+ 'title' => $options['title'],
576
+ 'required' => (bool)$options['required'],
577
+ 'type' => $options['type'], // select, radio, checkbox, multi
578
+ 'products' => $products
579
+ );
580
+ }
581
+
582
+ return $components;
583
+ }
584
+
585
+ /**
586
+ * Get configurable product with its options
587
+ * @param $current_product
588
+ * @return array
589
+ */
590
+ private function _getConfigurableProduct($current_product){
591
+ $components = array();
592
+ $instance = $current_product->getTypeInstance(true);
593
+ $associated_products = $instance->getUsedProducts(null, $current_product); // Retrieves associated products
594
+ $product_attributes = $instance->getConfigurableAttributesAsArray($current_product); // Retrieves products attributes
595
+
596
+ $attributes = array();
597
+ $attributes_name = array();
598
+ $options = array();
599
+ foreach($product_attributes as $attribute){
600
+ $i = 0;
601
+ foreach($attribute['values'] as $v){
602
+ // Creating an array: array(attribute title => array(value id => array())
603
+ $options[ $attribute['attribute_code'] ][$i++] = array(
604
+ 'value' => $v['label'], // attribute label
605
+ 'pricing_value' => is_null($v['pricing_value']) ? "0" : $v['pricing_value'], // price
606
+ 'is_percent' => (bool)$v['is_percent'] // True - price is percentage, false - fixed
607
+ );
608
+ }
609
+ }
610
+ return $options;
611
+ }
612
+
613
+ /**
614
+ * Gets Custom options
615
+ * @param $current_product
616
+ * @return array
617
+ */
618
+ private function _getOptions($current_product){
619
+ $options = array();
620
+
621
+ return $options;
622
+ }
623
+
624
+ /**
625
+ * Retrievies all (or recently updated) products,
626
+ * creates gzip-archive with json-encoded info and returns the link
627
+ */
628
+ public function productsAction(){
629
+ $collection = Mage::getModel('catalog/product')->getCollection() /** @var $collection */
630
+ ->joinField('stock_status','cataloginventory/stock_status','stock_status',
631
+ 'product_id=entity_id', array(
632
+ 'stock_status' => Mage_CatalogInventory_Model_Stock_Status::STATUS_IN_STOCK,
633
+ 'website_id' => Mage::app()->getWebsite()->getWebsiteId(),
634
+ ))
635
+ ->addAttributeToFilter('status', 1)
636
+ ->addAttributeToSelect('name')
637
+ ->addAttributeToSelect('description')
638
+ ->addAttributeToSelect('price')
639
+ ->addAttributeToSelect('image')
640
+ ->addAttributeToSelect('category')
641
+ ->addAttributeToSelect('category_ids')
642
+ ->addAttributeToSelect('url_path');
643
+ if(!empty($_REQUEST['from_ts'])){
644
+ $from_ts = (int)$_REQUEST['from_ts'];
645
+ if($from_ts > mktime(0, 0, 0, 0, 0, 2000) && $from_ts < time()){
646
+ $collection = $collection->addAttributeToFilter('updated_at', array('gt' => date('Y.m.d H:i:s', $from_ts)));
647
+ }
648
+ }
649
+ if(count($collection)){
650
+ addMediaGalleryAttributeToCollection($collection);
651
+ }
652
+ $products = array();
653
+ foreach($collection as $one){ /** @var $one Mage_Catalog_Model_Product */
654
+ $categories = $one->getCategoryIds();
655
+ if ($categories){
656
+ //making images array
657
+ $images = array();
658
+ if($imgCollection = $one->getMediaGalleryImages()){
659
+ $baseImage = $one->image;
660
+ foreach($imgCollection as $img){
661
+ if($img->file == $baseImage){
662
+ $images[] = array('path' => $img->url, 'status' => 1);
663
+ }else{
664
+ $images[] = array('path' => $img->url, 'status' => 0);
665
+ }
666
+ }
667
+ }
668
+ //info about the product
669
+ $options = array();
670
+
671
+ $type = $one->getTypeId();
672
+ switch($type){
673
+ case Mage_Catalog_Model_Product_Type::TYPE_BUNDLE: // Product type is Bundle
674
+ $options = $this->_getBundleProduct($one);
675
+ break;
676
+ case Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE: // Product type is Configurable
677
+ $options = $this->_getConfigurableProduct($one);
678
+ break;
679
+ }
680
+
681
+ $products[$one->getEntityId()] = array(
682
+ 'name' => $one->name,
683
+ 'sku' => $one->getSku(),
684
+ 'desc' => $one->description,
685
+ 'images' => $images,
686
+ 'price' => $one->getPrice(), //may be high load caused by "calculatePrice"
687
+ 'category' => $categories,
688
+ 'type' => $type, // simple, bundle, configurable
689
+ 'options' => $options,
690
+ 'components' => array()
691
+ );
692
+ }
693
+
694
+ }
695
+
696
+ // Gathering option values
697
+ $optionId2values = array();
698
+ $collection = Mage::getResourceModel('catalog/product_option_value_collection')->getValues(0);
699
+ foreach($collection as $one){
700
+ $data = $one->getData();
701
+ $optionId2values[ $data['option_id'] ][$data['option_type_id']] = array(
702
+ 'value' => $data['title'],
703
+ 'pricing_value' => $data['price'],
704
+ 'is_percent' => ($data['price_type'] == 'fixed') ? false : true, // fixed, percent
705
+ 'sku' => $data['sku'],
706
+ 'order' => $data['sort_order']
707
+ );
708
+ }
709
+
710
+ //Gathering custom options
711
+ $collection = Mage::getModel('catalog/product_option')
712
+ ->getCollection()
713
+ ->addTitleToResult(0)
714
+ ->addPriceToResult(0);
715
+ foreach($collection as $one){
716
+ $data = $one->getData();
717
+ $oid = $data['option_id'];
718
+ $oname = $data['title'];
719
+ $pid = $data['product_id'];
720
+ if(isset($products[$pid])){
721
+ $params = array(
722
+ 'option_id' => $oid,
723
+ 'type' => $data['type'],
724
+ 'required' => (bool)$data['is_require'],
725
+ 'order' => $data['sort_order']
726
+ );
727
+ $products[$pid]['options'][$oname]['_params'] = $params;
728
+ if (!empty($optionId2values[$oid])){
729
+ $products[$pid]['options'][$oname] += array_values($optionId2values[$oid]);
730
+ }
731
+ }
732
+ }
733
+
734
+ if ($data = self::_openArchive(self::DELETED_PRODUCTS_INFO)){
735
+ $deleted = preg_split('/,/', $data);
736
+ foreach ($deleted as $deleted_id) {
737
+ $products[$deleted_id]['type'] = "deleted";
738
+ }
739
+ unset($data);
740
+ unset($deleted);
741
+ }
742
+
743
+ unset($collection);
744
+ unset($optionId2values);
745
+ //dumping all
746
+ $archive = self::_createArchive('products', json_encode($products));
747
+ $response = array('link' => Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB) . 'var/'.self::YEAH_TEMP_DIR.'/'.$archive);
748
+ echo json_encode($response);
749
+ }
750
+
751
+ /**
752
+ * Retrievies all the categories, creates gzip-archive and returns the link
753
+ */
754
+ public function categoriesAction(){
755
+ $collection = Mage::getModel('catalog/category')->getCollection()
756
+ ->addAttributeToSelect('name')
757
+ ->addAttributeToSelect('image')
758
+ ->addAttributeToSelect('url_path')
759
+ ->addAttributeToSelect('is_active');
760
+
761
+ if(!empty($_REQUEST['from_ts'])){
762
+ $from_ts = (int)$_REQUEST['from_ts'];
763
+ if($from_ts > mktime(0, 0, 0, 0, 0, 2000) && $from_ts < time()){
764
+ $collection = $collection->addAttributeToFilter('updated_at', array('gt' => date('Y.m.d H:i:s', $from_ts)));
765
+ }
766
+ }
767
+
768
+ $cats = array();
769
+ $root_cat_id = Mage::app()->getStore()->getRootCategoryId();
770
+ $root_parent = null;
771
+ foreach($collection as $cat){
772
+ $cat_id = $cat->getEntityId();
773
+ //we memorize parent of root category in order to delete it in future
774
+ //we don't write the root category also
775
+ if($cat_id == $root_cat_id){
776
+ $root_parent = $cat->parent_id;
777
+ continue;
778
+ }
779
+ $parent_id = $cat->parent_id == $root_cat_id ? 0 : $cat->parent_id;
780
+ $cats[$cat_id] = array(
781
+ 'path' => '/'.$cat->url_path,
782
+ 'name' => $cat->name,
783
+ 'pid' => $parent_id,
784
+ 'img' => $cat->getImageUrl(),
785
+ 'isActive' => (bool)$cat->is_active,
786
+ );
787
+ }
788
+ //deleting parent of root category
789
+ if(!is_null($root_parent)){
790
+ unset($cats[$root_parent]);
791
+ }
792
+
793
+ $archive = self::_createArchive('category', json_encode($cats));
794
+ $response = array('link' => Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB) . 'var/'.self::YEAH_TEMP_DIR.'/'.$archive);
795
+ echo json_encode($response);
796
+ }
797
+
798
+ /**
799
+ * @param string $type
800
+ * @param string $data
801
+ * @throws Exception
802
+ * @return string File name
803
+ */
804
+ private static function _createArchive($type, $data){
805
+ if($type != 'category' && $type != 'products'){
806
+ throw new Exception('Wrong type: '.$type);
807
+ }
808
+
809
+ self::_cleanOldFiles();
810
+
811
+ $fname = $type."_".date('Y_m_d_H_i_s') . '.gz';
812
+ $path = self::_getVarFolder() . $fname;
813
+ $f = gzopen($path, 'w9');
814
+ gzwrite($f, $data);
815
+ gzclose($f);
816
+ return $fname;
817
+ }
818
+
819
+ /**
820
+ * @param string $fname
821
+ * @return string File content
822
+ */
823
+ private static function _openArchive($fname){
824
+ $path = self::_getVarFolder() . $fname;
825
+ $f = gzopen($path,'r');
826
+ $data = gzread($f, 10000);
827
+ gzclose($f);
828
+ return substr($data, 0, -1);
829
+ }
830
+
831
+ /**
832
+ * Clean old files
833
+ */
834
+ private function _cleanOldFiles(){
835
+ $path = self::_getVarFolder();
836
+ $files = scandir($path);
837
+ $prods = array_filter($files, function($v){ return preg_match('/^products_\d\d\d\d(_\d\d){5}\.gz$/', $v); });
838
+ $cats = array_filter($files, function($v){ return preg_match('/^category_\d\d\d\d(_\d\d){5}\.gz$/', $v); });
839
+ unset($files);
840
+ sort($prods);
841
+ sort($cats);
842
+ while(count($prods) > 2){
843
+ $file = array_shift($prods);
844
+ unlink($path.$file);
845
+ }
846
+ while(count($cats) > 2){
847
+ $file = array_shift($cats);
848
+ unlink($path.$file);
849
+ }
850
+ unlink($path.self::DELETED_PRODUCTS_INFO);
851
+ }
852
+
853
+ /**
854
+ * Checks that data folder in "var" is created and "htaccess" is set up
855
+ * @return string
856
+ */
857
+ private static function _getVarFolder(){
858
+ $var_dir = Mage::getBaseDir() . DS . 'var' . DS . self::YEAH_TEMP_DIR . DS;
859
+ if(!file_exists($var_dir)){
860
+ mkdir($var_dir, 0777);
861
+ //create htaccess file
862
+ $htaccess = $var_dir . '.htaccess';
863
+ $hf = fopen($htaccess, 'w');
864
+ fwrite($hf, "Order allow,deny\nAllow from all");
865
+ fclose($hf);
866
+ }
867
+ return $var_dir;
868
+ }
869
+ }
870
+
871
+ /**
872
+ * A really magic function. But there is no better way to load gallery images
873
+ * along with product collection
874
+ * @link http://www.magentocommerce.com/boards/viewthread/17414/#t141830
875
+ * @param $_productCollection
876
+ * @return
877
+ */
878
+ function addMediaGalleryAttributeToCollection($_productCollection) {
879
+ $_mediaGalleryAttributeId = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'media_gallery')->getAttributeId();
880
+ $_read = Mage::getSingleton('core/resource')->getConnection('catalog_read');
881
+
882
+ $_mediaGalleryData = $_read->fetchAll('
883
+ SELECT
884
+ main.entity_id, `main`.`value_id`, `main`.`value` AS `file`,
885
+ `value`.`label`, `value`.`position`, `value`.`disabled`, `default_value`.`label` AS `label_default`,
886
+ `default_value`.`position` AS `position_default`,
887
+ `default_value`.`disabled` AS `disabled_default`
888
+ FROM `catalog_product_entity_media_gallery` AS `main`
889
+ LEFT JOIN `catalog_product_entity_media_gallery_value` AS `value`
890
+ ON main.value_id=value.value_id AND value.store_id=' . Mage::app()->getStore()->getId() . '
891
+ LEFT JOIN `catalog_product_entity_media_gallery_value` AS `default_value`
892
+ ON main.value_id=default_value.value_id AND default_value.store_id=0
893
+ WHERE (
894
+ main.attribute_id = ' . $_read->quote($_mediaGalleryAttributeId) . ')
895
+ AND (main.entity_id IN (' . $_read->quote($_productCollection->getAllIds()) . '))
896
+ ORDER BY IF(value.position IS NULL, default_value.position, value.position) ASC
897
+ ');
898
+
899
+
900
+ $_mediaGalleryByProductId = array();
901
+ foreach ($_mediaGalleryData as $_galleryImage) {
902
+ $k = $_galleryImage['entity_id'];
903
+ unset($_galleryImage['entity_id']);
904
+ if (!isset($_mediaGalleryByProductId[$k])) {
905
+ $_mediaGalleryByProductId[$k] = array();
906
+ }
907
+ $_mediaGalleryByProductId[$k][] = $_galleryImage;
908
+ }
909
+ unset($_mediaGalleryData);
910
+ foreach ($_productCollection as &$_product) {
911
+ $_productId = $_product->getData('entity_id');
912
+ if (isset($_mediaGalleryByProductId[$_productId])) {
913
+ $_product->setData('media_gallery', array('images' => $_mediaGalleryByProductId[$_productId]));
914
+ }
915
+ }
916
+ unset($_mediaGalleryByProductId);
917
+
918
+ return $_productCollection;
919
+ }
920
  ?>
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>YeahCommerce_Catalog_Sync_Extension</name>
4
- <version>1.0.17</version>
5
  <stability>stable</stability>
6
  <license>GNU General Public License (GPL)</license>
7
  <channel>community</channel>
@@ -37,7 +37,7 @@ With Yeah!Commerce you get apps on:&#xD;
37
  &#xD;
38
  You can find more info at http://yeahcommerce.com&#xD;
39
  If you have any questions feel free to contact Yeah!Commerce support at mail@yeahcommerce.com</description>
40
- <notes>Version: 1.0.17&#xD;
41
  Stability: Stable&#xD;
42
  Notes: This module allows you to synchronize your product catalog with your Yeah!Commerce account.&#xD;
43
  Integration includes synchronization between your shop and your Yeah!Commerce apps:&#xD;
@@ -49,12 +49,12 @@ You can find more info at http://yeahcommerce.com&#xD;
49
  - Product Images&#xD;
50
  - Product Info&#xD;
51
  - Product Prices&#xD;
52
- New in version 1.0.17:&#xD;
53
- - Version Stability fixed to 'Stable'</notes>
54
  <authors><author><name>Boris Udachin</name><user>yeahcommerce</user><email>mail@yeahcommerce.com</email></author><author><name>Ilya Savinkov</name><user>Ilya_Savinkov</user><email>ilya.s@144mln.com</email></author><author><name>Anton Fedorov</name><user>afedorov42</user><email>afedorov42@gmail.com</email></author></authors>
55
- <date>2013-09-10</date>
56
- <time>06:47:13</time>
57
- <contents><target name="magecommunity"><dir name="YeahCommerce"><dir name="Sync"><dir name="Block"><file name="Lastchange.php" hash="e129e84293e56bff51fd7343cdd0431e"/></dir><dir name="Helper"><file name="Data.php" hash="1122ba5bb3664ac0ec269eac2303b49e"/></dir><dir name="Model"><file name="Mobile_Detect.php" hash="c7612e9fe3ed9c72b0f40a91ebf423ab"/><file name="Observer.php" hash="f747c0d2fed93bdb4d43f1408c676e0d"/></dir><dir name="controllers"><file name="IndexController.php" hash="4add1d07b57f4b84b02be92331d9ec37"/></dir><dir name="etc"><file name="config.xml" hash="351a42e064644e9335db86eb3ab91459"/><file name="system.xml" hash="b885b82688e14949e0a6a3fe4ed05d16"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="YeahCommerce_Sync.xml" hash="96e137d8bb2a0bb9111608aa3ed8af09"/></dir></target></contents>
58
  <compatible/>
59
  <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php><extension><name>zlib</name><min>1.0.9</min><max>/</max></extension><extension><name>curl</name><min/><max/></extension></required></dependencies>
60
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>YeahCommerce_Catalog_Sync_Extension</name>
4
+ <version>1.0.18</version>
5
  <stability>stable</stability>
6
  <license>GNU General Public License (GPL)</license>
7
  <channel>community</channel>
37
  &#xD;
38
  You can find more info at http://yeahcommerce.com&#xD;
39
  If you have any questions feel free to contact Yeah!Commerce support at mail@yeahcommerce.com</description>
40
+ <notes>Version: 1.0.18&#xD;
41
  Stability: Stable&#xD;
42
  Notes: This module allows you to synchronize your product catalog with your Yeah!Commerce account.&#xD;
43
  Integration includes synchronization between your shop and your Yeah!Commerce apps:&#xD;
49
  - Product Images&#xD;
50
  - Product Info&#xD;
51
  - Product Prices&#xD;
52
+ New in version 1.0.18:&#xD;
53
+ - Synchronization for deleted products</notes>
54
  <authors><author><name>Boris Udachin</name><user>yeahcommerce</user><email>mail@yeahcommerce.com</email></author><author><name>Ilya Savinkov</name><user>Ilya_Savinkov</user><email>ilya.s@144mln.com</email></author><author><name>Anton Fedorov</name><user>afedorov42</user><email>afedorov42@gmail.com</email></author></authors>
55
+ <date>2013-10-07</date>
56
+ <time>08:38:23</time>
57
+ <contents><target name="magecommunity"><dir name="YeahCommerce"><dir name="Sync"><dir name="Block"><file name="Lastchange.php" hash="e129e84293e56bff51fd7343cdd0431e"/></dir><dir name="Helper"><file name="Data.php" hash="1122ba5bb3664ac0ec269eac2303b49e"/></dir><dir name="Model"><file name="Mobile_Detect.php" hash="c7612e9fe3ed9c72b0f40a91ebf423ab"/><file name="Observer.php" hash="39779c61873624e67cde8caa58b80498"/></dir><dir name="controllers"><file name="IndexController.php" hash="41f8a4f4f8dd50c1b3434318f0c7b475"/></dir><dir name="etc"><file name="config.xml" hash="351a42e064644e9335db86eb3ab91459"/><file name="system.xml" hash="b885b82688e14949e0a6a3fe4ed05d16"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="YeahCommerce_Sync.xml" hash="96e137d8bb2a0bb9111608aa3ed8af09"/></dir></target></contents>
58
  <compatible/>
59
  <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php><extension><name>zlib</name><min>1.0.9</min><max>/</max></extension><extension><name>curl</name><min/><max/></extension></required></dependencies>
60
  </package>