Onefeed_Catalogfeed - Version 0.1.0

Version Notes

Export your product catalogue to integrate with the Onefeed feed management and optimisation service.

Download this release

Release Info

Developer Onefeed
Extension Onefeed_Catalogfeed
Version 0.1.0
Comparing to
See all releases


Version 0.1.0

app/code/local/Onefeed/Catalogfeed/Block/Adminhtml/Button.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Onefeed_Catalogfeed_Block_Adminhtml_Button extends Mage_Adminhtml_Block_System_Config_Form_Field
3
+ {
4
+ /*
5
+ * Set template
6
+ */
7
+ protected function _construct()
8
+ {
9
+ parent::_construct();
10
+ $this->setTemplate('onefeed/button.phtml');
11
+ }
12
+
13
+ /**
14
+ * Return element html
15
+ *
16
+ * @param Varien_Data_Form_Element_Abstract $element
17
+ * @return string
18
+ */
19
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
20
+ {
21
+ return $this->_toHtml();
22
+ }
23
+
24
+ /**
25
+ * Return ajax url for button
26
+ *
27
+ * @return string
28
+ */
29
+ public function getAjaxIndexUrl()
30
+ {
31
+ return Mage::helper('adminhtml')->getUrl('admin_catalogfeed/adminhtml_catalogfeedbackend/index');
32
+ }
33
+
34
+ public function getAjaxCheckUrl()
35
+ {
36
+ return Mage::helper('adminhtml')->getUrl('admin_catalogfeed/adminhtml_catalogfeedbackend/check');
37
+ }
38
+
39
+ /**
40
+ * Generate button html
41
+ *
42
+ * @return string
43
+ */
44
+ public function getButtonHtml()
45
+ {
46
+ $button = $this->getLayout()->createBlock('adminhtml/widget_button')
47
+ ->setData(array(
48
+ 'id' => 'check_button',
49
+ 'label' => $this->helper('adminhtml')->__('Export Now'),
50
+ 'onclick' => 'javascript:run(); return false;'
51
+ ));
52
+
53
+ return $button->toHtml();
54
+ }
55
+ }
app/code/local/Onefeed/Catalogfeed/Helper/Data.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Onefeed_Catalogfeed_Helper_Data extends Mage_Core_Helper_Abstract
3
+ {
4
+ public function isActive($store_id=null)
5
+ {
6
+ return Mage::getStoreConfig("onefeed_config/onefeed_general/enabled", $store_id);
7
+ }
8
+ }
app/code/local/Onefeed/Catalogfeed/Model/Adminhtml/System/Config/Backend/Cron.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Onefeed_Catalogfeed_Model_Adminhtml_System_Config_Backend_Cron extends Mage_Core_Model_Config_Data
3
+ {
4
+ const CRON_STRING_PATH = 'crontab/jobs/onefeed/schedule/cron_expr';
5
+
6
+ protected function _afterSave()
7
+ {
8
+ $time = $this->getData('groups/configurable_cron/fields/time/value');
9
+
10
+ $frequencyDaily = Mage_Adminhtml_Model_System_Config_Source_Cron_Frequency::CRON_DAILY;
11
+ $frequencyWeekly = Mage_Adminhtml_Model_System_Config_Source_Cron_Frequency::CRON_WEEKLY;
12
+ $frequencyMonthly = Mage_Adminhtml_Model_System_Config_Source_Cron_Frequency::CRON_MONTHLY;
13
+
14
+ $cronDayOfWeek = date('N');
15
+
16
+ $cronExprArray = array(
17
+ intval($time[1]), # Minute
18
+ intval($time[0]), # Hour
19
+ (frequency == $frequencyMonthly) ? '1' : '*', # Day of the Month
20
+ '*', # Month of the Year
21
+ (frequency == $frequencyWeekly) ? '1' : '*', # Day of the Week
22
+ );
23
+ $cronExprString = join(' ', $cronExprArray);
24
+
25
+ try {
26
+ Mage::getModel('core/config_data')
27
+ ->load(self::CRON_STRING_PATH, 'path')
28
+ ->setValue($cronExprString)
29
+ ->setPath(self::CRON_STRING_PATH)
30
+ ->save();
31
+ }
32
+ catch (Exception $e) {
33
+ throw new Exception(Mage::helper('cron')->__('Unable to save the cron expression.'));
34
+
35
+ }
36
+ }
37
+ }
app/code/local/Onefeed/Catalogfeed/Model/Cron.php ADDED
@@ -0,0 +1,768 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Onefeed_Catalogfeed_Model_Cron{
3
+
4
+ private $_tablePrefix;
5
+ private $_storeId;
6
+ private $_websiteId;
7
+ private $_mediaBaseUrl;
8
+ private $_webBaseUrl;
9
+ private $_mediaBasePath;
10
+ private $_dbi;
11
+ private $IncludeDisabled;
12
+ private $ExcludeOutOfStock;
13
+ private $DownloadAsAttachment;
14
+ private $_FtpHostName;
15
+ private $_FtpUserName;
16
+ private $_FtpPassword;
17
+ private $_selectLimit;
18
+ public $_lockFile;
19
+ public $_delimiter;
20
+
21
+
22
+ public function __construct(){
23
+ // Get the table prefix
24
+ $tableName = Mage::getSingleton('core/resource')->getTableName('core_website');
25
+ $this->_tablePrefix = substr($tableName, 0, strpos($tableName, 'core_website'));
26
+ $websites = Mage::app()->getWebsites();
27
+ $this->_websiteId = $websites[1]->getId();
28
+ $this->_storeId = $websites[1]->getDefaultStore()->getId();
29
+ $this->_mediaBaseUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA);
30
+ $this->_webBaseUrl = Mage::getBaseUrl();
31
+ $this->_dbi = Mage::getSingleton('core/resource') ->getConnection('core_read');
32
+ $this->_mediaBasePath = Mage::getBaseDir('media');
33
+ // check if onefeed dir exist
34
+ if(!file_exists($this->_mediaBasePath . DS . 'onefeed')){
35
+ mkdir($this->_mediaBasePath . DS .'onefeed' , 0777 , true);
36
+ chmod($this->_mediaBasePath . DS .'onefeed' , 0777);
37
+ }
38
+ $this->ExcludeOutOfStock = (Mage::getStoreConfig('onefeed_config/onefeed_defaults/excludeoutofstock') == '1') ? true : false;
39
+ $this->IncludeDisabled = (Mage::getStoreConfig('onefeed_config/onefeed_defaults/includedisabled') == '1') ? true : false;
40
+
41
+ // SET FTP Credentials
42
+ $this->_FtpHostName = 'ftp.onefeed.co.uk';
43
+ $this->_FtpUserName = Mage::getStoreConfig('onefeed_config/onefeed_ftp/username');
44
+ $this->_FtpPassword = Mage::getStoreConfig('onefeed_config/onefeed_ftp/password');
45
+
46
+ // set default select limit to 500
47
+ $this->_selectLimit = 5000;
48
+ if($this->getFreeMemory() > 500)
49
+ {
50
+ $this->_selectLimit = 5000+(int)(($this->getFreeMemory()-500));
51
+ }
52
+ $this->_lockFile = Mage::getBaseDir('var') . DS . 'onefeed.lock';
53
+ $this->_delimiter= Mage::getStoreConfig('onefeed_config/onefeed_defaults/delimeter');
54
+ }
55
+
56
+ public function generateFeed(){
57
+ // Run extraction
58
+ if(Mage::helper('catalogfeed')->isActive()){
59
+ return $this->_extractFromMySQL();
60
+ }else{
61
+ return false;
62
+ }
63
+ }
64
+
65
+
66
+ public function forceGenerateFeed(){
67
+ // Run extraction
68
+ return $this->_extractFromMySQL();
69
+ }
70
+ // Apply prefix to table names in the query
71
+ private function _applyTablePrefix($query)
72
+ {
73
+ return str_replace('PFX_', $this->_tablePrefix, $query);
74
+ }
75
+
76
+ // Extract natively directly from the database
77
+ private function _extractFromMySQL()
78
+ {
79
+ // set execution time to 3 mins
80
+ ini_set('max_execution_time', 100);
81
+ $exportContinue = false;
82
+ // Set up a file name
83
+ if(Mage::getStoreConfig('onefeed_config/onefeed_defaults/filename')!=''){
84
+ $FileName = sprintf('%s.csv',Mage::getStoreConfig('onefeed_config/onefeed_defaults/filename'));
85
+ } else {
86
+ $FileName = sprintf('%s_%d_%d.csv', date('Y-m-d'), $this->_websiteId, $this->_storeId);
87
+ }
88
+ //read lock file and manage accordingly
89
+ $lockVar = unserialize(file_get_contents($this->_lockFile));
90
+ // check if lock variable exist
91
+ if($lockVar){
92
+ // check if today export
93
+ if($lockVar['date'] == Mage::getModel('core/date')->date('Y-m-d'))
94
+ {
95
+ // check if export for today is done
96
+ if($lockVar['status'] == 'done'){
97
+ Mage::log('Export for '.$lockVar['date'].' is done' , null , 'onefeed.log');
98
+ return false;
99
+ }
100
+ // if last time is < 1 min than do not run
101
+ if($lockVar['timestamp'] > strtotime("-1 min") && $lockVar['status'] == 'continue')
102
+ {
103
+ Mage::log('Export for '.$lockVar['date'].' is running' , null , 'onefeed.log');
104
+ Mage::log('Current Datetime: '.date("Y-m-d H:i:s").' and Last run on :'.date("Y-m-d H:i:s",$lockVar['timestamp']) , null , 'onefeed.log');
105
+ return false;
106
+ }
107
+ else{
108
+ $exportContinue = true;
109
+ // file handler start in append mode
110
+ $fp = fopen($this->_mediaBasePath . DS .'onefeed'.DS.$FileName, 'a+');
111
+
112
+ }
113
+ }
114
+ else
115
+ {
116
+ // start fresh export
117
+ // file handler start in fresh write mode
118
+ $fp = fopen($this->_mediaBasePath . DS .'onefeed'.DS.$FileName, 'w');
119
+ }
120
+ }
121
+ else
122
+ {
123
+ $lockVar['date'] = Mage::getModel('core/date')->date('Y-m-d');
124
+ $lockVar['timestamp'] = time();
125
+ $lockVar['status'] = 'continue';
126
+ $lockVar['exported_entity_id'] = 0;
127
+ file_put_contents($this->_lockFile , serialize($lockVar));
128
+ $fp = fopen($this->_mediaBasePath . DS .'onefeed'.DS.$FileName, 'w');
129
+
130
+ }
131
+
132
+ if(empty($fp))
133
+ {
134
+ $fp = fopen($this->_mediaBasePath . DS .'onefeed'.DS.$FileName, 'w');
135
+ }
136
+ // Start sending file
137
+ // Check if Amasty Product Labels table exists
138
+ $query = "SHOW TABLES LIKE 'PFX_am_label'";
139
+ $query = $this->_applyTablePrefix($query);
140
+ $AmastyProductLabelsTableExists = $this->_dbi->fetchOne($query);
141
+ $AmastyProductLabelsTableExists = !empty($AmastyProductLabelsTableExists);
142
+
143
+ // Create a lookup table for the SKU to label_id
144
+ $AmastyProductLabelsLookupTable = array();
145
+ if($AmastyProductLabelsTableExists == true)
146
+ {
147
+ // NOTE: Only fetch simple labels and ignore all matching rules.
148
+ // include_type=0 means "all matching SKUs and listed SKUs"
149
+ // include_type=1 means "all matching SKUs EXCEPT listed SKUs"
150
+ // include_type=2 means "listed SKUs only"
151
+ $query = "SELECT label_id, name, include_sku
152
+ FROM PFX_am_label
153
+ WHERE include_type IN (0,2)
154
+ ORDER BY pos DESC";
155
+ $query = $this->_applyTablePrefix($query);
156
+ $labelsTable = $this->_dbi->fetchAll($query);
157
+ // Load each label into the lookup table
158
+ foreach($labelsTable as $row)
159
+ {
160
+ // Get the comma-separated SKUs
161
+ $skus = explode(",", $row[2]);
162
+ // Add each SKU to the lookup table
163
+ foreach($skus as $sku)
164
+ {
165
+ $AmastyProductLabelsLookupTable[$sku] = array($row[0], $row[1]);
166
+ }
167
+ }
168
+ }
169
+
170
+ // Increase maximium length for group_concat (for additional image URLs field)
171
+ $query = "SET SESSION group_concat_max_len = 1000000;";
172
+ $this->_dbi->query($query);
173
+
174
+ // By default, set media gallery attribute id to 703
175
+ // Look it up later
176
+ $MEDIA_GALLERY_ATTRIBUTE_ID = 703;
177
+
178
+
179
+ // Get the entity type for products
180
+ $query = "SELECT entity_type_id FROM PFX_eav_entity_type
181
+ WHERE entity_type_code = 'catalog_product'";
182
+ $query = $this->_applyTablePrefix($query);
183
+ $PRODUCT_ENTITY_TYPE_ID = $this->_dbi->fetchOne($query);
184
+
185
+
186
+ // Get attribute codes and types
187
+ $query = "SELECT attribute_id, attribute_code, backend_type, frontend_input
188
+ FROM PFX_eav_attribute
189
+ WHERE entity_type_id = $PRODUCT_ENTITY_TYPE_ID
190
+ ";
191
+ $query = $this->_applyTablePrefix($query);
192
+ $attributes = $this->_dbi->fetchAssoc($query);
193
+ $attributeCodes = array();
194
+ $blankProduct = array();
195
+ $blankProduct['sku'] = '';
196
+ foreach($attributes as $row)
197
+ {
198
+ // Save attribute ID for media gallery
199
+ if($row['attribute_code'] == 'media_gallery')
200
+ {
201
+ $MEDIA_GALLERY_ATTRIBUTE_ID = $row['attribute_id'];
202
+ }
203
+
204
+ switch($row['backend_type'])
205
+ {
206
+ case 'datetime':
207
+ case 'decimal':
208
+ case 'int':
209
+ case 'text':
210
+ case 'varchar':
211
+ $attributeCodes[$row['attribute_id']] = $row['attribute_code'];
212
+ $blankProduct[$row['attribute_code']] = '';
213
+ break;
214
+ case 'static':
215
+ // ignore columns in entity table
216
+ // print("Skipping static attribute: ".$row['attribute_code']."\n");
217
+ break;
218
+ default:
219
+ // print("Unsupported backend_type: ".$row['backend_type']."\n");
220
+ break;
221
+ }
222
+
223
+ // If the type is multiple choice, cache the option values
224
+ // in a lookup array for performance (avoids several joins/aggregations)
225
+ if($row['frontend_input'] == 'select' || $row['frontend_input'] == 'multiselect')
226
+ {
227
+ // Get the option_id => value from the attribute options
228
+ $query = "
229
+ SELECT
230
+ CASE WHEN SUM(aov.store_id) = 0 THEN MAX(aov.option_id) ELSE
231
+ MAX(CASE WHEN aov.store_id = ".$this->_storeId." THEN aov.option_id ELSE NULL END)
232
+ END AS 'option_id'
233
+ ,CASE WHEN SUM(aov.store_id) = 0 THEN MAX(aov.value) ELSE
234
+ MAX(CASE WHEN aov.store_id = ".$this->_storeId." THEN aov.value ELSE NULL END)
235
+ END AS 'value'
236
+ FROM PFX_eav_attribute_option AS ao
237
+ INNER JOIN PFX_eav_attribute_option_value AS aov
238
+ ON ao.option_id = aov.option_id
239
+ WHERE aov.store_id IN (".$this->_storeId.", 0)
240
+ AND ao.attribute_id = ".$row['attribute_id']."
241
+ GROUP BY aov.option_id
242
+ ";
243
+ $query = $this->_applyTablePrefix($query);
244
+ $result = $this->_dbi->fetchPairs($query);
245
+
246
+ // If found, then save the lookup table in the attributeOptions array
247
+ if(is_array($result))
248
+ {
249
+ $attributeOptions[$row['attribute_id']] = $result;
250
+ }
251
+ else
252
+ {
253
+ // Otherwise, leave a blank array
254
+ $attributeOptions[$row['attribute_id']] = array();
255
+ }
256
+ $result = null;
257
+ }
258
+
259
+ }
260
+ $blankProduct['onefeed_product_url'] = '';
261
+ $blankProduct['onefeed_image_url'] = '';
262
+ $blankProduct['onefeed_additional_image_url'] = '';
263
+ $blankProduct['onefeed_additional_image_value_id'] = '';
264
+ $blankProduct['json_categories'] = '';
265
+ $blankProduct['json_tier_pricing'] = '';
266
+ $blankProduct['qty'] = 0;
267
+ $blankProduct['stock_status'] = '';
268
+ $blankProduct['onefeed_color_attribute_id'] = '';
269
+ $blankProduct['onefeed_regular_price'] = '';
270
+ $blankProduct['parent_id'] = '';
271
+ $blankProduct['entity_id'] = '';
272
+ $blankProduct['created_at'] = '';
273
+ $blankProduct['updated_at'] = '';
274
+ if($AmastyProductLabelsTableExists == true)
275
+ {
276
+ $blankProduct['amasty_label_id'] = '';
277
+ $blankProduct['amasty_label_name'] = '';
278
+ }
279
+
280
+ // Build queries for each attribute type
281
+ $backendTypes = array(
282
+ 'datetime',
283
+ 'decimal',
284
+ 'int',
285
+ 'text',
286
+ 'varchar',
287
+ );
288
+ $queries = array();
289
+ foreach($backendTypes as $backendType)
290
+ {
291
+ // Get store value if there is one, otherwise, global value
292
+ $queries[] = "
293
+ SELECT CASE WHEN SUM(ev.store_id) = 0 THEN MAX(ev.value) ELSE
294
+ MAX(CASE WHEN ev.store_id = ".$this->_storeId." THEN ev.value ELSE NULL END)
295
+ END AS 'value', ev.attribute_id
296
+ FROM PFX_catalog_product_entity
297
+ INNER JOIN PFX_catalog_product_entity_$backendType AS ev
298
+ ON PFX_catalog_product_entity.entity_id = ev.entity_id
299
+ WHERE ev.store_id IN (".$this->_storeId.", 0)
300
+ AND ev.entity_type_id = $PRODUCT_ENTITY_TYPE_ID
301
+ AND ev.entity_id = @ENTITY_ID
302
+ GROUP BY ev.attribute_id, ev.entity_id
303
+ ";
304
+ }
305
+ $query = implode(" UNION ALL ", $queries);
306
+ $MasterProductQuery = $query;
307
+
308
+ // Get all entity_ids for all products in the selected store
309
+ // into an array - require SKU to be defined
310
+ // check if exportContinue is set
311
+ if(!$exportContinue){
312
+ $query = "
313
+ SELECT cpe.entity_id
314
+ FROM PFX_catalog_product_entity AS cpe
315
+ INNER JOIN PFX_catalog_product_website as cpw
316
+ ON cpw.product_id = cpe.entity_id
317
+ WHERE cpw.website_id = ".$this->_websiteId."
318
+ AND IFNULL(cpe.sku, '') != ''
319
+ LIMIT 0, ".$this->_selectLimit."
320
+ ";
321
+ }
322
+ else{
323
+ $query = "
324
+ SELECT cpe.entity_id
325
+ FROM PFX_catalog_product_entity AS cpe
326
+ INNER JOIN PFX_catalog_product_website as cpw
327
+ ON cpw.product_id = cpe.entity_id
328
+ WHERE cpw.website_id = ".$this->_websiteId."
329
+ AND IFNULL(cpe.sku, '') != '' AND cpe.entity_id > ".$lockVar['exported_entity_id']."
330
+ LIMIT 0, ".$this->_selectLimit."
331
+ ";
332
+ }
333
+ $query = $this->_applyTablePrefix($query);
334
+ // Just fetch the entity_id column to save memory
335
+ $entity_ids = $this->_dbi->fetchCol($query);
336
+
337
+
338
+ // check if $entity_ids count is zero than export is done
339
+ if(count($entity_ids) == 0)
340
+ {
341
+ $lockVar['timestamp'] = time();
342
+ $lockVar['status'] = 'done';
343
+ file_put_contents($this->_lockFile , serialize($lockVar));
344
+ Mage::log('Entity id count ==0 cron export finish' , null , 'onefeed.log');
345
+ return true;
346
+ }
347
+
348
+
349
+ // Print header row
350
+ $headerFields = array();
351
+ $headerFields[] = 'sku';
352
+ foreach($attributeCodes as $fieldName)
353
+ {
354
+ $headerFields[] = str_replace('"', '""', $fieldName);
355
+ }
356
+ $headerFields[] = 'onefeed_product_url';
357
+ $headerFields[] = 'onefeed_image_url';
358
+ $headerFields[] = 'onefeed_additional_image_url';
359
+ $headerFields[] = 'onefeed_additional_image_value_id';
360
+ $headerFields[] = 'json_categories';
361
+
362
+ $headerFields[] = 'json_tier_pricing';
363
+ $headerFields[] = 'qty';
364
+ $headerFields[] = 'stock_status';
365
+ $headerFields[] = 'onefeed_color_attribute_id';
366
+ $headerFields[] = 'onefeed_regular_price';
367
+ $headerFields[] = 'parent_id';
368
+ $headerFields[] = 'entity_id';
369
+ $headerFields[] = 'created_at';
370
+ $headerFields[] = 'updated_at';
371
+ if($AmastyProductLabelsTableExists == true)
372
+ {
373
+ $headerFields[] = 'amasty_label_id';
374
+ $headerFields[] = 'amasty_label_name';
375
+ }
376
+
377
+ $headerFields[] = 'category';
378
+ $headerFields[] = 'category2';
379
+ $headerFields[] = 'category3';
380
+
381
+ //print '"'.implode('","', $headerFields).'"'."\n";
382
+
383
+ // check if exportContinue mode is on than do not print headers
384
+ if(!$exportContinue)
385
+ {
386
+ fputcsv($fp ,$headerFields,$this->_delimiter);
387
+ }
388
+
389
+ // Loop through each product and output the data
390
+ foreach($entity_ids as $entity_id)
391
+ {
392
+ // Check if the item is out of stock and skip if needed
393
+ if($this->ExcludeOutOfStock == true)
394
+ {
395
+ $query = "
396
+ SELECT stock_status
397
+ FROM PFX_cataloginventory_stock_status AS ciss
398
+ WHERE ciss.website_id = ".$this->_websiteId."
399
+ AND ciss.product_id = ".$entity_id."
400
+ ";
401
+ $query = $this->_applyTablePrefix($query);
402
+ $stock_status = $this->_dbi->fetchOne($query);
403
+ // If stock status not found or equal to zero, skip the item
404
+ if(empty($stock_status))
405
+ {
406
+ continue;
407
+ }
408
+ }
409
+
410
+ // Create a new product record
411
+ $product = $blankProduct;
412
+ $product['entity_id'] = $entity_id;
413
+
414
+ // Get the basic product information
415
+ $query = "
416
+ SELECT cpe.sku, cpe.created_at, cpe.updated_at
417
+ FROM PFX_catalog_product_entity AS cpe
418
+ WHERE cpe.entity_id = ".$entity_id."
419
+ ";
420
+ $query = $this->_applyTablePrefix($query);
421
+ $entity = $this->_dbi->fetchRow($query);
422
+ if(empty($entity) == true)
423
+ {
424
+ continue;
425
+ }
426
+
427
+ // Initialize basic product data
428
+ $product['sku'] = $entity['sku'];
429
+ $product['created_at'] = $entity['created_at'];
430
+ $product['updated_at'] = $entity['updated_at'];
431
+
432
+ // Set label information
433
+ if($AmastyProductLabelsTableExists == true)
434
+ {
435
+ // Check if the SKU has a label
436
+ if(array_key_exists($product['sku'], $AmastyProductLabelsLookupTable) == true)
437
+ {
438
+ // Set the label ID and name
439
+ $product['amasty_label_id'] = $AmastyProductLabelsLookupTable[$product['sku']][0];
440
+ $product['amasty_label_name'] = $AmastyProductLabelsLookupTable[$product['sku']][1];
441
+ }
442
+ }
443
+
444
+ // Fill the master query with the entity ID
445
+ $query = str_replace('@ENTITY_ID', $entity_id, $MasterProductQuery);
446
+ $query = $this->_applyTablePrefix($query);
447
+ $result = $this->_dbi->query($query);
448
+
449
+ // Escape the SKU (it may contain double-quotes)
450
+ $product['sku'] = str_replace('"', '""', $product['sku']);
451
+
452
+ // Loop through each field in the row and get the value
453
+ while(true)
454
+ {
455
+ // Get next column
456
+ // $column[0] = value
457
+ // $column[1] = attribute_id
458
+ $column = $result->fetch(Zend_Db::FETCH_NUM);
459
+ // Break if no more rows
460
+ if(empty($column))
461
+ {
462
+ break;
463
+ }
464
+ // Skip attributes that don't exist in eav_attribute
465
+ if(!isset($attributeCodes[$column[1]]))
466
+ {
467
+ continue;
468
+ }
469
+
470
+ // Save color attribute ID (for CJM automatic color swatches extension)
471
+ // NOTE: do this prior to translating option_id to option_value below
472
+ if($attributeCodes[$column[1]] == 'color')
473
+ {
474
+ $product['onefeed_color_attribute_id'] = $column[0];
475
+ }
476
+
477
+ // Translate the option option_id to a value.
478
+ if(isset($attributeOptions[$column[1]]) == true)
479
+ {
480
+ // Convert all option values
481
+ $optionValues = explode(',', $column[0]);
482
+ $convertedOptionValues = array();
483
+ foreach($optionValues as $optionValue)
484
+ {
485
+ if(isset($attributeOptions[$column[1]][$optionValue]) == true)
486
+ {
487
+ // If a option_id is found, translate it
488
+ $convertedOptionValues[] = $attributeOptions[$column[1]][$optionValue];
489
+ }
490
+ }
491
+ // Erase values that are set to zero
492
+ if($column[0] == '0')
493
+ {
494
+ $column[0] = '';
495
+ }
496
+ elseif(empty($convertedOptionValues) == false)
497
+ {
498
+ // Use convert values if any conversions exist
499
+ $column[0] = implode(',', $convertedOptionValues);
500
+ }
501
+ // Otherwise, leave value as-is
502
+ }
503
+
504
+ // Escape double-quotes and add to product array
505
+
506
+ if($attributeCodes[$column[1]]=='description' || $attributeCodes[$column[1]]=='short_description')
507
+ {
508
+ $product[$attributeCodes[$column[1]]] = htmlspecialchars(strip_tags(str_replace(array("\n", "\t", "\r"), array(" "," "," "), $column[0])), ENT_QUOTES);
509
+ } else {
510
+ $product[$attributeCodes[$column[1]]] = str_replace('"', '""',str_replace(array("\n", "\t", "\r"), array(" "," "," "), $column[0]));
511
+ }
512
+
513
+ }
514
+
515
+ $result = null;
516
+
517
+ // Skip product that are disabled or have no status
518
+ // if the checkbox is not checked (this is the default setting)
519
+ if($this->IncludeDisabled == false)
520
+ {
521
+ if(empty($product['status']) || $product['status'] == Mage_Catalog_Model_Product_Status::STATUS_DISABLED)
522
+ {
523
+ continue;
524
+ }
525
+ }
526
+
527
+ // Get category information
528
+ $query = "
529
+ SELECT fs.entity_id, fs.path, fs.name
530
+ FROM PFX_catalog_category_product_index AS pi
531
+ INNER JOIN PFX_catalog_category_flat_store_".$this->_storeId." AS fs
532
+ ON pi.category_id = fs.entity_id
533
+ WHERE pi.product_id = ".$entity_id."
534
+ ";
535
+ $query = $this->_applyTablePrefix($query);
536
+ $categoriesTable = $this->_dbi->fetchAll($query);
537
+ // Save entire table in JSON format
538
+ $product['json_categories'] = json_encode($categoriesTable);
539
+ // Escape double-quotes
540
+ $product['json_categories'] = str_replace('"', '""', $product['json_categories']);
541
+
542
+ //get category,sub category,sub-sub-category
543
+
544
+ $query_cat1 = "
545
+ SELECT fs.name
546
+ FROM PFX_catalog_category_product_index AS pi
547
+ INNER JOIN PFX_catalog_category_flat_store_".$this->_storeId." AS fs
548
+ ON pi.category_id = fs.entity_id
549
+ WHERE pi.product_id = ".$entity_id." AND level=1
550
+ ";
551
+
552
+
553
+ $query_cat1 = $this->_applyTablePrefix($query_cat1);
554
+ $categoriesTable1 = $this->_dbi->fetchOne($query_cat1);
555
+ // Save entire table in JSON format
556
+ $product['category'] = $categoriesTable1;
557
+
558
+
559
+ $query_cat2 = "
560
+ SELECT fs.name
561
+ FROM PFX_catalog_category_product_index AS pi
562
+ INNER JOIN PFX_catalog_category_flat_store_".$this->_storeId." AS fs
563
+ ON pi.category_id = fs.entity_id
564
+ WHERE pi.product_id = ".$entity_id." AND level=2
565
+ ";
566
+
567
+ $query_cat2 = $this->_applyTablePrefix($query_cat2);
568
+ $categoriesTable2 = $this->_dbi->fetchOne($query_cat2);
569
+ // Save entire table in JSON format
570
+ $product['category2'] = $categoriesTable2;
571
+
572
+ $query_cat3 = "
573
+ SELECT fs.name
574
+ FROM PFX_catalog_category_product_index AS pi
575
+ INNER JOIN PFX_catalog_category_flat_store_".$this->_storeId." AS fs
576
+ ON pi.category_id = fs.entity_id
577
+ WHERE pi.product_id = ".$entity_id." AND level=3
578
+ ";
579
+
580
+ $query_cat3 = $this->_applyTablePrefix($query_cat3);
581
+
582
+ $categoriesTable3 = $this->_dbi->fetchOne($query_cat3);
583
+ // Save entire table in JSON format
584
+ $product['category3'] = $categoriesTable3;
585
+
586
+
587
+ // Get stock quantity
588
+ // NOTE: stock_id = 1 is the 'Default' stock
589
+ $query = "
590
+ SELECT qty, stock_status
591
+ FROM PFX_cataloginventory_stock_status
592
+ WHERE product_id=".$entity_id."
593
+ AND website_id=".$this->_websiteId."
594
+ AND stock_id = 1";
595
+ $query = $this->_applyTablePrefix($query);
596
+ $stockInfoResult = $this->_dbi->query($query);
597
+ $stockInfo = $stockInfoResult->fetch();
598
+ if(empty($stockInfo) == true)
599
+ {
600
+ $product['qty'] = '0';
601
+ $product['stock_status'] = '';
602
+ }
603
+ else
604
+ {
605
+ $product['qty'] = $stockInfo['qty'];
606
+ $product['stock_status'] = $stockInfo['stock_status'];
607
+ }
608
+ $stockInfoResult = null;
609
+
610
+ // Get additional image URLs
611
+ $galleryImagePrefix = $this->_dbi->quote($this->_mediaBaseUrl.'catalog/product');
612
+ $query = "
613
+ SELECT
614
+ GROUP_CONCAT(gallery.value_id SEPARATOR ',') AS value_id
615
+ ,GROUP_CONCAT(CONCAT(".$galleryImagePrefix.", gallery.value) SEPARATOR ',') AS value
616
+ FROM PFX_catalog_product_entity_media_gallery AS gallery
617
+ INNER JOIN PFX_catalog_product_entity_media_gallery_value AS gallery_value
618
+ ON gallery.value_id = gallery_value.value_id
619
+ WHERE gallery_value.store_id IN (".$this->_storeId.", 0)
620
+ AND gallery_value.disabled = 0
621
+ AND gallery.entity_id=".$entity_id."
622
+ AND gallery.attribute_id = ".$MEDIA_GALLERY_ATTRIBUTE_ID."
623
+ ORDER BY gallery_value.position ASC";
624
+ $query = $this->_applyTablePrefix($query);
625
+ $galleryValues = $this->_dbi->fetchAll($query);
626
+ if(empty($galleryValues) != true)
627
+ {
628
+ // Save value IDs for CJM automatic color swatches extension support
629
+
630
+ $product['onefeed_additional_image_value_id'] = $galleryValues[0][0];
631
+ $product['onefeed_additional_image_url'] = $galleryValues[0][1];
632
+ }
633
+
634
+ // Get parent ID
635
+ $query = "
636
+ SELECT GROUP_CONCAT(parent_id SEPARATOR ',') AS parent_id
637
+ FROM PFX_catalog_product_super_link AS super_link
638
+ WHERE super_link.product_id=".$entity_id."";
639
+ $query = $this->_applyTablePrefix($query);
640
+ $parentId = $this->_dbi->fetchAll($query);
641
+ if(empty($parentId) != true)
642
+ {
643
+ // Save value IDs for CJM automatic color swatches extension support
644
+ $product['parent_id'] = $parentId[0]['parent_id'];
645
+ }
646
+
647
+ // Get the regular price (before any catalog price rule is applied)
648
+ $product['onefeed_regular_price'] = $product['price'];
649
+
650
+ // Override price with catalog price rule, if found
651
+ $query = "
652
+ SELECT crpp.rule_price
653
+ FROM PFX_catalogrule_product_price AS crpp
654
+ WHERE crpp.rule_date = CURDATE()
655
+ AND crpp.product_id = ".$entity_id."
656
+ AND crpp.customer_group_id = 1
657
+ AND crpp.website_id = ".$this->_websiteId;
658
+ $query = $this->_applyTablePrefix($query);
659
+ $rule_price = $this->_dbi->fetchAll($query);
660
+ if(empty($rule_price) != true)
661
+ {
662
+ // Override price with catalog rule price
663
+ $product['price'] = $rule_price[0][0];
664
+ }
665
+
666
+ // Calculate image and product URLs
667
+ if(empty($product['url_path']) == false)
668
+ {
669
+ $product['onefeed_product_url'] = $this->_urlPathJoin($this->_webBaseUrl, $product['url_path']);
670
+ }
671
+ if(empty($product['image']) == false)
672
+ {
673
+ $product['onefeed_image_url'] = $this->_urlPathJoin($this->_mediaBaseUrl, 'catalog/product');
674
+ $product['onefeed_image_url'] = $this->_urlPathJoin($product['onefeed_image_url'], $product['image']);
675
+ }
676
+
677
+ // Get tier pricing information
678
+ $query = "
679
+ SELECT tp.qty, tp.value
680
+ FROM PFX_catalog_product_entity_tier_price AS tp
681
+ WHERE tp.entity_id = ".$entity_id."
682
+ AND tp.website_id IN (0, ".$this->_websiteId.")
683
+ AND tp.all_groups = 1
684
+ AND tp.customer_group_id = 0
685
+ ";
686
+ $query = $this->_applyTablePrefix($query);
687
+ $tierPricingTable = $this->_dbi->fetchAll($query);
688
+ // Save entire table in JSON format
689
+ $product['json_tier_pricing'] = json_encode($tierPricingTable);
690
+ // Escape double-quotes
691
+ $product['json_tier_pricing'] = str_replace('"', '""', $product['json_tier_pricing']);
692
+
693
+ // Print out the line in CSV format
694
+ //print '"'.implode('","', $product).'"'."\n";
695
+ fputcsv($fp ,$product,$this->_delimiter);
696
+
697
+ // re-write lock variable
698
+ $lockVar['date'] = Mage::getModel('core/date')->date('Y-m-d');
699
+ $lockVar['timestamp'] = time();
700
+ $lockVar['status'] = 'continue';
701
+ $lockVar['exported_entity_id'] = $entity_id;
702
+ file_put_contents($this->_lockFile , serialize($lockVar));
703
+ }
704
+ // now send file to FTP
705
+ $lockVar = unserialize(file_get_contents($this->_lockFile));
706
+ if($lockVar['status']=='done' && $lockVar['date']== Mage::getModel('core/date')->date('Y-m-d')){
707
+ return true;
708
+ }
709
+ else
710
+ {
711
+ $source = $this->_mediaBasePath . DS .'onefeed'.DS.$FileName;
712
+ $dest = $FileName;
713
+ $flocal = fopen($source, 'r');
714
+ $ftp = new Varien_Io_Ftp();
715
+ if(strlen($this->_FtpUserName)>0 && strlen($this->_FtpPassword)>0){
716
+ $ftp->open(
717
+ array(
718
+ 'host' => $this->_FtpHostName,
719
+ 'user' => $this->_FtpUserName,
720
+ 'password' => $this->_FtpPassword,
721
+ )
722
+ );
723
+ $ftp_w = $ftp->write($dest, $flocal);
724
+ $ftp->close();
725
+ }
726
+ $lockVar['date'] = Mage::getModel('core/date')->date('Y-m-d');
727
+ $lockVar['timestamp'] = time();
728
+ $lockVar['status'] = 'done';
729
+ file_put_contents($this->_lockFile , serialize($lockVar));
730
+ }
731
+ }
732
+
733
+ // Join two URL paths and handle forward slashes
734
+ private function _urlPathJoin($part1, $part2)
735
+ {
736
+ return rtrim($part1, '/').'/'.ltrim($part2, '/');
737
+ }
738
+
739
+ // Print the results of a select query to output for debugging purposes and exit
740
+ private function _debugPrintQuery($query)
741
+ {
742
+ $query = "SELECT 1";
743
+ print '<pre>';
744
+ print_r($this->_dbi->fetchAll($query));
745
+ print '</pre>';
746
+ exit();
747
+ }
748
+
749
+ public function getFreeMemory()
750
+ {
751
+ $used = memory_get_usage(true)/1048576;
752
+ $limitStr = (int)ini_get('memory_limit');
753
+ $limitStr = trim($limitStr);
754
+ $last = strtolower($limitStr[strlen($limitStr)-1]);
755
+ switch($last) {
756
+ // The 'G' modifier is available since PHP 5.1.0
757
+ case 'g':
758
+ $limit *= 1024;
759
+ case 'm':
760
+ $limit *= 1024;
761
+ case 'k':
762
+ $limit *= 1024;
763
+ }
764
+ $limit = $limit/1048576;
765
+ return $limit - $used;
766
+ }
767
+
768
+ }
app/code/local/Onefeed/Catalogfeed/controllers/Adminhtml/CatalogfeedbackendController.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Onefeed_Catalogfeed_Adminhtml_CatalogfeedbackendController extends Mage_Adminhtml_Controller_Action
3
+ {
4
+ public function indexAction()
5
+ {
6
+ $lockFile = Mage::getBaseDir('var') . DS . 'onefeed.lock';
7
+ unlink($lockFile);
8
+ $obj = new Onefeed_Catalogfeed_Model_Cron();
9
+ $obj->forceGenerateFeed();
10
+ echo "start";die();
11
+ }
12
+ public function checkAction(){
13
+ $lockFile = Mage::getBaseDir('var') . DS . 'onefeed.lock';
14
+ $lockVar = unserialize(file_get_contents($lockFile));
15
+ if($lockVar['status']=='done' && $lockVar['date']== Mage::getModel('core/date')->date('Y-m-d'))
16
+ {
17
+ echo "1";
18
+ Mage::getSingleton('adminhtml/session')->addSuccess('Feed generated successfully');
19
+ } else {
20
+ echo "0";
21
+ Mage::getSingleton('adminhtml/session')->addError('An error occurred.');
22
+ }
23
+ die();
24
+ }
25
+ }
app/code/local/Onefeed/Catalogfeed/etc/adminhtml.xml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <acl>
4
+ <resources>
5
+ <admin>
6
+ <children>
7
+ <system>
8
+ <children>
9
+ <config>
10
+ <children>
11
+ <onefeed_config translate="title" module="catalogfeed">
12
+ <title>One Feed Config Section</title>
13
+ <sort_order>10</sort_order>
14
+ </onefeed_config>
15
+ </children>
16
+ </config>
17
+ </children>
18
+ </system>
19
+ </children>
20
+ </admin>
21
+ </resources>
22
+ </acl>
23
+ </config>
app/code/local/Onefeed/Catalogfeed/etc/config.xml ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Onefeed_Catalogfeed>
5
+ <version>0.1.0</version>
6
+ </Onefeed_Catalogfeed>
7
+ </modules>
8
+ <global>
9
+ <blocks>
10
+ <catalogfeed>
11
+ <class>Onefeed_Catalogfeed_Block</class>
12
+ </catalogfeed>
13
+ </blocks>
14
+ <helpers>
15
+ <catalogfeed>
16
+ <class>Onefeed_Catalogfeed_Helper</class>
17
+ </catalogfeed>
18
+ </helpers>
19
+ <models>
20
+ <catalogfeed>
21
+ <class>Onefeed_Catalogfeed_Model</class>
22
+ <resourceModel>catalogfeed_mysql4</resourceModel>
23
+ </catalogfeed>
24
+ </models>
25
+ </global>
26
+ <crontab>
27
+ <jobs>
28
+ <onefeed>
29
+ <run>
30
+ <model>catalogfeed/cron::generateFeed</model>
31
+ </run>
32
+ </onefeed>
33
+ </jobs>
34
+ </crontab>
35
+
36
+ <admin>
37
+ <routers>
38
+ <catalogfeed>
39
+ <use>admin</use>
40
+ <args>
41
+ <module>Onefeed_Catalogfeed</module>
42
+ <frontName>admin_catalogfeed</frontName>
43
+ </args>
44
+ </catalogfeed>
45
+ </routers>
46
+ </admin>
47
+ <adminhtml>
48
+ <layout>
49
+ <updates>
50
+ <catalogfeed>
51
+ <file>catalogfeed.xml</file>
52
+ </catalogfeed>
53
+ </updates>
54
+ </layout>
55
+ </adminhtml>
56
+
57
+ <default>
58
+ <onefeed_config>
59
+ <onefeed_defaults>
60
+ <delimeter>|</delimeter>
61
+ </onefeed_defaults>
62
+ </onefeed_config>
63
+ </default>
64
+ </config>
app/code/local/Onefeed/Catalogfeed/etc/system.xml ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <tabs>
4
+ <onefeed translate="label" module="catalogfeed">
5
+ <label>One Feed</label>
6
+ <sort_order>0</sort_order>
7
+ </onefeed>
8
+ </tabs>
9
+ <sections>
10
+ <onefeed_config translate="label" module="catalogfeed">
11
+ <label>One Feed Config</label>
12
+ <tab>onefeed</tab>
13
+ <frontend_type>text</frontend_type>
14
+ <sort_order>0</sort_order>
15
+ <show_in_default>1</show_in_default>
16
+ <show_in_website>0</show_in_website>
17
+ <show_in_store>0</show_in_store>
18
+ <groups>
19
+
20
+ <onefeed_general translate="label">
21
+ <label>General</label>
22
+ <frontend_type>text</frontend_type>
23
+ <sort_order>100</sort_order>
24
+ <show_in_default>1</show_in_default>
25
+ <show_in_website>1</show_in_website>
26
+ <show_in_store>1</show_in_store>
27
+ <fields>
28
+ <enabled translate="label">
29
+ <label>Enabled</label>
30
+ <frontend_type>select</frontend_type>
31
+ <source_model>adminhtml/system_config_source_yesno</source_model>
32
+ <sort_order>0</sort_order>
33
+ <show_in_default>1</show_in_default>
34
+ <show_in_website>1</show_in_website>
35
+ <show_in_store>1</show_in_store>
36
+ </enabled>
37
+ </fields>
38
+ </onefeed_general>
39
+ <onefeed_ftp translate="label">
40
+ <label>Onefeed FTP</label>
41
+ <frontend_type>text</frontend_type>
42
+ <sort_order>200</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
+ <fields>
47
+ <username translate="label">
48
+ <label>User Name</label>
49
+ <frontend_type>text</frontend_type>
50
+ <sort_order>10</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
+ <comment>Username</comment>
55
+ </username>
56
+ <password translate="label">
57
+ <label>Password</label>
58
+ <frontend_type>password</frontend_type>
59
+ <sort_order>20</sort_order>
60
+ <show_in_default>1</show_in_default>
61
+ <show_in_website>0</show_in_website>
62
+ <show_in_store>0</show_in_store>
63
+ <comment>Password</comment>
64
+ </password>
65
+ </fields>
66
+ </onefeed_ftp>
67
+ <onefeed_defaults>
68
+ <label>Onefeed Defaults</label>
69
+ <frontend_type>text</frontend_type>
70
+ <sort_order>300</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
+ <excludeoutofstock translate="label">
76
+ <label>Exclude Out Of Stock</label>
77
+ <frontend_type>select</frontend_type>
78
+ <source_model>adminhtml/system_config_source_yesno</source_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
+ <comment>Remove Out Of Stock from FEED</comment>
84
+ </excludeoutofstock>
85
+ <includedisabled translate="label">
86
+ <label>Include Disabled</label>
87
+ <frontend_type>select</frontend_type>
88
+ <source_model>adminhtml/system_config_source_yesno</source_model>
89
+ <sort_order>20</sort_order>
90
+ <show_in_default>1</show_in_default>
91
+ <show_in_website>0</show_in_website>
92
+ <show_in_store>0</show_in_store>
93
+ <comment>Include Disabled Products in FEED</comment>
94
+ </includedisabled>
95
+ <filename translate="label">
96
+ <label>File Name</label>
97
+ <frontend_type>text</frontend_type>
98
+
99
+ <sort_order>30</sort_order>
100
+ <show_in_default>1</show_in_default>
101
+ <show_in_website>0</show_in_website>
102
+ <show_in_store>0</show_in_store>
103
+ <comment>Name of file to save feed</comment>
104
+ </filename>
105
+ <delimeter translate="label">
106
+ <label>Delimeter</label>
107
+ <frontend_type>text</frontend_type>
108
+
109
+ <sort_order>30</sort_order>
110
+ <show_in_default>1</show_in_default>
111
+ <show_in_website>0</show_in_website>
112
+ <show_in_store>0</show_in_store>
113
+ <comment>delimeter for csv seprator</comment>
114
+ </delimeter>
115
+ </fields>
116
+ </onefeed_defaults>
117
+ <configurable_cron translate="label">
118
+ <label>Cron Schedule</label>
119
+ <sort_order>400</sort_order>
120
+ <show_in_default>1</show_in_default>
121
+ <show_in_website>0</show_in_website>
122
+ <show_in_store>0</show_in_store>
123
+ <fields>
124
+ <time translate="label">
125
+ <label>Start Time</label>
126
+ <frontend_type>time</frontend_type>
127
+ <sort_order>10</sort_order>
128
+ <show_in_default>1</show_in_default>
129
+ <show_in_website>1</show_in_website>
130
+ <show_in_store>1</show_in_store>
131
+ </time>
132
+ <frequency translate="label">
133
+ <label>Frequency</label>
134
+ <frontend_type>select</frontend_type>
135
+ <source_model>adminhtml/system_config_source_cron_frequency</source_model>
136
+ <backend_model>catalogfeed/adminhtml_system_config_backend_cron</backend_model>
137
+ <sort_order>20</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
+ </frequency>
142
+ </fields>
143
+ </configurable_cron>
144
+ <tools translate="label">
145
+ <label>Export</label>
146
+ <sort_order>500</sort_order>
147
+ <show_in_default>1</show_in_default>
148
+ <show_in_website>1</show_in_website>
149
+ <show_in_store>1</show_in_store>
150
+ <fields>
151
+ <check translate="label">
152
+ <label>Export</label>
153
+ <frontend_type>button</frontend_type>
154
+ <frontend_model>Onefeed_Catalogfeed_Block_Adminhtml_Button</frontend_model>
155
+ <sort_order>10</sort_order>
156
+ <show_in_default>1</show_in_default>
157
+ <show_in_website>1</show_in_website>
158
+ <show_in_store>1</show_in_store>
159
+ </check>
160
+ </fields>
161
+ </tools>
162
+ </groups>
163
+ </onefeed_config>
164
+ </sections>
165
+ </config>
app/design/adminhtml/default/default/template/onefeed/button.phtml ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script type="text/javascript">
2
+ //<![CDATA[
3
+ function run() {
4
+ new Ajax.Request('<?php echo $this->getAjaxIndexUrl() ?>', {
5
+ method: 'get',
6
+ onSuccess: function(transport){
7
+ if (transport.responseText="start"){
8
+ $('check_button').disable();
9
+ check();
10
+ }
11
+ }
12
+ });
13
+ }
14
+ function check(){
15
+ new Ajax.Request('<?php echo $this->getAjaxCheckUrl() ?>', {
16
+ method: 'get',
17
+ onSuccess: function(transport){
18
+ if (transport.responseText){
19
+ $('check_button').enable();
20
+ window.location.reload();
21
+ }
22
+ }
23
+ });
24
+ //setTimeout(function(){ check(); }, 5000);
25
+ }
26
+ //]]>
27
+ </script>
28
+
29
+ <?php echo $this->getButtonHtml() ?>
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Onefeed_CatalogFeed</name>
4
+ <version>0.1.0</version>
5
+ <stability>stable</stability>
6
+ <license>OSL v3.0</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Export your product catalogue to integrate with the Onefeed feed management and optimisation service.</summary>
10
+ <description> Onefeed is a leading feed management and Google Shopping optimisation company. The Magento feed exporter allows for seamless integration into the Onefeed platform. The exporter uploads a fully comprehensive product datafeed into the FTP location of Onefeed. With a scheduler built in it&#x2019;s a very straight forward way of automating the delivery of your datafeed to Onefeed. Onefeed will optimise and management performance of your data on all shopping channels and most importantly Google Shopping. Onefeed is also a certified Google Partner which means your performance and management is in safe hands.</description>
11
+ <notes>Export your product catalogue to integrate with the Onefeed feed management and optimisation service.</notes>
12
+ <authors><author><name>Onefeed</name><user>Onefeed</user><email>rich@onefeed.co.uk</email></author></authors>
13
+ <date>2016-03-09</date>
14
+ <time>15:51:51</time>
15
+ <contents><target name="magelocal"><dir name="Onefeed"><dir name="Catalogfeed"><dir name="Block"><dir name="Adminhtml"><file name="Button.php" hash="030eefe5a822f205963e7afc55f0b27d"/></dir></dir><dir name="Helper"><file name="Data.php" hash="15b58ec437058e8f4180a0618e7de574"/></dir><dir name="Model"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Backend"><file name="Cron.php" hash="eab5b701d86d9d5940bc85e7bdedeb92"/></dir></dir></dir></dir><file name="Cron.php" hash="e7c2374610f4849491a22e05d646ed7f"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="CatalogfeedbackendController.php" hash="1b24daded216da28a7ac5c3064b26b57"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="edcb7b428b07f4b71b3bafbd2c66cc0e"/><file name="config.xml" hash="134b375c13f800e3164af3966fd7ac5c"/><file name="system.xml" hash="f328e7b15f0d863c5d38951b040f410e"/></dir></dir></dir><dir name="modules"><file name="Onefeed_Catalogfeed.xml" hash=""/></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="onefeed"><file name="button.phtml" hash="e4436369269b4af6045425b50f73089f"/></dir></dir></dir></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>