Doofinder_Feed - Version 1.6.5

Version Notes

Correctly handle custom boost fields.

Download this release

Release Info

Developer Carlos Escribano Rey
Extension Doofinder_Feed
Version 1.6.5
Comparing to
See all releases


Version 1.6.5

Files changed (76) hide show
  1. app/code/community/Doofinder/Feed/Block/Adminhtml/Log/View.php +76 -0
  2. app/code/community/Doofinder/Feed/Block/Adminhtml/Map/Additional.php +161 -0
  3. app/code/community/Doofinder/Feed/Block/Integration.php +34 -0
  4. app/code/community/Doofinder/Feed/Block/Settings/Buttons/Generate.php +44 -0
  5. app/code/community/Doofinder/Feed/Block/Settings/Buttons/ViewLog.php +34 -0
  6. app/code/community/Doofinder/Feed/Block/Settings/Panel/Cron.php +52 -0
  7. app/code/community/Doofinder/Feed/Block/Settings/Panel/Crondescription.php +15 -0
  8. app/code/community/Doofinder/Feed/Block/Settings/Panel/Datetime.php +49 -0
  9. app/code/community/Doofinder/Feed/Block/Settings/Panel/Description.php +54 -0
  10. app/code/community/Doofinder/Feed/Block/Settings/Panel/File.php +68 -0
  11. app/code/community/Doofinder/Feed/Block/Settings/Panel/Hashdescription.php +6 -0
  12. app/code/community/Doofinder/Feed/Block/Settings/Panel/Layerdescription.php +16 -0
  13. app/code/community/Doofinder/Feed/Block/Settings/Panel/Message.php +72 -0
  14. app/code/community/Doofinder/Feed/Helper/Data.php +552 -0
  15. app/code/community/Doofinder/Feed/Helper/Log.php +55 -0
  16. app/code/community/Doofinder/Feed/Helper/Search.php +80 -0
  17. app/code/community/Doofinder/Feed/Helper/Tax.php +24 -0
  18. app/code/community/Doofinder/Feed/Model/Adminhtml/System/Config/Backend/Cron.php +54 -0
  19. app/code/community/Doofinder/Feed/Model/Adminhtml/System/Config/Validation/Hashid.php +19 -0
  20. app/code/community/Doofinder/Feed/Model/CatalogSearch/Resource/Fulltext.php +137 -0
  21. app/code/community/Doofinder/Feed/Model/Config.php +200 -0
  22. app/code/community/Doofinder/Feed/Model/Cron.php +40 -0
  23. app/code/community/Doofinder/Feed/Model/Generator.php +837 -0
  24. app/code/community/Doofinder/Feed/Model/Log.php +19 -0
  25. app/code/community/Doofinder/Feed/Model/Map/Product/Abstract.php +645 -0
  26. app/code/community/Doofinder/Feed/Model/Map/Product/Associated.php +172 -0
  27. app/code/community/Doofinder/Feed/Model/Map/Product/Bundle.php +75 -0
  28. app/code/community/Doofinder/Feed/Model/Map/Product/Configurable.php +200 -0
  29. app/code/community/Doofinder/Feed/Model/Map/Product/Downloadable.php +20 -0
  30. app/code/community/Doofinder/Feed/Model/Map/Product/Grouped.php +62 -0
  31. app/code/community/Doofinder/Feed/Model/Map/Product/Simple.php +20 -0
  32. app/code/community/Doofinder/Feed/Model/Map/Product/Virtual.php +20 -0
  33. app/code/community/Doofinder/Feed/Model/Mysql4/Cron.php +17 -0
  34. app/code/community/Doofinder/Feed/Model/Mysql4/Cron/Collection.php +17 -0
  35. app/code/community/Doofinder/Feed/Model/Mysql4/Log.php +17 -0
  36. app/code/community/Doofinder/Feed/Model/Mysql4/Log/Collection.php +18 -0
  37. app/code/community/Doofinder/Feed/Model/Observers/Feed.php +350 -0
  38. app/code/community/Doofinder/Feed/Model/Observers/Logs.php +45 -0
  39. app/code/community/Doofinder/Feed/Model/Observers/Schedule.php +278 -0
  40. app/code/community/Doofinder/Feed/Model/Resource/Mysql4/Setup.php +14 -0
  41. app/code/community/Doofinder/Feed/Model/System/Config/Backend/Map/Additional.php +24 -0
  42. app/code/community/Doofinder/Feed/Model/System/Config/Backend/Total/Limit.php +17 -0
  43. app/code/community/Doofinder/Feed/Model/System/Config/Reset.php +18 -0
  44. app/code/community/Doofinder/Feed/Model/System/Config/Source/Product/Attributes.php +48 -0
  45. app/code/community/Doofinder/Feed/Model/Tools.php +383 -0
  46. app/code/community/Doofinder/Feed/Test/Controller/Index.php +47 -0
  47. app/code/community/Doofinder/Feed/Test/Controller/Index/fixtures/testConfig.yaml +1 -0
  48. app/code/community/Doofinder/Feed/Test/Controller/Index/fixtures/testFeed.yaml +6 -0
  49. app/code/community/Doofinder/Feed/Test/Controller/Index/fixtures/testIndex.yaml +1 -0
  50. app/code/community/Doofinder/Feed/Test/Controller/Index/providers/testConfig.yaml +1 -0
  51. app/code/community/Doofinder/Feed/Test/Controller/Index/providers/testFeed.yaml +2 -0
  52. app/code/community/Doofinder/Feed/Test/Controller/Index/providers/testIndex.yaml +1 -0
  53. app/code/community/Doofinder/Feed/Test/Model/Product.php +59 -0
  54. app/code/community/Doofinder/Feed/Test/Model/Product/expectations/testGenerator.yaml +12 -0
  55. app/code/community/Doofinder/Feed/Test/Model/Product/fixtures/testGenerator.yaml +118 -0
  56. app/code/community/Doofinder/Feed/Test/Model/Product/providers/testGenerator.yaml +12 -0
  57. app/code/community/Doofinder/Feed/controllers/DoofinderFeedFeedController.php +43 -0
  58. app/code/community/Doofinder/Feed/controllers/DoofinderFeedLogController.php +22 -0
  59. app/code/community/Doofinder/Feed/controllers/FeedController.php +311 -0
  60. app/code/community/Doofinder/Feed/controllers/IndexController.php +32 -0
  61. app/code/community/Doofinder/Feed/etc/config.xml +337 -0
  62. app/code/community/Doofinder/Feed/etc/system.xml +515 -0
  63. app/code/community/Doofinder/Feed/sql/doofinder_feed_setup/mysql4-install-1.5.4.php +59 -0
  64. app/code/community/Doofinder/Feed/sql/doofinder_feed_setup/mysql4-install-1.5.7.php +163 -0
  65. app/code/community/Doofinder/Feed/sql/doofinder_feed_setup/mysql4-upgrade-1.5.4-1.5.5.php +18 -0
  66. app/code/community/Doofinder/Feed/sql/doofinder_feed_setup/mysql4-upgrade-1.5.5-1.5.6.php +101 -0
  67. app/code/community/Doofinder/Feed/sql/doofinder_feed_setup/mysql4-upgrade-1.5.6-1.5.7.php +19 -0
  68. app/design/adminhtml/default/default/layout/doofinder.xml +16 -0
  69. app/design/frontend/base/default/layout/doofinder.xml +7 -0
  70. app/etc/modules/Doofinder_Feed.xml +9 -0
  71. js/doofinder/admin.js +41 -0
  72. lib/Doofinder/doofinder_api.php +804 -0
  73. lib/Doofinder/doofinder_management_api.php +408 -0
  74. lib/Doofinder/errors.php +48 -0
  75. package.xml +58 -0
  76. skin/adminhtml/default/default/doofinder/styles.css +50 -0
app/code/community/Doofinder/Feed/Block/Adminhtml/Log/View.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Adminhtml_Log_View extends Mage_Adminhtml_Block_Widget_Grid
13
+ {
14
+ protected $_defaultSort = 'id';
15
+ protected $_defaultDir = 'desc';
16
+
17
+ protected $_processId = null;
18
+
19
+ public function __construct()
20
+ {
21
+ parent::__construct();
22
+
23
+ $this->_processId = Mage::app()->getRequest()->getParam('processId', false);
24
+ }
25
+
26
+ protected function _prepareCollection()
27
+ {
28
+ $collection = Mage::getResourceModel('doofinder_feed/log_collection');
29
+
30
+ if ($this->_processId) {
31
+ $collection->getSelect()->where("process_id = $this->_processId");
32
+ }
33
+
34
+ $this->setCollection($collection);
35
+
36
+ return parent::_prepareCollection();
37
+ }
38
+
39
+ protected function _prepareColumns()
40
+ {
41
+ $this->addColumn('id', array(
42
+ 'header' => Mage::helper('doofinder_feed')->__('ID'),
43
+ 'index' => 'id',
44
+ 'type' => 'number',
45
+ ));
46
+
47
+ if (!$this->_processId) {
48
+ $this->addColumn('process_id', array(
49
+ 'header' => Mage::helper('doofinder_feed')->__('Process ID'),
50
+ 'index' => 'process_id',
51
+ 'type' => 'number',
52
+ ));
53
+ }
54
+
55
+ $this->addColumn('time', array(
56
+ 'header' => Mage::helper('doofinder_feed')->__('Time'),
57
+ 'index' => 'time',
58
+ 'type' => 'datetime',
59
+ ));
60
+
61
+ $this->addColumn('type', array(
62
+ 'header' => Mage::helper('doofinder_feed')->__('Type'),
63
+ 'index' => 'type',
64
+ 'type' => 'options',
65
+ 'options' => Mage::helper('doofinder_feed/log')->listLogTypes(),
66
+ ));
67
+
68
+ $this->addColumn('message', array(
69
+ 'header' => Mage::helper('doofinder_feed')->__('Message'),
70
+ 'index' => 'message',
71
+ 'type' => 'text',
72
+ ));
73
+
74
+ return parent::_prepareColumns();
75
+ }
76
+ }
app/code/community/Doofinder/Feed/Block/Adminhtml/Map/Additional.php ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Adminhtml_Map_Additional extends Mage_Adminhtml_Block_System_Config_Form_Field
13
+ {
14
+ protected $_addRowButtonHtml = array();
15
+ protected $_removeRowButtonHtml = array();
16
+
17
+ protected $_rows = 0;
18
+
19
+ /**
20
+ * Returns html part of the setting
21
+ *
22
+ * @param Varien_Data_Form_Element_Abstract $element
23
+ * @return string
24
+ */
25
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
26
+ {
27
+ $this->setElement($element);
28
+
29
+ $html = '<table style="display:none"><tbody id="doofinder_feed_additional_mapping_template">';
30
+ $html .= $this->_getRowTemplateHtml(-1);
31
+ $html .= '</tbody></table>';
32
+
33
+ $html .= '<table>';
34
+ $html .= '<thead><tr>';
35
+ $html .= '<th>' . $this->__('Label') . '</th><th>' . $this->__('Field') . '</th><th>' . $this->__('Attribute') . '</th>';
36
+ $html .= '</tr></thead>';
37
+ $html .= '<tbody id="doofinder_feed_additional_mapping_container">';
38
+
39
+ $count = 0;
40
+ if ($this->_getValue('additional_mapping')) {
41
+ foreach ($this->_getValue('additional_mapping') as $i => $f) {
42
+ $html .= $this->_getRowTemplateHtml($count++);
43
+ }
44
+ }
45
+
46
+ $html .= '</tbody></table>';
47
+ $html .= $this->_getAddRowButtonHtml();
48
+
49
+ $html .= '<script type="text/javascript">';
50
+ ob_start();
51
+ ?>
52
+ var DoofinderFeedMapAdditionalRowGenerator = function() {
53
+ this.count = <?php print $count; ?>;
54
+ };
55
+
56
+ DoofinderFeedMapAdditionalRowGenerator.prototype.add = function() {
57
+ var html = $('doofinder_feed_additional_mapping_template').innerHTML;
58
+ html = html.replace(/\[additional_mapping\]\[-1\]/g, '[additional_mapping][' + (this.count++) + ']');
59
+ Element.insert($('doofinder_feed_additional_mapping_container'), {bottom: html});
60
+ };
61
+
62
+ var doofinderFeedMapAdditionalRowGenerator = new DoofinderFeedMapAdditionalRowGenerator();
63
+ <?php
64
+ $html .= ob_get_clean();
65
+ $html .= '</script>';
66
+
67
+ return $html;
68
+ }
69
+
70
+ /**
71
+ * Retrieve html template for setting
72
+ *
73
+ * @param int $rowIndex
74
+ * @return string
75
+ */
76
+ protected function _getRowTemplateHtml($rowIndex = null)
77
+ {
78
+ $value = $rowIndex !== null ? (array) $this->_getValue('additional_mapping/' . $rowIndex) : array();
79
+ $value += array('field' => '', 'label' => '', 'attribute' => '');
80
+ $html = '<tr>';
81
+
82
+ $html .= '<td>';
83
+ $html .= '<input name="'
84
+ . $this->getElement()->getName() . '[additional_mapping][' . $rowIndex . '][label]" value="'
85
+ . $value['label'] . '" ' . $this->_getDisabled() . '/> ';
86
+ $html .= '</td><td>';
87
+ $html .= '<input name="'
88
+ . $this->getElement()->getName() . '[additional_mapping][' . $rowIndex . '][field]" value="'
89
+ . $value['field'] . '" ' . $this->_getDisabled() . '/> ';
90
+ $html .= '</td><td>';
91
+ $html .= '<select name="'
92
+ . $this->getElement()->getName() . '[additional_mapping][' . $rowIndex . '][attribute]" ' . $this->_getDisabled() . '>';
93
+ foreach (Mage::getSingleton('doofinder_feed/system_config_source_product_attributes')->toOptionArray() as $key => $label) {
94
+ $html .= '<option value="' . $key . '"'. ($value['attribute'] == $key ? 'selected="selected"' : '') . '>' . $label . '</option>';
95
+ }
96
+ $html .= '</select> ';
97
+ $html .= '</td><td>';
98
+ $html .= $this->_getRemoveRowButtonHtml();
99
+ $html .= '</td>';
100
+ $html .= '</tr>';
101
+
102
+ return $html;
103
+ }
104
+
105
+ protected function _getDisabled()
106
+ {
107
+ return $this->getElement()->getDisabled() ? 'disabled' : '';
108
+ }
109
+
110
+ protected function _getValue($key)
111
+ {
112
+ return $this->getElement()->getData('value/' . $key);
113
+ }
114
+
115
+ protected function _getSelected($key, $value)
116
+ {
117
+ return $this->getElement()->getData('value/' . $key) == $value ? 'selected="selected"' : '';
118
+ }
119
+
120
+ protected function _getAddRowButtonHtml()
121
+ {
122
+ $container = isset($container) ? $container : null;
123
+
124
+ if (!isset($this->_addRowButtonHtml[$container])) {
125
+ $_cssClass = 'add';
126
+
127
+ if (version_compare(Mage::getVersion(), '1.6', '<')) {
128
+ $_cssClass .= ' ' . $this->_getDisabled();
129
+ }
130
+
131
+ $this->_addRowButtonHtml[$container] = $this->getLayout()->createBlock('adminhtml/widget_button')
132
+ ->setType('button')
133
+ ->setClass($_cssClass)
134
+ ->setLabel($this->__('Add'))
135
+ ->setOnClick("doofinderFeedMapAdditionalRowGenerator.add()")
136
+ ->setDisabled($this->_getDisabled())
137
+ ->toHtml();
138
+ }
139
+ return $this->_addRowButtonHtml[$container];
140
+ }
141
+
142
+ protected function _getRemoveRowButtonHtml()
143
+ {
144
+ if (!$this->_removeRowButtonHtml) {
145
+ $_cssClass = 'delete v-middle';
146
+
147
+ if (version_compare(Mage::getVersion(), '1.6', '<')) {
148
+ $_cssClass .= ' ' . $this->_getDisabled();
149
+ }
150
+
151
+ $this->_removeRowButtonHtml = $this->getLayout()->createBlock('adminhtml/widget_button')
152
+ ->setType('button')
153
+ ->setClass($_cssClass)
154
+ ->setLabel($this->__('Delete'))
155
+ ->setOnClick("Element.remove($(this).up('tr'))")
156
+ ->setDisabled($this->_getDisabled())
157
+ ->toHtml();
158
+ }
159
+ return $this->_removeRowButtonHtml;
160
+ }
161
+ }
app/code/community/Doofinder/Feed/Block/Integration.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Integration extends Mage_Core_Block_Abstract
13
+ {
14
+ /**
15
+ * Produce the integration script
16
+ *
17
+ * @return string
18
+ */
19
+ protected function _toHtml()
20
+ {
21
+ $enabled = Mage::getStoreConfig('doofinder_search/layer_settings/enabled', Mage::app()->getStore());
22
+ $script = Mage::getStoreConfig('doofinder_search/layer_settings/script', Mage::app()->getStore());
23
+
24
+ if ($enabled) {
25
+ $script .= '<script type="text/javascript">';
26
+ $script .= "if (typeof Varien.searchForm !== 'undefined') Varien.searchForm.prototype.initAutocomplete = function() { $('search_autocomplete').hide(); };";
27
+ $script .= '</script>';
28
+
29
+ return $script;
30
+ } else {
31
+ return '';
32
+ }
33
+ }
34
+ }
app/code/community/Doofinder/Feed/Block/Settings/Buttons/Generate.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Settings_Buttons_Generate extends Mage_Adminhtml_Block_System_Config_Form_Field
13
+ {
14
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
15
+ {
16
+ $this->setElement($element);
17
+ $element->setScopeLabel('');
18
+
19
+ $storeCode = Mage::app()->getRequest()->getParam('store');
20
+ $url = Mage::helper("adminhtml")->getUrl('adminhtml/doofinderFeedFeed/generate', array('store' => $storeCode));
21
+
22
+ $script = "<script type=\"text/javascript\">
23
+ function generateFeed() {
24
+ var call = new Ajax.Request('" . $url . "', {
25
+ method: 'get',
26
+ onComplete: function(transport) {
27
+ alert(transport.responseText);
28
+ window.location.reload();
29
+ }
30
+ });
31
+ }
32
+ </script>";
33
+
34
+ $html = $this->getLayout()->createBlock('adminhtml/widget_button')
35
+ ->setType('button')
36
+ ->setClass('generate-feed')
37
+ ->setLabel('Start Feed Generation Now')
38
+ ->setOnClick("confirm('No changes will be saved, feed will be rescheduled (if there\'s a process running it will be stopped and the feed will be reset). Do you want to proceed?') && generateFeed()")
39
+ ->setAfterHtml($script)
40
+ ->toHtml();
41
+ return $html;
42
+ }
43
+
44
+ }
app/code/community/Doofinder/Feed/Block/Settings/Buttons/ViewLog.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Settings_Buttons_ViewLog extends Mage_Adminhtml_Block_System_Config_Form_Field
13
+ {
14
+
15
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
16
+ {
17
+ $this->setElement($element);
18
+ $element->setScopeLabel('');
19
+
20
+ $process = Mage::getModel('doofinder_feed/cron')->load(Mage::app()->getRequest()->getParam('store'), 'store_code');
21
+
22
+ $url = Mage::helper("adminhtml")->getUrl('adminhtml/doofinderFeedLog/view/processId/' . $process->getId());
23
+
24
+ $html = $this->getLayout()->createBlock('adminhtml/widget_button')
25
+ ->setType('button')
26
+ ->setClass('view-log')
27
+ ->setLabel('View log')
28
+ ->setOnClick("setLocation('$url')")
29
+ ->toHtml();
30
+
31
+ return $html;
32
+ }
33
+
34
+ }
app/code/community/Doofinder/Feed/Block/Settings/Panel/Cron.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Doofinder_Feed_Block_Settings_Panel_Cron extends Mage_Adminhtml_Block_System_Config_Form_Field
3
+ {
4
+ // 12 Hours in seconds
5
+ const ALLOWED_TIME = 43200;
6
+
7
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
8
+ {
9
+ $lastSchedule = Mage::getModel('cron/schedule')->getCollection()
10
+ ->setOrder('finished_at', 'desc')
11
+ ->getFirstItem();
12
+
13
+ $message = '';
14
+ if ($lastSchedule && count($lastSchedule->getData()) > 0) {
15
+ $scheduleTime = strtotime($lastSchedule->getFinishedAt());
16
+ $currentTime = time();
17
+
18
+ // Difference in seconds
19
+ $dif = ($currentTime - $scheduleTime);
20
+
21
+ // If difference is bigger than allowed, display message
22
+ if ($dif > self::ALLOWED_TIME) {
23
+
24
+ $message = sprintf('Cron was run for the last time at %s. Taking into account the settings of the step delay option, there might be problems with the cron\'s configuration.', $lastSchedule->getFinishedAt());
25
+ Mage::helper('doofinder_feed')->__($message);
26
+ }
27
+ } else {
28
+ $message = Mage::helper('doofinder_feed')->__('There are no registered cron tasks. Please, check your system\'s crontab configuration.');
29
+ }
30
+
31
+ return '<p class="error">' . $message . '</p>';
32
+ }
33
+
34
+ public function render(Varien_Data_Form_Element_Abstract $element)
35
+ {
36
+ $html = '<td class="label"></td>' .
37
+ '<td class="value" colspan="3">' . $this->_getElementHtml($element) . '</td>';
38
+ return $this->_decorateRowHtml($element, $html);
39
+ }
40
+
41
+ /**
42
+ * Decorate field row html
43
+ *
44
+ * @param Varien_Data_Form_Element_Abstract $element
45
+ * @param string $html
46
+ * @return string
47
+ */
48
+ protected function _decorateRowHtml($element, $html)
49
+ {
50
+ return '<tr id="row_' . $element->getHtmlId() . '">' . $html . '</tr>';
51
+ }
52
+ }
app/code/community/Doofinder/Feed/Block/Settings/Panel/Crondescription.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Settings_Panel_CronDescription extends Doofinder_Feed_Block_Settings_Panel_Description
13
+ {
14
+ protected $description = 'THIS FEATURE IS CURRENTLY IN BETA.<br>Feeds can be generated directly in your server to save computer resources. See <a href="http://www.doofinder.com/support/topics/plugins/magento">this article</a> for more information.';
15
+ }
app/code/community/Doofinder/Feed/Block/Settings/Panel/Datetime.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Settings_Panel_Datetime extends Mage_Adminhtml_Block_System_Config_Form_Field
13
+ {
14
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
15
+ {
16
+ $this->setElement($element);
17
+ $name = $element->getName();
18
+ $element->setScopeLabel('');
19
+ $code = Mage::app()->getRequest()->getParam('store');
20
+ $field = $this->_getField($name);
21
+ $html = '';
22
+ if ($field && $code) {
23
+ $datetime = Mage::getModel('doofinder_feed/cron')->load($code, 'store_code')->getData($field);
24
+ if ($datetime) {
25
+ $msg = $datetime;
26
+
27
+ try {
28
+ $dateTimestamp = Mage::getModel('core/date')->timestamp(strtotime($datetime));
29
+ $msg = Mage::helper('core')->formatDate(date('Y-m-d H:i:s', $dateTimestamp), null, true);
30
+ } catch (Exception $e) {}
31
+
32
+ $class = 'feed-datetime';
33
+ $html = "<p class='{$class}'>{$msg}</p>";
34
+ }
35
+ }
36
+ return $html;
37
+ }
38
+
39
+ private function _getField($name = null)
40
+ {
41
+ $pattern = '/groups\[panel\]\[fields\]\[([a-z_-]*)\]\[value\]/';
42
+ $preg = preg_match($pattern, $name, $match);
43
+ if ($preg && isset($match[1])) {
44
+ return $match[1];
45
+ } else {
46
+ return false;
47
+ }
48
+ }
49
+ }
app/code/community/Doofinder/Feed/Block/Settings/Panel/Description.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Settings_Panel_Description extends Mage_Adminhtml_Block_System_Config_Form_Field
13
+ {
14
+ const INFO = 'info';
15
+ const WARNING = 'warning';
16
+
17
+ protected $level = self::INFO;
18
+ protected $description = 'You can set the rest of the options for each store separately by modifying the Current Configuration Scope.';
19
+
20
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21
+ {
22
+ $text = '';
23
+
24
+ if (!Mage::app()->getRequest()->getParam('store'))
25
+ {
26
+ $text = $this->description;
27
+ }
28
+
29
+ $this->setElement($element);
30
+ $name = $element->getName();
31
+ $element->setScopeLabel('');
32
+
33
+ return '<p class="doofinder-' . $this->level . '">' . $text . '</p>';
34
+ }
35
+
36
+ public function render(Varien_Data_Form_Element_Abstract $element)
37
+ {
38
+ $html = '<td class="label"></td>' .
39
+ '<td class="value" colspan="3">' . $this->_getElementHtml($element) . '</td>';
40
+ return $this->_decorateRowHtml($element, $html);
41
+ }
42
+
43
+ /**
44
+ * Decorate field row html
45
+ *
46
+ * @param Varien_Data_Form_Element_Abstract $element
47
+ * @param string $html
48
+ * @return string
49
+ */
50
+ protected function _decorateRowHtml($element, $html)
51
+ {
52
+ return '<tr id="row_' . $element->getHtmlId() . '">' . $html . '</tr>';
53
+ }
54
+ }
app/code/community/Doofinder/Feed/Block/Settings/Panel/File.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Settings_Panel_File extends Mage_Adminhtml_Block_System_Config_Form_Field
13
+ {
14
+ /**
15
+ * Error prefix
16
+ * @var string
17
+ */
18
+ const ERROR_PREFIX = "#error#";
19
+
20
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21
+ {
22
+ $this->setElement($element);
23
+ $name = $element->getName();
24
+ $element->setScopeLabel('');
25
+ $store_code = Mage::app()->getRequest()->getParam('store');
26
+
27
+ $stores = array();
28
+
29
+ if ($store_code) {
30
+ $stores[$store_code] = Mage::getModel('core/store')->load($store_code);
31
+ } else {
32
+ foreach (Mage::app()->getStores() as $store) {
33
+ if ($store->getIsActive()) {
34
+ $stores[$store->getCode()] = $store;
35
+ }
36
+ }
37
+ }
38
+
39
+ $files = array();
40
+
41
+ foreach ($stores as $store) {
42
+ $process = Mage::getModel('doofinder_feed/cron')->load($store->getCode(), 'store_code');
43
+ $lastGeneratedName = $process->getLastFeedName();
44
+
45
+ $fileUrl = Mage::getBaseUrl('media').'doofinder'.DS.$lastGeneratedName;
46
+ $fileDir = Mage::getBaseDir('media').DS.'doofinder'.DS.$lastGeneratedName;
47
+ if ($lastGeneratedName && file_exists($fileDir)) {
48
+ $files[$store->getCode()] = "<a href='{$fileUrl}' target='_blank'>" . (count($stores) > 1 ? $fileUrl : "Get {$lastGeneratedName}") . "</a>";
49
+ } else {
50
+ $files[$store->getCode()] = "Currently there is no file to preview.";
51
+ }
52
+ }
53
+
54
+ $html = '';
55
+
56
+ if (count($files) > 1) {
57
+ $html .= '<ul>';
58
+ foreach ($files as $code => $file) {
59
+ $html .= '<li><b>' . $stores[$code]->getName() . ':</b><div>' . $file . '</div></li>';
60
+ }
61
+ $html .= '</ul>';
62
+ } else {
63
+ $html .= reset($files);
64
+ }
65
+
66
+ return $html;
67
+ }
68
+ }
app/code/community/Doofinder/Feed/Block/Settings/Panel/Hashdescription.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ class Doofinder_Feed_Block_Settings_Panel_HashDescription extends Doofinder_Feed_Block_Settings_Panel_Description
3
+ {
4
+ protected $level = self::WARNING;
5
+ protected $description = '<b>IMPORTANT:</b> You must configure a "hashid" for each store view. Use the "Current Configuration Scope" selector at the top left side of the page to choose a store view.';
6
+ }
app/code/community/Doofinder/Feed/Block/Settings/Panel/Layerdescription.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Settings_Panel_LayerDescription extends Doofinder_Feed_Block_Settings_Panel_Description
13
+ {
14
+ protected $level = self::WARNING;
15
+ protected $description = '<b>IMPORTANT:</b> You must configure a different Layer script for each store view. Use the "Current Configuration Scope" selector at the top left side of the page to choose a store view.';
16
+ }
app/code/community/Doofinder/Feed/Block/Settings/Panel/Message.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category blocks
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ class Doofinder_Feed_Block_Settings_Panel_Message extends Mage_Adminhtml_Block_System_Config_Form_Field
13
+ {
14
+ /**
15
+ * Error prefix
16
+ * @var string
17
+ */
18
+ const ERROR_PREFIX = "#error#";
19
+
20
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21
+ {
22
+ $this->setElement($element);
23
+ $name = $element->getName();
24
+ $element->setScopeLabel('');
25
+ $code = Mage::app()->getRequest()->getParam('store');
26
+ $field = $this->_getField($name);
27
+ $html = '';
28
+ if ($field && $code) {
29
+ $process = Mage::getModel('doofinder_feed/cron')->load($code, 'store_code');
30
+
31
+ if (!$process->getId()) {
32
+ switch ($field) {
33
+ case 'status':
34
+ $msg = Mage::helper('doofinder_feed')->__('Not created');
35
+ break;
36
+
37
+ case 'message':
38
+ $msg = Mage::helper('doofinder_feed')->__('Process not created yet, it will be created automatically by cron job');
39
+ break;
40
+
41
+ default:
42
+ $msg = '';
43
+ }
44
+
45
+ } else {
46
+ $msg = $process->getData($field);
47
+ }
48
+
49
+ $class = 'feed-message ';
50
+
51
+ // Mark message as an error
52
+ if (strpos($msg, self::ERROR_PREFIX) !== false) {
53
+ $msg = str_replace(self::ERROR_PREFIX, '', $msg);
54
+ $class .= 'error';
55
+ }
56
+
57
+ $html = "<p class='{$class}'>{$msg}</p>";
58
+ }
59
+ return $html;
60
+ }
61
+
62
+ private function _getField($name = null) {
63
+
64
+ $pattern = '/groups\[panel\]\[fields\]\[([a-z_-]*)\]\[value\]/';
65
+ $preg = preg_match($pattern, $name, $match);
66
+ if ($preg && isset($match[1])) {
67
+ return $match[1];
68
+ } else {
69
+ return false;
70
+ }
71
+ }
72
+ }
app/code/community/Doofinder/Feed/Helper/Data.php ADDED
@@ -0,0 +1,552 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category Helpers
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ /**
13
+ * Data helper for Doofinder Feed
14
+ *
15
+ * @version 1.6.5
16
+ * @package Doofinder_Feed
17
+ */
18
+ class Doofinder_Feed_Helper_Data extends Mage_Core_Helper_Abstract
19
+ {
20
+ private $store = null;
21
+
22
+ private $currencyConvert = false;
23
+
24
+ private $useMinimalPrice = false;
25
+
26
+ private $groupConfigurables = true;
27
+
28
+ private $minTierPrice = null;
29
+
30
+ const CRON_DAILY = Mage_Adminhtml_Model_System_Config_Source_Cron_Frequency::CRON_DAILY;
31
+ const CRON_WEEKLY = Mage_Adminhtml_Model_System_Config_Source_Cron_Frequency::CRON_WEEKLY;
32
+ const CRON_MONTHLY = Mage_Adminhtml_Model_System_Config_Source_Cron_Frequency::CRON_MONTHLY;
33
+
34
+ /**
35
+ * Panel info messages.
36
+ */
37
+ const STATUS_DISABLED = 'Disabled';
38
+ const STATUS_PENDING = Mage_Cron_Model_Schedule::STATUS_PENDING;
39
+ const STATUS_RUNNING = Mage_Cron_Model_Schedule::STATUS_RUNNING;
40
+ const STATUS_SUCCESS = Mage_Cron_Model_Schedule::STATUS_SUCCESS;
41
+ const STATUS_MISSED = Mage_Cron_Model_Schedule::STATUS_MISSED;
42
+ const STATUS_WAITING = 'Waiting...';
43
+ const STATUS_ERROR = Mage_Cron_Model_Schedule::STATUS_ERROR;
44
+ const JOB_CODE = 'doofinder_feed_generate';
45
+
46
+ const MSG_EMPTY = "Currently there is no message.";
47
+ const MSG_PENDING = "The new process of generating the feed has been registered and it's waiting to be activated.";
48
+ const MSG_DISABLED = "The feed generator for this view is currently disabled.";
49
+ const MSG_WAITING = "Waiting for registering the new process of generating the feed.";
50
+
51
+
52
+ /**
53
+ * $product => Product instance
54
+ * $oStore => Store instance
55
+ * $currencyConvert => Boolean, Convert prices to $oStore currency.
56
+ * $useMinimalPrice => Boolean, See below.
57
+ * $groupConfigurables => Boolean
58
+ *
59
+ * If $useMinimalPrice == true then, the price is checked against tier
60
+ * prices. If there is a smaller price in the tier then that price is used
61
+ * instead the regular one.
62
+ *
63
+ * So, if there is a special price defined and it is greater than the
64
+ * minimal price found in tier, then it is not returned as the "sale_price".
65
+ *
66
+ * ----
67
+ *
68
+ * If a Fixed Product Tax exists for the product, then it is applied if
69
+ * the $oStore settings are configured to do so.
70
+ *
71
+ * NOTICE: FPT are ALWAYS applied to prices including taxes. Configuration
72
+ * is only applied to prices excluding taxes.
73
+ */
74
+ public function collectProductPrices(Mage_Catalog_Model_Product $product, $oStore, $currencyConvert=false, $useMinimalPrice=false, $groupConfigurables=true)
75
+ {
76
+ $this->store = $oStore;
77
+ $this->currencyConvert = $currencyConvert;
78
+ $this->useMinimalPrice = $useMinimalPrice;
79
+ $this->groupConfigurables = $groupConfigurables;
80
+
81
+ $weeeHelper = Mage::helper('weee');
82
+ $taxHelper = Mage::helper('tax');
83
+ $coreHelper = Mage::helper('core');
84
+
85
+ // Tier Prices
86
+
87
+ $tierPrices = $this->getProductTierPrices($product, $oStore);
88
+
89
+ foreach ($tierPrices as $tier)
90
+ {
91
+ if ( is_null($this->minTierPrice) || $tier['base_price_excl_tax'] < $this->minTierPrice['base_price_excl_tax'] )
92
+ {
93
+ $this->minTierPrice = $tier;
94
+ continue;
95
+ }
96
+ }
97
+
98
+ if ( $product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_GROUPED )
99
+ {
100
+ $prices = $this->_getGroupedProductPrice($product);
101
+ }
102
+ elseif ( $product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE )
103
+ {
104
+ $prices = $this->_getBundleProductPrice($product);
105
+ }
106
+ else /* ! $product->isGrouped */
107
+ {
108
+ $prices = $this->_getProductPrice($product);
109
+ }
110
+
111
+ $prices = $this->_cleanPrices($prices);
112
+
113
+ foreach ( array('price', 'sale_price') as $priceType )
114
+ {
115
+ if ( !isset($prices[$priceType]) )
116
+ continue;
117
+ foreach ( $prices[$priceType] as $priceMode => $priceValue )
118
+ {
119
+ if ( $currencyConvert ) {
120
+ $priceValue = $oStore->convertPrice($priceValue, false, false);
121
+ }
122
+ $prices[$priceType][$priceMode] = $priceValue;
123
+ }
124
+ }
125
+
126
+ return $prices;
127
+ }
128
+
129
+ protected function _cleanPrices($prices)
130
+ {
131
+ if (!isset($prices['price'])) return $prices;
132
+ if ( isset($prices['sale_price']['excluding_tax']) &&
133
+ $prices['price']['excluding_tax'] <= $prices['sale_price']['excluding_tax'] )
134
+ {
135
+ unset($prices['sale_price']['excluding_tax']);
136
+ unset($prices['sale_price']['including_tax']);
137
+ }
138
+
139
+ if ( $prices['price']['excluding_tax'] <= 0 )
140
+ {
141
+ unset($prices['price']['excluding_tax']);
142
+ unset($prices['price']['including_tax']);
143
+ }
144
+
145
+ return $prices;
146
+ }
147
+
148
+ protected function _getProductPrice($product)
149
+ {
150
+ $prices = array();
151
+
152
+ $weeeHelper = Mage::helper('weee');
153
+ $taxHelper = Mage::helper('tax');
154
+ $coreHelper = Mage::helper('core');
155
+
156
+ $prices['price_type'] = 'normal';
157
+
158
+ $weeeTaxAmount = $weeeHelper->getAmountForDisplay($product);
159
+
160
+ $weeeTaxAttributes = null;
161
+
162
+ if ( $weeeHelper->typeOfDisplay($product, array(1, 2, 4), null, $this->store) )
163
+ {
164
+ $weeeTaxAmount = $weeeHelper->getAmount($product, null, null, $this->store->getWebsiteId(), false);
165
+ $weeeTaxAttributes = $weeeHelper->getProductWeeeAttributesForDisplay($product);
166
+ }
167
+
168
+ // Precios originales y finales (segun Magento) sin Weee
169
+
170
+ $base_price_excl_tax = $taxHelper->getPrice($product, $product->getPrice(), false, null, null, null, $this->store, null);
171
+ $base_price_incl_tax = $taxHelper->getPrice($product, $product->getPrice(), true, null, null, null, $this->store, null);
172
+
173
+ $final_price_excl_tax = $taxHelper->getPrice($product, $product->getFinalPrice(), false, null, null, null, $this->store, null);
174
+ $final_price_incl_tax = $taxHelper->getPrice($product, $product->getFinalPrice(), true, null, null, null, $this->store, null);
175
+
176
+ if ( $this->minTierPrice && $this->useMinimalPrice
177
+ && $this->minTierPrice['base_price_excl_tax'] < $final_price_excl_tax)
178
+ {
179
+ $prices['price_type'] = 'minimal';
180
+
181
+ $base_price_excl_tax = $this->minTierPrice['base_price_excl_tax'];
182
+ $base_price_incl_tax = $this->minTierPrice['base_price_incl_tax'];
183
+ }
184
+
185
+ // Algunas preguntas
186
+
187
+ $inclFptOnly = $weeeHelper->typeOfDisplay($product, 0, null, $this->store); // Including FPT only
188
+ $inclFptAndDescription = $weeeHelper->typeOfDisplay($product, 1, null, $this->store); // Including FPT and FPT description
189
+ $exclFptAndDescriptionFinalPrice = $weeeHelper->typeOfDisplay($product, 2, null, $this->store); // Excluding FPT, FPT description, final price
190
+ $exclFpt = $weeeHelper->typeOfDisplay($product, 3, null, $this->store); // Excluding FPT
191
+ $inclFptAndDescriptionWithTaxes = $weeeHelper->typeOfDisplay($product, 4, null, $this->store); // Including FPT and FPT description [incl. FPT VAT]
192
+
193
+ // Elegimos y calculamos los precios finales
194
+
195
+ if ( $final_price_excl_tax >= $base_price_excl_tax )
196
+ {
197
+ $prices['price']['excluding_tax'] = $base_price_excl_tax;
198
+ $prices['price']['including_tax'] = $base_price_incl_tax;
199
+
200
+ if ( $weeeTaxAmount )
201
+ {
202
+ $prices['price']['including_tax'] += $weeeTaxAmount;
203
+
204
+ if ( $inclFptOnly || $inclFptAndDescription || $inclFptAndDescriptionWithTaxes )
205
+ $prices['price']['excluding_tax'] += $weeeTaxAmount;
206
+ }
207
+ }
208
+ else
209
+ {
210
+ $prices['price']['excluding_tax'] = $base_price_excl_tax;
211
+ $prices['price']['including_tax'] = $base_price_incl_tax;
212
+
213
+ $prices['sale_price']['excluding_tax'] = $final_price_excl_tax;
214
+ $prices['sale_price']['including_tax'] = $final_price_incl_tax;
215
+
216
+ $originalWeeeTaxAmount = $weeeHelper->getOriginalAmount($product);
217
+
218
+ if ( $weeeTaxAmount )
219
+ {
220
+ $prices['price']['including_tax'] += $originalWeeeTaxAmount;
221
+ $prices['sale_price']['including_tax'] += $weeeTaxAmount;
222
+
223
+ if ( $inclFptOnly || $inclFptAndDescription || $inclFptAndDescriptionWithTaxes )
224
+ {
225
+ $prices['price']['excluding_tax'] += $originalWeeeTaxAmount;
226
+ $prices['sale_price']['excluding_tax'] += $weeeTaxAmount;
227
+ }
228
+ }
229
+ }
230
+
231
+ if ( $product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE && $this->groupConfigurables && $this->useMinimalPrice )
232
+ {
233
+ $prices = $this->_getConfigurableProductPrice($product);
234
+ }
235
+ return $prices;
236
+ }
237
+
238
+ protected function _getConfigurableProductPrice($product, $prices)
239
+ {
240
+ $childProducts = $product->getTypeInstance()->getUsedProducts();
241
+
242
+ foreach ( $childProducts as $child )
243
+ {
244
+ $childPrices = $this->collectProductPrices($child, $this->store, false, $this->useMinimalPrice, $this->groupConfigurables);
245
+
246
+ // Compare regular price
247
+ if ( $childPrices['price']['excluding_tax'] < $prices['price']['excluding_tax'] )
248
+ {
249
+ $prices['price']['excluding_tax'] = $childPrices['price']['excluding_tax'];
250
+ $prices['price']['including_tax'] = $childPrices['price']['including_tax'];
251
+ $prices['price']['overriden'] = true;
252
+ }
253
+
254
+ // Compare sale price
255
+ if ( array_key_exists('sale_price', $childPrices) )
256
+ {
257
+ if ( ! array_key_exists('sale_price', $prices)
258
+ || $childPrices['sale_price']['excluding_tax'] < $prices['sale_price']['excluding_tax'] )
259
+ {
260
+ $prices['sale_price']['excluding_tax'] = $childPrices['sale_price']['excluding_tax'];
261
+ $prices['sale_price']['including_tax'] = $childPrices['sale_price']['including_tax'];
262
+ $prices['sale_price']['overriden'] = true;
263
+ }
264
+ }
265
+ }
266
+ return $prices;
267
+ }
268
+
269
+ protected function _getGroupedProductPrice($product)
270
+ {
271
+ $weeeHelper = Mage::helper('weee');
272
+ $taxHelper = Mage::helper('tax');
273
+ $coreHelper = Mage::helper('core');
274
+
275
+ $minimal_prices = array(
276
+ 'price' => array(
277
+ 'including_tax' => 0,
278
+ 'excluding_tax' => 0
279
+ ),
280
+ 'sale_price' => array(
281
+ 'including_tax' => 0,
282
+ 'excluding_tax' => 0
283
+ )
284
+ );
285
+
286
+ $childrenIds = $product->getTypeInstance()->getChildrenIds($product->getId());
287
+ $childrenIds = $childrenIds[Mage_Catalog_Model_Product_Link::LINK_TYPE_GROUPED];
288
+
289
+ if (empty($childrenIds) || !is_array($childrenIds)) {
290
+ return $minimal_prices;
291
+ }
292
+
293
+ $collection = Mage::getModel('catalog/product')->getCollection();
294
+ $collection
295
+ ->addIdFilter($childrenIds)
296
+ ->addAttributeToSelect('*')
297
+ ->load();
298
+
299
+ foreach($collection as $product)
300
+ {
301
+ $sub_prices = $this->collectProductPrices($product, $this->store, $this->currencyConvert, $this->useMinimalPrice, $this->groupConfigurables);
302
+
303
+ if (! empty($sub_prices['price']['excluding_tax'])) {
304
+ if ($minimal_prices['price']['excluding_tax'] === 0 ||
305
+ $minimal_prices['price']['excluding_tax'] > $sub_prices['price']['excluding_tax'])
306
+ $minimal_prices = $sub_prices;
307
+ }
308
+ }
309
+
310
+ return $minimal_prices;
311
+ }
312
+
313
+ protected function _getBundleProductPrice($product)
314
+ {
315
+ $prices = array();
316
+
317
+ $weeeHelper = Mage::helper('weee');
318
+ $taxHelper = Mage::helper('tax');
319
+ $coreHelper = Mage::helper('core');
320
+
321
+ if ( method_exists($product->getPriceModel(), 'getTotalPrices') )
322
+ {
323
+ $bundle_price_excl_tax = $product->getPriceModel()->getTotalPrices($product, 'min', false, true);
324
+ $bundle_price_incl_tax = $product->getPriceModel()->getTotalPrices($product, 'min', true, true);
325
+ }
326
+ else // Magento 1.5.0.1 + 1.5.1.0
327
+ {
328
+ $bundle_price_excl_tax = $product->getPriceModel()->getPricesDependingOnTax($product, 'min', false);
329
+ $bundle_price_incl_tax = $product->getPriceModel()->getPricesDependingOnTax($product, 'min', true);
330
+ }
331
+
332
+ if ( $bundle_price_excl_tax )
333
+ {
334
+ $prices['price_type'] = 'minimal';
335
+
336
+ $prices['price']['excluding_tax'] = $bundle_price_excl_tax;
337
+ $prices['price']['including_tax'] = $bundle_price_incl_tax;
338
+ }
339
+
340
+ return $prices;
341
+ }
342
+
343
+ public function getProductTierPrices(Mage_Catalog_Model_Product $product, $oStore)
344
+ {
345
+ if (is_null($product))
346
+ return array();
347
+
348
+ $prices = array();
349
+ $taxHelper = Mage::helper('tax');
350
+
351
+ // Get Tier Prices
352
+
353
+ $tierPrices = $product->getTierPrice(null);
354
+
355
+ if (! is_array($tierPrices))
356
+ $tierPrices = (array) $tierPrices;
357
+
358
+ foreach ( $tierPrices as $price )
359
+ {
360
+ $result = array();
361
+
362
+ if ( $price['website_id'] != $oStore->getWebsiteId() && $price['website_id'] != 0 )
363
+ continue;
364
+
365
+ $result['price_qty'] = $price['price_qty'] * 1; // make int
366
+
367
+ if ( $price['price'] < $product->getFinalPrice() )
368
+ $result['save_percent'] = ceil(100 - ((100 / $product->getFinalPrice()) * $price['price']));
369
+
370
+ $result['base_price_excl_tax'] = $taxHelper->getPrice($product, $price['website_price'], false, null, null, null, $oStore, null);
371
+ $result['base_price_incl_tax'] = $taxHelper->getPrice($product, $price['website_price'], true, null, null, null, $oStore, null);
372
+
373
+ $prices[] = $result;
374
+ }
375
+
376
+ return $prices;
377
+ }
378
+
379
+ /**
380
+ * Gets store config for cron settings.
381
+ * @param string $storeCode
382
+ * @return array
383
+ */
384
+ public function getStoreConfig($storeCode = '') {
385
+ $xmlName = Mage::getStoreConfig('doofinder_cron/schedule_settings/name', $storeCode);
386
+ $config = array(
387
+ 'enabled' => Mage::getStoreConfig('doofinder_cron/schedule_settings/enabled', $storeCode),
388
+ 'display_price' => Mage::getStoreConfig('doofinder_cron/feed_settings/display_price', $storeCode),
389
+ 'grouped' => Mage::getStoreConfig('doofinder_cron/feed_settings/grouped', $storeCode),
390
+ 'image_size' => Mage::getStoreConfig('doofinder_cron/feed_settings/image_size', $storeCode),
391
+ 'stepSize' => Mage::getStoreConfig('doofinder_cron/schedule_settings/step', $storeCode),
392
+ 'stepDelay' => Mage::getStoreConfig('doofinder_cron/schedule_settings/delay', $storeCode),
393
+ 'frequency' => Mage::getStoreConfig('doofinder_cron/schedule_settings/frequency', $storeCode),
394
+ 'time' => explode(',', Mage::getStoreConfig('doofinder_cron/schedule_settings/time', $storeCode)),
395
+ 'storeCode' => $storeCode,
396
+ 'xmlName' => $this->_processXmlName($xmlName, $storeCode),
397
+ 'reset' => Mage::getStoreConfig('doofinder_cron/schedule_settings/reset', $storeCode),
398
+ );
399
+ return $config;
400
+ }
401
+
402
+ /**
403
+ * Process xml filename
404
+ * @param string $name
405
+ * @return bool
406
+ */
407
+ private function _processXmlName($name = 'doofinder-{store_code}.xml', $code = 'default') {
408
+ $pattern = '/\{\s*store_code\s*\}/';
409
+
410
+ $newName = preg_replace($pattern, $code, $name);
411
+ return $newName;
412
+ }
413
+
414
+ /**
415
+ * Create cron expr string
416
+ * @param string $time
417
+ * @return mixed
418
+ */
419
+ private function _getCronExpr($time = null, $frequency = null) {
420
+
421
+ if (!$time) return false;
422
+ $time = explode(',', $time);
423
+
424
+ $cronExprArray = array(
425
+ intval($time[1]),
426
+ intval($time[0]),
427
+ ($frequency == self::CRON_MONTHLY) ? '1' : '*',
428
+ '*',
429
+ ($frequency == self::CRON_WEEKLY) ? '1' : '*',
430
+ );
431
+ $cronExprString = join(' ', $cronExprArray);
432
+
433
+ return $cronExprString;
434
+ }
435
+
436
+ /**
437
+ * Creates new schedule entry.
438
+ * @param Doofinder_Feed_Model_Cron $process
439
+ */
440
+
441
+ public function createNewSchedule(Doofinder_Feed_Model_Cron $process) {
442
+ $helper = Mage::helper('doofinder_feed');
443
+
444
+ $config = $helper->getStoreConfig($process->getStoreCode());
445
+
446
+ // Set new schedule time
447
+ $delayInMin = intval($config['stepDelay']);
448
+ $timescheduled = strftime("%Y-%m-%d %H:%M:%S", mktime(date("H"), date("i") + $delayInMin, date("s"), date("m"), date("d"), date("Y")));
449
+
450
+ // Prepare new process data
451
+ $status = $helper::STATUS_RUNNING;
452
+ $nextRun = '-';
453
+
454
+ // Set process data and save
455
+ $process->setStatus($status)
456
+ ->setNextRun('-')
457
+ ->setNextIteration($timescheduled)
458
+ ->save();
459
+
460
+ Mage::helper('doofinder_feed/log')->log($process, Doofinder_Feed_Helper_Log::STATUS, $helper->__('Scheduling the next step for %s', $timescheduled));
461
+ }
462
+
463
+ public function getScheduledAt($time = null, $frequency = null, $timezoneOffset = true) {
464
+ $parts = array($time[0], $time[1], $time[2], date('m'), date('d'));
465
+ $offset = $this->getTimezoneOffset();
466
+
467
+ $now = time();
468
+ $start = mktime($parts[0] - $offset, $parts[1], $parts[2], $parts[3], $parts[4]);
469
+
470
+ if ($start < $now) {
471
+ switch ($frequency) {
472
+ case self::CRON_MONTHLY:
473
+ $parts[3] += 1;
474
+ break;
475
+
476
+ case self::CRON_WEEKLY:
477
+ $parts[4] += 7;
478
+ break;
479
+
480
+ case self::CRON_DAILY:
481
+ $parts[4] += 1;
482
+ break;
483
+ }
484
+ }
485
+
486
+ if ($timezoneOffset) {
487
+ $parts[0] -= $offset;
488
+ }
489
+
490
+ return strftime("%Y-%m-%d %H:%M:%S", mktime($parts[0], $parts[1], $parts[2], $parts[3], $parts[4]));
491
+ }
492
+
493
+ public function getTimezoneOffset() {
494
+ $timezone = Mage::getStoreConfig('general/locale/timezone');
495
+ $backTimezone = date_default_timezone_get();
496
+ // Set relative timezone
497
+ date_default_timezone_set($timezone);
498
+ $offset = (date('Z') / 60 / 60);
499
+ // Revoke server timezone
500
+ date_default_timezone_set($backTimezone);
501
+ return $offset;
502
+ }
503
+
504
+ /**
505
+ * Get path to feed file.
506
+ *
507
+ * @return string
508
+ */
509
+ public function getFeedDirectory()
510
+ {
511
+ return Mage::getBaseDir('media').DS.'doofinder';
512
+ }
513
+
514
+ /**
515
+ * Get path to feed file.
516
+ *
517
+ * @return string
518
+ */
519
+ public function getFeedPath($storeCode)
520
+ {
521
+ $config = $this->getStoreConfig($storeCode);
522
+
523
+ return $this->getFeedDirectory().DS.$config['xmlName'];
524
+ }
525
+
526
+ /**
527
+ * Get path to feed file.
528
+ *
529
+ * @return string
530
+ */
531
+ public function getFeedTemporaryPath($storeCode)
532
+ {
533
+ return $this->getFeedPath($storeCode) . '.tmp';
534
+ }
535
+
536
+ /**
537
+ * Creates feed directory.
538
+ *
539
+ * @param string $dir
540
+ * @return bool
541
+ */
542
+ public function createFeedDirectory()
543
+ {
544
+ $dir = $this->getFeedDirectory();
545
+
546
+ if ((!file_exists($dir) && !mkdir($dir, 0777, true)) || !is_dir($dir)) {
547
+ Mage::throwException('Could not create directory: '.$dir);
548
+ }
549
+
550
+ return true;
551
+ }
552
+ }
app/code/community/Doofinder/Feed/Helper/Log.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of Doofinder_Feed.
4
+ */
5
+
6
+ /**
7
+ * @category Helpers
8
+ * @package Doofinder_Feed
9
+ * @version 1.6.5
10
+ */
11
+
12
+ /**
13
+ * Log helper for Doofinder Feed
14
+ *
15
+ * @version 1.6.5
16
+ * @package Doofinder_Feed
17
+ */
18
+ class Doofinder_Feed_Helper_Log extends Mage_Core_Helper_Abstract
19
+ {
20
+ const STATUS = 'status';
21
+ const WARNING = 'warning';
22
+ const ERROR = 'error';
23
+
24
+ /**
25
+ * Log the feed event.
26
+ *
27
+ * @param Doofinder_Feed_Model_Cron $process
28
+ * @param string $type
29
+ * @param string $message
30
+ */
31
+ function log(Doofinder_Feed_Model_Cron $process, $type, $message)
32
+ {
33
+ $entry = Mage::getModel('doofinder_feed/log')
34
+ ->setProcessId($process->getId())
35
+ ->setType($type)
36
+ ->setMessage($message)
37
+ ->save();
38
+
39
+ return $this;
40
+ }
41
+
42
+ /**
43
+ * Get available log types
44
+ *
45
+ * @return array
46
+ */
47
+ function listLogTypes()
48
+ {
49
+ return array(
50
+ static::STATUS => $this->__('Status'),
51
+ static::WARNING => $this->__('Warning'),
52
+ static::ERROR => $this->__('Error'),
53
+ );
54
+ }
55
+ }
app/code/community/Doofinder/Feed/Helper/Search.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once(Mage::getBaseDir('lib') . DS. 'Doofinder' . DS .'doofinder_api.php');
3
+
4
+ class Doofinder_Feed_Helper_Search extends Mage_Core_Helper_Abstract
5
+ {
6
+ const DOOFINDER_PAGE_LIMIT = 100;
7
+ const DOOFINDER_RESULTS_LIMIT = 1000;
8
+
9
+ protected $_lastSearch = null;
10
+ protected $_lastResults = null;
11