Version Notes
- Attributes change
Download this release
Release Info
Developer | Klevu |
Extension | Klevu_SmartSearch |
Version | 1.1.13 |
Comparing to | |
See all releases |
Version 1.1.13
- app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Attribute/Mappings.php +98 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Automatic/Attribute/Mappings.php +23 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Html/Select.php +8 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Image/Button.php +49 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Image/Log.php +49 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Store/Level/Label.php +23 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Sync/Button.php +48 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Form/Information.php +28 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Notifications.php +24 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Wizard/Config/Button.php +86 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Wizard/Configure/Attributes.php +50 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Wizard/Configure/Store.php +48 -0
- app/code/community/Klevu/Search/Block/Adminhtml/Wizard/Configure/User.php +22 -0
- app/code/community/Klevu/Search/Block/Catalog/Product/Tracking.php +26 -0
- app/code/community/Klevu/Search/Helper/Api.php +210 -0
- app/code/community/Klevu/Search/Helper/Compat.php +51 -0
- app/code/community/Klevu/Search/Helper/Config.php +642 -0
- app/code/community/Klevu/Search/Helper/Data.php +197 -0
- app/code/community/Klevu/Search/Model/Api/Action.php +118 -0
- app/code/community/Klevu/Search/Model/Api/Action/Addrecords.php +232 -0
- app/code/community/Klevu/Search/Model/Api/Action/Adduser.php +32 -0
- app/code/community/Klevu/Search/Model/Api/Action/Addwebstore.php +56 -0
- app/code/community/Klevu/Search/Model/Api/Action/Debuginfo.php +24 -0
- app/code/community/Klevu/Search/Model/Api/Action/Deleterecords.php +12 -0
- app/code/community/Klevu/Search/Model/Api/Action/Gettimezone.php +14 -0
- app/code/community/Klevu/Search/Model/Api/Action/Getuserdetail.php +28 -0
- app/code/community/Klevu/Search/Model/Api/Action/Idsearch.php +70 -0
- app/code/community/Klevu/Search/Model/Api/Action/Producttracking.php +75 -0
- app/code/community/Klevu/Search/Model/Api/Action/Removetestmode.php +24 -0
- app/code/community/Klevu/Search/Model/Api/Action/Startsession.php +37 -0
- app/code/community/Klevu/Search/Model/Api/Action/Updaterecords.php +12 -0
- app/code/community/Klevu/Search/Model/Api/Request.php +178 -0
- app/code/community/Klevu/Search/Model/Api/Request/Get.php +32 -0
- app/code/community/Klevu/Search/Model/Api/Request/Post.php +32 -0
- app/code/community/Klevu/Search/Model/Api/Request/Xml.php +127 -0
- app/code/community/Klevu/Search/Model/Api/Response.php +107 -0
- app/code/community/Klevu/Search/Model/Api/Response/Data.php +37 -0
- app/code/community/Klevu/Search/Model/Api/Response/Empty.php +24 -0
- app/code/community/Klevu/Search/Model/Api/Response/Invalid.php +60 -0
- app/code/community/Klevu/Search/Model/Api/Response/Message.php +28 -0
- app/code/community/Klevu/Search/Model/Api/Response/Search.php +73 -0
- app/code/community/Klevu/Search/Model/Api/Response/Timezone.php +16 -0
- app/code/community/Klevu/Search/Model/Catalog/Model/Config.php +31 -0
- app/code/community/Klevu/Search/Model/CatalogSearch/Layer/Filter/Attribute.php +104 -0
- app/code/community/Klevu/Search/Model/CatalogSearch/Layer/Filter/Category.php +103 -0
- app/code/community/Klevu/Search/Model/CatalogSearch/Layer/Filter/Price.php +93 -0
- app/code/community/Klevu/Search/Model/CatalogSearch/Resource/Fulltext/Collection.php +463 -0
- app/code/community/Klevu/Search/Model/CatalogSearch/Resource/Layer/Filter/Attribute.php +20 -0
- app/code/community/Klevu/Search/Model/Config/Log/Level.php +15 -0
- app/code/community/Klevu/Search/Model/Cron.php +13 -0
- app/code/community/Klevu/Search/Model/Notification.php +8 -0
- app/code/community/Klevu/Search/Model/Observer.php +137 -0
- app/code/community/Klevu/Search/Model/Order/Sync.php +364 -0
- app/code/community/Klevu/Search/Model/Product/Sync.php +1969 -0
- app/code/community/Klevu/Search/Model/Resource/Notification.php +8 -0
- app/code/community/Klevu/Search/Model/Resource/Notification/Collection.php +8 -0
- app/code/community/Klevu/Search/Model/Session.php +8 -0
- app/code/community/Klevu/Search/Model/Sync.php +156 -0
- app/code/community/Klevu/Search/Model/System/Config/Source/Additional/Attributes.php +15 -0
- app/code/community/Klevu/Search/Model/System/Config/Source/Boosting/Attribute.php +62 -0
- app/code/community/Klevu/Search/Model/System/Config/Source/Frequency.php +37 -0
- app/code/community/Klevu/Search/Model/System/Config/Source/Landingoptions.php +19 -0
- app/code/community/Klevu/Search/Model/System/Config/Source/Log/Level.php +19 -0
- app/code/community/Klevu/Search/Model/System/Config/Source/Product/Attributes.php +36 -0
- app/code/community/Klevu/Search/Model/System/Config/Source/Yesnoforced.php +18 -0
- app/code/community/Klevu/Search/Test/Config/Base.php +13 -0
- app/code/community/Klevu/Search/Test/Controller/CatalogSearch.php +342 -0
- app/code/community/Klevu/Search/Test/Controller/CatalogSearch/fixtures/search_results.yaml +133 -0
- app/code/community/Klevu/Search/Test/Helper/Api.php +10 -0
- app/code/community/Klevu/Search/Test/Helper/Compat.php +20 -0
- app/code/community/Klevu/Search/Test/Helper/Config.php +345 -0
- app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testGetOrderSyncEnabledFlag.yaml +2 -0
- app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testGetOrderSyncFrequency.yaml +2 -0
- app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testGetProductSyncEnabledFlag.yaml +2 -0
- app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testGetProductSyncFrequency.yaml +2 -0
- app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testIsExtensionEnabledDisabled.yaml +2 -0
- app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testIsExtensionEnabledEnabled.yaml +2 -0
- app/code/community/Klevu/Search/Test/Helper/Config/providers/testIsOrderSyncEnabled.yaml +24 -0
- app/code/community/Klevu/Search/Test/Helper/Config/providers/testIsProductSyncEnabled.yaml +24 -0
- app/code/community/Klevu/Search/Test/Helper/Config/providers/testIsTestModeEnabled.yaml +16 -0
- app/code/community/Klevu/Search/Test/Helper/Data.php +49 -0
- app/code/community/Klevu/Search/Test/Helper/Data/providers/testBytesToHumanReadable.yaml +18 -0
- app/code/community/Klevu/Search/Test/Helper/Data/providers/testGetLanguageFromLocale.yaml +12 -0
- app/code/community/Klevu/Search/Test/Helper/Data/providers/testHumanReadableToBytes.yaml +18 -0
- app/code/community/Klevu/Search/Test/Helper/Data/providers/testIsProductionDomain.yaml +15 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action.php +55 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords.php +176 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords/providers/testValidateRequiredFields.yaml +4 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords/providers/testValidateRequiredFieldsRecords.yaml +14 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords/providers/testValidateRequiredFieldsRecordsAllowedEmpty.yaml +4 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords/providers/testValidateRequiredFieldsRecordsEmpty.yaml +10 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords/providers/testValidateRequiredFieldsRecordsOptional.yaml +26 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Adduser.php +62 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Adduser/providers/testValidateRequiredFields.yaml +6 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Addwebstore.php +67 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Addwebstore/providers/testValidateRequiredFields.yaml +10 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Getuserdetail.php +61 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Getuserdetail/providers/testValidateRequiredFields.yaml +4 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Idsearch.php +96 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Idsearch/providers/testValidateRequiredFields.yaml +12 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Producttracking.php +76 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Producttracking/providers/testValidateRequiredFields.yaml +14 -0
- app/code/community/Klevu/Search/Test/Model/Api/Action/Startsession.php +30 -0
- app/code/community/Klevu/Search/Test/Model/Api/Request.php +69 -0
- app/code/community/Klevu/Search/Test/Model/Api/Request/Xml.php +16 -0
- app/code/community/Klevu/Search/Test/Model/Api/Request/Xml/providers/testGetDataAsXml.yaml +25 -0
- app/code/community/Klevu/Search/Test/Model/Api/Response.php +19 -0
- app/code/community/Klevu/Search/Test/Model/Api/Response/Data.php +31 -0
- app/code/community/Klevu/Search/Test/Model/Api/Response/Data/providers/testIsSuccessful.yaml +12 -0
- app/code/community/Klevu/Search/Test/Model/Api/Response/Empty.php +33 -0
- app/code/community/Klevu/Search/Test/Model/Api/Response/Invalid.php +33 -0
- app/code/community/Klevu/Search/Test/Model/Api/Response/Message.php +29 -0
- app/code/community/Klevu/Search/Test/Model/Api/Response/Message/providers/testIsSuccessful.yaml +16 -0
- app/code/community/Klevu/Search/Test/Model/Api/Response/Timezone.php +17 -0
- app/code/community/Klevu/Search/Test/Model/Api/Response/Timezone/providers/testIsSuccessful.yaml +16 -0
- app/code/community/Klevu/Search/Test/Model/Api/Response/providers/response_testIsSuccessful.yaml +20 -0
- app/code/community/Klevu/Search/Test/Model/Api/Test/Case.php +64 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/data_response_data.xml +5 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/data_response_failure.xml +4 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/data_response_no_response.xml +3 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/data_response_success.xml +18 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/data_response_success_only.xml +3 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/message_response_failure.xml +4 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/message_response_missing_message.xml +3 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/message_response_missing_status.xml +3 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/message_response_session_id.xml +4 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/message_response_success.xml +4 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/response_malformed.xml +4 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/response_noxml.xml +1 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/response_valid.xml +4 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/search_response_empty.xml +18 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/search_response_paged.xml +22 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/search_response_sorted.xml +30 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/search_response_success.xml +30 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/startsession_response_success.xml +5 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/timezone_response_no_data.xml +3 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/timezone_response_no_status.xml +4 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/timezone_response_with_failure.xml +5 -0
- app/code/community/Klevu/Search/Test/Model/Api/data/timezone_response_with_success.xml +5 -0
- app/code/community/Klevu/Search/Test/Model/Config/Log/Level.php +19 -0
- app/code/community/Klevu/Search/Test/Model/Notification.php +47 -0
- app/code/community/Klevu/Search/Test/Model/Notification/fixtures/testLoad.yaml +7 -0
- app/code/community/Klevu/Search/Test/Model/Observer.php +98 -0
- app/code/community/Klevu/Search/Test/Model/Observer/fixtures/testScheduleOrderSync.yaml +320 -0
- app/code/community/Klevu/Search/Test/Model/Order/Sync.php +90 -0
- app/code/community/Klevu/Search/Test/Model/Order/Sync/fixtures/testAddOrderToQueue.yaml +319 -0
- app/code/community/Klevu/Search/Test/Model/Order/Sync/fixtures/testClearQueue.yaml +563 -0
- app/code/community/Klevu/Search/Test/Model/Order/Sync/fixtures/testRun.yaml +323 -0
- app/code/community/Klevu/Search/Test/Model/Product/Sync.php +275 -0
- app/code/community/Klevu/Search/Test/Model/Product/Sync/fixtures/testAddProducts.yaml +31 -0
- app/code/community/Klevu/Search/Test/Model/Product/Sync/fixtures/testClearAllProducts.yaml +20 -0
- app/code/community/Klevu/Search/Test/Model/Product/Sync/fixtures/testDeleteProducts.yaml +13 -0
- app/code/community/Klevu/Search/Test/Model/Product/Sync/fixtures/testRun.yaml +425 -0
- app/code/community/Klevu/Search/Test/Model/Product/Sync/fixtures/testUpdateProducts.yaml +39 -0
- app/code/community/Klevu/Search/Test/Model/Sync.php +130 -0
- app/code/community/Klevu/Search/Test/Model/Sync/providers/testSchedule.yaml +4 -0
- app/code/community/Klevu/Search/Test/Model/System/Config/Source/Test.php +26 -0
- app/code/community/Klevu/Search/Test/Model/System/Config/Source/Test/providers/testIsValidSourceModel.yaml +10 -0
- app/code/community/Klevu/Search/controllers/Adminhtml/Klevu/NotificationsController.php +18 -0
- app/code/community/Klevu/Search/controllers/Adminhtml/Klevu/Search/WizardController.php +214 -0
- app/code/community/Klevu/Search/controllers/Adminhtml/Klevu/SearchController.php +64 -0
- app/code/community/Klevu/Search/controllers/SearchController.php +139 -0
- app/code/community/Klevu/Search/etc/adminhtml.xml +26 -0
- app/code/community/Klevu/Search/etc/config.xml +285 -0
- app/code/community/Klevu/Search/etc/system.xml +342 -0
- app/code/community/Klevu/Search/sql/klevu_search_setup/mysql4-data-upgrade-1.1.1-1.1.2.php +60 -0
- app/code/community/Klevu/Search/sql/klevu_search_setup/mysql4-data-upgrade-1.1.7-1.1.8.php +113 -0
- app/code/community/Klevu/Search/sql/klevu_search_setup/mysql4-install-1.0.0.php +76 -0
- app/design/adminhtml/default/default/layout/klevu/search.xml +61 -0
- app/design/adminhtml/default/default/template/klevu/search/form/field/array_readonly.phtml +25 -0
- app/design/adminhtml/default/default/template/klevu/search/form/field/sync/button.phtml +9 -0
- app/design/adminhtml/default/default/template/klevu/search/form/field/sync/logbutton.phtml +9 -0
- app/design/adminhtml/default/default/template/klevu/search/form/information.phtml +11 -0
- app/design/adminhtml/default/default/template/klevu/search/notifications.phtml +8 -0
- app/design/adminhtml/default/default/template/klevu/search/wizard/complete.phtml +17 -0
- app/design/adminhtml/default/default/template/klevu/search/wizard/config/button.phtml +11 -0
- app/design/adminhtml/default/default/template/klevu/search/wizard/configure/attributes.phtml +22 -0
- app/design/adminhtml/default/default/template/klevu/search/wizard/configure/store.phtml +49 -0
- app/design/adminhtml/default/default/template/klevu/search/wizard/configure/user.phtml +106 -0
- app/design/adminhtml/default/default/template/klevu/search/wizard/form/field/array.phtml +139 -0
- app/design/frontend/base/default/layout/klevu/search.xml +28 -0
- app/design/frontend/base/default/template/klevu/search/form_js.phtml +55 -0
- app/design/frontend/base/default/template/klevu/search/klevulog.phtml +7 -0
- app/design/frontend/base/default/template/klevu/search/product_tracking.phtml +35 -0
- app/etc/modules/Klevu_Search.xml +9 -0
- js/klevu/search/lib/Wizard.js +179 -0
- package.xml +25 -0
- skin/adminhtml/default/default/klevu/search/notifications.css +10 -0
- skin/adminhtml/default/default/klevu/search/wizard.css +105 -0
- skin/frontend/base/default/css/klevu/klevu-landing-page-style.css +618 -0
- skin/frontend/base/default/css/klevu/klevu-landing-responsive.css +142 -0
- skin/frontend/base/default/images/klevu/btn-gridview.png +0 -0
- skin/frontend/base/default/images/klevu/btn-listview.png +0 -0
- skin/frontend/base/default/images/klevu/ku-loader.gif +0 -0
app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Attribute/Mappings.php
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Block_Adminhtml_Form_Field_Attribute_Mappings extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract {
|
4 |
+
|
5 |
+
protected $klevu_attribute_renderer;
|
6 |
+
|
7 |
+
protected $magento_attribute_renderer;
|
8 |
+
|
9 |
+
protected function _prepareToRender() {
|
10 |
+
$this->addColumn("klevu_attribute", array(
|
11 |
+
'label' => Mage::helper('klevu_search')->__("Klevu Attribute"),
|
12 |
+
'renderer' => $this->getKlevuAttributeRenderer()
|
13 |
+
));
|
14 |
+
$this->addColumn("magento_attribute", array(
|
15 |
+
'label' => Mage::helper('klevu_search')->__("Magento Attribute"),
|
16 |
+
'renderer' => $this->getMagentoAttributeRenderer()
|
17 |
+
));
|
18 |
+
|
19 |
+
$this->_addAfter = false;
|
20 |
+
$this->_addButtonLabel = Mage::helper('klevu_search')->__("Add Mapping");
|
21 |
+
}
|
22 |
+
|
23 |
+
protected function _prepareArrayRow(Varien_Object $row) {
|
24 |
+
$row->setData(
|
25 |
+
'option_extra_attr_' . $this->getKlevuAttributeRenderer()->calcOptionHash($row->getData('klevu_attribute')),
|
26 |
+
'selected="selected"'
|
27 |
+
);
|
28 |
+
$row->setData(
|
29 |
+
'option_extra_attr_' . $this->getMagentoAttributeRenderer()->calcOptionHash($row->getData('magento_attribute')),
|
30 |
+
'selected="selected"'
|
31 |
+
);
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Return a block to render the select element for Klevu Attribute.
|
36 |
+
*
|
37 |
+
* @return Klevu_Search_Block_Adminhtml_Form_Field_Html_Select
|
38 |
+
*/
|
39 |
+
protected function getKlevuAttributeRenderer() {
|
40 |
+
if (!$this->klevu_attribute_renderer) {
|
41 |
+
/** @var Mage_Core_Block_Html_Select $renderer */
|
42 |
+
$renderer = $this->getLayout()->createBlock('klevu_search/adminhtml_form_field_html_select', '', array(
|
43 |
+
'is_render_to_js_template' => true
|
44 |
+
));
|
45 |
+
$renderer->setOptions(Mage::getModel('klevu_search/system_config_source_additional_attributes')->toOptionArray());
|
46 |
+
$renderer->setExtraParams('style="width:120px"');
|
47 |
+
|
48 |
+
$this->klevu_attribute_renderer = $renderer;
|
49 |
+
}
|
50 |
+
|
51 |
+
return $this->klevu_attribute_renderer;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Return a block to render the select element for Magento Attribute.
|
56 |
+
*
|
57 |
+
* @return Klevu_Search_Block_Adminhtml_Form_Field_Html_Select
|
58 |
+
*/
|
59 |
+
protected function getMagentoAttributeRenderer() {
|
60 |
+
if (!$this->magento_attribute_renderer) {
|
61 |
+
/** @var Mage_Core_Block_Html_Select $renderer */
|
62 |
+
$renderer = $this->getLayout()->createBlock('klevu_search/adminhtml_form_field_html_select', '', array(
|
63 |
+
'is_render_to_js_template' => true
|
64 |
+
));
|
65 |
+
$renderer->setOptions($this->getOptions());
|
66 |
+
$renderer->setExtraParams('style="width:120px"');
|
67 |
+
|
68 |
+
$this->magento_attribute_renderer = $renderer;
|
69 |
+
}
|
70 |
+
|
71 |
+
return $this->magento_attribute_renderer;
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Get the options from our product attribute source model, and filter out the search attributes.
|
76 |
+
* @return array
|
77 |
+
*/
|
78 |
+
protected function getOptions() {
|
79 |
+
$options_with_search_filters = Mage::getModel('klevu_search/system_config_source_product_attributes')->toOptionArray();
|
80 |
+
$search_attributes_map = Mage::helper('klevu_search/config')->getAutomaticAttributesMap(Mage::app()->getRequest()->getParam('store'));
|
81 |
+
$options = array();
|
82 |
+
|
83 |
+
// Flatten the search_attributes_map
|
84 |
+
$search_attributes = array();
|
85 |
+
foreach($search_attributes_map as $attribute) {
|
86 |
+
$search_attributes[] = $attribute['magento_attribute'];
|
87 |
+
}
|
88 |
+
|
89 |
+
// We only want options that are not in the search_attributes array.
|
90 |
+
foreach($options_with_search_filters as $option) {
|
91 |
+
if(!in_array($option['value'], $search_attributes)) {
|
92 |
+
$options[] = $option;
|
93 |
+
}
|
94 |
+
}
|
95 |
+
|
96 |
+
return $options;
|
97 |
+
}
|
98 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Automatic/Attribute/Mappings.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Block_Adminhtml_Form_Field_Automatic_Attribute_Mappings extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Check if columns are defined, set template
|
7 |
+
*
|
8 |
+
*/
|
9 |
+
public function __construct()
|
10 |
+
{
|
11 |
+
parent::__construct();
|
12 |
+
$this->setTemplate('klevu/search/form/field/array_readonly.phtml');
|
13 |
+
}
|
14 |
+
|
15 |
+
protected function _prepareToRender() {
|
16 |
+
$this->addColumn("klevu_attribute", array(
|
17 |
+
'label' => Mage::helper('klevu_search')->__("Klevu Attribute")
|
18 |
+
));
|
19 |
+
$this->addColumn("magento_attribute", array(
|
20 |
+
'label' => Mage::helper('klevu_search')->__("Magento Attribute")
|
21 |
+
));
|
22 |
+
}
|
23 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Html/Select.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Block_Adminhtml_Form_Field_Html_Select extends Mage_Adminhtml_Block_Html_Select {
|
4 |
+
|
5 |
+
public function setInputName($value) {
|
6 |
+
return $this->setName($value);
|
7 |
+
}
|
8 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Image/Button.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Klevu_Search_Block_Adminhtml_Form_Field_Image_Button
|
5 |
+
*
|
6 |
+
* @method setStoreId($id)
|
7 |
+
* @method string getStoreId()
|
8 |
+
*/
|
9 |
+
|
10 |
+
class Klevu_Search_Block_Adminhtml_Form_Field_Image_Button extends Mage_Adminhtml_Block_System_Config_Form_Field {
|
11 |
+
|
12 |
+
protected function _prepareLayout() {
|
13 |
+
parent::_prepareLayout();
|
14 |
+
|
15 |
+
// Set the default template
|
16 |
+
if (!$this->getTemplate()) {
|
17 |
+
$this->setTemplate('klevu/search/form/field/sync/button.phtml');
|
18 |
+
}
|
19 |
+
|
20 |
+
return $this;
|
21 |
+
}
|
22 |
+
|
23 |
+
public function render(Varien_Data_Form_Element_Abstract $element) {
|
24 |
+
if ($element->getScope() == "stores") {
|
25 |
+
$this->setStoreId($element->getScopeId());
|
26 |
+
}
|
27 |
+
|
28 |
+
// Remove the scope information so it doesn't get printed out
|
29 |
+
$element
|
30 |
+
->unsScope()
|
31 |
+
->unsCanUseWebsiteValue()
|
32 |
+
->unsCanUseDefaultValue();
|
33 |
+
|
34 |
+
return parent::render($element);
|
35 |
+
}
|
36 |
+
|
37 |
+
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) {
|
38 |
+
$url_params = ($this->getStoreId()) ? array("store" => $this->getStoreId()) : array();
|
39 |
+
$label_suffix = ($this->getStoreId()) ? " for This Store" : "";
|
40 |
+
|
41 |
+
$this->addData(array(
|
42 |
+
"html_id" => $element->getHtmlId(),
|
43 |
+
"button_label" => sprintf("Generate Thumbnails For All Products%s", $label_suffix),
|
44 |
+
"destination_url" => $this->getUrl("adminhtml/klevu_search/generate_thumbnail", $url_params)
|
45 |
+
));
|
46 |
+
|
47 |
+
return $this->_toHtml();
|
48 |
+
}
|
49 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Image/Log.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Klevu_Search_Block_Adminhtml_Form_Field_Image_Button
|
5 |
+
*
|
6 |
+
* @method setStoreId($id)
|
7 |
+
* @method string getStoreId()
|
8 |
+
*/
|
9 |
+
|
10 |
+
class Klevu_Search_Block_Adminhtml_Form_Field_Image_Log extends Mage_Adminhtml_Block_System_Config_Form_Field {
|
11 |
+
|
12 |
+
protected function _prepareLayout() {
|
13 |
+
parent::_prepareLayout();
|
14 |
+
|
15 |
+
// Set the default template
|
16 |
+
if (!$this->getTemplate()) {
|
17 |
+
$this->setTemplate('klevu/search/form/field/sync/logbutton.phtml');
|
18 |
+
}
|
19 |
+
|
20 |
+
return $this;
|
21 |
+
}
|
22 |
+
|
23 |
+
public function render(Varien_Data_Form_Element_Abstract $element) {
|
24 |
+
if ($element->getScope() == "stores") {
|
25 |
+
$this->setStoreId($element->getScopeId());
|
26 |
+
}
|
27 |
+
|
28 |
+
// Remove the scope information so it doesn't get printed out
|
29 |
+
$element
|
30 |
+
->unsScope()
|
31 |
+
->unsCanUseWebsiteValue()
|
32 |
+
->unsCanUseDefaultValue();
|
33 |
+
|
34 |
+
return parent::render($element);
|
35 |
+
}
|
36 |
+
|
37 |
+
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) {
|
38 |
+
$url_params = array("debug" => "klevu");
|
39 |
+
$label_suffix = ($this->getStoreId()) ? " for This Store" : "";
|
40 |
+
|
41 |
+
$this->addData(array(
|
42 |
+
"html_id" => $element->getHtmlId(),
|
43 |
+
"button_label" => sprintf("Send Log"),
|
44 |
+
"destination_url" => $this->getUrl("klevu/search/runexternaly", $url_params)
|
45 |
+
));
|
46 |
+
|
47 |
+
return $this->_toHtml();
|
48 |
+
}
|
49 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Store/Level/Label.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Block_Adminhtml_Form_Field_Store_Level_Label extends Mage_Adminhtml_Block_System_Config_Form_Field {
|
4 |
+
|
5 |
+
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) {
|
6 |
+
if ($element->getScope() == "stores") {
|
7 |
+
return $element->getEscapedValue();
|
8 |
+
} else {
|
9 |
+
return Mage::helper("klevu_search")->__("Switch to store scope to see");
|
10 |
+
}
|
11 |
+
}
|
12 |
+
|
13 |
+
public function render(Varien_Data_Form_Element_Abstract $element) {
|
14 |
+
$this->setData('scope', $element->getScope());
|
15 |
+
|
16 |
+
// Remove the inheritance checkbox
|
17 |
+
$element
|
18 |
+
->unsCanUseWebsiteValue()
|
19 |
+
->unsCanUseDefaultValue();
|
20 |
+
|
21 |
+
return parent::render($element);
|
22 |
+
}
|
23 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Form/Field/Sync/Button.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Klevu_Search_Block_Adminhtml_Form_Field_Sync_Button
|
5 |
+
*
|
6 |
+
* @method setStoreId($id)
|
7 |
+
* @method string getStoreId()
|
8 |
+
*/
|
9 |
+
class Klevu_Search_Block_Adminhtml_Form_Field_Sync_Button extends Mage_Adminhtml_Block_System_Config_Form_Field {
|
10 |
+
|
11 |
+
protected function _prepareLayout() {
|
12 |
+
parent::_prepareLayout();
|
13 |
+
|
14 |
+
// Set the default template
|
15 |
+
if (!$this->getTemplate()) {
|
16 |
+
$this->setTemplate('klevu/search/form/field/sync/button.phtml');
|
17 |
+
}
|
18 |
+
|
19 |
+
return $this;
|
20 |
+
}
|
21 |
+
|
22 |
+
public function render(Varien_Data_Form_Element_Abstract $element) {
|
23 |
+
if ($element->getScope() == "stores") {
|
24 |
+
$this->setStoreId($element->getScopeId());
|
25 |
+
}
|
26 |
+
|
27 |
+
// Remove the scope information so it doesn't get printed out
|
28 |
+
$element
|
29 |
+
->unsScope()
|
30 |
+
->unsCanUseWebsiteValue()
|
31 |
+
->unsCanUseDefaultValue();
|
32 |
+
|
33 |
+
return parent::render($element);
|
34 |
+
}
|
35 |
+
|
36 |
+
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) {
|
37 |
+
$url_params = ($this->getStoreId()) ? array("store" => $this->getStoreId()) : array();
|
38 |
+
$label_suffix = ($this->getStoreId()) ? " for This Store" : "";
|
39 |
+
|
40 |
+
$this->addData(array(
|
41 |
+
"html_id" => $element->getHtmlId(),
|
42 |
+
"button_label" => sprintf("Sync All Products%s", $label_suffix),
|
43 |
+
"destination_url" => $this->getUrl("adminhtml/klevu_search/sync_all", $url_params)
|
44 |
+
));
|
45 |
+
|
46 |
+
return $this->_toHtml();
|
47 |
+
}
|
48 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Form/Information.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Block_Adminhtml_Form_Information extends Mage_Adminhtml_Block_System_Config_Form_Fieldset {
|
4 |
+
|
5 |
+
protected function _construct() {
|
6 |
+
parent::_construct();
|
7 |
+
|
8 |
+
if (!$this->getTemplate()) {
|
9 |
+
// Set the default template
|
10 |
+
$this->setTemplate("klevu/search/form/information.phtml");
|
11 |
+
}
|
12 |
+
}
|
13 |
+
|
14 |
+
public function render(Varien_Data_Form_Element_Abstract $element) {
|
15 |
+
$html = $this->_getHeaderHtml($element);
|
16 |
+
|
17 |
+
$html .= $this->_toHtml();
|
18 |
+
|
19 |
+
$html .= $this->_getFooterHtml($element);
|
20 |
+
|
21 |
+
return $html;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function getVersion() {
|
25 |
+
return Mage::getConfig()->getModuleConfig('Klevu_Search')->version;
|
26 |
+
}
|
27 |
+
|
28 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Notifications.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Block_Adminhtml_Notifications extends Mage_Adminhtml_Block_Template {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Return all notifications.
|
7 |
+
*
|
8 |
+
* @return Klevu_Search_Model_Resource_Notification_Collection
|
9 |
+
*/
|
10 |
+
protected function getNotifications() {
|
11 |
+
return Mage::getResourceModel("klevu_search/notification_collection");
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Return the URL to dismiss the given notification.
|
16 |
+
*
|
17 |
+
* @param $notification
|
18 |
+
*
|
19 |
+
* @return string
|
20 |
+
*/
|
21 |
+
protected function getDismissUrl($notification) {
|
22 |
+
return $this->getUrl("adminhtml/klevu_notifications/dismiss", array("id" => $notification->getId()));
|
23 |
+
}
|
24 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Wizard/Config/Button.php
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Klevu_Search_Block_Adminhtml_Wizard_Config_Button
|
4 |
+
*
|
5 |
+
* @method string getHtmlId()
|
6 |
+
* @method string getWizardUrl()
|
7 |
+
*/
|
8 |
+
class Klevu_Search_Block_Adminhtml_Wizard_Config_Button extends Mage_Adminhtml_Block_System_Config_Form_Field {
|
9 |
+
|
10 |
+
protected function _prepareLayout() {
|
11 |
+
parent::_prepareLayout();
|
12 |
+
|
13 |
+
// Set the default template
|
14 |
+
if (!$this->getTemplate()) {
|
15 |
+
$this->setTemplate('klevu/search/wizard/config/button.phtml');
|
16 |
+
}
|
17 |
+
|
18 |
+
return $this;
|
19 |
+
}
|
20 |
+
|
21 |
+
public function render(Varien_Data_Form_Element_Abstract $element) {
|
22 |
+
// Only show the current scope hasn't been configured yet
|
23 |
+
switch($element->getScope()) {
|
24 |
+
case "stores":
|
25 |
+
if ($this->hasApiKeys($element->getScopeId())) {
|
26 |
+
return "";
|
27 |
+
}
|
28 |
+
break;
|
29 |
+
case "websites":
|
30 |
+
$website = Mage::app()->getWebsite($element->getScopeId());
|
31 |
+
if ($this->hasApiKeys($website->getStores())) {
|
32 |
+
return "";
|
33 |
+
}
|
34 |
+
break;
|
35 |
+
default:
|
36 |
+
if ($this->hasApiKeys()) {
|
37 |
+
return "";
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
// Remove the scope information so it doesn't get printed out
|
42 |
+
$element
|
43 |
+
->unsScope()
|
44 |
+
->unsCanUseWebsiteValue()
|
45 |
+
->unsCanUseDefaultValue();
|
46 |
+
|
47 |
+
return parent::render($element);
|
48 |
+
}
|
49 |
+
|
50 |
+
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) {
|
51 |
+
$this->addData(array(
|
52 |
+
'html_id' => $element->getHtmlId(),
|
53 |
+
'wizard_url' => $this->getUrl("adminhtml/klevu_search_wizard/configure_user")
|
54 |
+
));
|
55 |
+
|
56 |
+
return $this->_toHtml();
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Check if the given stores all have Klevu API keys. If no stores are given, checks
|
61 |
+
* all configured stores.
|
62 |
+
*
|
63 |
+
* @param null $stores
|
64 |
+
*
|
65 |
+
* @return bool true if all stores have API keys, false otherwise.
|
66 |
+
*/
|
67 |
+
protected function hasApiKeys($stores = null) {
|
68 |
+
$config = Mage::helper("klevu_search/config");
|
69 |
+
|
70 |
+
if ($stores === null) {
|
71 |
+
$stores = Mage::app()->getStores(false);
|
72 |
+
}
|
73 |
+
|
74 |
+
if (!is_array($stores)) {
|
75 |
+
$stores = array($stores);
|
76 |
+
}
|
77 |
+
|
78 |
+
foreach ($stores as $store) {
|
79 |
+
if (!$config->getJsApiKey($store) || !$config->getRestApiKey($store)) {
|
80 |
+
return false;
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
return true;
|
85 |
+
}
|
86 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Wizard/Configure/Attributes.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Block_Adminhtml_Wizard_Configure_Attributes extends Mage_Adminhtml_Block_Template {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Return the submit URL for the store configuration form.
|
7 |
+
*
|
8 |
+
* @return string
|
9 |
+
*/
|
10 |
+
protected function getFormActionUrl() {
|
11 |
+
return $this->getUrl("adminhtml/klevu_search_wizard/configure_attributes_post");
|
12 |
+
}
|
13 |
+
|
14 |
+
protected function getAttributeMappingsHtml() {
|
15 |
+
$element = new Varien_Data_Form_Element_Text(array(
|
16 |
+
"name" => "attributes",
|
17 |
+
"label" => $this->__("Additional Attributes"),
|
18 |
+
"comment" => $this->__('Here you can set optional product attributes sent to Klevu by mapping them to your Magento attributes. If you specify multiple mappings for the same Klevu attribute, only the first mapping found on the product sent will be used, except for the "Other" attribute where all existing mappings are used.'),
|
19 |
+
"tooltip" => "",
|
20 |
+
"hint" => "",
|
21 |
+
"value" => Mage::helper("klevu_search/config")->getAdditionalAttributesMap($this->getStore()),
|
22 |
+
"inherit" => false,
|
23 |
+
"class" => "",
|
24 |
+
"can_use_default_value" => false,
|
25 |
+
"can_use_website_value" => false
|
26 |
+
));
|
27 |
+
$element->setForm(new Varien_Data_Form());
|
28 |
+
|
29 |
+
/** @var Klevu_Search_Block_Adminhtml_Form_Field_Attribute_Mappings $renderer */
|
30 |
+
$renderer = Mage::getBlockSingleton("klevu_search/adminhtml_form_field_attribute_mappings");
|
31 |
+
$renderer->setTemplate("klevu/search/wizard/form/field/array.phtml");
|
32 |
+
|
33 |
+
return $renderer->render($element);
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Return the Store model for the currently configured store.
|
38 |
+
*
|
39 |
+
* @return Mage_Core_Model_Store|null
|
40 |
+
*/
|
41 |
+
protected function getStore() {
|
42 |
+
if (!$this->hasData('store')) {
|
43 |
+
$store_code = Mage::getSingleton('klevu_search/session')->getConfiguredStoreCode();
|
44 |
+
|
45 |
+
$this->setData('store', Mage::app()->getStore($store_code));
|
46 |
+
}
|
47 |
+
|
48 |
+
return $this->getData('store');
|
49 |
+
}
|
50 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Wizard/Configure/Store.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Block_Adminhtml_Wizard_Configure_Store extends Mage_Adminhtml_Block_Template {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Return the submit URL for the store configuration form.
|
7 |
+
*
|
8 |
+
* @return string
|
9 |
+
*/
|
10 |
+
protected function getFormActionUrl() {
|
11 |
+
return $this->getUrl("adminhtml/klevu_search_wizard/configure_store_post");
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Return the list of stores that can be selected to be configured (i.e. haven't
|
16 |
+
* been configured already), organised by website name and group name.
|
17 |
+
*
|
18 |
+
* @return array
|
19 |
+
*/
|
20 |
+
protected function getStoreSelectData() {
|
21 |
+
$stores = Mage::app()->getStores(false);
|
22 |
+
$config = Mage::helper("klevu_search/config");
|
23 |
+
|
24 |
+
$data = array();
|
25 |
+
|
26 |
+
foreach ($stores as $store) {
|
27 |
+
/** @var Mage_Core_Model_Store $store */
|
28 |
+
if ($config->getJsApiKey($store) && $config->getRestApiKey($store)) {
|
29 |
+
// Skip already configured stores
|
30 |
+
continue;
|
31 |
+
}
|
32 |
+
|
33 |
+
$website = $store->getWebsite()->getName();
|
34 |
+
$group = $store->getGroup()->getName();
|
35 |
+
|
36 |
+
if (!isset($data[$website])) {
|
37 |
+
$data[$website] = array();
|
38 |
+
}
|
39 |
+
if (!isset($data[$website][$group])) {
|
40 |
+
$data[$website][$group] = array();
|
41 |
+
}
|
42 |
+
|
43 |
+
$data[$website][$group][] = $store;
|
44 |
+
}
|
45 |
+
|
46 |
+
return $data;
|
47 |
+
}
|
48 |
+
}
|
app/code/community/Klevu/Search/Block/Adminhtml/Wizard/Configure/User.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Block_Adminhtml_Wizard_Configure_User extends Mage_Adminhtml_Block_Template {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Return the submit URL for the user configuration form.
|
7 |
+
*
|
8 |
+
* @return string
|
9 |
+
*/
|
10 |
+
protected function getFormActionUrl() {
|
11 |
+
return $this->getUrl('adminhtml/klevu_search_wizard/configure_user_post');
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Return the base URL for the store.
|
16 |
+
*
|
17 |
+
* @return string
|
18 |
+
*/
|
19 |
+
protected function getStoreUrl() {
|
20 |
+
return $this->getBaseUrl();
|
21 |
+
}
|
22 |
+
}
|
app/code/community/Klevu/Search/Block/Catalog/Product/Tracking.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Block_Catalog_Product_Tracking extends Mage_Core_Block_Template {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* JSON of required tracking parameter for Klevu Product Click Tracking, based on current product
|
7 |
+
* @return string
|
8 |
+
* @throws Exception
|
9 |
+
*/
|
10 |
+
public function getJsonTrackingData() {
|
11 |
+
// Get the product
|
12 |
+
$product = Mage::registry('current_product');
|
13 |
+
$api_key = Mage::helper('klevu_search/config')->getJsApiKey();
|
14 |
+
|
15 |
+
$product = array(
|
16 |
+
'klevu_apiKey' => $api_key,
|
17 |
+
'klevu_term' => '',
|
18 |
+
'klevu_type' => 'clicked',
|
19 |
+
'klevu_productId' => $product->getId(),
|
20 |
+
'klevu_productName' => $product->getName(),
|
21 |
+
'klevu_productUrl' => $product->getProductUrl()
|
22 |
+
);
|
23 |
+
|
24 |
+
return json_encode($product);
|
25 |
+
}
|
26 |
+
}
|
app/code/community/Klevu/Search/Helper/Api.php
ADDED
@@ -0,0 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Helper_Api extends Mage_Core_Helper_Abstract {
|
4 |
+
|
5 |
+
const ENDPOINT_PROTOCOL = 'https://';
|
6 |
+
const ENDPOINT_DEFAULT_HOSTNAME = 'box.klevu.com';
|
7 |
+
/**
|
8 |
+
* Create a new Klevu user using the API and return the user details.
|
9 |
+
*
|
10 |
+
* @param $email
|
11 |
+
* @param $password
|
12 |
+
* @param $url
|
13 |
+
*
|
14 |
+
* @return array An array containing the following keys:
|
15 |
+
* success: boolean value indicating whether the user was created successfully.
|
16 |
+
* customer_id: the customer ID for the newly created user (on success only).
|
17 |
+
* message: a message to be shown to the user.
|
18 |
+
*/
|
19 |
+
public function createUser($email, $password, $userPlan, $url,$merchantEmail,$contactNo) {
|
20 |
+
$response = Mage::getModel("klevu_search/api_action_adduser")->execute(array(
|
21 |
+
"email" => $email,
|
22 |
+
"password" => $password,
|
23 |
+
"userPlan" => $userPlan,
|
24 |
+
"url" => $url,
|
25 |
+
"merchantEmail" => $merchantEmail,
|
26 |
+
"contactNo" => $contactNo
|
27 |
+
|
28 |
+
));
|
29 |
+
|
30 |
+
if ($response->isSuccessful()) {
|
31 |
+
return array(
|
32 |
+
"success" => true,
|
33 |
+
"customer_id" => $response->getCustomerId(),
|
34 |
+
"message" => $response->getMessage()
|
35 |
+
);
|
36 |
+
} else {
|
37 |
+
return array(
|
38 |
+
"success" => false,
|
39 |
+
"message" => $response->getMessage()
|
40 |
+
);
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Retrieve the details for the given Klevu user from the API.
|
46 |
+
*
|
47 |
+
* @param $email
|
48 |
+
* @param $password
|
49 |
+
*
|
50 |
+
* @return array An array containing the following keys:
|
51 |
+
* success: boolean value indicating whether the operation was successful.
|
52 |
+
* customer_id: (on success only) The customer ID of the requested user.
|
53 |
+
* webstores: (on success only) A list of webstores the given user has configured.
|
54 |
+
* message: (on failure only) Error message to be shown to the user.
|
55 |
+
*/
|
56 |
+
public function getUser($email, $password) {
|
57 |
+
$response = Mage::getModel("klevu_search/api_action_getuserdetail")->execute(array(
|
58 |
+
"email" => $email,
|
59 |
+
"password" => $password
|
60 |
+
));
|
61 |
+
|
62 |
+
if ($response->isSuccessful()) {
|
63 |
+
$webstores = array();
|
64 |
+
|
65 |
+
// Add each webstore as a Varien_Object
|
66 |
+
$webstores_data = $response->getWebstores();
|
67 |
+
if ($webstores_data && isset($webstores_data['webstore'])) {
|
68 |
+
$webstores_data = $webstores_data['webstore'];
|
69 |
+
|
70 |
+
if (isset($webstores_data['storeName'])) {
|
71 |
+
// Got a single webstore
|
72 |
+
$webstores_data = array($webstores_data);
|
73 |
+
}
|
74 |
+
|
75 |
+
$i = 0;
|
76 |
+
foreach ($webstores_data as $webstore_data) {
|
77 |
+
$webstore = array(
|
78 |
+
'id' => $i++
|
79 |
+
);
|
80 |
+
foreach($webstore_data as $key => $value) {
|
81 |
+
// Convert field names from camelCase to underscore (code taken from Varien_Object)
|
82 |
+
$webstore[strtolower(preg_replace('/(.)([A-Z])/', "$1_$2", $key))] = $value;
|
83 |
+
}
|
84 |
+
$webstores[] = new Varien_Object($webstore);
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
return array(
|
89 |
+
"success" => true,
|
90 |
+
"customer_id" => $response->getCustomerId(),
|
91 |
+
"webstores" => $webstores
|
92 |
+
);
|
93 |
+
} else {
|
94 |
+
return array(
|
95 |
+
"success" => false,
|
96 |
+
"message" => $response->getMessage()
|
97 |
+
);
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Create a Klevu Webstore using the API for the given Magento store.
|
103 |
+
*
|
104 |
+
* @param $customer_id
|
105 |
+
* @param Mage_Core_Model_Store $store
|
106 |
+
* @param bool $test_mode
|
107 |
+
*
|
108 |
+
* @return array An array with the following keys:
|
109 |
+
* success: boolean value indicating whether the operation was successful.
|
110 |
+
* webstore: (success only) Varien_Object containing Webstore information.
|
111 |
+
* message: message to be displayed to the user.
|
112 |
+
*/
|
113 |
+
public function createWebstore($customer_id, Mage_Core_Model_Store $store, $test_mode = false) {
|
114 |
+
$name = sprintf("%s - %s - %s",
|
115 |
+
$store->getWebsite()->getName(),
|
116 |
+
$store->getName(),
|
117 |
+
$store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)
|
118 |
+
);
|
119 |
+
$language = Mage::helper("klevu_search")->getStoreLanguage($store);
|
120 |
+
$timezone = $store->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE);
|
121 |
+
$country = $store->getConfig(Mage_Core_Helper_Data::XML_PATH_DEFAULT_COUNTRY);
|
122 |
+
$locale = $store->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_LOCALE);
|
123 |
+
|
124 |
+
$version = $this->getVersion();
|
125 |
+
|
126 |
+
// Convert $test_mode to string
|
127 |
+
$test_mode = ($test_mode) ? "true" : "false";
|
128 |
+
|
129 |
+
$response = Mage::getModel("klevu_search/api_action_addwebstore")->execute(array(
|
130 |
+
"customerId" => $customer_id,
|
131 |
+
"storeName" => $name,
|
132 |
+
"language" => $language,
|
133 |
+
"timezone" => $timezone,
|
134 |
+
"version" => $version,
|
135 |
+
"country" => $country,
|
136 |
+
"locale" => $locale,
|
137 |
+
"testMode" => $test_mode,
|
138 |
+
));
|
139 |
+
|
140 |
+
if ($response->isSuccessful()) {
|
141 |
+
$webstore = new Varien_Object(array(
|
142 |
+
"store_name" => $name,
|
143 |
+
"js_api_key" => $response->getJsApiKey(),
|
144 |
+
"rest_api_key" => $response->getRestApiKey(),
|
145 |
+
"test_account_enabled" => $test_mode,
|
146 |
+
"hosted_on" => $response->getHostedOn(),
|
147 |
+
"cloud_search_url" => $response->getCloudSearchUrl(),
|
148 |
+
"analytics_url" => $response->getAnalyticsUrl(),
|
149 |
+
"js_url" => $response->getJsUrl(),
|
150 |
+
"rest_hostname" => $response->getRestUrl(),
|
151 |
+
));
|
152 |
+
|
153 |
+
return array(
|
154 |
+
"success" => true,
|
155 |
+
"webstore" => $webstore,
|
156 |
+
"message" => $response->getMessage()
|
157 |
+
);
|
158 |
+
} else {
|
159 |
+
return array(
|
160 |
+
"success" => false,
|
161 |
+
"message" => $response->getMessage()
|
162 |
+
);
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
public function getTimezoneOptions() {
|
167 |
+
$response = Mage::getModel('klevu_search/api_action_gettimezone')->execute();
|
168 |
+
|
169 |
+
if ($response->isSuccessful()) {
|
170 |
+
$options = array();
|
171 |
+
|
172 |
+
$data = $response->getTimezone();
|
173 |
+
|
174 |
+
if (!is_array($data)) {
|
175 |
+
$data = array($data);
|
176 |
+
}
|
177 |
+
|
178 |
+
foreach ($data as $timezone) {
|
179 |
+
$options[] = array(
|
180 |
+
"label" => $this->__($timezone),
|
181 |
+
"value" => $this->escapeHtml($timezone)
|
182 |
+
);
|
183 |
+
}
|
184 |
+
|
185 |
+
return $options;
|
186 |
+
} else {
|
187 |
+
return $response->getMessage();
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Build the API Endpoint URL, based on system configuration API Hostname, and endpoint provided.
|
193 |
+
* @param string $endpoint
|
194 |
+
* @param null|Mage_Core_Model_Store $store
|
195 |
+
* @param null|string $hostname
|
196 |
+
* @return string
|
197 |
+
*/
|
198 |
+
public function buildEndpoint($endpoint, $store = null, $hostname = null) {
|
199 |
+
|
200 |
+
return static::ENDPOINT_PROTOCOL . (($hostname) ? $hostname : Mage::helper('klevu_search/config')->getHostname($store)) . $endpoint;
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Get the module version number from the module config.
|
205 |
+
* @return string
|
206 |
+
*/
|
207 |
+
public function getVersion() {
|
208 |
+
return Mage::getConfig()->getModuleConfig('Klevu_Search')->version;
|
209 |
+
}
|
210 |
+
}
|
app/code/community/Klevu/Search/Helper/Compat.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Helper_Compat extends Mage_Core_Helper_Abstract {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Return a Select statement for retrieving URL rewrites for the given list of products.
|
7 |
+
*
|
8 |
+
* Uses the Product URL Rewrite Helper if available, falling back to building the query manually.
|
9 |
+
*
|
10 |
+
* @param array $product_ids
|
11 |
+
* @param $category_id
|
12 |
+
* @param $store_id
|
13 |
+
*
|
14 |
+
* @return Varien_Db_Select
|
15 |
+
*/
|
16 |
+
public function getProductUrlRewriteSelect(array $product_ids, $category_id, $store_id) {
|
17 |
+
if (version_compare(Mage::getVersion(), '1.8.0', '>=')) {
|
18 |
+
$factory_model_class = Mage::app()->getConfig()->getModelClassName("catalog/factory");
|
19 |
+
if (class_exists($factory_model_class)) {
|
20 |
+
return Mage::getModel("catalog/factory")->getProductUrlRewriteHelper()
|
21 |
+
->getTableSelect($product_ids, $category_id, $store_id);
|
22 |
+
}
|
23 |
+
}
|
24 |
+
|
25 |
+
$resource = Mage::getModel("core/resource");
|
26 |
+
|
27 |
+
return $resource->getConnection("core_write")->select()
|
28 |
+
->from($resource->getTableName("core/url_rewrite"), array("product_id", "request_path"))
|
29 |
+
->where("store_id = ?", (int) $store_id)
|
30 |
+
->where("is_system = ?", 1)
|
31 |
+
->where("category_id = ? OR category_id IS NULL", (int) $category_id)
|
32 |
+
->where("product_id IN (?)", $product_ids)
|
33 |
+
->order("category_id " . Varien_Data_Collection::SORT_ORDER_DESC);
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Return the current date in internal format.
|
38 |
+
*
|
39 |
+
* @param bool $withoutTime day only flag
|
40 |
+
*
|
41 |
+
* @return string
|
42 |
+
*/
|
43 |
+
public function now($withoutTime = false) {
|
44 |
+
if (method_exists("Varien_Date", "now")) {
|
45 |
+
return Varien_Date::now($withoutTime);
|
46 |
+
} else {
|
47 |
+
$format = ($withoutTime) ? "Y-m-d" : "Y-m-d H:i:s";
|
48 |
+
return date($format);
|
49 |
+
}
|
50 |
+
}
|
51 |
+
}
|
app/code/community/Klevu/Search/Helper/Config.php
ADDED
@@ -0,0 +1,642 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Helper_Config extends Mage_Core_Helper_Abstract {
|
4 |
+
|
5 |
+
const XML_PATH_EXTENSION_ENABLED = "klevu_search/general/enabled";
|
6 |
+
const XML_PATH_TEST_MODE = "klevu_search/general/test_mode";
|
7 |
+
const XML_PATH_TAX_ENABLED = "klevu_search/tax_setting/enabled";
|
8 |
+
const XML_PATH_LANDING_ENABLED = "klevu_search/searchlanding/landenabled";
|
9 |
+
const XML_PATH_JS_API_KEY = "klevu_search/general/js_api_key";
|
10 |
+
const XML_PATH_REST_API_KEY = "klevu_search/general/rest_api_key";
|
11 |
+
const XML_PATH_TEST_JS_API_KEY = "klevu_search/general/test_js_api_key";
|
12 |
+
const XML_PATH_TEST_REST_API_KEY = "klevu_search/general/test_rest_api_key";
|
13 |
+
const XML_PATH_PRODUCT_SYNC_ENABLED = "klevu_search/product_sync/enabled";
|
14 |
+
const XML_PATH_PRODUCT_SYNC_FREQUENCY = "klevu_search/product_sync/frequency";
|
15 |
+
const XML_PATH_PRODUCT_SYNC_LAST_RUN = "klevu_search/product_sync/last_run";
|
16 |
+
const XML_PATH_ATTRIBUTES_ADDITIONAL = "klevu_search/attributes/additional";
|
17 |
+
const XML_PATH_ATTRIBUTES_AUTOMATIC = "klevu_search/attributes/automatic";
|
18 |
+
const XML_PATH_ATTRIBUTES_OTHER = "klevu_search/attributes/other";
|
19 |
+
const XML_PATH_ATTRIBUTES_BOOSTING = "klevu_search/attributes/boosting";
|
20 |
+
const XML_PATH_ORDER_SYNC_ENABLED = "klevu_search/order_sync/enabled";
|
21 |
+
const XML_PATH_ORDER_SYNC_FREQUENCY = "klevu_search/order_sync/frequency";
|
22 |
+
const XML_PATH_ORDER_SYNC_LAST_RUN = "klevu_search/order_sync/last_run";
|
23 |
+
const XML_PATH_FORCE_LOG = "klevu_search/developer/force_log";
|
24 |
+
const XML_PATH_LOG_LEVEL = "klevu_search/developer/log_level";
|
25 |
+
const XML_PATH_STORE_ID = "stores/%s/system/store/id";
|
26 |
+
const XML_PATH_HOSTNAME = "klevu_search/general/hostname";
|
27 |
+
const XML_PATH_RESTHOSTNAME = "klevu_search/general/rest_hostname";
|
28 |
+
const XML_PATH_TEST_HOSTNAME = "klevu_search/general/test_hostname";
|
29 |
+
const XML_PATH_CLOUD_SEARCH_URL = "klevu_search/general/cloud_search_url";
|
30 |
+
const XML_PATH_TEST_CLOUD_SEARCH_URL = "klevu_search/general/test_cloud_search_url";
|
31 |
+
const XML_PATH_ANALYTICS_URL = "klevu_search/general/analytics_url";
|
32 |
+
const XML_PATH_TEST_ANALYTICS_URL = "klevu_search/general/test_analytics_url";
|
33 |
+
const XML_PATH_JS_URL = "klevu_search/general/js_url";
|
34 |
+
const XML_PATH_TEST_JS_URL = "klevu_search/general/test_js_url";
|
35 |
+
|
36 |
+
const DATETIME_FORMAT = "Y-m-d H:i:s T";
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Set the Enable on Frontend flag in System Configuration for the given store.
|
40 |
+
*
|
41 |
+
* @param $flag
|
42 |
+
* @param Mage_Core_Model_Store|int|null $store Store to set the flag for. Defaults to current store.
|
43 |
+
*
|
44 |
+
* @return $this
|
45 |
+
*/
|
46 |
+
public function setExtensionEnabledFlag($flag, $store = null) {
|
47 |
+
$flag = ($flag) ? 1 : 0;
|
48 |
+
$this->setStoreConfig(static::XML_PATH_EXTENSION_ENABLED, $flag, $store);
|
49 |
+
return $this;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Check if the Klevu_Search extension is enabled in the system configuration for the current store.
|
54 |
+
*
|
55 |
+
* @param $store_id
|
56 |
+
*
|
57 |
+
* @return bool
|
58 |
+
*/
|
59 |
+
public function isExtensionEnabled($store_id = null) {
|
60 |
+
return Mage::getStoreConfigFlag(static::XML_PATH_EXTENSION_ENABLED, $store_id);
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Check if the Tax is enabled in the system configuration for the current store.
|
65 |
+
*
|
66 |
+
* @param $store_id
|
67 |
+
*
|
68 |
+
* @return bool
|
69 |
+
*/
|
70 |
+
public function isTaxEnabled($store_id = null) {
|
71 |
+
return Mage::getStoreConfigFlag(static::XML_PATH_TAX_ENABLED, $store_id);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Check if the Landing is enabled in the system configuration for the current store.
|
76 |
+
*
|
77 |
+
* @param $store_id
|
78 |
+
*
|
79 |
+
* @return bool
|
80 |
+
*/
|
81 |
+
public function isLandingEnabled($store = null) {
|
82 |
+
return intval(Mage::getStoreConfig(static::XML_PATH_LANDING_ENABLED, $store));
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Set the Test Mode flag in System Configuration for the given store.
|
87 |
+
*
|
88 |
+
* @param $flag
|
89 |
+
* @param null $store Store to use. If not specified, uses the current store.
|
90 |
+
*
|
91 |
+
* @return $this
|
92 |
+
*/
|
93 |
+
public function setTestModeEnabledFlag($flag, $store = null) {
|
94 |
+
$flag = ($flag) ? 1 : 0;
|
95 |
+
$this->setStoreConfig(static::XML_PATH_TEST_MODE, $flag, $store);
|
96 |
+
return $this;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Return the configuration flag for enabling test mode.
|
101 |
+
*
|
102 |
+
* @param Mage_Core_Model_Store|int $store
|
103 |
+
*
|
104 |
+
* @return bool
|
105 |
+
*/
|
106 |
+
public function getTestModeEnabledFlag($store = null) {
|
107 |
+
return Mage::getStoreConfigFlag(static::XML_PATH_TEST_MODE, $store);
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Set the Tax mode in System Configuration for the given store.
|
112 |
+
*
|
113 |
+
* @param $flag
|
114 |
+
* @param null $store Store to use. If not specified, uses the current store.
|
115 |
+
*
|
116 |
+
* @return $this
|
117 |
+
*/
|
118 |
+
public function setTaxEnabledFlag($flag, $store = null) {
|
119 |
+
|
120 |
+
$flag = ($flag) ? 1 : 0;
|
121 |
+
$this->setStoreConfig(static::XML_PATH_TAX_ENABLED, $flag, $store);
|
122 |
+
return $this;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Check if Test Mode is enabled for the given store.
|
127 |
+
*
|
128 |
+
* @param Mage_Core_Model_Store|int $store
|
129 |
+
*
|
130 |
+
* @return bool
|
131 |
+
*/
|
132 |
+
public function isTestModeEnabled($store = null) {
|
133 |
+
return $this->getTestModeEnabledFlag($store);
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Set the JS API key in System Configuration for the given store.
|
138 |
+
*
|
139 |
+
* @param string $key
|
140 |
+
* @param Mage_Core_Model_Store|int $store Store to use. If not specified, will use the current store.
|
141 |
+
* @param bool $test_mode Set the key to be used in Test Mode.
|
142 |
+
*
|
143 |
+
* @return $this
|
144 |
+
*/
|
145 |
+
public function setJsApiKey($key, $store = null, $test_mode = false) {
|
146 |
+
$path = ($test_mode) ? static::XML_PATH_TEST_JS_API_KEY : static::XML_PATH_JS_API_KEY;
|
147 |
+
$this->setStoreConfig($path, $key, $store);
|
148 |
+
return $this;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Return the JS API key configured for the specified store.
|
153 |
+
*
|
154 |
+
* @param Mage_Core_Model_Store|int $store
|
155 |
+
*
|
156 |
+
* @return string
|
157 |
+
*/
|
158 |
+
public function getJsApiKey($store = null) {
|
159 |
+
if ($this->isTestModeEnabled($store)) {
|
160 |
+
return Mage::getStoreConfig(static::XML_PATH_TEST_JS_API_KEY, $store);
|
161 |
+
} else {
|
162 |
+
return Mage::getStoreConfig(static::XML_PATH_JS_API_KEY, $store);
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Set the REST API key in System Configuration for the given store.
|
168 |
+
*
|
169 |
+
* @param string $key
|
170 |
+
* @param Mage_Core_Model_Store|int $store Store to use. If not specified, will use the current store.
|
171 |
+
* @param bool $test_mode Set the key to be used in Test Mode.
|
172 |
+
*
|
173 |
+
* @return $this
|
174 |
+
*/
|
175 |
+
public function setRestApiKey($key, $store = null, $test_mode = false) {
|
176 |
+
$path = ($test_mode) ? static::XML_PATH_TEST_REST_API_KEY : static::XML_PATH_REST_API_KEY;
|
177 |
+
$this->setStoreConfig($path, $key, $store);
|
178 |
+
return $this;
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Return the REST API key configured for the specified store.
|
183 |
+
*
|
184 |
+
* @param Mage_Core_Model_Store|int $store
|
185 |
+
*
|
186 |
+
* @return mixed
|
187 |
+
*/
|
188 |
+
public function getRestApiKey($store = null) {
|
189 |
+
if ($this->isTestModeEnabled($store)) {
|
190 |
+
return Mage::getStoreConfig(static::XML_PATH_TEST_REST_API_KEY, $store);
|
191 |
+
} else {
|
192 |
+
return Mage::getStoreConfig(static::XML_PATH_REST_API_KEY, $store);
|
193 |
+
}
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Set the API Hostname value in System Configuration for a given store
|
198 |
+
* @param $hostname
|
199 |
+
* @param null $store
|
200 |
+
* @param bool $test_mode
|
201 |
+
* @return $this
|
202 |
+
*/
|
203 |
+
public function setHostname($hostname, $store = null, $test_mode = false) {
|
204 |
+
$path = ($test_mode) ? static::XML_PATH_TEST_HOSTNAME : static::XML_PATH_HOSTNAME;
|
205 |
+
$this->setStoreConfig($path, $hostname, $store);
|
206 |
+
return $this;
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Return the API Hostname configured, used for API requests, for a specified store
|
211 |
+
* @param Mage_Core_Model_Store|int|null $store
|
212 |
+
* @return string
|
213 |
+
*/
|
214 |
+
public function getHostname($store = null) {
|
215 |
+
// Store was provided, check for test mode before getting the configured hostname
|
216 |
+
if($this->isTestModeEnabled($store)) {
|
217 |
+
$hostname = Mage::getStoreConfig(static::XML_PATH_TEST_HOSTNAME, $store);
|
218 |
+
} else {
|
219 |
+
$hostname = Mage::getStoreConfig(static::XML_PATH_HOSTNAME, $store);
|
220 |
+
}
|
221 |
+
|
222 |
+
return ($hostname) ? $hostname : Klevu_Search_Helper_Api::ENDPOINT_DEFAULT_HOSTNAME;
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Return the API Rest Hostname configured, used for API requests, for a specified store
|
227 |
+
* @param Mage_Core_Model_Store|int|null $store
|
228 |
+
* @return string
|
229 |
+
*/
|
230 |
+
public function getRestHostname($store = null) {
|
231 |
+
// Store was provided, check for test mode before getting the configured hostname
|
232 |
+
if($this->isTestModeEnabled($store)) {
|
233 |
+
$hostname = Mage::getStoreConfig(static::XML_PATH_RESTHOSTNAME, $store);
|
234 |
+
} else {
|
235 |
+
$hostname = Mage::getStoreConfig(static::XML_PATH_RESTHOSTNAME, $store);
|
236 |
+
}
|
237 |
+
|
238 |
+
return ($hostname) ? $hostname : Klevu_Search_Helper_Api::ENDPOINT_DEFAULT_HOSTNAME;
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Set the Rest Hostname value in System Configuration for a given store
|
243 |
+
* @param $url
|
244 |
+
* @param null $store
|
245 |
+
* @param bool $test_mode
|
246 |
+
* @return $this
|
247 |
+
*/
|
248 |
+
public function setRestHostname($url, $store = null, $test_mode = false) {
|
249 |
+
$path = ($test_mode) ? static::XML_PATH_RESTHOSTNAME : static::XML_PATH_RESTHOSTNAME;
|
250 |
+
$this->setStoreConfig($path, $url, $store);
|
251 |
+
return $this;
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* @param $url
|
256 |
+
* @param null $store
|
257 |
+
* @param bool $test_mode
|
258 |
+
* @return $this
|
259 |
+
*/
|
260 |
+
public function setCloudSearchUrl($url, $store = null, $test_mode = false) {
|
261 |
+
$path = ($test_mode) ? static::XML_PATH_TEST_CLOUD_SEARCH_URL : static::XML_PATH_CLOUD_SEARCH_URL;
|
262 |
+
$this->setStoreConfig($path, $url, $store);
|
263 |
+
return $this;
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* @param null $store
|
268 |
+
* @return string
|
269 |
+
*/
|
270 |
+
public function getCloudSearchUrl($store = null) {
|
271 |
+
if($this->isTestModeEnabled($store)) {
|
272 |
+
$url = Mage::getStoreConfig(static::XML_PATH_TEST_CLOUD_SEARCH_URL, $store);
|
273 |
+
} else {
|
274 |
+
$url = Mage::getStoreConfig(static::XML_PATH_CLOUD_SEARCH_URL, $store);
|
275 |
+
}
|
276 |
+
|
277 |
+
return ($url) ? $url : Klevu_Search_Helper_Api::ENDPOINT_DEFAULT_HOSTNAME;
|
278 |
+
}
|
279 |
+
|
280 |
+
/**
|
281 |
+
* @param $url
|
282 |
+
* @param null $store
|
283 |
+
* @param bool $test_mode
|
284 |
+
* @return $this
|
285 |
+
*/
|
286 |
+
public function setAnalyticsUrl($url, $store = null, $test_mode = false) {
|
287 |
+
$path = ($test_mode) ? static::XML_PATH_TEST_ANALYTICS_URL : static::XML_PATH_ANALYTICS_URL;
|
288 |
+
$this->setStoreConfig($path, $url, $store);
|
289 |
+
return $this;
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* @param null $store
|
294 |
+
* @return string
|
295 |
+
*/
|
296 |
+
public function getAnalyticsUrl($store = null) {
|
297 |
+
if($this->isTestModeEnabled($store)) {
|
298 |
+
$url = Mage::getStoreConfig(static::XML_PATH_TEST_ANALYTICS_URL);
|
299 |
+
} else {
|
300 |
+
$url = Mage::getStoreConfig(static::XML_PATH_ANALYTICS_URL);
|
301 |
+
}
|
302 |
+
|
303 |
+
return ($url) ? $url : Klevu_Search_Helper_Api::ENDPOINT_DEFAULT_HOSTNAME;
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* @param $url
|
308 |
+
* @param null $store
|
309 |
+
* @param bool $test_mode
|
310 |
+
* @return $this
|
311 |
+
*/
|
312 |
+
public function setJsUrl($url, $store = null, $test_mode = false) {
|
313 |
+
$path = ($test_mode) ? static::XML_PATH_TEST_JS_URL : static::XML_PATH_JS_URL;
|
314 |
+
$this->setStoreConfig($path, $url, $store);
|
315 |
+
return $this;
|
316 |
+
}
|
317 |
+
|
318 |
+
/**
|
319 |
+
* @param null $store
|
320 |
+
* @return string
|
321 |
+
*/
|
322 |
+
public function getJsUrl($store = null) {
|
323 |
+
if($this->isTestModeEnabled($store)) {
|
324 |
+
$url = Mage::getStoreConfig(static::XML_PATH_TEST_JS_URL);
|
325 |
+
} else {
|
326 |
+
$url = Mage::getStoreConfig(static::XML_PATH_JS_URL);
|
327 |
+
}
|
328 |
+
|
329 |
+
return ($url) ? $url : Klevu_Search_Helper_Api::ENDPOINT_DEFAULT_HOSTNAME;
|
330 |
+
}
|
331 |
+
|
332 |
+
/**
|
333 |
+
* Check if the Klevu Search extension is configured for the given store.
|
334 |
+
*
|
335 |
+
* @param null $store_id
|
336 |
+
*
|
337 |
+
* @return bool
|
338 |
+
*/
|
339 |
+
public function isExtensionConfigured($store_id = null) {
|
340 |
+
$js_api_key = $this->getJsApiKey($store_id);
|
341 |
+
$rest_api_key = $this->getRestApiKey($store_id);
|
342 |
+
|
343 |
+
return (
|
344 |
+
$this->isExtensionEnabled($store_id)
|
345 |
+
&& !empty($js_api_key)
|
346 |
+
&& !empty($rest_api_key)
|
347 |
+
);
|
348 |
+
}
|
349 |
+
|
350 |
+
/**
|
351 |
+
* Return the system configuration setting for enabling Product Sync for the specified store.
|
352 |
+
* The returned value can have one of three possible meanings: Yes, No and Forced. The
|
353 |
+
* values mapping to these meanings are available as constants on
|
354 |
+
* Klevu_Search_Model_System_Config_Source_Yesnoforced.
|
355 |
+
*
|
356 |
+
* @param $store_id
|
357 |
+
*
|
358 |
+
* @return int
|
359 |
+
*/
|
360 |
+
public function getProductSyncEnabledFlag($store_id = null) {
|
361 |
+
return intval(Mage::getStoreConfig(static::XML_PATH_PRODUCT_SYNC_ENABLED, $store_id));
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Check if Product Sync is enabled for the specified store and domain.
|
366 |
+
*
|
367 |
+
* @param $store_id
|
368 |
+
*
|
369 |
+
* @return bool
|
370 |
+
*/
|
371 |
+
public function isProductSyncEnabled($store_id = null) {
|
372 |
+
$flag = $this->getProductSyncEnabledFlag($store_id);
|
373 |
+
|
374 |
+
// Require "Forced" configuration setting to enable Product Sync on non production environments
|
375 |
+
//if (Mage::helper("klevu_search")->isProductionDomain(Mage::getBaseUrl())) {
|
376 |
+
return in_array($flag, array(
|
377 |
+
Klevu_Search_Model_System_Config_Source_Yesnoforced::YES,
|
378 |
+
//Klevu_Search_Model_System_Config_Source_Yesnoforced::FORCED
|
379 |
+
));
|
380 |
+
//} else {
|
381 |
+
// return $flag === Klevu_Search_Model_System_Config_Source_Yesnoforced::FORCED;
|
382 |
+
//}
|
383 |
+
}
|
384 |
+
|
385 |
+
/**
|
386 |
+
* Return the configured frequency expression for Product Sync.
|
387 |
+
*
|
388 |
+
* @return string
|
389 |
+
*/
|
390 |
+
public function getProductSyncFrequency() {
|
391 |
+
return Mage::getStoreConfig(static::XML_PATH_PRODUCT_SYNC_FREQUENCY);
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* Set the last Product Sync run time in System Configuration for the given store.
|
396 |
+
*
|
397 |
+
* @param DateTime|string $datetime If string is passed, it will be converted to DateTime.
|
398 |
+
* @param Mage_Core_Model_Store|int|null $store
|
399 |
+
*
|
400 |
+
* @return $this
|
401 |
+
*/
|
402 |
+
public function setLastProductSyncRun($datetime = "now", $store = null) {
|
403 |
+
if (!$datetime instanceof DateTime) {
|
404 |
+
$datetime = new DateTime($datetime);
|
405 |
+
}
|
406 |
+
|
407 |
+
$this->setStoreConfig(static::XML_PATH_PRODUCT_SYNC_LAST_RUN, $datetime->format(static::DATETIME_FORMAT), $store);
|
408 |
+
|
409 |
+
return $this;
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* Check if Product Sync has ever run for the given store.
|
414 |
+
*
|
415 |
+
* @param Mage_Core_Model_Store|int|null $store
|
416 |
+
*
|
417 |
+
* @return bool
|
418 |
+
*/
|
419 |
+
public function hasProductSyncRun($store = null) {
|
420 |
+
$config = Mage::getConfig();
|
421 |
+
|
422 |
+
if (!$config->getNode(static::XML_PATH_PRODUCT_SYNC_LAST_RUN, "store", Mage::app()->getStore($store)->getId())) {
|
423 |
+
return false;
|
424 |
+
}
|
425 |
+
|
426 |
+
return true;
|
427 |
+
}
|
428 |
+
|
429 |
+
public function setAdditionalAttributesMap($map, $store = null) {
|
430 |
+
unset($map["__empty"]);
|
431 |
+
$this->setStoreConfig(static::XML_PATH_ATTRIBUTES_ADDITIONAL, serialize($map), $store);
|
432 |
+
return $this;
|
433 |
+
}
|
434 |
+
|
435 |
+
/**
|
436 |
+
* Return the map of additional Klevu attributes to Magento attributes.
|
437 |
+
*
|
438 |
+
* @param int|Mage_Core_Model_Store $store
|
439 |
+
*
|
440 |
+
* @return array
|
441 |
+
*/
|
442 |
+
public function getAdditionalAttributesMap($store = null) {
|
443 |
+
$map = unserialize(Mage::getStoreConfig(static::XML_PATH_ATTRIBUTES_ADDITIONAL, $store));
|
444 |
+
|
445 |
+
return (is_array($map)) ? $map : array();
|
446 |
+
}
|
447 |
+
|
448 |
+
/**
|
449 |
+
* Set the automatically mapped attributes
|
450 |
+
* @param array $map
|
451 |
+
* @param int|Mage_Core_Model_Store $store
|
452 |
+
* @return $this
|
453 |
+
*/
|
454 |
+
public function setAutomaticAttributesMap($map, $store = null) {
|
455 |
+
unset($map["__empty"]);
|
456 |
+
$this->setStoreConfig(static::XML_PATH_ATTRIBUTES_AUTOMATIC, serialize($map), $store);
|
457 |
+
return $this;
|
458 |
+
}
|
459 |
+
|
460 |
+
/**
|
461 |
+
* Returns the automatically mapped attributes
|
462 |
+
* @param int|Mage_Core_Model_Store $store
|
463 |
+
* @return array
|
464 |
+
*/
|
465 |
+
public function getAutomaticAttributesMap($store = null) {
|
466 |
+
$map = unserialize(Mage::getStoreConfig(static::XML_PATH_ATTRIBUTES_AUTOMATIC, $store));
|
467 |
+
|
468 |
+
return (is_array($map)) ? $map : array();
|
469 |
+
}
|
470 |
+
|
471 |
+
/**
|
472 |
+
* Return the System Configuration setting for enabling Order Sync for the given store.
|
473 |
+
* The returned value can have one of three possible meanings: Yes, No and Forced. The
|
474 |
+
* values mapping to these meanings are available as constants on
|
475 |
+
* Klevu_Search_Model_System_Config_Source_Yesnoforced.
|
476 |
+
*
|
477 |
+
* @param Mage_Core_Model_Store|int $store
|
478 |
+
*
|
479 |
+
* @return int
|
480 |
+
*/
|
481 |
+
public function getOrderSyncEnabledFlag($store = null) {
|
482 |
+
return intval(Mage::getStoreConfig(static::XML_PATH_ORDER_SYNC_ENABLED, $store));
|
483 |
+
}
|
484 |
+
|
485 |
+
/**
|
486 |
+
* Check if Order Sync is enabled for the given store on the current domain.
|
487 |
+
*
|
488 |
+
* @param Mage_Core_Model_Store|int $store
|
489 |
+
*
|
490 |
+
* @return bool
|
491 |
+
*/
|
492 |
+
public function isOrderSyncEnabled($store = null) {
|
493 |
+
$flag = $this->getOrderSyncEnabledFlag($store);
|
494 |
+
// Require "Forced" configuration setting to enable Sync on non production environments
|
495 |
+
//if (Mage::helper("klevu_search")->isProductionDomain(Mage::getBaseUrl())) {
|
496 |
+
return in_array($flag, array(
|
497 |
+
Klevu_Search_Model_System_Config_Source_Yesnoforced::YES,
|
498 |
+
));
|
499 |
+
//} else {
|
500 |
+
//return $flag === Klevu_Search_Model_System_Config_Source_Yesnoforced::FORCED;
|
501 |
+
//}
|
502 |
+
}
|
503 |
+
|
504 |
+
/**
|
505 |
+
* Return the configured frequency expression for Order Sync.
|
506 |
+
*
|
507 |
+
* @return string
|
508 |
+
*/
|
509 |
+
public function getOrderSyncFrequency() {
|
510 |
+
return Mage::getStoreConfig(static::XML_PATH_ORDER_SYNC_FREQUENCY);
|
511 |
+
}
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Set the last Order Sync run time in System Configuration.
|
515 |
+
*
|
516 |
+
* @param DateTime|string $datetime If string is passed, it will be converted to DateTime.
|
517 |
+
*
|
518 |
+
* @return $this
|
519 |
+
*/
|
520 |
+
public function setLastOrderSyncRun($datetime = "now") {
|
521 |
+
if (!$datetime instanceof DateTime) {
|
522 |
+
$datetime = new DateTime($datetime);
|
523 |
+
}
|
524 |
+
|
525 |
+
$this->setGlobalConfig(static::XML_PATH_ORDER_SYNC_LAST_RUN, $datetime->format(static::DATETIME_FORMAT));
|
526 |
+
|
527 |
+
return $this;
|
528 |
+
}
|
529 |
+
|
530 |
+
/**
|
531 |
+
* Check if default Magento log settings should be overridden to force logging for this module.
|
532 |
+
*
|
533 |
+
* @return bool
|
534 |
+
*/
|
535 |
+
public function isLoggingForced() {
|
536 |
+
return Mage::getStoreConfigFlag(static::XML_PATH_FORCE_LOG);
|
537 |
+
}
|
538 |
+
|
539 |
+
/**
|
540 |
+
* Return the minimum log level configured. Default to Zend_Log::WARN.
|
541 |
+
*
|
542 |
+
* @return int
|
543 |
+
*/
|
544 |
+
public function getLogLevel() {
|
545 |
+
$log_level = Mage::getStoreConfig(static::XML_PATH_LOG_LEVEL);
|
546 |
+
|
547 |
+
return ($log_level !== null) ? intval($log_level) : Zend_Log::INFO;
|
548 |
+
}
|
549 |
+
|
550 |
+
/**
|
551 |
+
* Return an multi-dimensional array of magento and klevu attributes that are mapped by default.
|
552 |
+
* @return array
|
553 |
+
*/
|
554 |
+
public function getDefaultMappedAttributes() {
|
555 |
+
return array(
|
556 |
+
"magento_attribute" => array(
|
557 |
+
"name",
|
558 |
+
"sku",
|
559 |
+
"image",
|
560 |
+
"description",
|
561 |
+
"short_description",
|
562 |
+
"price",
|
563 |
+
"tax_class_id",
|
564 |
+
"weight"),
|
565 |
+
"klevu_attribute" => array(
|
566 |
+
"name",
|
567 |
+
"sku",
|
568 |
+
"image",
|
569 |
+
"desc",
|
570 |
+
"shortDesc",
|
571 |
+
"salePrice",
|
572 |
+
"salePrice",
|
573 |
+
"weight"
|
574 |
+
)
|
575 |
+
);
|
576 |
+
}
|
577 |
+
|
578 |
+
/**
|
579 |
+
* Returns array of other attributes map from store configuration.
|
580 |
+
*
|
581 |
+
* @param Mage_Core_Model_Store|int|null $store
|
582 |
+
* @return array
|
583 |
+
*/
|
584 |
+
public function getOtherAttributesToIndex($store = null) {
|
585 |
+
if (Mage::getStoreConfig(static::XML_PATH_ATTRIBUTES_OTHER, $store)) {
|
586 |
+
return explode(",", Mage::getStoreConfig(static::XML_PATH_ATTRIBUTES_OTHER, $store));
|
587 |
+
}
|
588 |
+
|
589 |
+
return array();
|
590 |
+
}
|
591 |
+
|
592 |
+
/**
|
593 |
+
* Return the boosting attribute defined in store configuration.
|
594 |
+
*
|
595 |
+
* @param Mage_Core_Model_Store|int|null $store
|
596 |
+
* @return array
|
597 |
+
*/
|
598 |
+
public function getBoostingAttribute($store = null) {
|
599 |
+
return Mage::getStoreConfig(static::XML_PATH_ATTRIBUTES_BOOSTING, $store);
|
600 |
+
}
|
601 |
+
|
602 |
+
/**
|
603 |
+
* Set the global scope System Configuration value for the given key.
|
604 |
+
*
|
605 |
+
* @param string $key
|
606 |
+
* @param string $value
|
607 |
+
*
|
608 |
+
* @return $this
|
609 |
+
*/
|
610 |
+
protected function setGlobalConfig($key, $value) {
|
611 |
+
Mage::getConfig()
|
612 |
+
->saveConfig($key, $value, "default")
|
613 |
+
->reinit();
|
614 |
+
|
615 |
+
return $this;
|
616 |
+
}
|
617 |
+
|
618 |
+
/**
|
619 |
+
* Set the store scope System Configuration value for the given key.
|
620 |
+
*
|
621 |
+
* @param string $key
|
622 |
+
* @param string $value
|
623 |
+
* @param Mage_Core_Model_Store|int|null $store If not given, current store will be used.
|
624 |
+
*
|
625 |
+
* @return $this
|
626 |
+
*/
|
627 |
+
public function setStoreConfig($key, $value, $store = null) {
|
628 |
+
$config = Mage::getConfig();
|
629 |
+
|
630 |
+
$store_code = Mage::app()->getStore($store)->getCode();
|
631 |
+
$scope_id = $config->getNode(sprintf(static::XML_PATH_STORE_ID, $store_code));
|
632 |
+
if ($scope_id !== null) {
|
633 |
+
$scope_id = (int) $scope_id;
|
634 |
+
|
635 |
+
$config->saveConfig($key, $value, "stores", $scope_id);
|
636 |
+
|
637 |
+
$config->reinit();
|
638 |
+
}
|
639 |
+
|
640 |
+
return $this;
|
641 |
+
}
|
642 |
+
}
|
app/code/community/Klevu/Search/Helper/Data.php
ADDED
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Helper_Data extends Mage_Core_Helper_Abstract {
|
4 |
+
|
5 |
+
const LOG_FILE = "Klevu_Search.log";
|
6 |
+
|
7 |
+
const ID_SEPARATOR = "-";
|
8 |
+
|
9 |
+
const SANITISE_STRING = "/:|,|;/";
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Given a locale code, extract the language code from it
|
13 |
+
* e.g. en_GB => en, fr_FR => fr
|
14 |
+
*
|
15 |
+
* @param string $locale
|
16 |
+
*/
|
17 |
+
function getLanguageFromLocale($locale) {
|
18 |
+
if (strlen($locale) == 5 && strpos($locale, "_") == 2) {
|
19 |
+
return substr($locale, 0, 2);
|
20 |
+
}
|
21 |
+
|
22 |
+
return $locale;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Return the language code for the given store.
|
27 |
+
*
|
28 |
+
* @param int|Mage_Core_Model_Store $store
|
29 |
+
*
|
30 |
+
* @return string
|
31 |
+
*/
|
32 |
+
function getStoreLanguage($store = null) {
|
33 |
+
if ($store = Mage::app()->getStore($store)) {
|
34 |
+
return $this->getLanguageFromLocale($store->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_LOCALE));
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Check if the given domain is considered to be a valid domain for a production environment.
|
40 |
+
*
|
41 |
+
* @param $domain
|
42 |
+
*
|
43 |
+
* @return bool
|
44 |
+
*/
|
45 |
+
public function isProductionDomain($domain) {
|
46 |
+
return preg_match("/\b(staging|dev|local)\b/", $domain) == 0;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Generate a Klevu product ID for the given product.
|
51 |
+
*
|
52 |
+
* @param int $product_id Magento ID of the product to generate a Klevu ID for.
|
53 |
+
* @param null|int $parent_id Optional Magento ID of the parent product.
|
54 |
+
*
|
55 |
+
* @return string
|
56 |
+
*/
|
57 |
+
public function getKlevuProductId($product_id, $parent_id = 0) {
|
58 |
+
if ($parent_id != 0) {
|
59 |
+
$parent_id .= static::ID_SEPARATOR;
|
60 |
+
} else {
|
61 |
+
$parent_id = "";
|
62 |
+
}
|
63 |
+
|
64 |
+
return sprintf("%s%s", $parent_id, $product_id);
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Convert a Klevu product ID back into a Magento product ID. Returns an
|
69 |
+
* array with "product_id" element for the product ID and a "parent_id"
|
70 |
+
* element for the parent product ID or 0 if the Klevu product doesn't have
|
71 |
+
* a parent.
|
72 |
+
*
|
73 |
+
* @param $klevu_id
|
74 |
+
*
|
75 |
+
* @return array
|
76 |
+
*/
|
77 |
+
public function getMagentoProductId($klevu_id) {
|
78 |
+
$parts = explode(static::ID_SEPARATOR, $klevu_id, 2);
|
79 |
+
|
80 |
+
if (count($parts) > 1) {
|
81 |
+
return array('product_id' => $parts[1], 'parent_id' => $parts[0]);
|
82 |
+
} else {
|
83 |
+
return array('product_id' => $parts[0], 'parent_id' => "0");
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Format bytes into a human readable representation, e.g.
|
89 |
+
* 6815744 => 6.5M
|
90 |
+
*
|
91 |
+
* @param $bytes
|
92 |
+
* @param int $precision
|
93 |
+
*
|
94 |
+
* @return string
|
95 |
+
*/
|
96 |
+
public function bytesToHumanReadable($bytes, $precision = 2) {
|
97 |
+
$suffixes = array("", "k", "M", "G", "T", "P");
|
98 |
+
$base = log($bytes) / log(1024);
|
99 |
+
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Convert human readable formatting of bytes to bytes, e.g.
|
104 |
+
* 6.5M => 6815744
|
105 |
+
*
|
106 |
+
* @param $string
|
107 |
+
*
|
108 |
+
* @return int
|
109 |
+
*/
|
110 |
+
public function humanReadableToBytes($string) {
|
111 |
+
$suffix = strtolower(substr($string, -1));
|
112 |
+
$result = substr($string, 0, -1);
|
113 |
+
|
114 |
+
switch ($suffix) {
|
115 |
+
case 'g': // G is the max unit as of PHP 5.5.12
|
116 |
+
$result *= 1024;
|
117 |
+
case 'm':
|
118 |
+
$result *= 1024;
|
119 |
+
case 'k':
|
120 |
+
$result *= 1024;
|
121 |
+
break;
|
122 |
+
default:
|
123 |
+
$result = $string;
|
124 |
+
}
|
125 |
+
|
126 |
+
return ceil($result);
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Return the configuration data for a "Sync All Products" button displayed
|
131 |
+
* on the Manage Products page in the backend.
|
132 |
+
*
|
133 |
+
* @return array
|
134 |
+
*/
|
135 |
+
public function getSyncAllButtonData() {
|
136 |
+
return array(
|
137 |
+
'label' => $this->__("Sync All Products to Klevu"),
|
138 |
+
'onclick' => sprintf("setLocation('%s')", Mage::getModel('adminhtml/url')->getUrl("adminhtml/klevu_search/sync_all"))
|
139 |
+
);
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Write a log message to the Klevu_Search log file.
|
144 |
+
*
|
145 |
+
* @param int $level
|
146 |
+
* @param string $message
|
147 |
+
*/
|
148 |
+
public function log($level, $message) {
|
149 |
+
$config = Mage::helper("klevu_search/config");
|
150 |
+
|
151 |
+
if ($level <= $config->getLogLevel()) {
|
152 |
+
Mage::log($message, $level, static::LOG_FILE, $config->isLoggingForced());
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Remove the characters used to organise the other attribute values from the
|
158 |
+
* passed in string.
|
159 |
+
*
|
160 |
+
* @param string $value
|
161 |
+
* @return string
|
162 |
+
*/
|
163 |
+
public function santiseAttributeValue($value) {
|
164 |
+
if (is_array($value)) {
|
165 |
+
$sanitised_array = array();
|
166 |
+
foreach($value as $item) {
|
167 |
+
$sanitised_array[] = preg_replace(self::SANITISE_STRING, " ", $item);
|
168 |
+
}
|
169 |
+
return $sanitised_array;
|
170 |
+
}
|
171 |
+
return preg_replace(self::SANITISE_STRING, " ", $value);
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Return whether or not the current page is CatalogSearch.
|
176 |
+
* @return bool
|
177 |
+
*/
|
178 |
+
public function isCatalogSearch() {
|
179 |
+
return in_array('catalogsearch_result_index', Mage::app()->getLayout()->getUpdate()->getHandles());
|
180 |
+
}
|
181 |
+
/**
|
182 |
+
Generate a Klevu product sku with parent product.
|
183 |
+
*
|
184 |
+
* @param string $product_sku Magento Sku of the product to generate a Klevu sku for.
|
185 |
+
* @param null $parent_sku Optional Magento Parent Sku of the parent product.
|
186 |
+
*
|
187 |
+
* @return string
|
188 |
+
*/
|
189 |
+
public function getKlevuProductSku($product_sku, $parent_sku = "") {
|
190 |
+
if (!empty($parent_sku)) {
|
191 |
+
$parent_sku .= static::ID_SEPARATOR;
|
192 |
+
} else {
|
193 |
+
$parent_sku = "";
|
194 |
+
}
|
195 |
+
return sprintf("%s%s", $parent_sku, $product_sku);
|
196 |
+
}
|
197 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action extends Varien_Object {
|
4 |
+
|
5 |
+
const ENDPOINT = "";
|
6 |
+
const METHOD = "GET";
|
7 |
+
|
8 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request";
|
9 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response";
|
10 |
+
|
11 |
+
/** @var Klevu_Search_Model_Api_Request $request */
|
12 |
+
protected $request;
|
13 |
+
|
14 |
+
/** @var Klevu_Search_Model_Api_Response $response */
|
15 |
+
protected $response;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Set the request model to use for this API action.
|
19 |
+
*
|
20 |
+
* @param Klevu_Search_Model_Api_Request $request_model
|
21 |
+
*
|
22 |
+
* @return $this
|
23 |
+
*/
|
24 |
+
public function setRequest(Klevu_Search_Model_Api_Request $request_model) {
|
25 |
+
$this->request = $request_model;
|
26 |
+
|
27 |
+
return $this;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Return the request model used for this API action.
|
32 |
+
*
|
33 |
+
* @return Klevu_Search_Model_Api_Request
|
34 |
+
*/
|
35 |
+
public function getRequest() {
|
36 |
+
if (!$this->request) {
|
37 |
+
$this->request = Mage::getModel(static::DEFAULT_REQUEST_MODEL);
|
38 |
+
}
|
39 |
+
|
40 |
+
return $this->request;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Set the response model to use for this API action.
|
45 |
+
*
|
46 |
+
* @param Klevu_Search_Model_Api_Response $response_model
|
47 |
+
*
|
48 |
+
* @return $this
|
49 |
+
*/
|
50 |
+
public function setResponse(Klevu_Search_Model_Api_Response $response_model) {
|
51 |
+
$this->response = $response_model;
|
52 |
+
|
53 |
+
return $this;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Return the response model used for this API action.
|
58 |
+
*
|
59 |
+
* @return Klevu_Search_Model_Api_Response
|
60 |
+
*/
|
61 |
+
public function getResponse() {
|
62 |
+
if (!$this->response) {
|
63 |
+
$this->response = Mage::getModel(static::DEFAULT_RESPONSE_MODEL);
|
64 |
+
}
|
65 |
+
|
66 |
+
return $this->response;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Execute the API action with the given parameters.
|
71 |
+
*
|
72 |
+
* @param array $parameters
|
73 |
+
*
|
74 |
+
* @return Klevu_Search_Model_Api_Response
|
75 |
+
*/
|
76 |
+
public function execute($parameters = array()) {
|
77 |
+
$validation_result = $this->validate($parameters);
|
78 |
+
if ($validation_result !== true) {
|
79 |
+
return Mage::getModel('klevu_search/api_response_invalid')->setErrors($validation_result);
|
80 |
+
}
|
81 |
+
|
82 |
+
$request = $this->getRequest();
|
83 |
+
|
84 |
+
$endpoint = Mage::helper('klevu_search/api')->buildEndpoint(static::ENDPOINT, $this->getStore(),Mage::helper('klevu_search/config')->getHostname($this->getStore()));
|
85 |
+
|
86 |
+
$request
|
87 |
+
->setResponseModel($this->getResponse())
|
88 |
+
->setEndpoint($endpoint)
|
89 |
+
->setMethod(static::METHOD)
|
90 |
+
->setData($parameters);
|
91 |
+
|
92 |
+
return $request->send();
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Get the store used for this request
|
97 |
+
* @return Mage_Core_Model_Store
|
98 |
+
*/
|
99 |
+
public function getStore() {
|
100 |
+
if(!$this->hasData('store')) {
|
101 |
+
$this->setData('store', Mage::app()->getStore());
|
102 |
+
}
|
103 |
+
return $this->getData('store');
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Validate the given parameters against the API action specification and
|
108 |
+
* return true if validation passed or an array of validation error messages
|
109 |
+
* otherwise.
|
110 |
+
*
|
111 |
+
* @param $parameters
|
112 |
+
*
|
113 |
+
* @return bool|array
|
114 |
+
*/
|
115 |
+
protected function validate($parameters) {
|
116 |
+
return true;
|
117 |
+
}
|
118 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Addrecords.php
ADDED
@@ -0,0 +1,232 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action_Addrecords extends Klevu_Search_Model_Api_Action {
|
4 |
+
|
5 |
+
const ENDPOINT = "/rest/service/addRecords";
|
6 |
+
const METHOD = "POST";
|
7 |
+
|
8 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request_xml";
|
9 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response_message";
|
10 |
+
|
11 |
+
// mandatory_field_name => allowed_empty
|
12 |
+
protected $mandatory_fields = array(
|
13 |
+
"id" => false,
|
14 |
+
"name" => false,
|
15 |
+
"url" => false,
|
16 |
+
"salePrice" => false,
|
17 |
+
"currency" => false,
|
18 |
+
"category" => true,
|
19 |
+
"listCategory" => true
|
20 |
+
);
|
21 |
+
|
22 |
+
public function execute($parameters = array()) {
|
23 |
+
$response = $this->getResponse();
|
24 |
+
|
25 |
+
$validation_result = $this->validate($parameters);
|
26 |
+
if ($validation_result !== true) {
|
27 |
+
return Mage::getModel('klevu_search/api_response_invalid')->setErrors($validation_result);
|
28 |
+
}
|
29 |
+
|
30 |
+
$skipped_records = $this->validateRecords($parameters);
|
31 |
+
if (count($parameters['records']) > 0) {
|
32 |
+
if ($skipped_records != null) {
|
33 |
+
// Validation has removed some of the records due to errors, but the rest
|
34 |
+
// can still be submitted, so just log and proceed
|
35 |
+
$response->setData("skipped_records", $skipped_records);
|
36 |
+
}
|
37 |
+
} else {
|
38 |
+
return Mage::getModel('klevu_search/api_response_invalid')->setErrors(array(
|
39 |
+
"all_records_invalid" => implode(", ", $skipped_records["messages"])
|
40 |
+
));
|
41 |
+
}
|
42 |
+
|
43 |
+
$this->prepareParameters($parameters);
|
44 |
+
$endpoint = Mage::helper('klevu_search/api')->buildEndpoint(static::ENDPOINT, $this->getStore(),Mage::helper('klevu_search/config')->getRestHostname($this->getStore()));
|
45 |
+
|
46 |
+
$request = $this->getRequest();
|
47 |
+
$request
|
48 |
+
->setResponseModel($response)
|
49 |
+
->setEndpoint($endpoint)
|
50 |
+
->setMethod(static::METHOD)
|
51 |
+
->setData($parameters);
|
52 |
+
|
53 |
+
return $request->send();
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Get the store used for this request.
|
58 |
+
* @return Mage_Core_Model_Store
|
59 |
+
*/
|
60 |
+
public function getStore() {
|
61 |
+
if (!$this->hasData('store')) {
|
62 |
+
$this->setData('store', Mage::app()->getStore());
|
63 |
+
}
|
64 |
+
|
65 |
+
return $this->getData('store');
|
66 |
+
}
|
67 |
+
|
68 |
+
protected function validate($parameters) {
|
69 |
+
$errors = array();
|
70 |
+
|
71 |
+
if (!isset($parameters['sessionId']) || empty($parameters['sessionId'])) {
|
72 |
+
$errors['sessionId'] = "Missing session ID";
|
73 |
+
}
|
74 |
+
|
75 |
+
if (!isset($parameters['records']) || !is_array($parameters['records']) || count($parameters['records']) == 0) {
|
76 |
+
$errors['records'] = "No records";
|
77 |
+
}
|
78 |
+
|
79 |
+
if (count($errors) == 0) {
|
80 |
+
return true;
|
81 |
+
}
|
82 |
+
|
83 |
+
return $errors;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Validate the records parameter and remove records that are invalid. Modifies
|
88 |
+
* the $parameters argument in place. Return the list of skipped records and
|
89 |
+
* their error messages.
|
90 |
+
*
|
91 |
+
* @param $parameters
|
92 |
+
*
|
93 |
+
* @return array
|
94 |
+
*/
|
95 |
+
protected function validateRecords(&$parameters) {
|
96 |
+
if (isset($parameters['records']) && is_array($parameters['records'])) {
|
97 |
+
$skipped_records = array(
|
98 |
+
"index" => array(),
|
99 |
+
"messages" => array()
|
100 |
+
);
|
101 |
+
|
102 |
+
foreach ($parameters['records'] as $i => $record) {
|
103 |
+
$missing_fields = array();
|
104 |
+
$empty_fields = array();
|
105 |
+
|
106 |
+
foreach ($this->mandatory_fields as $mandatory_field => $allowed_empty) {
|
107 |
+
if (!array_key_exists($mandatory_field, $record)) {
|
108 |
+
$missing_fields[] = $mandatory_field;
|
109 |
+
} else {
|
110 |
+
if (!$allowed_empty && !is_numeric($record[$mandatory_field]) && empty($record[$mandatory_field])) {
|
111 |
+
$empty_fields[] = $mandatory_field;
|
112 |
+
}
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
$id = (isset($record['id']) && !empty($record['id'])) ? sprintf(" (id: %d)", $record['id']) : "";
|
117 |
+
|
118 |
+
if (count($missing_fields) > 0 || count($empty_fields) > 0) {
|
119 |
+
unset($parameters["records"][$i]);
|
120 |
+
$skipped_records["index"][] = $i;
|
121 |
+
if (count($missing_fields) > 0) {
|
122 |
+
$skipped_records["messages"][] = sprintf("Record %d%s is missing mandatory fields: %s", $i, $id, implode(", ", $missing_fields));
|
123 |
+
}
|
124 |
+
if (count($empty_fields) > 0) {
|
125 |
+
$skipped_records["messages"][] = sprintf("Record %d%s has empty mandatory fields: %s", $i, $id, implode(", ", $empty_fields));
|
126 |
+
}
|
127 |
+
}
|
128 |
+
}
|
129 |
+
|
130 |
+
return $skipped_records;
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Convert the given parameters to a format expected by the XML request model.
|
136 |
+
*
|
137 |
+
* @param $parameters
|
138 |
+
*/
|
139 |
+
protected function prepareParameters(&$parameters) {
|
140 |
+
foreach ($parameters['records'] as &$record) {
|
141 |
+
if (isset($record['listCategory']) && is_array($record['listCategory'])) {
|
142 |
+
$record['listCategory'] = implode(";", $record['listCategory']);
|
143 |
+
}
|
144 |
+
|
145 |
+
if (isset($record['other']) && is_array($record['other'])) {
|
146 |
+
$this->prepareOtherParameters($record);
|
147 |
+
}
|
148 |
+
|
149 |
+
if (isset($record['otherAttributeToIndex']) && is_array($record['otherAttributeToIndex'])) {
|
150 |
+
$this->prepareOtherAttributeToIndexParameters($record);
|
151 |
+
}
|
152 |
+
|
153 |
+
$pairs = array();
|
154 |
+
|
155 |
+
|
156 |
+
foreach ($record as $key => $value) {
|
157 |
+
$pairs[] = array(
|
158 |
+
'pair' => array(
|
159 |
+
'key' => $key,
|
160 |
+
'value' => $value
|
161 |
+
)
|
162 |
+
);
|
163 |
+
}
|
164 |
+
|
165 |
+
$record = array(
|
166 |
+
'record' => array(
|
167 |
+
'pairs' => $pairs
|
168 |
+
)
|
169 |
+
);
|
170 |
+
}
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Flattens other parameters array to a string formatted: key:value[,value]
|
175 |
+
* @param string
|
176 |
+
*/
|
177 |
+
protected function prepareOtherParameters(&$record) {
|
178 |
+
foreach ($record['other'] as $key => &$value) {
|
179 |
+
$key = $this->sanitiseOtherAttribute($key);
|
180 |
+
if(is_array($value)){
|
181 |
+
$label = $this->sanitiseOtherAttribute($value['label']);
|
182 |
+
$value = $this->sanitiseOtherAttribute($value['values']);
|
183 |
+
}else {
|
184 |
+
$label = $this->sanitiseOtherAttribute($key);
|
185 |
+
$value = $this->sanitiseOtherAttribute($value);
|
186 |
+
}
|
187 |
+
|
188 |
+
if (is_array($value)) {
|
189 |
+
$value = implode(",", $value);
|
190 |
+
}
|
191 |
+
|
192 |
+
$value = sprintf("%s:%s:%s", $key, $label, $value);
|
193 |
+
}
|
194 |
+
$record['other'] = implode(";", $record['other']);
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Flattens otherAttributeToIndex parameters array to a string formatted: key:value[,value]
|
199 |
+
* @param string
|
200 |
+
*/
|
201 |
+
protected function prepareOtherAttributeToIndexParameters(&$record) {
|
202 |
+
foreach ($record['otherAttributeToIndex'] as $key => &$value) {
|
203 |
+
$key = $this->sanitiseOtherAttribute($key);
|
204 |
+
if(is_array($value)){
|
205 |
+
$label = $this->sanitiseOtherAttribute($value['label']);
|
206 |
+
$value = $this->sanitiseOtherAttribute($value['values']);
|
207 |
+
}else {
|
208 |
+
$label = $this->sanitiseOtherAttribute($key);
|
209 |
+
$value = $this->sanitiseOtherAttribute($value);
|
210 |
+
}
|
211 |
+
|
212 |
+
if (is_array($value)) {
|
213 |
+
$value = implode(",", $value);
|
214 |
+
}
|
215 |
+
|
216 |
+
$value = sprintf("%s:%s:%s", $key, $label, $value);
|
217 |
+
}
|
218 |
+
$record['otherAttributeToIndex'] = implode(";", $record['otherAttributeToIndex']);
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Remove the characters used to organise the other attribute values from the
|
223 |
+
* passed in string.
|
224 |
+
*
|
225 |
+
* @param $value
|
226 |
+
*
|
227 |
+
* @return string
|
228 |
+
*/
|
229 |
+
protected function sanitiseOtherAttribute($value) {
|
230 |
+
return Mage::helper('klevu_search')->santiseAttributeValue($value);
|
231 |
+
}
|
232 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Adduser.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action_Adduser extends Klevu_Search_Model_Api_Action {
|
4 |
+
|
5 |
+
const ENDPOINT = "/n-search/addUser";
|
6 |
+
const METHOD = "POST";
|
7 |
+
|
8 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request_post";
|
9 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response_data";
|
10 |
+
|
11 |
+
protected function validate($parameters) {
|
12 |
+
$errors = array();
|
13 |
+
|
14 |
+
if (!isset($parameters['email']) || empty($parameters['email'])) {
|
15 |
+
$errors['email'] = "Missing email";
|
16 |
+
}
|
17 |
+
|
18 |
+
if (!isset($parameters['password']) || empty($parameters['password'])) {
|
19 |
+
$errors['password'] = "Missing password";
|
20 |
+
}
|
21 |
+
|
22 |
+
if (!isset($parameters['url']) || empty($parameters['password'])) {
|
23 |
+
$errors['url'] = "Missing url";
|
24 |
+
}
|
25 |
+
|
26 |
+
if (count($errors) == 0) {
|
27 |
+
return true;
|
28 |
+
}
|
29 |
+
|
30 |
+
return $errors;
|
31 |
+
}
|
32 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Addwebstore.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action_Addwebstore extends Klevu_Search_Model_Api_Action {
|
4 |
+
|
5 |
+
const ENDPOINT = "/n-search/addWebstore";
|
6 |
+
const METHOD = "POST";
|
7 |
+
|
8 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request_post";
|
9 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response_data";
|
10 |
+
|
11 |
+
protected function validate($parameters) {
|
12 |
+
$errors = array();
|
13 |
+
|
14 |
+
if (!isset($parameters['customerId']) || empty($parameters['customerId'])) {
|
15 |
+
$errors['customerId'] = "Missing customer id.";
|
16 |
+
}
|
17 |
+
|
18 |
+
if (!isset($parameters['testMode']) || empty($parameters['testMode'])) {
|
19 |
+
$errors['testMode'] = "Missing test mode.";
|
20 |
+
} else {
|
21 |
+
if (!in_array($parameters['testMode'], array("true", "false"))) {
|
22 |
+
$errors['testMode'] = "Test mode must contain the text true or false.";
|
23 |
+
}
|
24 |
+
}
|
25 |
+
|
26 |
+
if (!isset($parameters['storeName']) || empty($parameters['storeName'])) {
|
27 |
+
$errors['storeName'] = "Missing store name.";
|
28 |
+
}
|
29 |
+
|
30 |
+
if (!isset($parameters['language']) || empty($parameters['language'])) {
|
31 |
+
$errors['language'] = "Missing language.";
|
32 |
+
}
|
33 |
+
|
34 |
+
if (!isset($parameters['timezone']) || empty($parameters['timezone'])) {
|
35 |
+
$errors['timezone'] = "Missing timezone.";
|
36 |
+
}
|
37 |
+
|
38 |
+
if (!isset($parameters['version']) || empty($parameters['version'])) {
|
39 |
+
$errors['version'] = "Missing module version";
|
40 |
+
}
|
41 |
+
|
42 |
+
if (!isset($parameters['country']) || empty($parameters['country'])) {
|
43 |
+
$errors['country'] = "Missing country.";
|
44 |
+
}
|
45 |
+
|
46 |
+
if (!isset($parameters['locale']) || empty($parameters['locale'])) {
|
47 |
+
$errors['locale'] = "Missing locale.";
|
48 |
+
}
|
49 |
+
|
50 |
+
if (count($errors) == 0) {
|
51 |
+
return true;
|
52 |
+
}
|
53 |
+
|
54 |
+
return $errors;
|
55 |
+
}
|
56 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Debuginfo.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Klevu_Search_Model_Api_Action_Debuginfo extends Klevu_Search_Model_Api_Action {
|
3 |
+
|
4 |
+
const ENDPOINT = "/n-search/logReceiver";
|
5 |
+
const METHOD = "POST";
|
6 |
+
|
7 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request_post";
|
8 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response_data";
|
9 |
+
|
10 |
+
public function debugKlevu($parameters)
|
11 |
+
{
|
12 |
+
$endpoint = Mage::helper('klevu_search/api')->buildEndpoint(static::ENDPOINT);
|
13 |
+
$response = $this->getResponse();
|
14 |
+
$request = $this->getRequest();
|
15 |
+
$request
|
16 |
+
->setResponseModel($response)
|
17 |
+
->setEndpoint($endpoint)
|
18 |
+
->setMethod(static::METHOD)
|
19 |
+
->setData($parameters);
|
20 |
+
return $request->send();
|
21 |
+
|
22 |
+
|
23 |
+
}
|
24 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Deleterecords.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action_Deleterecords extends Klevu_Search_Model_Api_Action_Addrecords {
|
4 |
+
|
5 |
+
const ENDPOINT = "/rest/service/deleteRecords";
|
6 |
+
const METHOD = "POST";
|
7 |
+
|
8 |
+
// mandatory_field_name => allowed_empty
|
9 |
+
protected $mandatory_fields = array(
|
10 |
+
"id" => false
|
11 |
+
);
|
12 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Gettimezone.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action_Gettimezone extends Klevu_Search_Model_Api_Action {
|
4 |
+
|
5 |
+
const ENDPOINT = "/analytics/getTimezone";
|
6 |
+
const METHOD = "POST";
|
7 |
+
|
8 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request_post";
|
9 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response_timezone";
|
10 |
+
|
11 |
+
protected function validate($parameters) {
|
12 |
+
return true;
|
13 |
+
}
|
14 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Getuserdetail.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action_Getuserdetail extends Klevu_Search_Model_Api_Action {
|
4 |
+
|
5 |
+
const ENDPOINT = "/n-search/getUserDetail";
|
6 |
+
const METHOD = "POST";
|
7 |
+
|
8 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request_post";
|
9 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response_data";
|
10 |
+
|
11 |
+
protected function validate($parameters) {
|
12 |
+
$errors = array();
|
13 |
+
|
14 |
+
if (!isset($parameters['email']) || empty($parameters['email'])) {
|
15 |
+
$errors['email'] = "Missing email";
|
16 |
+
}
|
17 |
+
|
18 |
+
if (!isset($parameters['password']) || empty($parameters['password'])) {
|
19 |
+
$errors['password'] = "Missing password";
|
20 |
+
}
|
21 |
+
|
22 |
+
if (count($errors) == 0) {
|
23 |
+
return true;
|
24 |
+
}
|
25 |
+
|
26 |
+
return $errors;
|
27 |
+
}
|
28 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Idsearch.php
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action_Idsearch extends Klevu_Search_Model_Api_Action {
|
4 |
+
const ENDPOINT = "/cloud-search/n-search/idsearch";
|
5 |
+
const METHOD = "GET";
|
6 |
+
|
7 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request_post";
|
8 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response_search";
|
9 |
+
|
10 |
+
protected function validate($parameters) {
|
11 |
+
$errors = array();
|
12 |
+
|
13 |
+
if (!isset($parameters['ticket']) || empty($parameters['ticket'])) {
|
14 |
+
$errors['ticket'] = "Missing ticket (Search API Key)";
|
15 |
+
}
|
16 |
+
|
17 |
+
if (!isset($parameters['noOfResults']) || empty($parameters['noOfResults'])) {
|
18 |
+
$errors['noOfResults'] = "Missing number of results to return";
|
19 |
+
}
|
20 |
+
|
21 |
+
if(!isset($parameters['term']) || empty($parameters['term'])) {
|
22 |
+
$errors['term'] = "Missing search term";
|
23 |
+
}
|
24 |
+
|
25 |
+
if(!isset($parameters['paginationStartsFrom'])) {
|
26 |
+
$errors['paginationStartsFrom'] = "Missing pagination start from value ";
|
27 |
+
} else if (intval($parameters['paginationStartsFrom']) < 0) {
|
28 |
+
$errors['paginationStartsFrom'] = "Pagination needs to start from 0 or higher";
|
29 |
+
}
|
30 |
+
|
31 |
+
if(!isset($parameters['klevuSort']) || empty($parameters['klevuSort'])) {
|
32 |
+
$errors['klevuSort'] = "Missing Klevu Sort order";
|
33 |
+
}
|
34 |
+
|
35 |
+
if(!isset($parameters['enableFilters']) || empty($parameters['enableFilters'])) {
|
36 |
+
$errors['enableFilters'] = "Missing Enable Filters parameter";
|
37 |
+
}
|
38 |
+
|
39 |
+
if (count($errors) == 0) {
|
40 |
+
return true;
|
41 |
+
}
|
42 |
+
return $errors;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Execute the API action with the given parameters.
|
47 |
+
*
|
48 |
+
* @param array $parameters
|
49 |
+
*
|
50 |
+
* @return Klevu_Search_Model_Api_Response
|
51 |
+
*/
|
52 |
+
public function execute($parameters = array()) {
|
53 |
+
$validation_result = $this->validate($parameters);
|
54 |
+
if ($validation_result !== true) {
|
55 |
+
return Mage::getModel('klevu_search/api_response_invalid')->setErrors($validation_result);
|
56 |
+
}
|
57 |
+
|
58 |
+
$request = $this->getRequest();
|
59 |
+
|
60 |
+
$endpoint = Mage::helper('klevu_search/api')->buildEndpoint(static::ENDPOINT, $this->getStore(), Mage::helper('klevu_search/config')->getCloudSearchUrl($this->getStore()));
|
61 |
+
|
62 |
+
$request
|
63 |
+
->setResponseModel($this->getResponse())
|
64 |
+
->setEndpoint($endpoint)
|
65 |
+
->setMethod(static::METHOD)
|
66 |
+
->setData($parameters);
|
67 |
+
|
68 |
+
return $request->send();
|
69 |
+
}
|
70 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Producttracking.php
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action_Producttracking extends Klevu_Search_Model_Api_Action {
|
4 |
+
|
5 |
+
const ENDPOINT = "/analytics/productTracking";
|
6 |
+
const METHOD = "POST";
|
7 |
+
|
8 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request_post";
|
9 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response_data";
|
10 |
+
|
11 |
+
protected function validate($parameters) {
|
12 |
+
$errors = array();
|
13 |
+
|
14 |
+
if (!isset($parameters["klevu_apiKey"]) || empty($parameters["klevu_apiKey"])) {
|
15 |
+
$errors["klevu_apiKey"] = "Missing JS API key.";
|
16 |
+
}
|
17 |
+
|
18 |
+
if (!isset($parameters["klevu_type"]) || empty($parameters["klevu_type"])) {
|
19 |
+
$errors["klevu_type"] = "Missing type.";
|
20 |
+
}
|
21 |
+
|
22 |
+
if (!isset($parameters["klevu_productId"]) || empty($parameters["klevu_productId"])) {
|
23 |
+
$errors["klevu_productId"] = "Missing product ID.";
|
24 |
+
}
|
25 |
+
|
26 |
+
if (!isset($parameters["klevu_unit"]) || empty($parameters["klevu_unit"])) {
|
27 |
+
$errors["klevu_unit"] = "Missing unit.";
|
28 |
+
}
|
29 |
+
|
30 |
+
if (!isset($parameters["klevu_salePrice"]) || empty($parameters["klevu_salePrice"])) {
|
31 |
+
$errors["klevu_salePrice"] = "Missing sale price.";
|
32 |
+
}
|
33 |
+
|
34 |
+
if (!isset($parameters["klevu_currency"]) || empty($parameters["klevu_currency"])) {
|
35 |
+
$errors["klevu_currency"] = "Missing currency.";
|
36 |
+
}
|
37 |
+
|
38 |
+
|
39 |
+
if (count($errors) == 0) {
|
40 |
+
return true;
|
41 |
+
}
|
42 |
+
return $errors;
|
43 |
+
}
|
44 |
+
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Execute the API action with the given parameters.
|
48 |
+
*
|
49 |
+
* @param array $parameters
|
50 |
+
*
|
51 |
+
* @return Klevu_Search_Model_Api_Response
|
52 |
+
*/
|
53 |
+
public function execute($parameters = array()) {
|
54 |
+
$validation_result = $this->validate($parameters);
|
55 |
+
if ($validation_result !== true) {
|
56 |
+
return Mage::getModel('klevu_search/api_response_invalid')->setErrors($validation_result);
|
57 |
+
}
|
58 |
+
|
59 |
+
$request = $this->getRequest();
|
60 |
+
|
61 |
+
$endpoint = Mage::helper('klevu_search/api')->buildEndpoint(
|
62 |
+
static::ENDPOINT,
|
63 |
+
$this->getStore(),
|
64 |
+
Mage::helper('klevu_search/config')->getAnalyticsUrl()
|
65 |
+
);
|
66 |
+
|
67 |
+
$request
|
68 |
+
->setResponseModel($this->getResponse())
|
69 |
+
->setEndpoint($endpoint)
|
70 |
+
->setMethod(static::METHOD)
|
71 |
+
->setData($parameters);
|
72 |
+
|
73 |
+
return $request->send();
|
74 |
+
}
|
75 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Removetestmode.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Klevu_Search_Model_Api_Action_Removetestmode extends Klevu_Search_Model_Api_Action {
|
3 |
+
|
4 |
+
const ENDPOINT = "/n-search/changeWebstoreMode";
|
5 |
+
const METHOD = "POST";
|
6 |
+
|
7 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request_post";
|
8 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response_data";
|
9 |
+
|
10 |
+
public function removeTestMode($parameters)
|
11 |
+
{
|
12 |
+
$endpoint = Mage::helper('klevu_search/api')->buildEndpoint(static::ENDPOINT);
|
13 |
+
$response = $this->getResponse();
|
14 |
+
$request = $this->getRequest();
|
15 |
+
$request
|
16 |
+
->setResponseModel($response)
|
17 |
+
->setEndpoint($endpoint)
|
18 |
+
->setMethod(static::METHOD)
|
19 |
+
->setData($parameters);
|
20 |
+
return $request->send();
|
21 |
+
|
22 |
+
|
23 |
+
}
|
24 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Startsession.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action_Startsession extends Klevu_Search_Model_Api_Action {
|
4 |
+
|
5 |
+
const ENDPOINT = "/rest/service/startSession";
|
6 |
+
const METHOD = "POST";
|
7 |
+
|
8 |
+
const DEFAULT_REQUEST_MODEL = "klevu_search/api_request_xml";
|
9 |
+
const DEFAULT_RESPONSE_MODEL = "klevu_search/api_response_message";
|
10 |
+
|
11 |
+
public function execute($parameters = array()) {
|
12 |
+
$validation_result = $this->validate($parameters);
|
13 |
+
if ($validation_result !== true) {
|
14 |
+
return Mage::getModel('klevu_search/api_response_invalid')->setErrors($validation_result);
|
15 |
+
}
|
16 |
+
|
17 |
+
$request = $this->getRequest();
|
18 |
+
$endpoint = Mage::helper('klevu_search/api')->buildEndpoint(static::ENDPOINT,$parameters['store'],Mage::helper('klevu_search/config')->getRestHostname($parameters['store']));
|
19 |
+
|
20 |
+
$request
|
21 |
+
->setResponseModel($this->getResponse())
|
22 |
+
->setEndpoint($endpoint)
|
23 |
+
->setMethod(static::METHOD)
|
24 |
+
->setHeader("Authorization", $parameters['api_key']);
|
25 |
+
|
26 |
+
return $request->send();
|
27 |
+
}
|
28 |
+
|
29 |
+
protected function validate($parameters) {
|
30 |
+
if (!isset($parameters['api_key']) || empty($parameters['api_key'])) {
|
31 |
+
return array("Missing API key.");
|
32 |
+
} else {
|
33 |
+
return true;
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Action/Updaterecords.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Action_Updaterecords extends Klevu_Search_Model_Api_Action_Addrecords {
|
4 |
+
|
5 |
+
const ENDPOINT = "/rest/service/updateRecords";
|
6 |
+
const METHOD = "POST";
|
7 |
+
|
8 |
+
// mandatory_field_name => allowed_empty
|
9 |
+
protected $mandatory_fields = array(
|
10 |
+
"id" => false
|
11 |
+
);
|
12 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Request.php
ADDED
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Request extends Varien_Object {
|
4 |
+
|
5 |
+
protected $endpoint;
|
6 |
+
|
7 |
+
protected $method;
|
8 |
+
|
9 |
+
protected $headers;
|
10 |
+
|
11 |
+
protected $response_model;
|
12 |
+
|
13 |
+
public function _construct() {
|
14 |
+
parent::_construct();
|
15 |
+
|
16 |
+
$this->method = Zend_Http_Client::GET;
|
17 |
+
$this->headers = array();
|
18 |
+
$this->response_model = Mage::getModel('klevu_search/api_response');
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Set the target endpoint URL for this API request.
|
23 |
+
*
|
24 |
+
* @param $url
|
25 |
+
*
|
26 |
+
* @return $this
|
27 |
+
*/
|
28 |
+
public function setEndpoint($url) {
|
29 |
+
$this->endpoint = $url;
|
30 |
+
|
31 |
+
return $this;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Return the target endpoint for this API request.
|
36 |
+
*
|
37 |
+
* @return string
|
38 |
+
*/
|
39 |
+
public function getEndpoint() {
|
40 |
+
return $this->endpoint;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Set the HTTP method to use for this API request.
|
45 |
+
*
|
46 |
+
* @param $method
|
47 |
+
*
|
48 |
+
* @return $this
|
49 |
+
*/
|
50 |
+
public function setMethod($method) {
|
51 |
+
$this->method = $method;
|
52 |
+
|
53 |
+
return $this;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Get the HTTP method configured for this API request.
|
58 |
+
*
|
59 |
+
* @return mixed
|
60 |
+
*/
|
61 |
+
public function getMethod() {
|
62 |
+
return $this->method;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Set a HTTP header for this API request.
|
67 |
+
*
|
68 |
+
* @param $name
|
69 |
+
* @param $value
|
70 |
+
*
|
71 |
+
* @return $this
|
72 |
+
*/
|
73 |
+
public function setHeader($name, $value) {
|
74 |
+
$this->headers[$name] = $value;
|
75 |
+
|
76 |
+
return $this;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Get the array of HTTP headers configured for this API request.
|
81 |
+
*
|
82 |
+
* @return array
|
83 |
+
*/
|
84 |
+
public function getHeaders() {
|
85 |
+
return $this->headers;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Set the response model to use for this API request.
|
90 |
+
*
|
91 |
+
* @param Klevu_Search_Model_Api_Response $response_model
|
92 |
+
*
|
93 |
+
* @return $this
|
94 |
+
*/
|
95 |
+
public function setResponseModel(Klevu_Search_Model_Api_Response $response_model) {
|
96 |
+
$this->response_model = $response_model;
|
97 |
+
|
98 |
+
return $this;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Return the response model used for this API request.
|
103 |
+
*
|
104 |
+
* @return Klevu_Search_Model_Api_Response
|
105 |
+
*/
|
106 |
+
public function getResponseModel() {
|
107 |
+
return $this->response_model;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Perform the API request and return the received response.
|
112 |
+
*
|
113 |
+
* @return Klevu_Search_Model_Api_Response
|
114 |
+
*/
|
115 |
+
public function send() {
|
116 |
+
if (!$this->getEndpoint()) {
|
117 |
+
// Can't make a request without a URL
|
118 |
+
Mage::throwException("Unable to send a Klevu Search API request: No URL specified.");
|
119 |
+
}
|
120 |
+
|
121 |
+
$raw_request = $this->build();
|
122 |
+
Mage::helper('klevu_search')->log(Zend_Log::DEBUG, sprintf("API request:\n%s", $this->__toString()));
|
123 |
+
|
124 |
+
try {
|
125 |
+
$raw_response = $raw_request->request();
|
126 |
+
} catch (Zend_Http_Client_Exception $e) {
|
127 |
+
// Return an empty response
|
128 |
+
Mage::helper('klevu_search')->log(Zend_Log::ERR, sprintf("HTTP error: %s", $e->getMessage()));
|
129 |
+
return Mage::getModel('klevu_search/api_response_empty');
|
130 |
+
}
|
131 |
+
|
132 |
+
Mage::helper('klevu_search')->log(Zend_Log::DEBUG, sprintf(
|
133 |
+
"API response:\n%s\n%s",
|
134 |
+
$raw_response->getHeadersAsString(true, "\n"),
|
135 |
+
$raw_response->getBody()
|
136 |
+
));
|
137 |
+
|
138 |
+
$response = $this->getResponseModel();
|
139 |
+
$response->setRawResponse($raw_response);
|
140 |
+
|
141 |
+
return $response;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Return the string representation of the API request.
|
146 |
+
*
|
147 |
+
* @return string
|
148 |
+
*/
|
149 |
+
public function __toString() {
|
150 |
+
$headers = $this->getHeaders();
|
151 |
+
if (count($headers) > 0) {
|
152 |
+
array_walk($headers, function (&$value, $key) {
|
153 |
+
$value = ($value !== null && $value !== false) ? sprintf("%s: %s", $key, $value) : null;
|
154 |
+
});
|
155 |
+
}
|
156 |
+
return sprintf("%s %s\n%s\n",
|
157 |
+
$this->getMethod(),
|
158 |
+
$this->getEndpoint(),
|
159 |
+
implode("\n", array_filter($headers))
|
160 |
+
);
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Build the HTTP request to be sent.
|
165 |
+
*
|
166 |
+
* @return Zend_Http_Client
|
167 |
+
*/
|
168 |
+
protected function build() {
|
169 |
+
$client = new Zend_Http_Client();
|
170 |
+
|
171 |
+
$client
|
172 |
+
->setUri($this->getEndpoint())
|
173 |
+
->setMethod($this->getMethod())
|
174 |
+
->setHeaders($this->getHeaders());
|
175 |
+
|
176 |
+
return $client;
|
177 |
+
}
|
178 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Request/Get.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Request_Get extends Klevu_Search_Model_Api_Request {
|
4 |
+
|
5 |
+
public function __toString() {
|
6 |
+
$string = parent::__toString();
|
7 |
+
|
8 |
+
$parameters = $this->getData();
|
9 |
+
if (count($parameters) > 0) {
|
10 |
+
array_walk($parameters, function(&$value, $key) {
|
11 |
+
$value = sprintf("%s: %s", $key, $value);
|
12 |
+
});
|
13 |
+
}
|
14 |
+
|
15 |
+
return sprintf("%s\nGET parameters:\n%s\n", $string, implode("\n", $parameters));
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Add GET parameters to the request, force GET method.
|
20 |
+
*
|
21 |
+
* @return Zend_Http_Client
|
22 |
+
*/
|
23 |
+
protected function build() {
|
24 |
+
$client = parent::build();
|
25 |
+
|
26 |
+
$client
|
27 |
+
->setMethod("GET")
|
28 |
+
->setParameterGet($this->getData());
|
29 |
+
|
30 |
+
return $client;
|
31 |
+
}
|
32 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Request/Post.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Request_Post extends Klevu_Search_Model_Api_Request {
|
4 |
+
|
5 |
+
public function __toString() {
|
6 |
+
$string = parent::__toString();
|
7 |
+
|
8 |
+
$parameters = $this->getData();
|
9 |
+
if (count($parameters) > 0) {
|
10 |
+
array_walk($parameters, function(&$value, $key) {
|
11 |
+
$value = sprintf("%s: %s", $key, $value);
|
12 |
+
});
|
13 |
+
}
|
14 |
+
|
15 |
+
return sprintf("%s\nPOST parameters:\n%s\n", $string, implode("\n", $parameters));
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Add POST parameters to the request, force POST method.
|
20 |
+
*
|
21 |
+
* @return Zend_Http_Client
|
22 |
+
*/
|
23 |
+
protected function build() {
|
24 |
+
$client = parent::build();
|
25 |
+
|
26 |
+
$client
|
27 |
+
->setMethod(Zend_Http_Client::POST)
|
28 |
+
->setParameterPost($this->getData());
|
29 |
+
|
30 |
+
return $client;
|
31 |
+
}
|
32 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Request/Xml.php
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Request_Xml extends Klevu_Search_Model_Api_Request {
|
4 |
+
|
5 |
+
public function __toString() {
|
6 |
+
$string = parent::__toString();
|
7 |
+
|
8 |
+
return sprintf("%s\n%s\n", $string, $this->getDataAsXml());
|
9 |
+
}
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Convert the request data into an XML string.
|
13 |
+
*
|
14 |
+
* @return string
|
15 |
+
*/
|
16 |
+
public function getDataAsXml() {
|
17 |
+
$xml = new SimpleXMLElement("<request/>");
|
18 |
+
$this->_convertArrayToXml($this->getData(), $xml);
|
19 |
+
return $xml->asXML();
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Add data to the request as XML content and set the Content-Type to application/xml.
|
24 |
+
*
|
25 |
+
* @return Zend_Http_Client
|
26 |
+
*/
|
27 |
+
protected function build() {
|
28 |
+
$client = parent::build();
|
29 |
+
|
30 |
+
$client
|
31 |
+
->setHeaders("Content-Type", "application/xml")
|
32 |
+
->setRawData($this->getDataAsXml());
|
33 |
+
|
34 |
+
return $client;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Convert the given array of data into a SimpleXMLElement. Uses array keys as XML element
|
39 |
+
* names and values as element values, except for numeric keys where the element name gets
|
40 |
+
* set to "item{numeric_key}" unless the value is an array in which case it gets added to
|
41 |
+
* the parent XML element directly. Recursively descends into array values to convert them
|
42 |
+
* into XML. For example:
|
43 |
+
*
|
44 |
+
* array(
|
45 |
+
* "sessionId" => "Klevu-ses-132123123123_123",
|
46 |
+
* "records" => array(
|
47 |
+
* 0 => array(
|
48 |
+
* "record" => array(
|
49 |
+
* "pairs" => array(
|
50 |
+
* 0 => array(
|
51 |
+
* "pair" => array(
|
52 |
+
* "key" => "id",
|
53 |
+
* "value" => "1"
|
54 |
+
* )
|
55 |
+
* ),
|
56 |
+
* 1 => array(
|
57 |
+
* "pair" => array(
|
58 |
+
* "key" => "name",
|
59 |
+
* "value" => "Test product"
|
60 |
+
* )
|
61 |
+
* )
|
62 |
+
* )
|
63 |
+
* )
|
64 |
+
* ),
|
65 |
+
* 1 => array(
|
66 |
+
* "record" => array(
|
67 |
+
* "pairs" => array(
|
68 |
+
* 0 => array(
|
69 |
+
* "pair" => array(
|
70 |
+
* "key" => "id",
|
71 |
+
* "value" => "1"
|
72 |
+
* )
|
73 |
+
* )
|
74 |
+
* )
|
75 |
+
* )
|
76 |
+
* )
|
77 |
+
* )
|
78 |
+
* );
|
79 |
+
*
|
80 |
+
* will get converted to:
|
81 |
+
*
|
82 |
+
* <?xml version="1.0"?>
|
83 |
+
* <request>
|
84 |
+
* <sessionId>Klevu-ses-132123123123_123</sessionId>
|
85 |
+
* <records>
|
86 |
+
* <record>
|
87 |
+
* <pairs>
|
88 |
+
* <pair>
|
89 |
+
* <key>id</key>
|
90 |
+
* <value>1</value>
|
91 |
+
* </pair>
|
92 |
+
* <pair>
|
93 |
+
* <key>name</key>
|
94 |
+
* <value>Test product</value>
|
95 |
+
* </pair>
|
96 |
+
* </pairs>
|
97 |
+
* </record>
|
98 |
+
* <record>
|
99 |
+
* <pairs>
|
100 |
+
* <pair>
|
101 |
+
* <key>id</key>
|
102 |
+
* <value>1</value>
|
103 |
+
* </pair>
|
104 |
+
* </pairs>
|
105 |
+
* </record>
|
106 |
+
* </records>
|
107 |
+
* </request>
|
108 |
+
*
|
109 |
+
* @param array $array The data to convert.
|
110 |
+
* @param SimpleXmlElement $parent XML element used as a parent for the data.
|
111 |
+
*/
|
112 |
+
protected function _convertArrayToXml(array $array, SimpleXmlElement &$parent) {
|
113 |
+
foreach ($array as $key => $value) {
|
114 |
+
if (is_array($value)) {
|
115 |
+
if (is_numeric($key)) {
|
116 |
+
$this->_convertArrayToXml($value, $parent);
|
117 |
+
} else {
|
118 |
+
$child = $parent->addChild($key);
|
119 |
+
$this->_convertArrayToXml($value, $child);
|
120 |
+
}
|
121 |
+
} else {
|
122 |
+
$key = (is_numeric($key)) ? "item" . $key : $key;
|
123 |
+
$parent->addChild($key, htmlspecialchars($value));
|
124 |
+
}
|
125 |
+
}
|
126 |
+
}
|
127 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Response.php
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Klevu_Search_Model_Api_Response
|
5 |
+
*
|
6 |
+
* @method setMessage($message)
|
7 |
+
* @method getMessage()
|
8 |
+
*/
|
9 |
+
class Klevu_Search_Model_Api_Response extends Varien_Object {
|
10 |
+
|
11 |
+
protected $raw_response;
|
12 |
+
|
13 |
+
protected $successful;
|
14 |
+
protected $xml;
|
15 |
+
|
16 |
+
public function _construct() {
|
17 |
+
parent::_construct();
|
18 |
+
|
19 |
+
$this->successful = false;
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Set the raw response object representing this API response.
|
24 |
+
*
|
25 |
+
* @param Zend_Http_Response $response
|
26 |
+
*
|
27 |
+
* @return $this
|
28 |
+
*/
|
29 |
+
public function setRawResponse(Zend_Http_Response $response) {
|
30 |
+
$this->raw_response = $response;
|
31 |
+
|
32 |
+
$this->parseRawResponse($response);
|
33 |
+
|
34 |
+
return $this;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Check if the API response indicates success.
|
39 |
+
*
|
40 |
+
* @return boolean
|
41 |
+
*/
|
42 |
+
public function isSuccessful() {
|
43 |
+
return $this->successful;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Return the response XML content.
|
48 |
+
*
|
49 |
+
* @return SimpleXMLElement
|
50 |
+
*/
|
51 |
+
public function getXml() {
|
52 |
+
return $this->xml;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Extract the API response data from the given HTTP response object.
|
57 |
+
*
|
58 |
+
* @param Zend_Http_Response $response
|
59 |
+
*
|
60 |
+
* @return $this
|
61 |
+
*/
|
62 |
+
protected function parseRawResponse(Zend_Http_Response $response) {
|
63 |
+
if ($response->isSuccessful()) {
|
64 |
+
$content = $response->getBody();
|
65 |
+
|
66 |
+
if (strlen($content) > 0) {
|
67 |
+
try {
|
68 |
+
$xml = simplexml_load_string($response->getBody());
|
69 |
+
} catch (Exception $e) {
|
70 |
+
// Failed to parse XML
|
71 |
+
$this->successful = false;
|
72 |
+
$this->setMessage("Failed to parse a response from Klevu.");
|
73 |
+
Mage::helper('klevu_search')->log(Zend_Log::ERR, sprintf("Failed to parse XML response: %s", $e->getMessage()));
|
74 |
+
return $this;
|
75 |
+
}
|
76 |
+
|
77 |
+
$this->xml = $xml;
|
78 |
+
$this->successful = true;
|
79 |
+
} else {
|
80 |
+
// Response contains no content
|
81 |
+
$this->successful = false;
|
82 |
+
$this->setMessage('Failed to parse a response from Klevu.');
|
83 |
+
Mage::helper('klevu_search')->log(Zend_Log::ERR, "API response content is empty.");
|
84 |
+
}
|
85 |
+
} else {
|
86 |
+
// Unsuccessful HTTP response
|
87 |
+
$this->successful = false;
|
88 |
+
switch ($response->getStatus()) {
|
89 |
+
case 403:
|
90 |
+
$message = "Incorrect API keys.";
|
91 |
+
break;
|
92 |
+
case 500:
|
93 |
+
$message = "API server error.";
|
94 |
+
break;
|
95 |
+
case 503:
|
96 |
+
$message = "API server unavailable.";
|
97 |
+
break;
|
98 |
+
default:
|
99 |
+
$message = "Unexpected error.";
|
100 |
+
}
|
101 |
+
$this->setMessage(sprintf("Failed to connect to Klevu: %s", $message));
|
102 |
+
Mage::helper('klevu_search')->log(Zend_Log::ERR, sprintf("Unsuccessful HTTP response: %s %s", $response->getStatus(), $response->responseCodeAsText($response->getStatus())));
|
103 |
+
}
|
104 |
+
|
105 |
+
return $this;
|
106 |
+
}
|
107 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Response/Data.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Response_Data extends Klevu_Search_Model_Api_Response {
|
4 |
+
|
5 |
+
protected function parseRawResponse(Zend_Http_Response $response) {
|
6 |
+
parent::parseRawResponse($response);
|
7 |
+
|
8 |
+
if ($this->isSuccessful()) {
|
9 |
+
$data = $this->xmlToArray($this->getXml());
|
10 |
+
|
11 |
+
$this->successful = false;
|
12 |
+
if (isset($data['response'])) {
|
13 |
+
if (strtolower($data['response']) == 'success') {
|
14 |
+
$this->successful = true;
|
15 |
+
}
|
16 |
+
unset($data['response']);
|
17 |
+
}
|
18 |
+
|
19 |
+
foreach ($data as $key => $value) {
|
20 |
+
$this->setData($this->_underscore($key), $value);
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
return $this;
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Convert XML to an array.
|
29 |
+
*
|
30 |
+
* @param SimpleXMLElement $xml
|
31 |
+
*
|
32 |
+
* @return array
|
33 |
+
*/
|
34 |
+
protected function xmlToArray(SimpleXMLElement $xml) {
|
35 |
+
return json_decode(json_encode($xml), true);
|
36 |
+
}
|
37 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Response/Empty.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Response_Empty extends Klevu_Search_Model_Api_Response {
|
4 |
+
|
5 |
+
public function _construct() {
|
6 |
+
$this->successful = false;
|
7 |
+
$this->addData(array(
|
8 |
+
'message' => "No HTTP response received. if you are using PHP version 5.4, please make sure to enable the php_openssl.dll module in your php.ini file."
|
9 |
+
));
|
10 |
+
}
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Override the parse response method, this API response is static.
|
14 |
+
*
|
15 |
+
* @param Zend_Http_Response $response
|
16 |
+
*
|
17 |
+
* @return $this
|
18 |
+
*/
|
19 |
+
protected function parseRawResponse(Zend_Http_Response $response) {
|
20 |
+
// Do nothing
|
21 |
+
return $this;
|
22 |
+
}
|
23 |
+
|
24 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Response/Invalid.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Klevu_Search_Model_Api_Response_Invalid
|
5 |
+
*
|
6 |
+
* @method setErrors($errors)
|
7 |
+
*/
|
8 |
+
class Klevu_Search_Model_Api_Response_Invalid extends Klevu_Search_Model_Api_Response {
|
9 |
+
|
10 |
+
public function _construct() {
|
11 |
+
$this->successful = false;
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Return the array of errors.
|
16 |
+
*
|
17 |
+
* @return array
|
18 |
+
*/
|
19 |
+
public function getErrors() {
|
20 |
+
$errors = $this->getData('errors');
|
21 |
+
|
22 |
+
if (!$errors) {
|
23 |
+
$errors = array();
|
24 |
+
}
|
25 |
+
|
26 |
+
if (!is_array($errors)) {
|
27 |
+
$errors = array($errors);
|
28 |
+
}
|
29 |
+
|
30 |
+
return $errors;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Return the response message.
|
35 |
+
*
|
36 |
+
* @return string
|
37 |
+
*/
|
38 |
+
public function getMessage() {
|
39 |
+
$message = "Invalid request";
|
40 |
+
|
41 |
+
$errors = $this->getErrors();
|
42 |
+
if (count($errors) > 0) {
|
43 |
+
$message = sprintf("%s: %s", $message, implode(", ", $errors));
|
44 |
+
}
|
45 |
+
|
46 |
+
return $message;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Override the parse response method, this API response is doesn't use HTTP.
|
51 |
+
*
|
52 |
+
* @param Zend_Http_Response $response
|
53 |
+
*
|
54 |
+
* @return $this
|
55 |
+
*/
|
56 |
+
protected function parseRawResponse(Zend_Http_Response $response) {
|
57 |
+
// Do nothing
|
58 |
+
return $this;
|
59 |
+
}
|
60 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Response/Message.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Response_Message extends Klevu_Search_Model_Api_Response {
|
4 |
+
|
5 |
+
protected function parseRawResponse(Zend_Http_Response $response) {
|
6 |
+
parent::parseRawResponse($response);
|
7 |
+
|
8 |
+
if ($this->isSuccessful()) {
|
9 |
+
$xml = $this->getXml();
|
10 |
+
|
11 |
+
if (isset($xml->status) && strtolower($xml->status) === "success") {
|
12 |
+
$this->successful = true;
|
13 |
+
} else {
|
14 |
+
$this->successful = false;
|
15 |
+
}
|
16 |
+
|
17 |
+
if (isset($xml->msg)) {
|
18 |
+
$this->setMessage((string) $xml->msg);
|
19 |
+
}
|
20 |
+
|
21 |
+
if (isset($xml->sessionId)) {
|
22 |
+
$this->setSessionId((string) $xml->sessionId);
|
23 |
+
}
|
24 |
+
}
|
25 |
+
|
26 |
+
return $this;
|
27 |
+
}
|
28 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Response/Search.php
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Response_Search extends Klevu_Search_Model_Api_Response {
|
4 |
+
|
5 |
+
protected function parseRawResponse(Zend_Http_Response $response) {
|
6 |
+
parent::parseRawResponse($response);
|
7 |
+
|
8 |
+
if ($this->isSuccessful()) {
|
9 |
+
$data = $this->xmlToArray($this->getXml());
|
10 |
+
|
11 |
+
$this->successful = false;
|
12 |
+
if (isset($data['response'])) {
|
13 |
+
if (strtolower($data['response']) == 'success') {
|
14 |
+
$this->successful = true;
|
15 |
+
}
|
16 |
+
unset($data['response']);
|
17 |
+
}
|
18 |
+
|
19 |
+
foreach ($data as $key => $value) {
|
20 |
+
switch($key) {
|
21 |
+
case 'result':
|
22 |
+
$prepared_value = $value;
|
23 |
+
if (isset($value['id'])) {
|
24 |
+
$prepared_value = array($value);
|
25 |
+
}
|
26 |
+
|
27 |
+
break;
|
28 |
+
case 'filters':
|
29 |
+
if (isset($value['filter'])) {
|
30 |
+
$prepared_value = $this->_prepareFilters($value['filter']);
|
31 |
+
} else {
|
32 |
+
$prepared_value ='';
|
33 |
+
}
|
34 |
+
break;
|
35 |
+
default:
|
36 |
+
$prepared_value = $value;
|
37 |
+
break;
|
38 |
+
}
|
39 |
+
|
40 |
+
$this->setData($this->_underscore($key), $prepared_value);
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
return $this;
|
45 |
+
}
|
46 |
+
|
47 |
+
protected function _prepareFilters($filters) {
|
48 |
+
$prepared_filters = array();
|
49 |
+
$i = 0;
|
50 |
+
|
51 |
+
foreach ($filters as $filter) {
|
52 |
+
$prepared_filters[$i] = $filter['@attributes'];
|
53 |
+
$options = isset($filter['option']) ? $filter['option'] : $filter[0];
|
54 |
+
foreach ($options as $option) {
|
55 |
+
$prepared_filters[$i]['options'][] = isset($option['@attributes']) ? $option['@attributes'] : $option;
|
56 |
+
}
|
57 |
+
$i++;
|
58 |
+
}
|
59 |
+
|
60 |
+
return $prepared_filters;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Convert XML to an array.
|
65 |
+
*
|
66 |
+
* @param SimpleXMLElement $xml
|
67 |
+
*
|
68 |
+
* @return array
|
69 |
+
*/
|
70 |
+
protected function xmlToArray(SimpleXMLElement $xml) {
|
71 |
+
return json_decode(json_encode($xml), true);
|
72 |
+
}
|
73 |
+
}
|
app/code/community/Klevu/Search/Model/Api/Response/Timezone.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Api_Response_Timezone extends Klevu_Search_Model_Api_Response_Data {
|
4 |
+
|
5 |
+
protected function parseRawResponse(Zend_Http_Response $response) {
|
6 |
+
parent::parseRawResponse($response);
|
7 |
+
|
8 |
+
// Timezone responses don't have a status parameters, just data
|
9 |
+
// So the presence of the data is the status
|
10 |
+
if ($this->hasData('timezone')) {
|
11 |
+
$this->successful = true;
|
12 |
+
} else {
|
13 |
+
$this->successful = false;
|
14 |
+
}
|
15 |
+
}
|
16 |
+
}
|
app/code/community/Klevu/Search/Model/Catalog/Model/Config.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Klevu_Search_Model_Catalog_Model_Config extends Mage_Catalog_Model_Config
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Retrieve Attributes Used for Sort by as array
|
6 |
+
* key = code, value = name
|
7 |
+
*
|
8 |
+
* @return array
|
9 |
+
*/
|
10 |
+
public function getAttributeUsedForSortByArray()
|
11 |
+
{
|
12 |
+
if (!Mage::helper('klevu_search/config')->isExtensionConfigured() || !Mage::helper('klevu_search')->isCatalogSearch()) {
|
13 |
+
$options = array(
|
14 |
+
'position' => Mage::helper('catalog')->__('Position')
|
15 |
+
);
|
16 |
+
foreach ($this->getAttributesUsedForSortBy() as $attribute) {
|
17 |
+
/* @var $attribute Mage_Eav_Model_Entity_Attribute_Abstract */
|
18 |
+
$options[$attribute->getAttributeCode()] = $attribute->getStoreLabel();
|
19 |
+
}
|
20 |
+
}else {
|
21 |
+
$options = array(
|
22 |
+
'position' => Mage::helper('catalog')->__('Position'),
|
23 |
+
'name' => Mage::helper('catalog')->__('Name'),
|
24 |
+
'price' => Mage::helper('catalog')->__('Price'),
|
25 |
+
);
|
26 |
+
|
27 |
+
}
|
28 |
+
|
29 |
+
return $options;
|
30 |
+
}
|
31 |
+
}
|
app/code/community/Klevu/Search/Model/CatalogSearch/Layer/Filter/Attribute.php
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
class Klevu_Search_Model_CatalogSearch_Layer_Filter_Attribute extends Mage_CatalogSearch_Model_Layer_Filter_Attribute {
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Prepare and fetch an attributes options.
|
8 |
+
*
|
9 |
+
* @return array|null
|
10 |
+
*/
|
11 |
+
protected function _getItemsData()
|
12 |
+
{
|
13 |
+
if (!Mage::helper('klevu_search/config')->isExtensionConfigured() || !Mage::helper('klevu_search')->isCatalogSearch()) {
|
14 |
+
return parent::_getItemsData();
|
15 |
+
}
|
16 |
+
|
17 |
+
$attribute = $this->getAttributeModel();
|
18 |
+
$this->_requestVar = $attribute->getAttributeCode();
|
19 |
+
|
20 |
+
$key = $this->getLayer()->getStateKey().'_'.$this->_requestVar;
|
21 |
+
$data = $this->getLayer()->getAggregator()->getCacheData($key);
|
22 |
+
|
23 |
+
|
24 |
+
if ($data === null) {
|
25 |
+
$klevu_filters = $this->_getKlevuAttributeFilters();
|
26 |
+
if (!isset($klevu_filters[$this->_requestVar])) {
|
27 |
+
return array(); // No results found for filter in Klevu response. Return empty array.
|
28 |
+
}
|
29 |
+
if ($this->getLayer()->getProductCollection()->count() == 0) {
|
30 |
+
return array(); // No visible results found in search
|
31 |
+
}
|
32 |
+
|
33 |
+
$klevu_attribute = $klevu_filters[$this->_requestVar];
|
34 |
+
$options = $attribute->getFrontend()->getSelectOptions();
|
35 |
+
$data = array();
|
36 |
+
foreach ($options as $option) {
|
37 |
+
$klevu_option = $this->_findKlevuOption($option, $klevu_attribute);
|
38 |
+
if (!$klevu_option) {
|
39 |
+
continue; // Skip record since klevu option was not found.
|
40 |
+
}
|
41 |
+
if (is_array($option['value'])) {
|
42 |
+
continue;
|
43 |
+
}
|
44 |
+
if (Mage::helper('core/string')->strlen($option['value'])) {
|
45 |
+
// Check filter type
|
46 |
+
if ($this->_getIsFilterableAttribute($attribute) == self::OPTIONS_ONLY_WITH_RESULTS) {
|
47 |
+
if (!empty($klevu_option['count'])) {
|
48 |
+
$data[] = array(
|
49 |
+
'label' => $option['label'],
|
50 |
+
'value' => $option['value'],
|
51 |
+
'count' => $klevu_option['count'],
|
52 |
+
);
|
53 |
+
}
|
54 |
+
}
|
55 |
+
else {
|
56 |
+
$data[] = array(
|
57 |
+
'label' => $option['label'],
|
58 |
+
'value' => $option['value'],
|
59 |
+
'count' => $klevu_option['count'],
|
60 |
+
);
|
61 |
+
}
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
$tags = array(
|
66 |
+
Mage_Eav_Model_Entity_Attribute::CACHE_TAG.':'.$attribute->getId()
|
67 |
+
);
|
68 |
+
|
69 |
+
$tags = $this->getLayer()->getStateTags($tags);
|
70 |
+
$this->getLayer()->getAggregator()->saveCacheData($data, $key, $tags);
|
71 |
+
}
|
72 |
+
return $data;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Attempt to find the Klevu option from the array of magento options.
|
77 |
+
* Returns false if there were no matches, otherwise returns Klevu option.
|
78 |
+
*
|
79 |
+
* @param $option
|
80 |
+
* @param $klevu_attribute
|
81 |
+
* @return array|bool
|
82 |
+
*/
|
83 |
+
protected function _findKlevuOption($option, $klevu_attribute) {
|
84 |
+
|
85 |
+
foreach ($klevu_attribute['options'] as $klevu_option) {
|
86 |
+
if(strtolower($option['label']) == strtolower($klevu_option['label'])) {
|
87 |
+
return $klevu_option;
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
return false;
|
92 |
+
}
|
93 |
+
/**
|
94 |
+
* Returns array of attribute filters from Klevu [ 'label' => 'T-Shirts', 'count' => 1, 'selected' => false ]
|
95 |
+
* @return array
|
96 |
+
*/
|
97 |
+
protected function _getKlevuAttributeFilters() {
|
98 |
+
/** @var Klevu_Search_Model_CatalogSearch_Resource_Fulltext_Collection $collection */
|
99 |
+
$collection = $this->getLayer()->getProductCollection();
|
100 |
+
return $collection->getKlevuFilters();
|
101 |
+
}
|
102 |
+
|
103 |
+
|
104 |
+
}
|
app/code/community/Klevu/Search/Model/CatalogSearch/Layer/Filter/Category.php
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_CatalogSearch_Layer_Filter_Category extends Mage_Catalog_Model_Layer_Filter_Category {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Get data array for building category filter items
|
7 |
+
*
|
8 |
+
* @return array
|
9 |
+
*/
|
10 |
+
protected function _getItemsData()
|
11 |
+
{
|
12 |
+
if (!Mage::helper('klevu_search/config')->isExtensionConfigured() || !Mage::helper('klevu_search')->isCatalogSearch()) {
|
13 |
+
return parent::_getItemsData();
|
14 |
+
}
|
15 |
+
|
16 |
+
$key = $this->getLayer()->getStateKey().'_SUBCATEGORIES';
|
17 |
+
$data = $this->getLayer()->getAggregator()->getCacheData($key);
|
18 |
+
|
19 |
+
|
20 |
+
if ($data === null) {
|
21 |
+
// Fetch filters from Klevu
|
22 |
+
$filters = $this->_getKlevuCategoryFilters();
|
23 |
+
|
24 |
+
if ($this->getLayer()->getProductCollection()->count() == 0) {
|
25 |
+
return array(); // No visible results found in search
|
26 |
+
}
|
27 |
+
|
28 |
+
// Prepare all the available category names
|
29 |
+
$category_names = array();
|
30 |
+
foreach($filters as $filter) {
|
31 |
+
$category_names[] = $filter['label'];
|
32 |
+
}
|
33 |
+
$category = $this->getCategory();
|
34 |
+
// Get the all categories returned from klevu, and apply the current parent category.
|
35 |
+
$categories = Mage::getModel('catalog/category')->getCollection()
|
36 |
+
->addAttributeToSelect('is_active')
|
37 |
+
->addFieldToFilter('name', array('in' => $category_names));
|
38 |
+
|
39 |
+
$this->getLayer()->getProductCollection()
|
40 |
+
->addCountToCategories($categories);
|
41 |
+
|
42 |
+
$data = array();
|
43 |
+
$k_cat = Mage::app()->getRequest()->getParam('cat');
|
44 |
+
if(!isset($k_cat)) {
|
45 |
+
foreach ($categories as $category) {
|
46 |
+
// Ensure the category exists within the Klevu filters.
|
47 |
+
if (!$klevu_category = $this->_findKlevuCategory($category, $filters)) {
|
48 |
+
continue;
|
49 |
+
}
|
50 |
+
|
51 |
+
if ($category->getIsActive() && $category->getProductCount()) {
|
52 |
+
$data[] = array(
|
53 |
+
'label' => Mage::helper('core')->escapeHtml($category->getName()),
|
54 |
+
'value' => $category->getId(),
|
55 |
+
'count' => $klevu_category['count'],
|
56 |
+
);
|
57 |
+
}
|
58 |
+
}
|
59 |
+
}
|
60 |
+
$tags = $this->getLayer()->getStateTags();
|
61 |
+
$this->getLayer()->getAggregator()->saveCacheData($data, $key, $tags);
|
62 |
+
}
|
63 |
+
|
64 |
+
return $data;
|
65 |
+
}
|
66 |
+
|
67 |
+
protected function _findKlevuCategory($category, $filters) {
|
68 |
+
foreach($filters as $filter) {
|
69 |
+
if(strtolower($filter['label']) == strtolower($category->getName())) {
|
70 |
+
return $filter;
|
71 |
+
}
|
72 |
+
}
|
73 |
+
return false;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* This method in Mage_Catalog_Model_Layer_Filter_Category would ensure when a category filter is remove, the parent
|
78 |
+
* category is applied as a filter. This isn't expected functionality for Klevu, and has been reset to a null value.
|
79 |
+
* @return null
|
80 |
+
*/
|
81 |
+
public function getResetValue() {
|
82 |
+
if (!Mage::helper('klevu_search/config')->isExtensionConfigured() || !Mage::helper('klevu_search')->isCatalogSearch()) {
|
83 |
+
return parent::getResetValue();
|
84 |
+
}
|
85 |
+
|
86 |
+
return null;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Returns array of category filters from Klevu [ 'label' => 'T-Shirts', 'count' => 1, 'selected' => false ]
|
91 |
+
* @return array
|
92 |
+
*/
|
93 |
+
protected function _getKlevuCategoryFilters() {
|
94 |
+
/** @var Klevu_Search_Model_CatalogSearch_Resource_Fulltext_Collection $collection */
|
95 |
+
$collection = $this->getLayer()->getProductCollection();
|
96 |
+
$klevu_filters = $collection->getKlevuFilters();
|
97 |
+
if (!empty($klevu_filters['category'])) {
|
98 |
+
return $klevu_filters['category']['options'];
|
99 |
+
}
|
100 |
+
|
101 |
+
return array();
|
102 |
+
}
|
103 |
+
}
|
app/code/community/Klevu/Search/Model/CatalogSearch/Layer/Filter/Price.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_CatalogSearch_Layer_Filter_Price extends Mage_Catalog_Model_Layer_Filter_Price {
|
4 |
+
|
5 |
+
public function apply(Zend_Controller_Request_Abstract $request, $filterBlock) {
|
6 |
+
if (!Mage::helper('klevu_search/config')->isExtensionConfigured() || !Mage::helper('klevu_search')->isCatalogSearch()) {
|
7 |
+
return parent::apply($request, $filterBlock);
|
8 |
+
}
|
9 |
+
|
10 |
+
// In Magento 1.7 the price filter parameter was changed from the "<index>,<range>"
|
11 |
+
// format to the "<from>-<to>" format. Klevu uses the latter, so in <1.7 we need
|
12 |
+
// to parse the parameter manually
|
13 |
+
if (version_compare(Mage::getVersion(), "1.7", ">=")) {
|
14 |
+
return parent::apply($request, $filterBlock);
|
15 |
+
} else {
|
16 |
+
$filter = $request->getParam($this->getRequestVar());
|
17 |
+
if (!$filter) {
|
18 |
+
return $this;
|
19 |
+
}
|
20 |
+
|
21 |
+
$filter = explode("-", $filter);
|
22 |
+
if (count($filter) != 2) {
|
23 |
+
return $this;
|
24 |
+
}
|
25 |
+
|
26 |
+
list($from, $to) = $filter;
|
27 |
+
|
28 |
+
$this->setInterval(array($from, $to));
|
29 |
+
|
30 |
+
$this->getLayer()->getState()->addFilter(
|
31 |
+
$this->_createItem($this->_renderRangeLabel(empty($from) ? 0 : $from, $to), $filter)
|
32 |
+
);
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Get data for build price filter items
|
38 |
+
*
|
39 |
+
* @return array
|
40 |
+
*/
|
41 |
+
protected function _getItemsData()
|
42 |
+
{
|
43 |
+
if (!Mage::helper('klevu_search/config')->isExtensionConfigured() || !Mage::helper('klevu_search')->isCatalogSearch()) {
|
44 |
+
return parent::_getItemsData();
|
45 |
+
}
|
46 |
+
|
47 |
+
$klevu_price_filters = $this->_getKlevuPriceFilters();
|
48 |
+
$data = array();
|
49 |
+
$k_price = Mage::app()->getRequest()->getParam('price');
|
50 |
+
if(!isset($k_price)) {
|
51 |
+
if (!empty($klevu_price_filters) && $this->getLayer()->getProductCollection()->count() > 0) {
|
52 |
+
foreach ($klevu_price_filters as $filter) {
|
53 |
+
$prices = explode(" - ", $filter['label']);
|
54 |
+
$fromPrice = $prices[0];
|
55 |
+
$toPrice = $prices[1];
|
56 |
+
|
57 |
+
$data[] = array(
|
58 |
+
'label' => $this->_renderRangeLabel($fromPrice, $toPrice),
|
59 |
+
'value' => $fromPrice . '-' . $toPrice,
|
60 |
+
'count' => $filter['count'],
|
61 |
+
);
|
62 |
+
}
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
return $data;
|
67 |
+
}
|
68 |
+
|
69 |
+
protected function _renderRangeLabel($fromPrice, $toPrice) {
|
70 |
+
//if (method_exists(get_parent_class($this), "_renderRangeLabel")) {
|
71 |
+
// return parent::_renderRangeLabel($fromPrice, $toPrice);
|
72 |
+
// } else {
|
73 |
+
$range = $toPrice - $fromPrice;
|
74 |
+
$value = $toPrice / $range;
|
75 |
+
return parent::_renderItemLabel($range, $value);
|
76 |
+
//}
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Returns array of price ranges from Klevu [ 'label' => '10 - 25', 'count' => 1, 'selected' => false ]
|
81 |
+
* @return array
|
82 |
+
*/
|
83 |
+
protected function _getKlevuPriceFilters() {
|
84 |
+
/** @var Klevu_Search_Model_CatalogSearch_Resource_Fulltext_Collection $collection */
|
85 |
+
$collection = $this->getLayer()->getProductCollection();
|
86 |
+
$klevu_filters = $collection->getKlevuFilters();
|
87 |
+
if (!empty($klevu_filters['Price Range'])) {
|
88 |
+
return $klevu_filters['Price Range']['options'];
|
89 |
+
}
|
90 |
+
|
91 |
+
return array();
|
92 |
+
}
|
93 |
+
}
|
app/code/community/Klevu/Search/Model/CatalogSearch/Resource/Fulltext/Collection.php
ADDED
@@ -0,0 +1,463 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_CatalogSearch_Resource_Fulltext_Collection extends Mage_CatalogSearch_Model_Mysql4_Fulltext_Collection {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Klevu Search API Parameters
|
7 |
+
* @var array
|
8 |
+
*/
|
9 |
+
protected $_klevu_parameters;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Klevu Search API Product IDs
|
13 |
+
* @var array
|
14 |
+
*/
|
15 |
+
protected $_klevu_product_ids = array();
|
16 |
+
protected $_klevu_parent_child_ids = array();
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Klevu Search API Response
|
20 |
+
* @var Klevu_Search_Model_Api_Response
|
21 |
+
*/
|
22 |
+
protected $_klevu_response;
|
23 |
+
/**
|
24 |
+
* Search query
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
protected $_query;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Total number of results found
|
31 |
+
* @var int
|
32 |
+
*/
|
33 |
+
protected $_klevu_size;
|
34 |
+
/**
|
35 |
+
* The XML Response from Klevu
|
36 |
+
* @var SimpleXMLElement
|
37 |
+
*/
|
38 |
+
protected $_klevu_response_xml;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Prepare the search query for Klevu Search API Call
|
42 |
+
*
|
43 |
+
* @param string $query
|
44 |
+
* @return $this|Mage_CatalogSearch_Model_Resource_Fulltext_Collection
|
45 |
+
*/
|
46 |
+
public function addSearchFilter($query) {
|
47 |
+
if (!$this->isExtensionConfigured()) {
|
48 |
+
return parent::addSearchFilter($query);
|
49 |
+
}
|
50 |
+
|
51 |
+
$this->_query = $query;
|
52 |
+
return $this;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Stub method to prevent sort order being changed.
|
57 |
+
* @param string $attribute
|
58 |
+
* @param string $dir
|
59 |
+
* @return $this|Mage_CatalogSearch_Model_Resource_Fulltext_Collection
|
60 |
+
*/
|
61 |
+
public function setOrder($attribute, $dir = 'desc')
|
62 |
+
{
|
63 |
+
if (!$this->isExtensionConfigured()) {
|
64 |
+
return parent::setOrder($attribute, $dir);
|
65 |
+
}
|
66 |
+
|
67 |
+
return $this;
|
68 |
+
}
|
69 |
+
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Return the Klevu api search filters
|
73 |
+
* @return array
|
74 |
+
*/
|
75 |
+
public function getSearchFilters() {
|
76 |
+
if (empty($this->_klevu_parameters)) {
|
77 |
+
|
78 |
+
$noOfResults = $this->getPageSize();
|
79 |
+
|
80 |
+
// If getPageSize() returns false, we need to get the page size from the toolbar block.
|
81 |
+
// Rather than re-writing our own version.
|
82 |
+
if(!$noOfResults) {
|
83 |
+
/** @var Mage_Catalog_Block_Product_List $productListBlock */
|
84 |
+
$productListBlock = Mage::getBlockSingleton('catalog/product_list');
|
85 |
+
$toolbarBlock = $productListBlock->getToolbarBlock();
|
86 |
+
$noOfResults = (int) $toolbarBlock->getLimit();
|
87 |
+
}
|
88 |
+
|
89 |
+
$page = Mage::app()->getRequest()->getParam('p');
|
90 |
+
$this->_klevu_parameters = array(
|
91 |
+
'ticket' => Mage::helper('klevu_search/config')->getJsApiKey(),
|
92 |
+
'noOfResults' => $noOfResults,
|
93 |
+
'term' => $this->_query,
|
94 |
+
'paginationStartsFrom' => $this->_getStartFrom($page),
|
95 |
+
'klevuSort' => $this->_getSortOrder(),
|
96 |
+
'enableFilters' => 'true',
|
97 |
+
'filterResults' => $this->_getPreparedFilters(),
|
98 |
+
|
99 |
+
);
|
100 |
+
$this->log(Zend_Log::DEBUG, sprintf("Starting search for term: %s", $this->_getQuery()->getQueryText()));
|
101 |
+
}
|
102 |
+
|
103 |
+
return $this->_klevu_parameters;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Send the API Request and return the API Response.
|
108 |
+
* @return Klevu_Search_Model_Api_Response
|
109 |
+
*/
|
110 |
+
public function getKlevuResponse() {
|
111 |
+
if (!$this->_klevu_response) {
|
112 |
+
$this->_klevu_response = Mage::getModel('klevu_search/api_action_idsearch')->execute($this->getSearchFilters());
|
113 |
+
}
|
114 |
+
return $this->_klevu_response;
|
115 |
+
}
|
116 |
+
|
117 |
+
public function getKlevuFilters() {
|
118 |
+
$attributes = array();
|
119 |
+
$filters = $this->getKlevuResponse()->getData('filters');
|
120 |
+
|
121 |
+
// If there are no filters, return empty array.
|
122 |
+
if (empty($filters)) {
|
123 |
+
return array();
|
124 |
+
}
|
125 |
+
|
126 |
+
foreach($filters as $filter)
|
127 |
+
{
|
128 |
+
$key = (string) $filter['key'];
|
129 |
+
$attributes[$key] = array('label' => (string) $filter['label']);
|
130 |
+
$attributes[$key]['options'] = array();
|
131 |
+
if($filter['options']) {
|
132 |
+
foreach($filter['options'] as $option) {
|
133 |
+
$attributes[$key]['options'][] = array(
|
134 |
+
'label' => trim((string) $option['name']),
|
135 |
+
'count' => trim((string) $option['count']),
|
136 |
+
'selected' => trim((string) $option['selected'])
|
137 |
+
);
|
138 |
+
}
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
return $attributes;
|
143 |
+
}
|
144 |
+
|
145 |
+
protected function _beforeLoad() {
|
146 |
+
if ($this->isExtensionConfigured()) {
|
147 |
+
$this->setVisibility(array(
|
148 |
+
Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE,
|
149 |
+
Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG,
|
150 |
+
Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_SEARCH,
|
151 |
+
Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH));
|
152 |
+
$this->addAttributeToSelect('visibility');
|
153 |
+
}
|
154 |
+
|
155 |
+
return parent::_beforeLoad();
|
156 |
+
}
|
157 |
+
|
158 |
+
protected function _renderFilters()
|
159 |
+
{
|
160 |
+
if (!$this->isExtensionConfigured()) {
|
161 |
+
return parent::_renderFilters();
|
162 |
+
}
|
163 |
+
|
164 |
+
// Do nothing. The results returned by the API are already filtered
|
165 |
+
// and the collection is filtered to only include those results
|
166 |
+
// in _loadEntities()
|
167 |
+
|
168 |
+
return $this;
|
169 |
+
}
|
170 |
+
|
171 |
+
protected function _renderOrders()
|
172 |
+
{
|
173 |
+
if (!$this->isExtensionConfigured()) {
|
174 |
+
return parent::_renderOrders();
|
175 |
+
}
|
176 |
+
|
177 |
+
// Do nothing. The results returned by the API are already in order
|
178 |
+
// which is enforced in _loadEntities()
|
179 |
+
|
180 |
+
return $this;
|
181 |
+
}
|
182 |
+
|
183 |
+
protected function _afterLoad()
|
184 |
+
{
|
185 |
+
parent::_afterLoad();
|
186 |
+
|
187 |
+
if (!$this->isExtensionConfigured()) {
|
188 |
+
return $this;
|
189 |
+
}
|
190 |
+
|
191 |
+
foreach ($this->_klevu_parent_child_ids as $item) {
|
192 |
+
|
193 |
+
|
194 |
+
if ($item['parent_id'] > 0) {
|
195 |
+
/** @var Mage_Catalog_Model_Product $parent */
|
196 |
+
$parent = $this->_items[$item['parent_id']];
|
197 |
+
/** @var Mage_Catalog_Model_Product $child */
|
198 |
+
$child = $this->_items[$item['product_id']];
|
199 |
+
|
200 |
+
// Parent isn't visible. Unset both child and parent products and skip.
|
201 |
+
if (!$parent || !$this->_isProductVisible($parent)) {
|
202 |
+
unset($this->_items[$item['parent_id']], $this->_items[$item['product_id']]);
|
203 |
+
continue;
|
204 |
+
}
|
205 |
+
|
206 |
+
if ($child) {
|
207 |
+
// Set children images on parent product
|
208 |
+
if (($image = $child->getData('image')) != 'no_selection') {
|
209 |
+
$parent->setData('image', $image);
|
210 |
+
}
|
211 |
+
|
212 |
+
if (($small_image = $child->getData('small_image')) != 'no_selection') {
|
213 |
+
$parent->setData('small_image', $small_image);
|
214 |
+
}
|
215 |
+
|
216 |
+
if (($thumbnail = $child->getData('thumbnail')) != 'no_selection') {
|
217 |
+
$parent->setData('thumbnail', $thumbnail);
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
unset($this->_items[$item['product_id']]);
|
222 |
+
}
|
223 |
+
|
224 |
+
// If the child exists, but isn't visible unset the item from our collection.
|
225 |
+
if (isset($this->_items[$item['product_id']]) && !$this->_isProductVisible($this->_items[$item['product_id']])) {
|
226 |
+
unset($this->_items[$item['product_id']]);
|
227 |
+
}
|
228 |
+
}
|
229 |
+
|
230 |
+
return $this;
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* @param Mage_Catalog_Model_Product $product
|
235 |
+
* @return bool
|
236 |
+
*/
|
237 |
+
protected function _isProductVisible($product) {
|
238 |
+
return in_array(
|
239 |
+
$product->getData('visibility'),
|
240 |
+
array(
|
241 |
+
Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_SEARCH,
|
242 |
+
Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH
|
243 |
+
)
|
244 |
+
);
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* This method executes the the Klevu API request if it has not already been called, and takes the result
|
249 |
+
* with the result we get all the item IDs, pass into our helper which returns the child and parent id's.
|
250 |
+
* We then add all these values to our class variable $_klevu_product_ids.
|
251 |
+
*
|
252 |
+
* @return array
|
253 |
+
*/
|
254 |
+
protected function _getProductIds() {
|
255 |
+
if (empty($this->_klevu_product_ids)) {
|
256 |
+
|
257 |
+
// If no results, return an empty array
|
258 |
+
if (!$this->getKlevuResponse()->hasData('result')) {
|
259 |
+
return array();
|
260 |
+
}
|
261 |
+
|
262 |
+
foreach ($this->getKlevuResponse()->getData('result') as $result) {
|
263 |
+
$item_id = Mage::helper('klevu_search')->getMagentoProductId((string) $result['id']);
|
264 |
+
$this->_klevu_parent_child_ids[] = $item_id;
|
265 |
+
if ($item_id['parent_id'] != 0) {
|
266 |
+
$this->_klevu_product_ids[$item_id['parent_id']] = $item_id['parent_id'];
|
267 |
+
}
|
268 |
+
|
269 |
+
$this->_klevu_product_ids[$item_id['product_id']] = $item_id['product_id'];
|
270 |
+
}
|
271 |
+
$this->_klevu_product_ids = array_unique($this->_klevu_product_ids);
|
272 |
+
$this->log(Zend_Log::DEBUG, sprintf("Products count returned: %s", count($this->_klevu_product_ids)));
|
273 |
+
}
|
274 |
+
|
275 |
+
return $this->_klevu_product_ids;
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Return the current sort order, as used by Klevu.
|
280 |
+
*
|
281 |
+
* @return string
|
282 |
+
*/
|
283 |
+
protected function _getSortOrder() {
|
284 |
+
$order = $this->_getToolbar()->getCurrentOrder();
|
285 |
+
$direction = $this->_getToolbar()->getCurrentDirection();
|
286 |
+
|
287 |
+
switch ($order) {
|
288 |
+
case "price":
|
289 |
+
return ($direction == "desc") ? "htl" : "lth";
|
290 |
+
case "name":
|
291 |
+
return ($direction == "desc") ? "namedesc" : "nameasc";
|
292 |
+
default:
|
293 |
+
// Default to sorting by relevance
|
294 |
+
return "rel";
|
295 |
+
}
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Returns where Klevu should start pagination from, e.g. 0, 30 or 60 records (page 1, 2 and 3)
|
300 |
+
*
|
301 |
+
* @param null|int $current_page
|
302 |
+
* @return int
|
303 |
+
*/
|
304 |
+
protected function _getStartFrom($current_page = null) {
|
305 |
+
if ($current_page == 1 || is_null($current_page)) {
|
306 |
+
return 0;
|
307 |
+
}
|
308 |
+
return ($current_page - 1) * ($this->getPageSize());
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Overwriting the getSize method to use Klevu's result of total records.
|
313 |
+
*
|
314 |
+
* @return int
|
315 |
+
*/
|
316 |
+
public function getSize() {
|
317 |
+
if (!$this->isExtensionConfigured()) {
|
318 |
+
return parent::getSize();
|
319 |
+
}
|
320 |
+
|
321 |
+
$response = $this->getKlevuResponse()->getData('meta');
|
322 |
+
return (int) $response['totalResultsFound'];
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Get the current page size. If _pageSize is false, get the limit from the toolbar block.
|
327 |
+
*
|
328 |
+
* @return int|string
|
329 |
+
*/
|
330 |
+
public function getPageSize() {
|
331 |
+
if (!$this->isExtensionConfigured()) {
|
332 |
+
return parent::getPageSize();
|
333 |
+
}
|
334 |
+
|
335 |
+
if(!$this->_pageSize) {
|
336 |
+
return $this->_getToolbar()->getLimit();
|
337 |
+
}
|
338 |
+
return $this->_pageSize;
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Fetch the toolbar block
|
343 |
+
*
|
344 |
+
* @return Mage_Catalog_Block_Product_List_Toolbar
|
345 |
+
*/
|
346 |
+
protected function _getToolbar() {
|
347 |
+
/** @var Mage_Catalog_Block_Product_List $productListBlock */
|
348 |
+
$productListBlock = Mage::getBlockSingleton('catalog/product_list');
|
349 |
+
return $productListBlock->getToolbarBlock();
|
350 |
+
}
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Load entities records into items
|
354 |
+
*
|
355 |
+
* Removed page limiting SQL from this method to prevent issues with paging and Klevu.
|
356 |
+
*
|
357 |
+
* @throws Exception
|
358 |
+
* @return Mage_Eav_Model_Entity_Collection_Abstract
|
359 |
+
*/
|
360 |
+
public function _loadEntities($printQuery = false, $logQuery = false)
|
361 |
+
{
|
362 |
+
if (!$this->isExtensionConfigured()) {
|
363 |
+
return parent::_loadEntities($printQuery, $logQuery);
|
364 |
+
}
|
365 |
+
|
366 |
+
// API results are already filtered, so include only the products
|
367 |
+
// returned by the API in the collection
|
368 |
+
$this->getSelect()->reset(Zend_Db_Select::WHERE);
|
369 |
+
$this->addFieldToFilter('entity_id', array('in' => $this->_getProductIds()));
|
370 |
+
|
371 |
+
// API results are ordered using the selected sort order, so enforce
|
372 |
+
// the collection order to match the API results
|
373 |
+
$this->getSelect()->reset(Zend_Db_Select::ORDER);
|
374 |
+
$this->getSelect()->reset(Zend_Db_Select::LIMIT_OFFSET);
|
375 |
+
if (count($this->_getProductIds())) {
|
376 |
+
// Use "FIELD (column, 1[,2,3,4]) ASC" for ordering, where "1[,2,3,4]" is the list of IDs in the order required
|
377 |
+
$this->getSelect()->order(sprintf('FIELD(`e`.`entity_id`, %s) ASC', implode(',', $this->_getProductIds())));
|
378 |
+
}
|
379 |
+
|
380 |
+
$this->printLogQuery($printQuery, $logQuery);
|
381 |
+
|
382 |
+
try {
|
383 |
+
/**
|
384 |
+
* Prepare select query
|
385 |
+
* @var string $query
|
386 |
+
*/
|
387 |
+
if (is_callable(array($this, "_prepareSelect"))) {
|
388 |
+
$query = $this->_prepareSelect($this->getSelect());
|
389 |
+
} else {
|
390 |
+
$query = $this->getSelect();
|
391 |
+
}
|
392 |
+
$rows = $this->_fetchAll($query);
|
393 |
+
} catch (Exception $e) {
|
394 |
+
Mage::printException($e, $query);
|
395 |
+
$this->printLogQuery(true, true, $query);
|
396 |
+
throw $e;
|
397 |
+
}
|
398 |
+
|
399 |
+
foreach ($rows as $v) {
|
400 |
+
$object = $this->getNewEmptyItem()
|
401 |
+
->setData($v);
|
402 |
+
$this->addItem($object);
|
403 |
+
if (isset($this->_itemsById[$object->getId()])) {
|
404 |
+
$this->_itemsById[$object->getId()][] = $object;
|
405 |
+
} else {
|
406 |
+
$this->_itemsById[$object->getId()] = array($object);
|
407 |
+
}
|
408 |
+
}
|
409 |
+
|
410 |
+
return $this;
|
411 |
+
}
|
412 |
+
|
413 |
+
/**
|
414 |
+
* Get the active filters, then prepare them for Klevu.
|
415 |
+
*
|
416 |
+
* @return string
|
417 |
+
*/
|
418 |
+
protected function _getPreparedFilters() {
|
419 |
+
$layer = Mage::getSingleton('catalogsearch/layer');
|
420 |
+
$filters = $layer->getState()->getFilters();
|
421 |
+
$prepared_filters = array();
|
422 |
+
|
423 |
+
/** @var Mage_Catalog_Model_Layer_Filter_Item $filter */
|
424 |
+
foreach ($filters as $filter) {
|
425 |
+
$filter_type = $filter->getFilter()->getRequestVar();
|
426 |
+
$label = Mage::helper('klevu_search')->santiseAttributeValue(strtolower($filter->getData('label')));
|
427 |
+
|
428 |
+
switch($filter_type) {
|
429 |
+
case "cat":
|
430 |
+
$prepared_filters['category'] = $label;
|
431 |
+
break;
|
432 |
+
case "price":
|
433 |
+
$prepared_filters['klevu_price'] = implode(' - ', $filter->getFilter()->getData('interval'));
|
434 |
+
break;
|
435 |
+
default:
|
436 |
+
$prepared_filters[$filter->getFilter()->getAttributeModel()->getAttributeCode()] = $label;
|
437 |
+
break;
|
438 |
+
}
|
439 |
+
}
|
440 |
+
|
441 |
+
$this->log(Zend_Log::DEBUG, sprintf('Active Filters: %s', var_export($prepared_filters, true)));
|
442 |
+
|
443 |
+
return implode(
|
444 |
+
';;',
|
445 |
+
array_map(
|
446 |
+
function($v, $k) {
|
447 |
+
return sprintf('%s:%s', $k, $v);
|
448 |
+
},
|
449 |
+
$prepared_filters,
|
450 |
+
array_keys($prepared_filters)
|
451 |
+
)
|
452 |
+
);
|
453 |
+
|
454 |
+
}
|
455 |
+
|
456 |
+
protected function log($level, $message) {
|
457 |
+
Mage::helper('klevu_search')->log($level, $message);
|
458 |
+
}
|
459 |
+
|
460 |
+
protected function isExtensionConfigured() {
|
461 |
+
return Mage::helper('klevu_search/config')->isExtensionConfigured();
|
462 |
+
}
|
463 |
+
}
|
app/code/community/Klevu/Search/Model/CatalogSearch/Resource/Layer/Filter/Attribute.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_CatalogSearch_Resource_Layer_Filter_Attribute extends Mage_Catalog_Model_Resource_Eav_Mysql4_Layer_Filter_Attribute {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Stub method to prevent filters being applied. Klevu handles all filtering.
|
7 |
+
*
|
8 |
+
* @param Mage_Catalog_Model_Layer_Filter_Attribute $filter
|
9 |
+
* @param int $value
|
10 |
+
* @return $this|Mage_Catalog_Model_Resource_Layer_Filter_Attribute
|
11 |
+
*/
|
12 |
+
public function applyFilterToCollection($filter, $value) {
|
13 |
+
// If the Klevu module is not configured/enabled, run the parent method.
|
14 |
+
if (!Mage::helper('klevu_search/config')->isExtensionConfigured() || !Mage::helper('klevu_search')->isCatalogSearch()) {
|
15 |
+
parent::applyFilterToCollection($filter, $value);
|
16 |
+
}
|
17 |
+
|
18 |
+
return $this;
|
19 |
+
}
|
20 |
+
}
|
app/code/community/Klevu/Search/Model/Config/Log/Level.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Config_Log_Level extends Mage_Core_Model_Config_Data {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Return the log level value. Return Zend_Log::WARN as default, if none set.
|
7 |
+
*
|
8 |
+
* @return int
|
9 |
+
*/
|
10 |
+
public function getValue() {
|
11 |
+
$value = $this->getData('value');
|
12 |
+
|
13 |
+
return ($value != null) ? intval($value) : Zend_Log::WARN;
|
14 |
+
}
|
15 |
+
}
|
app/code/community/Klevu/Search/Model/Cron.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Cron extends Varien_Object {
|
4 |
+
|
5 |
+
public function clearCronCheckNotification() {
|
6 |
+
$collection = Mage::getResourceModel("klevu_search/notification_collection");
|
7 |
+
$collection->addFieldToFilter("type", array("eq" => "cron_check"));
|
8 |
+
|
9 |
+
foreach ($collection as $notification) {
|
10 |
+
$notification->delete();
|
11 |
+
}
|
12 |
+
}
|
13 |
+
}
|
app/code/community/Klevu/Search/Model/Notification.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Notification extends Mage_Core_Model_Abstract {
|
4 |
+
|
5 |
+
protected function _construct() {
|
6 |
+
$this->_init("klevu_search/notification");
|
7 |
+
}
|
8 |
+
}
|
app/code/community/Klevu/Search/Model/Observer.php
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Klevu_Search_Model_Observer
|
5 |
+
*
|
6 |
+
* @method setIsProductSyncScheduled($flag)
|
7 |
+
* @method bool getIsProductSyncScheduled()
|
8 |
+
*/
|
9 |
+
class Klevu_Search_Model_Observer extends Varien_Object {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Schedule a Product Sync to run immediately.
|
13 |
+
*
|
14 |
+
* @param Varien_Event_Observer $observer
|
15 |
+
*/
|
16 |
+
public function scheduleProductSync(Varien_Event_Observer $observer) {
|
17 |
+
if (!$this->getIsProductSyncScheduled()) {
|
18 |
+
Mage::getModel("klevu_search/product_sync")->schedule();
|
19 |
+
$this->setIsProductSyncScheduled(true);
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Schedule an Order Sync to run immediately. If the observed event
|
25 |
+
* contains an order, add it to the sync queue before scheduling.
|
26 |
+
*
|
27 |
+
* @param Varien_Event_Observer $observer
|
28 |
+
*/
|
29 |
+
public function scheduleOrderSync(Varien_Event_Observer $observer) {
|
30 |
+
$model = Mage::getModel("klevu_search/order_sync");
|
31 |
+
|
32 |
+
$order = $observer->getEvent()->getOrder();
|
33 |
+
if ($order) {
|
34 |
+
$model->addOrderToQueue($order);
|
35 |
+
}
|
36 |
+
|
37 |
+
$model->schedule();
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* When products are updated in bulk, update products so that they will be synced.
|
42 |
+
* @param Varien_Event_Observer $observer
|
43 |
+
*/
|
44 |
+
public function setProductsToSync(Varien_Event_Observer $observer) {
|
45 |
+
$product_ids = $observer->getData('product_ids');
|
46 |
+
|
47 |
+
if(empty($product_ids)) {
|
48 |
+
return;
|
49 |
+
}
|
50 |
+
|
51 |
+
$product_ids = implode(',', $product_ids);
|
52 |
+
$where = sprintf("product_id IN(%s) OR parent_id IN(%s)", $product_ids, $product_ids);
|
53 |
+
$resource = Mage::getSingleton('core/resource');
|
54 |
+
$resource->getConnection('core_write')
|
55 |
+
->update(
|
56 |
+
$resource->getTableName('klevu_search/product_sync'),
|
57 |
+
array('last_synced_at' => '0'),
|
58 |
+
$where
|
59 |
+
);
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Mark all of the products for update and then schedule a sync
|
64 |
+
* to run immediately.
|
65 |
+
*
|
66 |
+
* @param Varien_Event_Observer $observer
|
67 |
+
*/
|
68 |
+
public function syncAllProducts(Varien_Event_Observer $observer) {
|
69 |
+
$store = null;
|
70 |
+
$sync = Mage::getModel("klevu_search/product_sync");
|
71 |
+
|
72 |
+
$attribute = $observer->getEvent()->getAttribute();
|
73 |
+
if ($attribute instanceof Mage_Catalog_Model_Resource_Eav_Attribute) {
|
74 |
+
// On attribute change, sync only if the attribute was added
|
75 |
+
// or removed from layered navigation
|
76 |
+
if ($attribute->getOrigData("is_filterable_in_search") == $attribute->getData("is_filterable_in_search")) {
|
77 |
+
return;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
if ($observer->getEvent()->getStore()) {
|
82 |
+
// Only sync products for a specific store if the event was fired in that store
|
83 |
+
$store = Mage::app()->getStore($observer->getEvent()->getStore());
|
84 |
+
}
|
85 |
+
|
86 |
+
$sync->markAllProductsForUpdate($store);
|
87 |
+
|
88 |
+
if (!$this->getIsProductSyncScheduled()) {
|
89 |
+
$sync->schedule();
|
90 |
+
$this->setIsProductSyncScheduled(true);
|
91 |
+
}
|
92 |
+
}
|
93 |
+
/**
|
94 |
+
* When product image updated from admin this will generate the image thumb.
|
95 |
+
* @param Varien_Event_Observer $observer
|
96 |
+
*/
|
97 |
+
public function createThumb(Varien_Event_Observer $observer) {
|
98 |
+
$image = $observer->getEvent()->getProduct()->getImage();
|
99 |
+
if(($image != "no_selection") && (!empty($image))) {
|
100 |
+
Mage::getModel("klevu_search/product_sync")->thumbImage($image);
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Apply model rewrites for the search landing page, if it is enabled.
|
106 |
+
*
|
107 |
+
* @param Varien_Event_Observer $observer
|
108 |
+
*/
|
109 |
+
public function applyLandingPageModelRewrites(Varien_Event_Observer $observer) {
|
110 |
+
if (Mage::helper("klevu_search/config")->isLandingEnabled()) {
|
111 |
+
$rewrites = array(
|
112 |
+
"global/models/catalogsearch_resource/rewrite/fulltext_collection" => "Klevu_Search_Model_CatalogSearch_Resource_Fulltext_Collection",
|
113 |
+
"global/models/catalogsearch_mysql4/rewrite/fulltext_collection" => "Klevu_Search_Model_CatalogSearch_Resource_Fulltext_Collection",
|
114 |
+
"global/models/catalogsearch/rewrite/layer_filter_attribute" => "Klevu_Search_Model_CatalogSearch_Layer_Filter_Attribute",
|
115 |
+
"global/models/catalog/rewrite/config" => "Klevu_Search_Model_Catalog_Model_Config",
|
116 |
+
"global/models/catalog/rewrite/layer_filter_price" => "Klevu_Search_Model_CatalogSearch_Layer_Filter_Price",
|
117 |
+
"global/models/catalog/rewrite/layer_filter_category" => "Klevu_Search_Model_CatalogSearch_Layer_Filter_Category",
|
118 |
+
"global/models/catalog_resource/rewrite/layer_filter_attribute" => "Klevu_Search_Model_CatalogSearch_Resource_Layer_Filter_Attribute",
|
119 |
+
"global/models/catalog_resource_eav_mysql4/rewrite/layer_filter_attribute" => "Klevu_Search_Model_CatalogSearch_Resource_Layer_Filter_Attribute"
|
120 |
+
);
|
121 |
+
|
122 |
+
$config = Mage::app()->getConfig();
|
123 |
+
foreach ($rewrites as $key => $value) {
|
124 |
+
$config->setNode($key, $value);
|
125 |
+
}
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
public function removeTest()
|
130 |
+
{
|
131 |
+
Mage::getModel("klevu_search/product_sync")->removeTestMode();
|
132 |
+
|
133 |
+
}
|
134 |
+
|
135 |
+
|
136 |
+
|
137 |
+
}
|
app/code/community/Klevu/Search/Model/Order/Sync.php
ADDED
@@ -0,0 +1,364 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Klevu_Search_Model_Order_Sync
|
5 |
+
* @method Varien_Db_Adapter_Interface getConnection()
|
6 |
+
*/
|
7 |
+
class Klevu_Search_Model_Order_Sync extends Klevu_Search_Model_Sync {
|
8 |
+
|
9 |
+
const NOTIFICATION_TYPE = "order_sync";
|
10 |
+
|
11 |
+
public function _construct() {
|
12 |
+
parent::_construct();
|
13 |
+
|
14 |
+
$this->addData(array(
|
15 |
+
"connection" => Mage::getModel("core/resource")->getConnection("core_write")
|
16 |
+
));
|
17 |
+
}
|
18 |
+
|
19 |
+
public function getJobCode() {
|
20 |
+
return "klevu_search_order_sync";
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Add the items from the given order to the Order Sync queue. Does nothing if
|
25 |
+
* Order Sync is disabled for the store that the order was placed in.
|
26 |
+
*
|
27 |
+
* @param Mage_Sales_Model_Order $order
|
28 |
+
* @param bool $force Skip enabled check
|
29 |
+
*
|
30 |
+
* @return $this
|
31 |
+
*/
|
32 |
+
public function addOrderToQueue(Mage_Sales_Model_Order $order, $force = false) {
|
33 |
+
if (!$this->isEnabled($order->getStoreId()) && !$force) {
|
34 |
+
return $this;
|
35 |
+
}
|
36 |
+
|
37 |
+
$items = array();
|
38 |
+
foreach ($order->getAllVisibleItems() as $item) {
|
39 |
+
/** @var Mage_Sales_Model_Order_Item $item */
|
40 |
+
|
41 |
+
// For configurable products add children items only, for all other products add parents
|
42 |
+
if ($item->getProductType() == Mage_Catalog_Model_Product_Type_Configurable::TYPE_CODE) {
|
43 |
+
foreach ($item->getChildrenItems() as $child) {
|
44 |
+
if($child->getId()!=null) {
|
45 |
+
$items[] = $child->getId();
|
46 |
+
}
|
47 |
+
}
|
48 |
+
} else {
|
49 |
+
if($item->getId()!=null) {
|
50 |
+
$items[] = $item->getId();
|
51 |
+
}
|
52 |
+
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
// in case of multiple addresses used for shipping
|
57 |
+
// its possible that items object here is empty
|
58 |
+
// if so, we do not add to the item.
|
59 |
+
if(!empty($items)) {
|
60 |
+
$this->addItemsToQueue($items);
|
61 |
+
}
|
62 |
+
|
63 |
+
return $this;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Clear the Order Sync queue for the given store. If no store is given, clears
|
68 |
+
* the queue for all stores.
|
69 |
+
*
|
70 |
+
* @param Mage_Core_Model_Store|int|null $store
|
71 |
+
*
|
72 |
+
* @return int
|
73 |
+
*/
|
74 |
+
public function clearQueue($store = null) {
|
75 |
+
$select = $this->getConnection()
|
76 |
+
->select()
|
77 |
+
->from(array("k" => $this->getTableName("klevu_search/order_sync")));
|
78 |
+
|
79 |
+
if ($store) {
|
80 |
+
$store = Mage::app()->getStore($store);
|
81 |
+
$select
|
82 |
+
->join(
|
83 |
+
array("i" => $this->getTableName("sales/order_item")),
|
84 |
+
"k.order_item_id = i.item_id",
|
85 |
+
""
|
86 |
+
)
|
87 |
+
->where("i.store_id = ?", $store->getId());
|
88 |
+
}
|
89 |
+
|
90 |
+
$result = $this->getConnection()->query($select->deleteFromSelect("k"));
|
91 |
+
return $result->rowCount();
|
92 |
+
}
|
93 |
+
|
94 |
+
public function run() {
|
95 |
+
try {
|
96 |
+
if ($this->isRunning(2)) {
|
97 |
+
// Stop if another copy is already running
|
98 |
+
$this->log(Zend_Log::INFO, "Another copy is already running. Stopped.");
|
99 |
+
return;
|
100 |
+
}
|
101 |
+
|
102 |
+
$this->log(Zend_Log::INFO, "Starting sync.");
|
103 |
+
|
104 |
+
$items_synced = 0;
|
105 |
+
$errors = 0;
|
106 |
+
|
107 |
+
$item = Mage::getModel("sales/order_item");
|
108 |
+
|
109 |
+
$stmt = $this->getConnection()->query($this->getSyncQueueSelect());
|
110 |
+
while ($item_id = $stmt->fetchColumn()) {
|
111 |
+
if ($this->rescheduleIfOutOfMemory()) {
|
112 |
+
return;
|
113 |
+
}
|
114 |
+
|
115 |
+
$item->setData(array());
|
116 |
+
$item->load($item_id);
|
117 |
+
|
118 |
+
if ($item->getId()) {
|
119 |
+
if ($this->isEnabled($item->getStoreId())) {
|
120 |
+
if ($this->getApiKey($item->getStoreId())) {
|
121 |
+
$result = $this->sync($item);
|
122 |
+
if ($result === true) {
|
123 |
+
$this->removeItemFromQueue($item_id);
|
124 |
+
$items_synced++;
|
125 |
+
} else {
|
126 |
+
$this->log(Zend_Log::INFO, sprintf("Skipped order item %d: %s", $item_id, $result));
|
127 |
+
$errors++;
|
128 |
+
}
|
129 |
+
}
|
130 |
+
} else {
|
131 |
+
$this->log(Zend_Log::ERR, sprintf("Skipped item %d: Order Sync is not enabled for this store.", $item_id));
|
132 |
+
$this->removeItemFromQueue($item_id);
|
133 |
+
}
|
134 |
+
} else {
|
135 |
+
$this->log(Zend_Log::ERR, sprintf("Order item %d does not exist: Removed from sync!", $item_id));
|
136 |
+
$this->removeItemFromQueue($item_id);
|
137 |
+
$errors++;
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
$this->log(Zend_Log::INFO, sprintf("Sync finished. %d items synced.", $items_synced));
|
142 |
+
Mage::helper("klevu_search/config")->setLastOrderSyncRun();
|
143 |
+
|
144 |
+
if ($errors) {
|
145 |
+
//$this->notify(Mage::helper("klevu_search")->__("Order Sync failed to sync some of the order items. Please consult the logs for more details."));
|
146 |
+
} else {
|
147 |
+
// If a sync finished without errors, existing notifications no longer apply
|
148 |
+
$this->deleteNotifications();
|
149 |
+
}
|
150 |
+
} catch(Exception $e) {
|
151 |
+
// Catch the exception that was thrown, log it, then throw a new exception to be caught the Magento cron.
|
152 |
+
Mage::helper('klevu_search')->log(Zend_Log::CRIT, sprintf("Exception thrown in %s::%s - %s", __CLASS__, __METHOD__, $e->getMessage()));
|
153 |
+
throw $e;
|
154 |
+
}
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Sync the given order item to Klevu. Returns true on successful sync and
|
159 |
+
* the error message otherwise.
|
160 |
+
*
|
161 |
+
* @param Mage_Sales_Model_Order_Item $item
|
162 |
+
*
|
163 |
+
* @return bool|string
|
164 |
+
*/
|
165 |
+
protected function sync($item) {
|
166 |
+
if (!$this->getApiKey($item->getStoreId())) {
|
167 |
+
return "Klevu Search is not configured for this store.";
|
168 |
+
}
|
169 |
+
|
170 |
+
$parent = null;
|
171 |
+
if ($item->getParentItemId()) {
|
172 |
+
$parent = Mage::getModel("sales/order_item")->load($item->getParentItemId());
|
173 |
+
}
|
174 |
+
|
175 |
+
$response = Mage::getModel("klevu_search/api_action_producttracking")
|
176 |
+
->setStore(Mage::app()->getStore($item->getStoreId()))
|
177 |
+
->execute(array(
|
178 |
+
"klevu_apiKey" => $this->getApiKey($item->getStoreId()),
|
179 |
+
"klevu_type" => "checkout",
|
180 |
+
"klevu_productId" => Mage::helper("klevu_search")->getKlevuProductId($item->getProductId(), ($parent) ? $parent->getProductId() : 0),
|
181 |
+
"klevu_unit" => $item->getQtyOrdered() ? $item->getQtyOrdered() : ($parent ? $parent->getQtyOrdered() : null),
|
182 |
+
"klevu_salePrice" => $item->getPriceInclTax() ? $item->getPriceInclTax() : ($parent ? $parent->getPriceInclTax() : null),
|
183 |
+
"klevu_currency" => $this->getStoreCurrency($item->getStoreId()),
|
184 |
+
"klevu_shopperIP" => $this->getOrderIP($item->getOrderId())
|
185 |
+
));
|
186 |
+
|
187 |
+
if ($response->isSuccessful()) {
|
188 |
+
return true;
|
189 |
+
} else {
|
190 |
+
return $response->getMessage();
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Check if Order Sync is enabled for the given store.
|
196 |
+
*
|
197 |
+
* @param $store_id
|
198 |
+
*
|
199 |
+
* @return bool
|
200 |
+
*/
|
201 |
+
protected function isEnabled($store_id) {
|
202 |
+
$is_enabled = $this->getData("is_enabled");
|
203 |
+
if (!is_array($is_enabled)) {
|
204 |
+
$is_enabled = array();
|
205 |
+
}
|
206 |
+
|
207 |
+
if (!isset($is_enabled[$store_id])) {
|
208 |
+
$is_enabled[$store_id] = Mage::helper("klevu_search/config")->isOrderSyncEnabled($store_id);
|
209 |
+
$this->setData("is_enabled", $is_enabled);
|
210 |
+
}
|
211 |
+
|
212 |
+
return $is_enabled[$store_id];
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Return the JS API key for the given store.
|
217 |
+
*
|
218 |
+
* @param $store_id
|
219 |
+
*
|
220 |
+
* @return string|null
|
221 |
+
*/
|
222 |
+
protected function getApiKey($store_id) {
|
223 |
+
$api_keys = $this->getData("api_keys");
|
224 |
+
if (!is_array($api_keys)) {
|
225 |
+
$api_keys = array();
|
226 |
+
}
|
227 |
+
|
228 |
+
if (!isset($api_keys[$store_id])) {
|
229 |
+
$api_keys[$store_id] = Mage::helper("klevu_search/config")->getJsApiKey($store_id);
|
230 |
+
$this->setData("api_keys", $api_keys);
|
231 |
+
}
|
232 |
+
|
233 |
+
return $api_keys[$store_id];
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Get the currency code for the given store.
|
238 |
+
*
|
239 |
+
* @param $store_id
|
240 |
+
*
|
241 |
+
* @return string
|
242 |
+
*/
|
243 |
+
protected function getStoreCurrency($store_id) {
|
244 |
+
$currencies = $this->getData("currencies");
|
245 |
+
if (!is_array($currencies)) {
|
246 |
+
$currencies = array();
|
247 |
+
}
|
248 |
+
|
249 |
+
if (!isset($currencies[$store_id])) {
|
250 |
+
$currencies[$store_id] = Mage::app()->getStore($store_id)->getDefaultCurrencyCode();
|
251 |
+
$this->setData("currencies", $currencies);
|
252 |
+
}
|
253 |
+
|
254 |
+
return $currencies[$store_id];
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Return the customer IP for the given order.
|
259 |
+
*
|
260 |
+
* @param $order_id
|
261 |
+
*
|
262 |
+
* @return string
|
263 |
+
*/
|
264 |
+
protected function getOrderIP($order_id) {
|
265 |
+
$order_ips = $this->getData("order_ips");
|
266 |
+
if (!is_array($order_ips)) {
|
267 |
+
$order_ips = array();
|
268 |
+
}
|
269 |
+
|
270 |
+
if (!isset($order_ips[$order_id])) {
|
271 |
+
$order_ips[$order_id] = $this->getConnection()->fetchOne(
|
272 |
+
$this->getConnection()
|
273 |
+
->select()
|
274 |
+
->from(array("order" => $this->getTableName("sales/order")), "remote_ip")
|
275 |
+
->where("order.entity_id = ?", $order_id)
|
276 |
+
);
|
277 |
+
$this->setData("order_ips", $order_ips);
|
278 |
+
}
|
279 |
+
|
280 |
+
return $order_ips[$order_id];
|
281 |
+
}
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Return a select statement for getting all items in the sync queue.
|
285 |
+
*
|
286 |
+
* @return Zend_Db_Select
|
287 |
+
*/
|
288 |
+
protected function getSyncQueueSelect() {
|
289 |
+
return $this->getConnection()
|
290 |
+
->select()
|
291 |
+
->from($this->getTableName("klevu_search/order_sync"));
|
292 |
+
}
|
293 |
+
|
294 |
+
/**
|
295 |
+
* Add the given order item IDs to the sync queue.
|
296 |
+
*
|
297 |
+
* @param $order_item_ids
|
298 |
+
*
|
299 |
+
* @return int
|
300 |
+
*/
|
301 |
+
protected function addItemsToQueue($order_item_ids) {
|
302 |
+
if (!is_array($order_item_ids)) {
|
303 |
+
$order_item_ids = array($order_item_ids);
|
304 |
+
}
|
305 |
+
|
306 |
+
return $this->getConnection()->insertArray(
|
307 |
+
$this->getTableName("klevu_search/order_sync"),
|
308 |
+
array("order_item_id"),
|
309 |
+
$order_item_ids
|
310 |
+
);
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Remove the given item from the sync queue.
|
315 |
+
*
|
316 |
+
* @param $order_item_id
|
317 |
+
*
|
318 |
+
* @return bool
|
319 |
+
*/
|
320 |
+
protected function removeItemFromQueue($order_item_id) {
|
321 |
+
return $this->getConnection()->delete(
|
322 |
+
$this->getTableName("klevu_search/order_sync"),
|
323 |
+
array("order_item_id" => $order_item_id)
|
324 |
+
) === 1;
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Create an Adminhtml notification for Order Sync, overwriting
|
329 |
+
* any existing ones.
|
330 |
+
*
|
331 |
+
* @param $message
|
332 |
+
*
|
333 |
+
* @return $this
|
334 |
+
*/
|
335 |
+
protected function notify($message) {
|
336 |
+
$notification = Mage::getResourceModel("klevu_search/notification_collection")
|
337 |
+
->addFieldToFilter("type", array("eq" => static::NOTIFICATION_TYPE))
|
338 |
+
->getFirstItem();
|
339 |
+
|
340 |
+
$notification->addData(array(
|
341 |
+
"type" => static::NOTIFICATION_TYPE,
|
342 |
+
"date" => Mage::getModel("core/date")->timestamp(),
|
343 |
+
"message" => $message
|
344 |
+
));
|
345 |
+
|
346 |
+
$notification->save();
|
347 |
+
|
348 |
+
return $this;
|
349 |
+
}
|
350 |
+
|
351 |
+
/**
|
352 |
+
* Delete Adminhtml notifications for Order Sync.
|
353 |
+
*
|
354 |
+
* @return $this
|
355 |
+
*/
|
356 |
+
protected function deleteNotifications() {
|
357 |
+
$this->getConnection()->delete(
|
358 |
+
$this->getTableName('klevu_search/notification'),
|
359 |
+
array("type" => static::NOTIFICATION_TYPE)
|
360 |
+
);
|
361 |
+
|
362 |
+
return $this;
|
363 |
+
}
|
364 |
+
}
|
app/code/community/Klevu/Search/Model/Product/Sync.php
ADDED
@@ -0,0 +1,1969 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Klevu_Search_Model_Product_Sync
|
5 |
+
* @method Varien_Db_Adapter_Interface getConnection()
|
6 |
+
* @method Mage_Core_Model_Store getStore()
|
7 |
+
* @method string getSessionId()
|
8 |
+
*/
|
9 |
+
class Klevu_Search_Model_Product_Sync extends Klevu_Search_Model_Sync {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* It has been determined during development that Product Sync uses around
|
13 |
+
* 120kB of memory for each product it syncs, or around 10MB of memory for
|
14 |
+
* each 100 product page.
|
15 |
+
*/
|
16 |
+
const RECORDS_PER_PAGE = 100;
|
17 |
+
|
18 |
+
const NOTIFICATION_GLOBAL_TYPE = "product_sync";
|
19 |
+
const NOTIFICATION_STORE_TYPE_PREFIX = "product_sync_store_";
|
20 |
+
|
21 |
+
public function _construct() {
|
22 |
+
parent::_construct();
|
23 |
+
|
24 |
+
$this->addData(array(
|
25 |
+
'connection' => Mage::getModel('core/resource')->getConnection("core_write")
|
26 |
+
));
|
27 |
+
}
|
28 |
+
|
29 |
+
public function getJobCode() {
|
30 |
+
return "klevu_search_product_sync";
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Perform Product Sync on any configured stores, adding new products, updating modified and
|
35 |
+
* deleting removed products since last sync.
|
36 |
+
*/
|
37 |
+
public function run() {
|
38 |
+
try {
|
39 |
+
if ($this->isRunning(2)) {
|
40 |
+
// Stop if another copy is already running
|
41 |
+
$this->log(Zend_Log::INFO, "Stopping because another copy is already running.");
|
42 |
+
return;
|
43 |
+
}
|
44 |
+
|
45 |
+
$stores = Mage::app()->getStores();
|
46 |
+
|
47 |
+
foreach ($stores as $store) {
|
48 |
+
/** @var Mage_Core_Model_Store $store */
|
49 |
+
$this->reset();
|
50 |
+
|
51 |
+
if ($this->rescheduleIfOutOfMemory()) {
|
52 |
+
return;
|
53 |
+
}
|
54 |
+
|
55 |
+
if (!$this->setupSession($store)) {
|
56 |
+
continue;
|
57 |
+
}
|
58 |
+
|
59 |
+
$this->log(Zend_Log::INFO, sprintf("Starting sync for %s (%s).", $store->getWebsite()->getName(), $store->getName()));
|
60 |
+
|
61 |
+
$actions = array(
|
62 |
+
'delete' => $this->getConnection()
|
63 |
+
->select()
|
64 |
+
/*
|
65 |
+
* Select synced products in the current store/mode that are no longer enabled
|
66 |
+
* (don't exist in the products table, or have status disabled for the current
|
67 |
+
* store, or have status disabled for the default store) or are not visible
|
68 |
+
* (in the case of configurable products, check the parent visibility instead).
|
69 |
+
*/
|
70 |
+
->from(
|
71 |
+
array('k' => $this->getTableName("klevu_search/product_sync")),
|
72 |
+
array('product_id' => "k.product_id", 'parent_id' => "k.parent_id")
|
73 |
+
)
|
74 |
+
->joinLeft(
|
75 |
+
array('v' => $this->getTableName("catalog/category_product_index")),
|
76 |
+
"v.product_id = k.product_id AND v.store_id = :store_id",
|
77 |
+
""
|
78 |
+
)
|
79 |
+
->joinLeft(
|
80 |
+
array('p' => $this->getTableName("catalog/product")),
|
81 |
+
"p.entity_id = k.product_id",
|
82 |
+
""
|
83 |
+
)
|
84 |
+
->joinLeft(
|
85 |
+
array('ss' => $this->getProductStatusAttribute()->getBackendTable()),
|
86 |
+
"ss.attribute_id = :status_attribute_id AND ss.entity_id = k.product_id AND ss.store_id = :store_id",
|
87 |
+
""
|
88 |
+
)
|
89 |
+
->joinLeft(
|
90 |
+
array('sd' => $this->getProductStatusAttribute()->getBackendTable()),
|
91 |
+
"sd.attribute_id = :status_attribute_id AND sd.entity_id = k.product_id AND sd.store_id = :default_store_id",
|
92 |
+
""
|
93 |
+
)
|
94 |
+
->where("(k.store_id = :store_id) AND (k.test_mode = :test_mode) AND ((p.entity_id IS NULL) OR (CASE WHEN ss.value_id > 0 THEN ss.value ELSE sd.value END != :status_enabled) OR (CASE WHEN k.parent_id = 0 THEN k.product_id ELSE k.parent_id END NOT IN (?)))",
|
95 |
+
$this->getConnection()
|
96 |
+
->select()
|
97 |
+
->from(
|
98 |
+
array('i' => $this->getTableName("catalog/category_product_index")),
|
99 |
+
array('id' => "i.product_id")
|
100 |
+
)
|
101 |
+
->where("(i.store_id = :store_id) AND (i.visibility IN (:visible_both, :visible_search))")
|
102 |
+
)
|
103 |
+
->group(array('k.product_id', 'k.parent_id'))
|
104 |
+
->bind(array(
|
105 |
+
'store_id' => $store->getId(),
|
106 |
+
'default_store_id' => Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID,
|
107 |
+
'test_mode' => $this->isTestModeEnabled(),
|
108 |
+
'status_attribute_id' => $this->getProductStatusAttribute()->getId(),
|
109 |
+
'status_enabled' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED,
|
110 |
+
'visible_both' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
|
111 |
+
'visible_search' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_SEARCH
|
112 |
+
)),
|
113 |
+
|
114 |
+
'update' => $this->getConnection()
|
115 |
+
->select()
|
116 |
+
->union(array(
|
117 |
+
// Select products without parents that need to be updated
|
118 |
+
$this->getConnection()
|
119 |
+
->select()
|
120 |
+
/*
|
121 |
+
* Select synced non-configurable products for the current store/mode
|
122 |
+
* that are visible (using the category product index) and have been
|
123 |
+
* updated since last sync.
|
124 |
+
*/
|
125 |
+
->from(
|
126 |
+
array('k' => $this->getTableName("klevu_search/product_sync")),
|
127 |
+
array('product_id' => "k.product_id", 'parent_id' => "k.parent_id")
|
128 |
+
)
|
129 |
+
->join(
|
130 |
+
array('p' => $this->getTableName("catalog/product")),
|
131 |
+
"p.entity_id = k.product_id",
|
132 |
+
""
|
133 |
+
)
|
134 |
+
->join(
|
135 |
+
array('i' => $this->getTableName("catalog/category_product_index")),
|
136 |
+
"i.product_id = k.product_id AND k.store_id = i.store_id AND i.visibility IN (:visible_both, :visible_search)",
|
137 |
+
""
|
138 |
+
)
|
139 |
+
->where("(k.store_id = :store_id) AND (k.test_mode = :test_mode) AND (p.type_id != :configurable) AND (p.updated_at > k.last_synced_at)"),
|
140 |
+
// Select products with parents (configurable) that need to be updated
|
141 |
+
$this->getConnection()
|
142 |
+
->select()
|
143 |
+
/*
|
144 |
+
* Select synced products for the current store/mode that are configurable
|
145 |
+
* children (have entries in the super link table), are enabled for the current
|
146 |
+
* store (or the default store), have visible parents (using the category product
|
147 |
+
* index) and, either the product or the parent, have been updated since last sync.
|
148 |
+
*/
|
149 |
+
->from(
|
150 |
+
array('k' => $this->getTableName("klevu_search/product_sync")),
|
151 |
+
array('product_id' => "k.product_id", 'parent_id' => "k.parent_id")
|
152 |
+
)
|
153 |
+
->join(
|
154 |
+
array('s' => $this->getTableName("catalog/product_super_link")),
|
155 |
+
"k.parent_id = s.parent_id AND k.product_id = s.product_id",
|
156 |
+
""
|
157 |
+
)
|
158 |
+
->join(
|
159 |
+
array('i' => $this->getTableName("catalog/category_product_index")),
|
160 |
+
"k.parent_id = i.product_id AND k.store_id = i.store_id AND i.visibility IN (:visible_both, :visible_search)",
|
161 |
+
""
|
162 |
+
)
|
163 |
+
->join(
|
164 |
+
array('p1' => $this->getTableName("catalog/product")),
|
165 |
+
"k.product_id = p1.entity_id",
|
166 |
+
""
|
167 |
+
)
|
168 |
+
->join(
|
169 |
+
array('p2' => $this->getTableName("catalog/product")),
|
170 |
+
"k.parent_id = p2.entity_id",
|
171 |
+
""
|
172 |
+
)
|
173 |
+
->joinLeft(
|
174 |
+
array('ss' => $this->getProductStatusAttribute()->getBackendTable()),
|
175 |
+
"ss.attribute_id = :status_attribute_id AND ss.entity_id = k.product_id AND ss.store_id = :store_id",
|
176 |
+
""
|
177 |
+
)
|
178 |
+
->joinLeft(
|
179 |
+
array('sd' => $this->getProductStatusAttribute()->getBackendTable()),
|
180 |
+
"sd.attribute_id = :status_attribute_id AND sd.entity_id = k.product_id AND sd.store_id = :default_store_id",
|
181 |
+
""
|
182 |
+
)
|
183 |
+
->where("(k.store_id = :store_id) AND (k.test_mode = :test_mode) AND (CASE WHEN ss.value_id > 0 THEN ss.value ELSE sd.value END = :status_enabled) AND ((p1.updated_at > k.last_synced_at) OR (p2.updated_at > k.last_synced_at))")
|
184 |
+
))
|
185 |
+
->group(array('k.product_id', 'k.parent_id'))
|
186 |
+
->bind(array(
|
187 |
+
'store_id' => $store->getId(),
|
188 |
+
'default_store_id' => Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID,
|
189 |
+
'test_mode' => $this->isTestModeEnabled(),
|
190 |
+
'configurable' => Mage_Catalog_Model_Product_Type_Configurable::TYPE_CODE,
|
191 |
+
'visible_both' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
|
192 |
+
'visible_search' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_SEARCH,
|
193 |
+
'status_attribute_id' => $this->getProductStatusAttribute()->getId(),
|
194 |
+
'status_enabled' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED,
|
195 |
+
)),
|
196 |
+
|
197 |
+
'add' => $this->getConnection()
|
198 |
+
->select()
|
199 |
+
->union(array(
|
200 |
+
// Select non-configurable products that need to be added
|
201 |
+
$this->getConnection()
|
202 |
+
->select()
|
203 |
+
/*
|
204 |
+
* Select non-configurable products that are visible in the current
|
205 |
+
* store (using the category product index), but have not been synced
|
206 |
+
* for this store yet.
|
207 |
+
*/
|
208 |
+
->from(
|
209 |
+
array('p' => $this->getTableName("catalog/product")),
|
210 |
+
array('product_id' => "p.entity_id", 'parent_id' => new Zend_Db_Expr("0"))
|
211 |
+
)
|
212 |
+
->join(
|
213 |
+
array('i' => $this->getTableName("catalog/category_product_index")),
|
214 |
+
"p.entity_id = i.product_id AND i.store_id = :store_id AND i.visibility IN (:visible_both, :visible_search)",
|
215 |
+
""
|
216 |
+
)
|
217 |
+
->joinLeft(
|
218 |
+
array('k' => $this->getTableName("klevu_search/product_sync")),
|
219 |
+
"p.entity_id = k.product_id AND k.parent_id = 0 AND i.store_id = k.store_id AND k.test_mode = :test_mode",
|
220 |
+
""
|
221 |
+
)
|
222 |
+
->where("(p.type_id != :configurable) AND (k.product_id IS NULL)"),
|
223 |
+
// Select configurable parent & product pairs that need to be added
|
224 |
+
$this->getConnection()
|
225 |
+
->select()
|
226 |
+
/*
|
227 |
+
* Select configurable product children that are enabled (for the current
|
228 |
+
* store or for the default store), have visible parents (using the category
|
229 |
+
* product index) and have not been synced yet for the current store with
|
230 |
+
* the current parent.
|
231 |
+
*/
|
232 |
+
->from(
|
233 |
+
array('s' => $this->getTableName("catalog/product_super_link")),
|
234 |
+
array('product_id' => "s.product_id", 'parent_id' => "s.parent_id")
|
235 |
+
)
|
236 |
+
->join(
|
237 |
+
array('i' => $this->getTableName("catalog/category_product_index")),
|
238 |
+
"s.parent_id = i.product_id AND i.store_id = :store_id AND i.visibility IN (:visible_both, :visible_search)",
|
239 |
+
""
|
240 |
+
)
|
241 |
+
->joinLeft(
|
242 |
+
array('ss' => $this->getProductStatusAttribute()->getBackendTable()),
|
243 |
+
"ss.attribute_id = :status_attribute_id AND ss.entity_id = s.product_id AND ss.store_id = :store_id",
|
244 |
+
""
|
245 |
+
)
|
246 |
+
->joinLeft(
|
247 |
+
array('sd' => $this->getProductStatusAttribute()->getBackendTable()),
|
248 |
+
"sd.attribute_id = :status_attribute_id AND sd.entity_id = s.product_id AND sd.store_id = :default_store_id",
|
249 |
+
""
|
250 |
+
)
|
251 |
+
->joinLeft(
|
252 |
+
array('k' => $this->getTableName("klevu_search/product_sync")),
|
253 |
+
"s.parent_id = k.parent_id AND s.product_id = k.product_id AND k.store_id = :store_id AND k.test_mode = :test_mode",
|
254 |
+
""
|
255 |
+
)
|
256 |
+
->where("(CASE WHEN ss.value_id > 0 THEN ss.value ELSE sd.value END = :status_enabled) AND (k.product_id IS NULL)")
|
257 |
+
))
|
258 |
+
->group(array('k.product_id', 'k.parent_id'))
|
259 |
+
->bind(array(
|
260 |
+
'store_id' => $store->getId(),
|
261 |
+
'default_store_id' => Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID,
|
262 |
+
'test_mode' => $this->isTestModeEnabled(),
|
263 |
+
'configurable' => Mage_Catalog_Model_Product_Type_Configurable::TYPE_CODE,
|
264 |
+
'visible_both' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
|
265 |
+
'visible_search' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_SEARCH,
|
266 |
+
'status_attribute_id' => $this->getProductStatusAttribute()->getId(),
|
267 |
+
'status_enabled' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED
|
268 |
+
))
|
269 |
+
);
|
270 |
+
|
271 |
+
$errors = 0;
|
272 |
+
|
273 |
+
foreach ($actions as $action => $statement) {
|
274 |
+
if ($this->rescheduleIfOutOfMemory()) {
|
275 |
+
return;
|
276 |
+
}
|
277 |
+
$method = $action . "Products";
|
278 |
+
|
279 |
+
$products = $this->getConnection()->fetchAll($statement, $statement->getBind());
|
280 |
+
|
281 |
+
$total = count($products);
|
282 |
+
$this->log(Zend_Log::INFO, sprintf("Found %d products to %s.", $total, $action));
|
283 |
+
$pages = ceil($total / static::RECORDS_PER_PAGE);
|
284 |
+
for ($page = 1; $page <= $pages; $page++) {
|
285 |
+
if ($this->rescheduleIfOutOfMemory()) {
|
286 |
+
return;
|
287 |
+
}
|
288 |
+
|
289 |
+
$offset = ($page - 1) * static::RECORDS_PER_PAGE;
|
290 |
+
$result = $this->$method(array_slice($products, $offset, static::RECORDS_PER_PAGE));
|
291 |
+
|
292 |
+
if ($result !== true) {
|
293 |
+
$errors++;
|
294 |
+
$this->log(Zend_Log::ERR, sprintf("Errors occurred while attempting to %s products %d - %d: %s",
|
295 |
+
$action,
|
296 |
+
$offset + 1,
|
297 |
+
($offset + static::RECORDS_PER_PAGE <= $total) ? $offset + static::RECORDS_PER_PAGE : $total,
|
298 |
+
$result
|
299 |
+
));
|
300 |
+
/*$this->notify(
|
301 |
+
Mage::helper('klevu_search')->__("Product Sync for %s (%s) failed to %s some products. Please consult the logs for more details.",
|
302 |
+
$store->getWebsite()->getName(),
|
303 |
+
$store->getName(),
|
304 |
+
$action
|
305 |
+
),
|
306 |
+
$store
|
307 |
+
);*/
|
308 |
+
}
|
309 |
+
}
|
310 |
+
}
|
311 |
+
|
312 |
+
$this->log(Zend_Log::INFO, sprintf("Finished sync for %s (%s).", $store->getWebsite()->getName(), $store->getName()));
|
313 |
+
|
314 |
+
$config = Mage::helper('klevu_search/config');
|
315 |
+
if (!$config->isExtensionEnabled($store) && !$config->hasProductSyncRun($store)) {
|
316 |
+
// Enable Klevu Search after the first sync
|
317 |
+
$config->setExtensionEnabledFlag(true, $store);
|
318 |
+
$this->log(Zend_Log::INFO, sprintf("Automatically enabled Klevu Search on Frontend for %s (%s).",
|
319 |
+
$store->getWebsite()->getName(),
|
320 |
+
$store->getName()
|
321 |
+
));
|
322 |
+
}
|
323 |
+
$config->setLastProductSyncRun("now", $store);
|
324 |
+
|
325 |
+
if ($errors == 0) {
|
326 |
+
// If Product Sync finished without any errors, notifications are not relevant anymore
|
327 |
+
$this->deleteNotifications($store);
|
328 |
+
}
|
329 |
+
}
|
330 |
+
} catch (Exception $e) {
|
331 |
+
// Catch the exception that was thrown, log it, then throw a new exception to be caught the Magento cron.
|
332 |
+
Mage::helper('klevu_search')->log(Zend_Log::CRIT, sprintf("Exception thrown in %s::%s - %s", __CLASS__, __METHOD__, $e->getMessage()));
|
333 |
+
throw $e;
|
334 |
+
}
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Run the product sync manually, creating a cron schedule entry
|
339 |
+
* to prevent other syncs from running.
|
340 |
+
*/
|
341 |
+
public function runManually() {
|
342 |
+
$time = date_create("now")->format("Y-m-d H:i:s");
|
343 |
+
$schedule = Mage::getModel("cron/schedule");
|
344 |
+
$schedule
|
345 |
+
->setJobCode($this->getJobCode())
|
346 |
+
->setCreatedAt($time)
|
347 |
+
->setScheduledAt($time)
|
348 |
+
->setExecutedAt($time)
|
349 |
+
->setStatus(Mage_Cron_Model_Schedule::STATUS_RUNNING)
|
350 |
+
->save();
|
351 |
+
|
352 |
+
try {
|
353 |
+
$this->run();
|
354 |
+
} catch (Exception $e) {
|
355 |
+
Mage::logException($e);
|
356 |
+
|
357 |
+
$schedule
|
358 |
+
->setMessages($e->getMessage())
|
359 |
+
->setStatus(Mage_Cron_Model_Schedule::STATUS_ERROR)
|
360 |
+
->save();
|
361 |
+
|
362 |
+
return;
|
363 |
+
}
|
364 |
+
|
365 |
+
$time = date_create("now")->format("Y-m-d H:i:s");
|
366 |
+
$schedule
|
367 |
+
->setFinishedAt($time)
|
368 |
+
->setStatus(Mage_Cron_Model_Schedule::STATUS_SUCCESS)
|
369 |
+
->save();
|
370 |
+
|
371 |
+
return;
|
372 |
+
}
|
373 |
+
|
374 |
+
/**
|
375 |
+
* Mark all products to be updated the next time Product Sync runs.
|
376 |
+
*
|
377 |
+
* @param Mage_Core_Model_Store|int $store If passed, will only update products for the given store.
|
378 |
+
*
|
379 |
+
* @return $this
|
380 |
+
*/
|
381 |
+
public function markAllProductsForUpdate($store = null) {
|
382 |
+
$where = "";
|
383 |
+
if ($store !== null) {
|
384 |
+
$store = Mage::app()->getStore($store);
|
385 |
+
|
386 |
+
$where = $this->getConnection()->quoteInto("store_id = ?", $store->getId());
|
387 |
+
}
|
388 |
+
|
389 |
+
$this->getConnection()->update(
|
390 |
+
$this->getTableName('klevu_search/product_sync'),
|
391 |
+
array('last_synced_at' => '0'),
|
392 |
+
$where
|
393 |
+
);
|
394 |
+
|
395 |
+
return $this;
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* Forget the sync status of all the products for the given Store and test mode.
|
400 |
+
* If no store or test mode status is given, clear products for all stores and modes respectively.
|
401 |
+
*
|
402 |
+
* @param Mage_Core_Model_Store|int|null $store
|
403 |
+
* @param bool|null $test_mode
|
404 |
+
*
|
405 |
+
* @return int
|
406 |
+
*/
|
407 |
+
public function clearAllProducts($store = null, $test_mode = null) {
|
408 |
+
$select = $this->getConnection()
|
409 |
+
->select()
|
410 |
+
->from(
|
411 |
+
array("k" => $this->getTableName("klevu_search/product_sync"))
|
412 |
+
);
|
413 |
+
|
414 |
+
if ($store) {
|
415 |
+
$store = Mage::app()->getStore($store);
|
416 |
+
|
417 |
+
$select->where("k.store_id = ?", $store->getId());
|
418 |
+
}
|
419 |
+
|
420 |
+
if ($test_mode !== null) {
|
421 |
+
$test_mode = ($test_mode) ? 1 : 0;
|
422 |
+
|
423 |
+
$select->where("k.test_mode = ?", $test_mode);
|
424 |
+
}
|
425 |
+
|
426 |
+
$result = $this->getConnection()->query($select->deleteFromSelect("k"));
|
427 |
+
return $result->rowCount();
|
428 |
+
}
|
429 |
+
|
430 |
+
/**
|
431 |
+
* Return the product status attribute model.
|
432 |
+
*
|
433 |
+
* @return Mage_Catalog_Model_Resource_Eav_Attribute
|
434 |
+
*/
|
435 |
+
protected function getProductStatusAttribute() {
|
436 |
+
if (!$this->hasData("status_attribute")) {
|
437 |
+
$this->setData("status_attribute", Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'status'));
|
438 |
+
}
|
439 |
+
|
440 |
+
return $this->getData("status_attribute");
|
441 |
+
}
|
442 |
+
|
443 |
+
/**
|
444 |
+
* Return the product visibility attribute model.
|
445 |
+
*
|
446 |
+
* @return Mage_Catalog_Model_Resource_Eav_Attribute
|
447 |
+
*/
|
448 |
+
protected function getProductVisibilityAttribute() {
|
449 |
+
if (!$this->hasData("visibility_attribute")) {
|
450 |
+
$this->setData("visibility_attribute", Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'visibility'));
|
451 |
+
}
|
452 |
+
|
453 |
+
return $this->getData("visibility_attribute");
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Setup an API session for the given store. Sets the store and session ID on self. Returns
|
458 |
+
* true on success or false if Product Sync is disabled, store is not configured or the
|
459 |
+
* session API call fails.
|
460 |
+
*
|
461 |
+
* @param Mage_Core_Model_Store $store
|
462 |
+
*
|
463 |
+
* @return bool
|
464 |
+
*/
|
465 |
+
protected function setupSession(Mage_Core_Model_Store $store) {
|
466 |
+
$config = Mage::helper('klevu_search/config');
|
467 |
+
|
468 |
+
if (!$config->isProductSyncEnabled($store->getId())) {
|
469 |
+
$this->log(Zend_Log::INFO, sprintf("Disabled for %s (%s).", $store->getWebsite()->getName(), $store->getName()));
|
470 |
+
return null;
|
471 |
+
}
|
472 |
+
|
473 |
+
$api_key = $config->getRestApiKey($store->getId());
|
474 |
+
if (!$api_key) {
|
475 |
+
$this->log(Zend_Log::INFO, sprintf("No API key found for %s (%s).", $store->getWebsite()->getName(), $store->getName()));
|
476 |
+
return null;
|
477 |
+
}
|
478 |
+
|
479 |
+
$response = Mage::getModel('klevu_search/api_action_startsession')->execute(array(
|
480 |
+
'api_key' => $api_key,
|
481 |
+
'store' => $store,
|
482 |
+
));
|
483 |
+
|
484 |
+
if ($response->isSuccessful()) {
|
485 |
+
$this->addData(array(
|
486 |
+
'store' => $store,
|
487 |
+
'session_id' => $response->getSessionId()
|
488 |
+
));
|
489 |
+
return true;
|
490 |
+
} else {
|
491 |
+
$this->log(Zend_Log::ERR, sprintf("Failed to start a session for %s (%s): %s",
|
492 |
+
$store->getWebsite()->getName(),
|
493 |
+
$store->getName(),
|
494 |
+
$response->getMessage()
|
495 |
+
));
|
496 |
+
|
497 |
+
if ($response instanceof Klevu_Search_Model_Api_Response_Empty) {
|
498 |
+
/*$this->notify(
|
499 |
+
Mage::helper('klevu_search')->__(
|
500 |
+
"Product Sync failed for %s (%s): Could not contact Klevu.",
|
501 |
+
$store->getWebsite()->getName(),
|
502 |
+
$store->getName()
|
503 |
+
)
|
504 |
+
);*/
|
505 |
+
} else {
|
506 |
+
$this->notify(
|
507 |
+
Mage::helper('klevu_search')->__(
|
508 |
+
"Product Sync failed for %s (%s): %s",
|
509 |
+
$store->getWebsite()->getName(),
|
510 |
+
$store->getName(),
|
511 |
+
$response->getMessage()
|
512 |
+
)
|
513 |
+
);
|
514 |
+
}
|
515 |
+
|
516 |
+
return false;
|
517 |
+
}
|
518 |
+
}
|
519 |
+
|
520 |
+
/**
|
521 |
+
* Delete the given products from Klevu Search. Returns true if the operation was
|
522 |
+
* successful, or the error message if the operation failed.
|
523 |
+
*
|
524 |
+
* @param array $data List of products to delete. Each element should be an array
|
525 |
+
* containing an element with "product_id" as the key and product id as
|
526 |
+
* the value and an optional "parent_id" element with the parent id.
|
527 |
+
*
|
528 |
+
* @return bool|string
|
529 |
+
*/
|
530 |
+
protected function deleteProducts(array $data) {
|
531 |
+
$total = count($data);
|
532 |
+
|
533 |
+
$response = Mage::getModel('klevu_search/api_action_deleterecords')
|
534 |
+
->setStore($this->getStore())
|
535 |
+
->execute(array(
|
536 |
+
'sessionId' => $this->getSessionId(),
|
537 |
+
'records' => array_map(function ($v) {
|
538 |
+
return array('id' => Mage::helper('klevu_search')->getKlevuProductId($v['product_id'], $v['parent_id']));
|
539 |
+
}, $data)
|
540 |
+
));
|
541 |
+
|
542 |
+
if ($response->isSuccessful()) {
|
543 |
+
$connection = $this->getConnection();
|
544 |
+
|
545 |
+
$select = $connection
|
546 |
+
->select()
|
547 |
+
->from(array('k' => $this->getTableName("klevu_search/product_sync")))
|
548 |
+
->where("k.store_id = ?", $this->getStore()->getId())
|
549 |
+
->where("k.test_mode = ?", $this->isTestModeEnabled());
|
550 |
+
|
551 |
+
$skipped_record_ids = array();
|
552 |
+
if ($skipped_records = $response->getSkippedRecords()) {
|
553 |
+
$skipped_record_ids = array_flip($skipped_records["index"]);
|
554 |
+
}
|
555 |
+
|
556 |
+
$or_where = array();
|
557 |
+
for ($i = 0; $i < count($data); $i++) {
|
558 |
+
if (isset($skipped_record_ids[$i])) {
|
559 |
+
continue;
|
560 |
+
}
|
561 |
+
$or_where[] = sprintf("(%s AND %s)",
|
562 |
+
$connection->quoteInto("k.product_id = ?", $data[$i]['product_id']),
|
563 |
+
$connection->quoteInto("k.parent_id = ?", $data[$i]['parent_id'])
|
564 |
+
);
|
565 |
+
}
|
566 |
+
$select->where(implode(" OR ", $or_where));
|
567 |
+
|
568 |
+
$connection->query($select->deleteFromSelect("k"));
|
569 |
+
|
570 |
+
$skipped_count = count($skipped_record_ids);
|
571 |
+
if ($skipped_count > 0) {
|
572 |
+
return sprintf("%d product%s failed (%s)",
|
573 |
+
$skipped_count,
|
574 |
+
($skipped_count > 1) ? "s" : "",
|
575 |
+
implode(", ", $skipped_records["messages"])
|
576 |
+
);
|
577 |
+
} else {
|
578 |
+
return true;
|
579 |
+
}
|
580 |
+
} else {
|
581 |
+
return sprintf("%d product%s failed (%s)",
|
582 |
+
$total,
|
583 |
+
($total > 1) ? "s" : "",
|
584 |
+
$response->getMessage()
|
585 |
+
);
|
586 |
+
}
|
587 |
+
}
|
588 |
+
|
589 |
+
/**
|
590 |
+
* Update the given products on Klevu Search. Returns true if the operation was successful,
|
591 |
+
* or the error message if it failed.
|
592 |
+
*
|
593 |
+
* @param array $data List of products to update. Each element should be an array
|
594 |
+
* containing an element with "product_id" as the key and product id as
|
595 |
+
* the value and an optional "parent_id" element with the parent id.
|
596 |
+
*
|
597 |
+
* @return bool|string
|
598 |
+
*/
|
599 |
+
protected function updateProducts(array $data) {
|
600 |
+
$total = count($data);
|
601 |
+
|
602 |
+
$this->addProductSyncData($data);
|
603 |
+
|
604 |
+
$response = Mage::getModel('klevu_search/api_action_updaterecords')
|
605 |
+
->setStore($this->getStore())
|
606 |
+
->execute(array(
|
607 |
+
'sessionId' => $this->getSessionId(),
|
608 |
+
'records' => $data
|
609 |
+
));
|
610 |
+
|
611 |
+
if ($response->isSuccessful()) {
|
612 |
+
$helper = Mage::helper('klevu_search');
|
613 |
+
$connection = $this->getConnection();
|
614 |
+
|
615 |
+
$skipped_record_ids = array();
|
616 |
+
if ($skipped_records = $response->getSkippedRecords()) {
|
617 |
+
$skipped_record_ids = array_flip($skipped_records["index"]);
|
618 |
+
}
|
619 |
+
|
620 |
+
$where = array();
|
621 |
+
for ($i = 0; $i < count($data); $i++) {
|
622 |
+
if (isset($skipped_record_ids[$i])) {
|
623 |
+
continue;
|
624 |
+
}
|
625 |
+
|
626 |
+
$ids = $helper->getMagentoProductId($data[$i]['id']);
|
627 |
+
|
628 |
+
$where[] = sprintf("(%s AND %s)",
|
629 |
+
$connection->quoteInto("product_id = ?", $ids['product_id']),
|
630 |
+
$connection->quoteInto("parent_id = ?", $ids['parent_id'])
|
631 |
+
);
|
632 |
+
}
|
633 |
+
|
634 |
+
$where = sprintf("(%s) AND (%s) AND (%s)",
|
635 |
+
$connection->quoteInto("store_id = ?", $this->getStore()->getId()),
|
636 |
+
$connection->quoteInto("test_mode = ?", $this->isTestModeEnabled()),
|
637 |
+
implode(" OR ", $where)
|
638 |
+
);
|
639 |
+
|
640 |
+
$this->getConnection()->update(
|
641 |
+
$this->getTableName('klevu_search/product_sync'),
|
642 |
+
array('last_synced_at' => Mage::helper("klevu_search/compat")->now()),
|
643 |
+
$where
|
644 |
+
);
|
645 |
+
|
646 |
+
$skipped_count = count($skipped_record_ids);
|
647 |
+
if ($skipped_count > 0) {
|
648 |
+
return sprintf("%d product%s failed (%s)",
|
649 |
+
$skipped_count,
|
650 |
+
($skipped_count > 1) ? "s" : "",
|
651 |
+
implode(", ", $skipped_records["messages"])
|
652 |
+
);
|
653 |
+
} else {
|
654 |
+
return true;
|
655 |
+
}
|
656 |
+
} else {
|
657 |
+
return sprintf("%d product%s failed (%s)",
|
658 |
+
$total,
|
659 |
+
($total > 1) ? "s" : "",
|
660 |
+
$response->getMessage()
|
661 |
+
);
|
662 |
+
}
|
663 |
+
}
|
664 |
+
|
665 |
+
/**
|
666 |
+
* Add the given products to Klevu Search. Returns true if the operation was successful,
|
667 |
+
* or the error message if it failed.
|
668 |
+
*
|
669 |
+
* @param array $data List of products to add. Each element should be an array
|
670 |
+
* containing an element with "product_id" as the key and product id as
|
671 |
+
* the value and an optional "parent_id" element with the parent id.
|
672 |
+
*
|
673 |
+
* @return bool|string
|
674 |
+
*/
|
675 |
+
protected function addProducts(array $data) {
|
676 |
+
$total = count($data);
|
677 |
+
|
678 |
+
$this->addProductSyncData($data);
|
679 |
+
|
680 |
+
$response = Mage::getModel('klevu_search/api_action_addrecords')
|
681 |
+
->setStore($this->getStore())
|
682 |
+
->execute(array(
|
683 |
+
'sessionId' => $this->getSessionId(),
|
684 |
+
'records' => $data
|
685 |
+
));
|
686 |
+
|
687 |
+
if ($response->isSuccessful()) {
|
688 |
+
|
689 |
+
$skipped_record_ids = array();
|
690 |
+
if ($skipped_records = $response->getSkippedRecords()) {
|
691 |
+
$skipped_record_ids = array_flip($skipped_records["index"]);
|
692 |
+
}
|
693 |
+
|
694 |
+
$sync_time = Mage::helper("klevu_search/compat")->now();
|
695 |
+
|
696 |
+
foreach($data as $i => &$record) {
|
697 |
+
if (isset($skipped_record_ids[$i])) {
|
698 |
+
unset($data[$i]);
|
699 |
+
continue;
|
700 |
+
}
|
701 |
+
|
702 |
+
$ids = Mage::helper("klevu_search")->getMagentoProductId($data[$i]['id']);
|
703 |
+
|
704 |
+
$record = array(
|
705 |
+
$ids["product_id"],
|
706 |
+
$ids["parent_id"],
|
707 |
+
$this->getStore()->getId(),
|
708 |
+
$this->isTestModeEnabled(),
|
709 |
+
$sync_time
|
710 |
+
);
|
711 |
+
}
|
712 |
+
|
713 |
+
$this->getConnection()->insertArray(
|
714 |
+
$this->getTableName('klevu_search/product_sync'),
|
715 |
+
array("product_id", "parent_id", "store_id", "test_mode", "last_synced_at"),
|
716 |
+
$data
|
717 |
+
);
|
718 |
+
|
719 |
+
$skipped_count = count($skipped_record_ids);
|
720 |
+
if ($skipped_count > 0) {
|
721 |
+
return sprintf("%d product%s failed (%s)",
|
722 |
+
$skipped_count,
|
723 |
+
($skipped_count > 1) ? "s" : "",
|
724 |
+
implode(", ", $skipped_records["messages"])
|
725 |
+
);
|
726 |
+
} else {
|
727 |
+
return true;
|
728 |
+
}
|
729 |
+
} else {
|
730 |
+
return sprintf("%d product%s failed (%s)",
|
731 |
+
$total,
|
732 |
+
($total > 1) ? "s" : "",
|
733 |
+
$response->getMessage()
|
734 |
+
);
|
735 |
+
}
|
736 |
+
}
|
737 |
+
|
738 |
+
/**
|
739 |
+
* Add the Product Sync data to each product in the given list. Updates the given
|
740 |
+
* list directly to save memory.
|
741 |
+
*
|
742 |
+
* @param array $products An array of products. Each element should be an array with
|
743 |
+
* containing an element with "id" as the key and the product
|
744 |
+
* ID as the value.
|
745 |
+
*
|
746 |
+
* @return $this
|
747 |
+
*/
|
748 |
+
protected function addProductSyncData(&$products) {
|
749 |
+
$product_ids = array();
|
750 |
+
$parent_ids = array();
|
751 |
+
foreach ($products as $product) {
|
752 |
+
$product_ids[] = $product['product_id'];
|
753 |
+
if ($product['parent_id'] != 0) {
|
754 |
+
$product_ids[] = $product['parent_id'];
|
755 |
+
$parent_ids[] = $product['parent_id'];
|
756 |
+
}
|
757 |
+
}
|
758 |
+
$product_ids = array_unique($product_ids);
|
759 |
+
$parent_ids = array_unique($parent_ids);
|
760 |
+
|
761 |
+
$data = Mage::getModel('catalog/product')->getCollection()
|
762 |
+
->addIdFilter($product_ids)
|
763 |
+
->setStore($this->getStore())
|
764 |
+
->addStoreFilter()
|
765 |
+
->addAttributeToSelect($this->getUsedMagentoAttributes());
|
766 |
+
|
767 |
+
$data->load()
|
768 |
+
->addCategoryIds();
|
769 |
+
|
770 |
+
$url_rewrite_data = $this->getUrlRewriteData($product_ids);
|
771 |
+
$visibility_data = $this->getVisibilityData($product_ids);
|
772 |
+
$price_data = $this->getPriceData($product_ids);
|
773 |
+
$configurable_price_data = $this->getConfigurablePriceData($parent_ids);
|
774 |
+
|
775 |
+
$stock_data = $this->getStockData($product_ids);
|
776 |
+
|
777 |
+
$attribute_map = $this->getAttributeMap();
|
778 |
+
$base_url = $this->getStore()->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK);
|
779 |
+
$currency = $this->getStore()->getDefaultCurrencyCode();
|
780 |
+
$media_url = $this->getStore()->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA);
|
781 |
+
$media_url .= Mage::getModel('catalog/product_media_config')->getBaseMediaUrlAddition();
|
782 |
+
|
783 |
+
foreach ($products as $index => &$product) {
|
784 |
+
$item = $data->getItemById($product['product_id']);
|
785 |
+
$parent = ($product['parent_id'] != 0) ? $data->getItemById($product['parent_id']) : null;
|
786 |
+
|
787 |
+
if (!$item) {
|
788 |
+
// Product data query did not return any data for this product
|
789 |
+
// Remove it from the list to skip syncing it
|
790 |
+
$this->log(Zend_Log::WARN, sprintf("Failed to retrieve data for product ID %d", $product['product_id']));
|
791 |
+
unset($products[$index]);
|
792 |
+
continue;
|
793 |
+
}
|
794 |
+
|
795 |
+
// Add data from mapped attributes
|
796 |
+
foreach ($attribute_map as $key => $attributes) {
|
797 |
+
$product[$key] = null;
|
798 |
+
|
799 |
+
switch ($key) {
|
800 |
+
case "boostingAttribute":
|
801 |
+
foreach ($attributes as $attribute) {
|
802 |
+
if ($parent && $parent->getData($attribute)) {
|
803 |
+
$product[$key] = $parent->getData($attribute);
|
804 |
+
break;
|
805 |
+
} else {
|
806 |
+
$product[$key] = $item->getData($attribute);
|
807 |
+
break;
|
808 |
+
}
|
809 |
+
}
|
810 |
+
break;
|
811 |
+
case "otherAttributeToIndex":
|
812 |
+
case "other":
|
813 |
+
$product[$key] = array();
|
814 |
+
foreach ($attributes as $attribute) {
|
815 |
+
if ($item->getData($attribute)) {
|
816 |
+
$product[$key][$attribute] = $this->getAttributeData($attribute, $item->getData($attribute));
|
817 |
+
} else if ($parent && $parent->getData($attribute)) {
|
818 |
+
$product[$key][$attribute] = $this->getAttributeData($attribute, $parent->getData($attribute));
|
819 |
+
}
|
820 |
+
}
|
821 |
+
break;
|
822 |
+
case "sku":
|
823 |
+
foreach ($attributes as $attribute) {
|
824 |
+
if ($parent && $parent->getData($attribute)) {
|
825 |
+
$product[$key] = Mage::helper('klevu_search')->getKlevuProductSku($item->getData($attribute), $parent->getData($attribute));
|
826 |
+
break;
|
827 |
+
} else {
|
828 |
+
$product[$key] = $item->getData($attribute);
|
829 |
+
break;
|
830 |
+
}
|
831 |
+
}
|
832 |
+
break;
|
833 |
+
case "name":
|
834 |
+
foreach ($attributes as $attribute) {
|
835 |
+
if ($parent && $parent->getData($attribute)) {
|
836 |
+
$product[$key] = $parent->getData($attribute);
|
837 |
+
break;
|
838 |
+
}else if ($item->getData($attribute)) {
|
839 |
+
$product[$key] = $item->getData($attribute);
|
840 |
+
break;
|
841 |
+
}
|
842 |
+
}
|
843 |
+
break;
|
844 |
+
case "image":
|
845 |
+
foreach ($attributes as $attribute) {
|
846 |
+
if ($item->getData($attribute) && $item->getData($attribute) != "no_selection") {
|
847 |
+
$product[$key] = $item->getData($attribute);
|
848 |
+
break;
|
849 |
+
} else if ($parent && $parent->getData($attribute) && $parent->getData($attribute) != "no_selection") {
|
850 |
+
$product[$key] = $parent->getData($attribute);
|
851 |
+
break;
|
852 |
+
}
|
853 |
+
}
|
854 |
+
if ($product[$key] != "" && strpos($product[$key], "http") !== 0) {
|
855 |
+
// Prepend media base url for relative image locations
|
856 |
+
$imageResized = Mage::getBaseDir('media').DS."klevu_images".$product[$key];
|
857 |
+
if (file_exists($imageResized)) {
|
858 |
+
$product[$key] = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA)."klevu_images".$product[$key];
|
859 |
+
}else{
|
860 |
+
$product[$key] = $media_url . $product[$key];
|
861 |
+
}
|
862 |
+
}
|
863 |
+
break;
|
864 |
+
case "salePrice":
|
865 |
+
// Default to 0 if price can't be determined
|
866 |
+
$product['salePrice'] = 0;
|
867 |
+
$tax_class_id = "";
|
868 |
+
if ($item->getData("tax_class_id") !== null) {
|
869 |
+
$tax_class_id = $item->getData("tax_class_id");
|
870 |
+
} else if ($parent) {
|
871 |
+
$tax_class_id = $parent->getData("tax_class_id");
|
872 |
+
}else {
|
873 |
+
$tax_class_id = "";
|
874 |
+
}
|
875 |
+
|
876 |
+
if ($parent && $parent->getData("type_id") == Mage_Catalog_Model_Product_Type_Configurable::TYPE_CODE) {
|
877 |
+
// Calculate configurable product price based on option values
|
878 |
+
$price = (isset($price_data[$product['parent_id']])) ? $price_data[$product['parent_id']]['min_price'] : $parent->getData("price");
|
879 |
+
$markup = 0;
|
880 |
+
|
881 |
+
if (isset($configurable_price_data[$product['parent_id']])) {
|
882 |
+
foreach ($configurable_price_data[$product['parent_id']] as $attribute => $pricing_data) {
|
883 |
+
$value = $item->getData($attribute);
|
884 |
+
if ($value && isset($pricing_data[$value])) {
|
885 |
+
if ($pricing_data[$value]["is_percent"]) {
|
886 |
+
$markup += $price * ($pricing_data[$value]["value"] / 100);
|
887 |
+
} else {
|
888 |
+
$markup += $pricing_data[$value]["value"];
|
889 |
+
}
|
890 |
+
}
|
891 |
+
}
|
892 |
+
}
|
893 |
+
// show low price for config products
|
894 |
+
$product['startPrice'] = $this->processPrice($price , $tax_class_id, $parent);
|
895 |
+
} else {
|
896 |
+
// Use price index prices to set the product price and start/end prices if available
|
897 |
+
// Falling back to product price attribute if not
|
898 |
+
if (isset($price_data[$product['product_id']])) {
|
899 |
+
// Always use minimum price as the sale price as it's the most accurate
|
900 |
+
$product['salePrice'] = $this->processPrice($price_data[$product['product_id']]['min_price'], $tax_class_id, $item);
|
901 |
+
if ($price_data[$product['product_id']]['min_price'] != $price_data[$product['product_id']]['max_price']) {
|
902 |
+
$product['startPrice'] = $this->processPrice($price_data[$product['product_id']]['min_price'], $tax_class_id, $item);
|
903 |
+
|
904 |
+
// Maximum price on a grouped product is meaningless as it depends on quantity and items bought
|
905 |
+
if ($item->getData('type_id') != Mage_Catalog_Model_Product_Type::TYPE_GROUPED) {
|
906 |
+
$product['toPrice'] = $this->processPrice($price_data[$product['product_id']]['max_price'], $tax_class_id, $item);
|
907 |
+
}
|
908 |
+
}
|
909 |
+
} else {
|
910 |
+
if ($item->getData("price") !== null) {
|
911 |
+
$product["salePrice"] = $this->processPrice($item->getData("price"), $tax_class_id, $item);
|
912 |
+
} else if ($parent) {
|
913 |
+
$product["salePrice"] = $this->processPrice($parent->getData("price"), $tax_class_id, $item);
|
914 |
+
}
|
915 |
+
}
|
916 |
+
}
|
917 |
+
|
918 |
+
break;
|
919 |
+
default:
|
920 |
+
foreach ($attributes as $attribute) {
|
921 |
+
if ($item->getData($attribute)) {
|
922 |
+
$product[$key] = $this->getAttributeData($attribute, $item->getData($attribute));
|
923 |
+
break;
|
924 |
+
} else if ($parent && $parent->getData($attribute)) {
|
925 |
+
$product[$key] = $this->getAttributeData($attribute, $parent->getData($attribute));
|
926 |
+
break;
|
927 |
+
}
|
928 |
+
}
|
929 |
+
}
|
930 |
+
}
|
931 |
+
|
932 |
+
// Add non-attribute data
|
933 |
+
$product['currency'] = $currency;
|
934 |
+
|
935 |
+
if ($item->getCategoryIds()) {
|
936 |
+
$product['category'] = $this->getLongestPathCategoryName($item->getCategoryIds());
|
937 |
+
$product['listCategory'] = $this->getCategoryNames($item->getCategoryIds());
|
938 |
+
} else if ($parent) {
|
939 |
+
$product['category'] = $this->getLongestPathCategoryName($parent->getCategoryIds());
|
940 |
+
$product['listCategory'] = $this->getCategoryNames($parent->getCategoryIds());
|
941 |
+
} else {
|
942 |
+
$product['category'] = "";
|
943 |
+
$product['listCategory'] = "";
|
944 |
+
}
|
945 |
+
|
946 |
+
|
947 |
+
// Use the parent URL if the product is invisible (and has a parent) and
|
948 |
+
// use a URL rewrite if one exists, falling back to catalog/product/view
|
949 |
+
if (isset($visibility_data[$product['product_id']]) && !$visibility_data[$product['product_id']] && $parent) {
|
950 |
+
$product['url'] = $base_url . (
|
951 |
+
(isset($url_rewrite_data[$product['parent_id']])) ?
|
952 |
+
$url_rewrite_data[$product['parent_id']] :
|
953 |
+
"catalog/product/view/id/" . $product['parent_id']
|
954 |
+
);
|
955 |
+
} else {
|
956 |
+
if($parent) {
|
957 |
+
$product['url'] = $base_url . (
|
958 |
+
(isset($url_rewrite_data[$product['parent_id']])) ?
|
959 |
+
$url_rewrite_data[$product['parent_id']] :
|
960 |
+
"catalog/product/view/id/" . $product['parent_id']
|
961 |
+
);
|
962 |
+
} else {
|
963 |
+
$product['url'] = $base_url . (
|
964 |
+
(isset($url_rewrite_data[$product['product_id']])) ?
|
965 |
+
$url_rewrite_data[$product['product_id']] :
|
966 |
+
"catalog/product/view/id/" . $product['product_id']
|
967 |
+
);
|
968 |
+
}
|
969 |
+
}
|
970 |
+
|
971 |
+
// Add stock data
|
972 |
+
$product['inStock'] = ($stock_data[$product['product_id']]) ? "yes" : "no";
|
973 |
+
|
974 |
+
// Configurable product relation
|
975 |
+
if ($product['parent_id'] != 0) {
|
976 |
+
$product['itemGroupId'] = $product['parent_id'];
|
977 |
+
}
|
978 |
+
|
979 |
+
// Set ID data
|
980 |
+
$product['id'] = Mage::helper('klevu_search')->getKlevuProductId($product['product_id'], $product['parent_id']);
|
981 |
+
unset($product['product_id']);
|
982 |
+
unset($product['parent_id']);
|
983 |
+
}
|
984 |
+
|
985 |
+
return $this;
|
986 |
+
}
|
987 |
+
|
988 |
+
/**
|
989 |
+
* Return the URL rewrite data for the given products for the current store.
|
990 |
+
*
|
991 |
+
* @param array $product_ids A list of product IDs.
|
992 |
+
*
|
993 |
+
* @return array A list with product IDs as keys and request paths as values.
|
994 |
+
*/
|
995 |
+
protected function getUrlRewriteData($product_ids) {
|
996 |
+
$stmt = $this->getConnection()->query(
|
997 |
+
Mage::helper('klevu_search/compat')->getProductUrlRewriteSelect($product_ids, 0, $this->getStore()->getId())
|
998 |
+
);
|
999 |
+
|
1000 |
+
$url_suffix = Mage::helper('catalog/product')->getProductUrlSuffix($this->getStore()->getId());
|
1001 |
+
if ($url_suffix && substr($url_suffix, 0, 1) !== ".") {
|
1002 |
+
$url_suffix = "." . $url_suffix;
|
1003 |
+
}
|
1004 |
+
|
1005 |
+
$data = array();
|
1006 |
+
while ($row = $stmt->fetch()) {
|
1007 |
+
if (!isset($data[$row['product_id']])) {
|
1008 |
+
$data[$row['product_id']] = $row['request_path'];
|
1009 |
+
// Append the product URL suffix if the rewrite does not have one already
|
1010 |
+
if ($url_suffix && substr($row['request_path'], -1 * strlen($url_suffix)) !== $url_suffix) {
|
1011 |
+
$data[$row['product_id']] .= $url_suffix;
|
1012 |
+
}
|
1013 |
+
}
|
1014 |
+
}
|
1015 |
+
|
1016 |
+
return $data;
|
1017 |
+
}
|
1018 |
+
|
1019 |
+
/**
|
1020 |
+
* Return the visibility data for the given products for the current store.
|
1021 |
+
*
|
1022 |
+
* @param array $product_ids A list of product IDs.
|
1023 |
+
*
|
1024 |
+
* @return array A list with product IDs as keys and boolean visibility values.
|
1025 |
+
*/
|
1026 |
+
protected function getVisibilityData($product_ids) {
|
1027 |
+
$stmt = $this->getConnection()->query(
|
1028 |
+
$this->getConnection()
|
1029 |
+
->select()
|
1030 |
+
->from(
|
1031 |
+
array('p' => $this->getTableName("catalog/product")),
|
1032 |
+
array(
|
1033 |
+
'product_id' => "p.entity_id"
|
1034 |
+
)
|
1035 |
+
)
|
1036 |
+
->joinLeft(
|
1037 |
+
array('vs' => $this->getProductVisibilityAttribute()->getBackendTable()),
|
1038 |
+
"vs.attribute_id = :visibility_attribute_id AND vs.entity_id = p.entity_id AND vs.store_id = :store_id",
|
1039 |
+
""
|
1040 |
+
)
|
1041 |
+
->joinLeft(
|
1042 |
+
array('vd' => $this->getProductVisibilityAttribute()->getBackendTable()),
|
1043 |
+
"vd.attribute_id = :visibility_attribute_id AND vd.entity_id = p.entity_id AND vd.store_id = :default_store_id",
|
1044 |
+
array(
|
1045 |
+
"visibility" => new Zend_Db_Expr("IF(vs.value IS NOT NULL, vs.value, vd.value)")
|
1046 |
+
)
|
1047 |
+
)
|
1048 |
+
->where("p.entity_id IN (?)", $product_ids),
|
1049 |
+
array(
|
1050 |
+
"visibility_attribute_id" => $this->getProductVisibilityAttribute()->getId(),
|
1051 |
+
"store_id" => $this->getStore()->getId(),
|
1052 |
+
"default_store_id" => Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID
|
1053 |
+
)
|
1054 |
+
);
|
1055 |
+
|
1056 |
+
$data = array();
|
1057 |
+
while ($row = $stmt->fetch()) {
|
1058 |
+
$data[$row['product_id']] = ($row['visibility'] != Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE) ? true : false;
|
1059 |
+
}
|
1060 |
+
|
1061 |
+
return $data;
|
1062 |
+
}
|
1063 |
+
|
1064 |
+
/**
|
1065 |
+
* Return the "Is in stock?" flags for the given products.
|
1066 |
+
* Considers if the stock is managed on the product or per store when deciding if a product
|
1067 |
+
* is in stock.
|
1068 |
+
*
|
1069 |
+
* @param array $product_ids A list of product IDs.
|
1070 |
+
*
|
1071 |
+
* @return array A list with product IDs as keys and "Is in stock?" booleans as values.
|
1072 |
+
*/
|
1073 |
+
protected function getStockData($product_ids) {
|
1074 |
+
$stmt = $this->getConnection()->query(
|
1075 |
+
$this->getConnection()
|
1076 |
+
->select()
|
1077 |
+
->from(
|
1078 |
+
array('s' => $this->getTableName("cataloginventory/stock_item")),
|
1079 |
+
array(
|
1080 |
+
'product_id' => "s.product_id",
|
1081 |
+
'in_stock' => "s.is_in_stock",
|
1082 |
+
'manage_stock' => "s.manage_stock",
|
1083 |
+
'use_config' => "s.use_config_manage_stock"
|
1084 |
+
)
|
1085 |
+
)
|
1086 |
+
->where("s.product_id IN (?)", $product_ids)
|
1087 |
+
);
|
1088 |
+
|
1089 |
+
$data = array();
|
1090 |
+
while ($row = $stmt->fetch()) {
|
1091 |
+
if (($row['use_config'] && $this->getStoreManageStock()) || (!$row['use_config'] && $row['manage_stock'])) {
|
1092 |
+
$data[$row['product_id']] = ($row['in_stock']) ? true : false;
|
1093 |
+
} else {
|
1094 |
+
$data[$row['product_id']] = true;
|
1095 |
+
}
|
1096 |
+
}
|
1097 |
+
|
1098 |
+
return $data;
|
1099 |
+
}
|
1100 |
+
|
1101 |
+
/**
|
1102 |
+
* Return the price information from the price index for the given products.
|
1103 |
+
*
|
1104 |
+
* @param $product_ids
|
1105 |
+
*
|
1106 |
+
* @return array
|
1107 |
+
*/
|
1108 |
+
protected function getPriceData($product_ids) {
|
1109 |
+
$stmt = $this->getConnection()->query(
|
1110 |
+
$this->getConnection()
|
1111 |
+
->select()
|
1112 |
+
->from(
|
1113 |
+
array('p' => $this->getTableName("catalog/product_index_price")),
|
1114 |
+
array(
|
1115 |
+
'product_id' => "p.entity_id",
|
1116 |
+
'price' => "p.price",
|
1117 |
+
'final_price' => "p.final_price",
|
1118 |
+
'min_price' => "p.min_price",
|
1119 |
+
'max_price' => "p.max_price"
|
1120 |
+
)
|
1121 |
+
)
|
1122 |
+
->where("p.website_id = ?", $this->getStore()->getWebsiteId())
|
1123 |
+
->where("p.customer_group_id = ?", Mage_Customer_Model_Group::NOT_LOGGED_IN_ID)
|
1124 |
+
->where("p.entity_id IN (?)", $product_ids)
|
1125 |
+
);
|
1126 |
+
|
1127 |
+
$data = array();
|
1128 |
+
while ($row = $stmt->fetch()) {
|
1129 |
+
$data[$row['product_id']] = $row;
|
1130 |
+
}
|
1131 |
+
|
1132 |
+
return $data;
|
1133 |
+
}
|
1134 |
+
|
1135 |
+
/**
|
1136 |
+
* Return the configurable price information (price markup for each value of each configurable
|
1137 |
+
* attribute) for the given configurable product IDs.
|
1138 |
+
*
|
1139 |
+
* @param $parent_ids
|
1140 |
+
*
|
1141 |
+
* @return array
|
1142 |
+
*/
|
1143 |
+
protected function getConfigurablePriceData($parent_ids) {
|
1144 |
+
$default_website_id = Mage::app()->getStore(Mage_Core_Model_Store::ADMIN_CODE)->getWebsiteId();
|
1145 |
+
$store_website_id = $this->getStore()->getWebsiteId();
|
1146 |
+
$sort_order = ($default_website_id > $store_website_id) ? Varien_Db_Select::SQL_ASC : Varien_Db_Select::SQL_DESC;
|
1147 |
+
|
1148 |
+
$stmt = $this->getConnection()->query(
|
1149 |
+
$this->getConnection()
|
1150 |
+
->select()
|
1151 |
+
->from(array("s" => $this->getTableName("catalog/product_super_attribute")), "")
|
1152 |
+
->join(array("a" => $this->getTableName("eav/attribute")), "s.attribute_id = a.attribute_id", "")
|
1153 |
+
->join(array("p" => $this->getTableName("catalog/product_super_attribute_pricing")), "s.product_super_attribute_id = p.product_super_attribute_id", "")
|
1154 |
+
->columns(array(
|
1155 |
+
"parent_id" => "s.product_id",
|
1156 |
+
"attribute_code" => "a.attribute_code",
|
1157 |
+
"attribute_value" => "p.value_index",
|
1158 |
+
"price_is_percent" => "p.is_percent",
|
1159 |
+
"price_value" => "p.pricing_value"
|
1160 |
+
))
|
1161 |
+
->where("s.product_id IN (?)", $parent_ids)
|
1162 |
+
->where("p.website_id IN (?)", array($default_website_id, $store_website_id))
|
1163 |
+
->order(array(
|
1164 |
+
"s.product_id " . Varien_Db_Select::SQL_ASC,
|
1165 |
+
"a.attribute_code " . Varien_Db_Select::SQL_ASC,
|
1166 |
+
"p.website_id " . $sort_order
|
1167 |
+
))
|
1168 |
+
->group(array("s.product_id", "a.attribute_code", "p.value_index"))
|
1169 |
+
);
|
1170 |
+
|
1171 |
+
$data = array();
|
1172 |
+
while ($row = $stmt->fetch()) {
|
1173 |
+
if (!isset($data[$row["parent_id"]])) {
|
1174 |
+
$data[$row["parent_id"]] = array();
|
1175 |
+
}
|
1176 |
+
if (!isset($data[$row["parent_id"]][$row["attribute_code"]])) {
|
1177 |
+
$data[$row["parent_id"]][$row["attribute_code"]] = array();
|
1178 |
+
}
|
1179 |
+
if (!isset($data[$row["parent_id"]][$row["attribute_code"]][$row["attribute_value"]])) {
|
1180 |
+
$data[$row["parent_id"]][$row["attribute_code"]][$row["attribute_value"]] = array(
|
1181 |
+
"is_percent" => ($row["price_is_percent"]) ? true : false,
|
1182 |
+
"value" => $row["price_value"]
|
1183 |
+
);
|
1184 |
+
}
|
1185 |
+
}
|
1186 |
+
|
1187 |
+
return $data;
|
1188 |
+
}
|
1189 |
+
|
1190 |
+
/**
|
1191 |
+
* Return a map of Klevu attributes to Magento attributes.
|
1192 |
+
*
|
1193 |
+
* @return array
|
1194 |
+
*/
|
1195 |
+
protected function getAttributeMap() {
|
1196 |
+
if (!$this->hasData('attribute_map')) {
|
1197 |
+
$attribute_map = array();
|
1198 |
+
|
1199 |
+
$automatic_attributes = $this->getAutomaticAttributes();
|
1200 |
+
$attribute_map = $this->prepareAttributeMap($attribute_map, $automatic_attributes);
|
1201 |
+
|
1202 |
+
$additional_attributes = Mage::helper('klevu_search/config')->getAdditionalAttributesMap($this->getStore());
|
1203 |
+
$attribute_map = $this->prepareAttributeMap($attribute_map, $additional_attributes);
|
1204 |
+
|
1205 |
+
|
1206 |
+
// Add otherAttributeToIndex to $attribute_map.
|
1207 |
+
$otherAttributeToIndex = Mage::helper('klevu_search/config')->getOtherAttributesToIndex($this->getStore());
|
1208 |
+
if(!empty($otherAttributeToIndex)) {
|
1209 |
+
$attribute_map['otherAttributeToIndex'] = $otherAttributeToIndex;
|
1210 |
+
}
|
1211 |
+
// Add boostingAttribute to $attribute_map.
|
1212 |
+
if(($boosting_attribute = Mage::helper('klevu_search/config')->getBoostingAttribute($this->getStore())) && !is_null($boosting_attribute)) {
|
1213 |
+
$attribute_map['boostingAttribute'][] = $boosting_attribute;
|
1214 |
+
}
|
1215 |
+
|
1216 |
+
$this->setData('attribute_map', $attribute_map);
|
1217 |
+
}
|
1218 |
+
|
1219 |
+
return $this->getData('attribute_map');
|
1220 |
+
}
|
1221 |
+
|
1222 |
+
/**
|
1223 |
+
* Returns an array of all automatically matched attributes. Includes defaults and filterable in search attributes.
|
1224 |
+
* @return array
|
1225 |
+
*/
|
1226 |
+
public function getAutomaticAttributes() {
|
1227 |
+
if(!$this->hasData('automatic_attributes')) {
|
1228 |
+
// Default mapped attributes
|
1229 |
+
$default_attributes = Mage::helper('klevu_search/config')->getDefaultMappedAttributes();
|
1230 |
+
$attributes = array();
|
1231 |
+
for($i = 0; $i < count($default_attributes['klevu_attribute']); $i++) {
|
1232 |
+
$attributes[] = array(
|
1233 |
+
'klevu_attribute' => $default_attributes['klevu_attribute'][$i],
|
1234 |
+
'magento_attribute' => $default_attributes['magento_attribute'][$i]
|
1235 |
+
);
|
1236 |
+
}
|
1237 |
+
|
1238 |
+
// Get all layered navigation / filterable in search attributes
|
1239 |
+
foreach($this->getLayeredNavigationAttributes() as $layeredAttribute) {
|
1240 |
+
$attributes[] = array (
|
1241 |
+
'klevu_attribute' => 'other',
|
1242 |
+
'magento_attribute' => $layeredAttribute
|
1243 |
+
);
|
1244 |
+
}
|
1245 |
+
|
1246 |
+
$this->setData('automatic_attributes', $attributes);
|
1247 |
+
// Update the store system config with the updated automatic attributes map.
|
1248 |
+
Mage::helper('klevu_search/config')->setAutomaticAttributesMap($attributes, $this->getStore());
|
1249 |
+
}
|
1250 |
+
|
1251 |
+
return $this->getData('automatic_attributes');
|
1252 |
+
}
|
1253 |
+
|
1254 |
+
/**
|
1255 |
+
* Takes system configuration attribute data and adds to $attribute_map
|
1256 |
+
* @param $attribute_map
|
1257 |
+
* @param $additional_attributes
|
1258 |
+
* @return array
|
1259 |
+
*/
|
1260 |
+
protected function prepareAttributeMap($attribute_map, $additional_attributes) {
|
1261 |
+
|
1262 |
+
foreach ($additional_attributes as $mapping) {
|
1263 |
+
if (!isset($attribute_map[$mapping['klevu_attribute']])) {
|
1264 |
+
$attribute_map[$mapping['klevu_attribute']] = array();
|
1265 |
+
}
|
1266 |
+
$attribute_map[$mapping['klevu_attribute']][] = $mapping['magento_attribute'];
|
1267 |
+
}
|
1268 |
+
return $attribute_map;
|
1269 |
+
}
|
1270 |
+
|
1271 |
+
/**
|
1272 |
+
* Return the attribute codes for all filterable in search attributes.
|
1273 |
+
* @return array
|
1274 |
+
*/
|
1275 |
+
protected function getLayeredNavigationAttributes() {
|
1276 |
+
$attributes = Mage::helper('klevu_search/config')->getDefaultMappedAttributes();
|
1277 |
+
$select = $this->getConnection()
|
1278 |
+
->select()
|
1279 |
+
->from(
|
1280 |
+
array("a" => $this->getTableName("eav/attribute")),
|
1281 |
+
array("attribute" => "a.attribute_code")
|
1282 |
+
)
|
1283 |
+
->join(
|
1284 |
+
array("ca" => $this->getTableName("catalog/eav_attribute")),
|
1285 |
+
"ca.attribute_id = a.attribute_id",
|
1286 |
+
""
|
1287 |
+
)
|
1288 |
+
// Only if the attribute is filterable in search, i.e. attribute appears in search layered navigation.
|
1289 |
+
->where("ca.is_filterable_in_search = ?", "1")
|
1290 |
+
// Make sure we exclude the attributes thar synced by default.
|
1291 |
+
->where("a.attribute_code NOT IN(?)", array_unique($attributes['magento_attribute']))
|
1292 |
+
->group(array("attribute_code"));
|
1293 |
+
|
1294 |
+
return $this->getConnection()->fetchCol($select);
|
1295 |
+
}
|
1296 |
+
|
1297 |
+
/**
|
1298 |
+
* Return the attribute codes for all attributes currently used in
|
1299 |
+
* configurable products.
|
1300 |
+
*
|
1301 |
+
* @return array
|
1302 |
+
*/
|
1303 |
+
protected function getConfigurableAttributes() {
|
1304 |
+
$select = $this->getConnection()
|
1305 |
+
->select()
|
1306 |
+
->from(
|
1307 |
+
array("a" => $this->getTableName("eav/attribute")),
|
1308 |
+
array("attribute" => "a.attribute_code")
|
1309 |
+
)
|
1310 |
+
->join(
|
1311 |
+
array("s" => $this->getTableName("catalog/product_super_attribute")),
|
1312 |
+
"a.attribute_id = s.attribute_id",
|
1313 |
+
""
|
1314 |
+
)
|
1315 |
+
->group(array("a.attribute_code"));
|
1316 |
+
|
1317 |
+
return $this->getConnection()->fetchCol($select);
|
1318 |
+
}
|
1319 |
+
|
1320 |
+
/**
|
1321 |
+
* Return a list of all Magento attributes that are used by Product Sync
|
1322 |
+
* when collecting product data.
|
1323 |
+
*
|
1324 |
+
* @return array
|
1325 |
+
*/
|
1326 |
+
protected function getUsedMagentoAttributes() {
|
1327 |
+
$result = array();
|
1328 |
+
|
1329 |
+
foreach ($this->getAttributeMap() as $attributes) {
|
1330 |
+
$result = array_merge($result, $attributes);
|
1331 |
+
}
|
1332 |
+
|
1333 |
+
$result = array_merge($result, $this->getConfigurableAttributes());
|
1334 |
+
|
1335 |
+
return array_unique($result);
|
1336 |
+
}
|
1337 |
+
|
1338 |
+
/**
|
1339 |
+
* Return an array of category paths for all the categories in the
|
1340 |
+
* current store, not including the store root.
|
1341 |
+
*
|
1342 |
+
* @return array A list of category paths where each key is a category
|
1343 |
+
* ID and each value is an array of category names for
|
1344 |
+
* each category in the path, the last element being the
|
1345 |
+
* name of the category referenced by the ID.
|
1346 |
+
*/
|
1347 |
+
protected function getCategoryPaths() {
|
1348 |
+
if (!$category_paths = $this->getData('category_paths')) {
|
1349 |
+
$category_paths = array();
|
1350 |
+
$rootId = $this->getStore()->getRootCategoryId();
|
1351 |
+
$collection = Mage::getResourceModel('catalog/category_collection')
|
1352 |
+
->setStoreId($this->getStore()->getId())
|
1353 |
+
->addFieldToFilter('level', array('gt' => 1))
|
1354 |
+
->addFieldToFilter('path', array('like'=> "1/$rootId/%"))
|
1355 |
+
->addNameToResult();
|
1356 |
+
|
1357 |
+
foreach ($collection as $category) {
|
1358 |
+
$category_paths[$category->getId()] = array();
|
1359 |
+
|
1360 |
+
$path_ids = $category->getPathIds();
|
1361 |
+
foreach ($path_ids as $id) {
|
1362 |
+
if ($item = $collection->getItemById($id)) {
|
1363 |
+
$category_paths[$category->getId()][] = $item->getName();
|
1364 |
+
}
|
1365 |
+
}
|
1366 |
+
}
|
1367 |
+
|
1368 |
+
$this->setData('category_paths', $category_paths);
|
1369 |
+
}
|
1370 |
+
|
1371 |
+
return $category_paths;
|
1372 |
+
}
|
1373 |
+
|
1374 |
+
/**
|
1375 |
+
* Return a list of the names of all the categories in the
|
1376 |
+
* paths of the given categories (including the given categories)
|
1377 |
+
* up to, but not including the store root.
|
1378 |
+
*
|
1379 |
+
* @param array $categories
|
1380 |
+
*
|
1381 |
+
* @return array
|
1382 |
+
*/
|
1383 |
+
protected function getCategoryNames(array $categories) {
|
1384 |
+
$category_paths = $this->getCategoryPaths();
|
1385 |
+
|
1386 |
+
$result = array();
|
1387 |
+
foreach ($categories as $category) {
|
1388 |
+
if (isset($category_paths[$category])) {
|
1389 |
+
$result = array_merge($result, $category_paths[$category]);
|
1390 |
+
}
|
1391 |
+
}
|
1392 |
+
|
1393 |
+
return array_unique($result);
|
1394 |
+
}
|
1395 |
+
|
1396 |
+
/**
|
1397 |
+
* Given a list of category IDs, return the name of the category
|
1398 |
+
* in that list that has the longest path.
|
1399 |
+
*
|
1400 |
+
* @param array $categories
|
1401 |
+
*
|
1402 |
+
* @return string
|
1403 |
+
*/
|
1404 |
+
protected function getLongestPathCategoryName(array $categories) {
|
1405 |
+
$category_paths = $this->getCategoryPaths();
|
1406 |
+
|
1407 |
+
$length = 0;
|
1408 |
+
$name = "";
|
1409 |
+
foreach ($categories as $id) {
|
1410 |
+
if (isset($category_paths[$id])) {
|
1411 |
+
if (count($category_paths[$id]) > $length) {
|
1412 |
+
$length = count($category_paths[$id]);
|
1413 |
+
$name = end($category_paths[$id]);
|
1414 |
+
}
|
1415 |
+
}
|
1416 |
+
}
|
1417 |
+
|
1418 |
+
return $name;
|
1419 |
+
}
|
1420 |
+
|
1421 |
+
/**
|
1422 |
+
* Returns either array containing the label and value(s) of an attribute, or just the given value
|
1423 |
+
*
|
1424 |
+
* In the case that there are multiple options selected, all values are returned
|
1425 |
+
*
|
1426 |
+
* @param string $code
|
1427 |
+
* @param null $value
|
1428 |
+
*
|
1429 |
+
* @return array|string
|
1430 |
+
*/
|
1431 |
+
protected function getAttributeData($code, $value = null) {
|
1432 |
+
if (!$attribute_data = $this->getData('attribute_data')) {
|
1433 |
+
$attribute_data = array();
|
1434 |
+
|
1435 |
+
$collection = Mage::getResourceModel('catalog/product_attribute_collection')
|
1436 |
+
->addFieldToFilter('attribute_code', array('in' => $this->getUsedMagentoAttributes()));
|
1437 |
+
|
1438 |
+
foreach ($collection as $attr) {
|
1439 |
+
$attr->setStoreId($this->getStore()->getId());
|
1440 |
+
$attribute_data[$attr->getAttributeCode()] = array(
|
1441 |
+
'label' => $attr->getFrontendLabel(),
|
1442 |
+
'values' => ''
|
1443 |
+
);
|
1444 |
+
|
1445 |
+
if ($attr->usesSource()) {
|
1446 |
+
// $attribute_data[$attr->getAttributeCode()] = array();
|
1447 |
+
foreach($attr->getSource()->getAllOptions(false) as $option) {
|
1448 |
+
if (is_array($option['value'])) {
|
1449 |
+
foreach ($option['value'] as $sub_option) {
|
1450 |
+
if (strlen($sub_option)) {
|
1451 |
+
$attribute_data[$attr->getAttributeCode()]['values'][$sub_option['value']] = $sub_option['label'];
|
1452 |
+
}
|
1453 |
+
}
|
1454 |
+
} else {
|
1455 |
+
$attribute_data[$attr->getAttributeCode()]['values'][$option['value']] = $option['label'];
|
1456 |
+
}
|
1457 |
+
}
|
1458 |
+
}
|
1459 |
+
}
|
1460 |
+
|
1461 |
+
$this->setData('attribute_data', $attribute_data);
|
1462 |
+
}
|
1463 |
+
|
1464 |
+
// make sure the attribute exists
|
1465 |
+
if (isset($attribute_data[$code])) {
|
1466 |
+
// was $value passed a parameter?
|
1467 |
+
if (!is_null($value)) {
|
1468 |
+
// If not values are set on attribute_data for the attribute, return just the value passed. (attributes like: name, description etc)
|
1469 |
+
if(empty($attribute_data[$code]['values'])) {
|
1470 |
+
return $value;
|
1471 |
+
}
|
1472 |
+
// break up our value into an array by a comma, this is for catching multiple select attributes.
|
1473 |
+
$values = explode(",", $value);
|
1474 |
+
|
1475 |
+
// loop over our array of attribute values
|
1476 |
+
foreach ($values as $key => $valueOption) {
|
1477 |
+
// if there is a value on the attribute_data use that value (it will be the label for a dropdown select attribute)
|
1478 |
+
if (isset($attribute_data[$code]['values'][$valueOption])) {
|
1479 |
+
$values[$key] = $attribute_data[$code]['values'][$valueOption];
|
1480 |
+
} else { // If no label was found, log an error and unset the value.
|
1481 |
+
Mage::helper('klevu_search')->log(Zend_Log::WARN, sprintf("Attribute: %s option label was not found, option ID provided: %s", $code, $valueOption));
|
1482 |
+
unset($values[$key]);
|
1483 |
+
}
|
1484 |
+
}
|
1485 |
+
|
1486 |
+
// If there was only one value in the array, return the first (select menu, single option), or if there was more, return them all (multi-select).
|
1487 |
+
if (count($values) == 1) {
|
1488 |
+
$attribute_data[$code]['values'] = $values[0];
|
1489 |
+
} else {
|
1490 |
+
$attribute_data[$code]['values'] = $values;
|
1491 |
+
}
|
1492 |
+
|
1493 |
+
}
|
1494 |
+
return $attribute_data[$code];
|
1495 |
+
}
|
1496 |
+
|
1497 |
+
$result['label'] = $code;
|
1498 |
+
$result['values'] = $value;
|
1499 |
+
return $result;
|
1500 |
+
}
|
1501 |
+
|
1502 |
+
/**
|
1503 |
+
* Apply tax to the given price, if needed, remove if not.
|
1504 |
+
*
|
1505 |
+
* @param float $price
|
1506 |
+
* @param int $tax_class_id The tax class to use.
|
1507 |
+
*
|
1508 |
+
* @return float
|
1509 |
+
*/
|
1510 |
+
protected function applyTax($price, $tax_class_id) {
|
1511 |
+
if ($this->usePriceInclTax()) {
|
1512 |
+
if (!$this->priceIncludesTax()) {
|
1513 |
+
// We need to include tax in the price
|
1514 |
+
$price += $this->calcTaxAmount($price, $tax_class_id, false);
|
1515 |
+
}
|
1516 |
+
} else {
|
1517 |
+
if ($this->priceIncludesTax()) {
|
1518 |
+
// Price includes tax, but we don't need it
|
1519 |
+
$price -= $this->calcTaxAmount($price, $tax_class_id, true);
|
1520 |
+
}
|
1521 |
+
}
|
1522 |
+
|
1523 |
+
return $price;
|
1524 |
+
}
|
1525 |
+
|
1526 |
+
/**
|
1527 |
+
* Calculate the amount of tax on the given price.
|
1528 |
+
*
|
1529 |
+
* @param $price
|
1530 |
+
* @param $tax_class_id
|
1531 |
+
* @param bool $price_includes_tax
|
1532 |
+
*
|
1533 |
+
* @return float
|
1534 |
+
*/
|
1535 |
+
protected function calcTaxAmount($price, $tax_class_id, $price_includes_tax = false) {
|
1536 |
+
$calc = Mage::getSingleton("tax/calculation");
|
1537 |
+
|
1538 |
+
if (!$tax_rates = $this->getData("tax_rates")) {
|
1539 |
+
// Get tax rates for the default destination
|
1540 |
+
$tax_rates = $calc->getRatesForAllProductTaxClasses($calc->getRateOriginRequest($this->getStore()));
|
1541 |
+
$this->setData("tax_rates", $tax_rates);
|
1542 |
+
}
|
1543 |
+
|
1544 |
+
if (isset($tax_rates[$tax_class_id])) {
|
1545 |
+
return $calc->calcTaxAmount($price, $tax_rates[$tax_class_id], $price_includes_tax);
|
1546 |
+
}
|
1547 |
+
|
1548 |
+
return 0.0;
|
1549 |
+
}
|
1550 |
+
|
1551 |
+
/**
|
1552 |
+
* Convert the given price into the current store currency.
|
1553 |
+
*
|
1554 |
+
* @param $price
|
1555 |
+
*
|
1556 |
+
* @return float
|
1557 |
+
*/
|
1558 |
+
protected function convertPrice($price) {
|
1559 |
+
return $this->getStore()->convertPrice($price, false);
|
1560 |
+
}
|
1561 |
+
|
1562 |
+
/**
|
1563 |
+
* Process the given product price for using in Product Sync.
|
1564 |
+
* Applies tax, if needed, and converts to the currency of the current store.
|
1565 |
+
*
|
1566 |
+
* @param $price
|
1567 |
+
* @param $tax_class_id
|
1568 |
+
* @param product object
|
1569 |
+
*
|
1570 |
+
* @return float
|
1571 |
+
*/
|
1572 |
+
protected function processPrice($price, $tax_class_id, $pro) {
|
1573 |
+
if($price < 0){$price = 0;}else{$price = $price;}
|
1574 |
+
$config = Mage::helper('klevu_search/config');
|
1575 |
+
if($config->isTaxEnabled($this->getStore()->getId())) {
|
1576 |
+
return $this->convertPrice(Mage::helper("tax")->getPrice($pro, $price, true, null, null, null, $this->getStore(),false));
|
1577 |
+
} else {
|
1578 |
+
return $this->convertPrice($price);
|
1579 |
+
}
|
1580 |
+
}
|
1581 |
+
|
1582 |
+
/**
|
1583 |
+
* Return the "Manage Stock" flag for the current store.
|
1584 |
+
*
|
1585 |
+
* @return int
|
1586 |
+
*/
|
1587 |
+
protected function getStoreManageStock() {
|
1588 |
+
if (!$this->hasData('store_manage_stock')) {
|
1589 |
+
$this->setData('store_manage_stock', intval(Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK, $this->getStore())));
|
1590 |
+
}
|
1591 |
+
|
1592 |
+
return $this->getData('store_manage_stock');
|
1593 |
+
}
|
1594 |
+
|
1595 |
+
/**
|
1596 |
+
* Return the "Display Out of Stock Products".
|
1597 |
+
*
|
1598 |
+
* @return bool
|
1599 |
+
*/
|
1600 |
+
protected function getShowOutOfStock() {
|
1601 |
+
if (!$this->hasData('show_out_of_stock')) {
|
1602 |
+
$this->setData('show_out_of_stock', Mage::helper('cataloginventory')->isShowOutOfStock());
|
1603 |
+
}
|
1604 |
+
|
1605 |
+
return $this->getData('show_out_of_stock');
|
1606 |
+
}
|
1607 |
+
|
1608 |
+
/**
|
1609 |
+
* Check if the Test Mode is enabled for the current store.
|
1610 |
+
*
|
1611 |
+
* @return int 1 if Test Mode is enabled, 0 otherwise.
|
1612 |
+
*/
|
1613 |
+
protected function isTestModeEnabled() {
|
1614 |
+
if (!$this->hasData("test_mode_enabled")) {
|
1615 |
+
$test_mode = Mage::helper("klevu_search/config")->isTestModeEnabled($this->getStore());
|
1616 |
+
$test_mode = ($test_mode) ? 1 : 0;
|
1617 |
+
$this->setData("test_mode_enabled", $test_mode);
|
1618 |
+
}
|
1619 |
+
|
1620 |
+
return $this->getData("test_mode_enabled");
|
1621 |
+
}
|
1622 |
+
|
1623 |
+
/**
|
1624 |
+
* Check if product price includes tax for the current store.
|
1625 |
+
*
|
1626 |
+
* @return bool
|
1627 |
+
*/
|
1628 |
+
protected function priceIncludesTax() {
|
1629 |
+
if (!$this->hasData("price_includes_tax")) {
|
1630 |
+
$this->setData("price_includes_tax", Mage::getModel("tax/config")->priceIncludesTax($this->getStore()));
|
1631 |
+
}
|
1632 |
+
|
1633 |
+
return $this->getData("price_includes_tax");
|
1634 |
+
}
|
1635 |
+
|
1636 |
+
/**
|
1637 |
+
* Check if product prices should include tax when synced for the current store.
|
1638 |
+
*
|
1639 |
+
* @return bool
|
1640 |
+
*/
|
1641 |
+
protected function usePriceInclTax() {
|
1642 |
+
if (!$this->hasData("use_price_incl_tax")) {
|
1643 |
+
// Include tax in prices in all cases except when
|
1644 |
+
// catalog prices exclude tax
|
1645 |
+
$value = true;
|
1646 |
+
|
1647 |
+
if (Mage::getModel("tax/config")->getPriceDisplayType($this->getStore()) == Mage_Tax_Model_Config::DISPLAY_TYPE_EXCLUDING_TAX) {
|
1648 |
+
$value = false;
|
1649 |
+
}
|
1650 |
+
|
1651 |
+
$this->setData("use_price_incl_tax", $value);
|
1652 |
+
}
|
1653 |
+
|
1654 |
+
return $this->getData("use_price_incl_tax");
|
1655 |
+
}
|
1656 |
+
|
1657 |
+
/**
|
1658 |
+
* Remove any session specific data.
|
1659 |
+
*
|
1660 |
+
* @return $this
|
1661 |
+
*/
|
1662 |
+
protected function reset() {
|
1663 |
+
$this->unsetData('session_id');
|
1664 |
+
$this->unsetData('store');
|
1665 |
+
$this->unsetData('attribute_map');
|
1666 |
+
$this->unsetData('placeholder_image');
|
1667 |
+
$this->unsetData('category_paths');
|
1668 |
+
$this->unsetData('attribute_data');
|
1669 |
+
$this->unsetData('store_manage_stock');
|
1670 |
+
$this->unsetData('test_mode_enabled');
|
1671 |
+
$this->unsetData('tax_rates');
|
1672 |
+
$this->unsetData('price_includes_tax');
|
1673 |
+
$this->unsetData('use_price_incl_tax');
|
1674 |
+
|
1675 |
+
return $this;
|
1676 |
+
}
|
1677 |
+
|
1678 |
+
/**
|
1679 |
+
* Create an Adminhtml notification for Product Sync, overwriting any
|
1680 |
+
* existing ones. If a store is specified, creates a notification specific
|
1681 |
+
* to that store, separate from the main Product Sync notification.
|
1682 |
+
*
|
1683 |
+
* Overwrites any existing notifications for product sync.
|
1684 |
+
*
|
1685 |
+
* @param $message
|
1686 |
+
* @param Mage_Core_Model_Store|null $store
|
1687 |
+
*
|
1688 |
+
* @return $this
|
1689 |
+
*/
|
1690 |
+
protected function notify($message, $store = null) {
|
1691 |
+
$type = ($store === null) ? static::NOTIFICATION_GLOBAL_TYPE : static::NOTIFICATION_STORE_TYPE_PREFIX . $store->getId();
|
1692 |
+
|
1693 |
+
/** @var Klevu_Search_Model_Notification $notification */
|
1694 |
+
$notification = Mage::getResourceModel('klevu_search/notification_collection')
|
1695 |
+
->addFieldToFilter("type", array('eq' => $type))
|
1696 |
+
->getFirstItem();
|
1697 |
+
|
1698 |
+
$notification->addData(array(
|
1699 |
+
'type' => $type,
|
1700 |
+
'date' => Mage::getModel('core/date')->timestamp(),
|
1701 |
+
'message' => $message
|
1702 |
+
));
|
1703 |
+
|
1704 |
+
$notification->save();
|
1705 |
+
|
1706 |
+
return $this;
|
1707 |
+
}
|
1708 |
+
|
1709 |
+
/**
|
1710 |
+
* Delete Adminhtml notifications for Product Sync. If a store is specified,
|
1711 |
+
* deletes the notifications for the specific store.
|
1712 |
+
*
|
1713 |
+
* @param Mage_Core_Model_Store|null $store
|
1714 |
+
* @return $this
|
1715 |
+
*/
|
1716 |
+
protected function deleteNotifications($store = null) {
|
1717 |
+
$type = ($store === null) ? static::NOTIFICATION_GLOBAL_TYPE : static::NOTIFICATION_STORE_TYPE_PREFIX . $store->getId();
|
1718 |
+
|
1719 |
+
$this->getConnection()->delete($this->getTableName('klevu_search/notification'), array("type = ?" => $type));
|
1720 |
+
|
1721 |
+
return $this;
|
1722 |
+
}
|
1723 |
+
/**
|
1724 |
+
* Generate thumbnail for search through out the cron job
|
1725 |
+
* @return $this
|
1726 |
+
*/
|
1727 |
+
public function generateThumbParrallel()
|
1728 |
+
{
|
1729 |
+
try {
|
1730 |
+
Mage::helper("klevu_search")->log(Zend_Log::INFO, sprintf("Product thumbnail generation process is started."));
|
1731 |
+
$this->curlRequest();
|
1732 |
+
Mage::helper("klevu_search")->log(Zend_Log::INFO, sprintf("Product thumbnail generation process is completed successfully."));
|
1733 |
+
} catch(Exception $e) {
|
1734 |
+
Mage::log($e->getMessage(),null,'klevu_Search.log');
|
1735 |
+
}
|
1736 |
+
}
|
1737 |
+
/**
|
1738 |
+
* Generate Parrallel curl request
|
1739 |
+
* @return $this
|
1740 |
+
*/
|
1741 |
+
public function curlRequest()
|
1742 |
+
{
|
1743 |
+
$query = $this->getConnection()->select()
|
1744 |
+
->from($this->getTableName("klevu_search/image_thumb"), array('id'))
|
1745 |
+
->where('is_processed=?',0)
|
1746 |
+
->limit(4);
|
1747 |
+
$data = $query->query()->fetchAll();
|
1748 |
+
if(count($data) > 0) {
|
1749 |
+
$curl_multi_handle = curl_multi_init();
|
1750 |
+
foreach($data as $key => $value)
|
1751 |
+
{
|
1752 |
+
Mage::getModel('klevu_search/product_sync')->isBelowMemoryLimit();
|
1753 |
+
$url = Mage::getUrl("klevu/search/index",array("id" => $value['id']));
|
1754 |
+
$curl_array[$value['id']] = curl_init($url);
|
1755 |
+
curl_setopt($curl_array[$value['id']], CURLOPT_RETURNTRANSFER, true);
|
1756 |
+
//Add a normal cURL handle to a cURL multi handle
|
1757 |
+
curl_multi_add_handle($curl_multi_handle, $curl_array[$value['id']]);
|
1758 |
+
$running = NULL;
|
1759 |
+
do {
|
1760 |
+
//Run the sub-connections of the current cURL handle
|
1761 |
+
$mrc = curl_multi_exec($curl_multi_handle,$running);
|
1762 |
+
} while($running > 0) ;
|
1763 |
+
|
1764 |
+
}
|
1765 |
+
curl_multi_close($curl_multi_handle);
|
1766 |
+
}
|
1767 |
+
if(count($data) > 0 && $running==0) {
|
1768 |
+
$this->curlRequest();
|
1769 |
+
}
|
1770 |
+
}
|
1771 |
+
/**
|
1772 |
+
* Generate batch for thumbnail image
|
1773 |
+
* @param $image
|
1774 |
+
* @return $this
|
1775 |
+
*/
|
1776 |
+
|
1777 |
+
public function thumbImage($image)
|
1778 |
+
{
|
1779 |
+
$_imageUrl = Mage::getBaseDir('media').DS."catalog".DS."product".$image;
|
1780 |
+
$imageResized = Mage::getBaseDir('media').DS."klevu_images".$image;
|
1781 |
+
if(!file_exists($imageResized)&& file_exists($_imageUrl)) :
|
1782 |
+
$imageObj = new Varien_Image($_imageUrl);
|
1783 |
+
$imageObj->constrainOnly(TRUE);
|
1784 |
+
$imageObj->keepAspectRatio(TRUE);
|
1785 |
+
$imageObj->keepFrame(FALSE);
|
1786 |
+
$imageObj->resize(140, 140);
|
1787 |
+
$imageObj->save($imageResized);
|
1788 |
+
endif;
|
1789 |
+
}
|
1790 |
+
|
1791 |
+
/**
|
1792 |
+
* Create batch for thumbnail image
|
1793 |
+
* @return $this
|
1794 |
+
*/
|
1795 |
+
public function getEntityIds()
|
1796 |
+
{
|
1797 |
+
$this->getConnection()->delete($this->getTableName("klevu_search/image_thumb"));
|
1798 |
+
$select = $this->getConnection()->select()
|
1799 |
+
->from($this->getTableName("catalog_product_entity"), array('entity_id'));
|
1800 |
+
$data = $this->getConnection()->fetchAll($select);
|
1801 |
+
foreach ($data as $key => $value) {
|
1802 |
+
$entity_ids[] = $value['entity_id'];
|
1803 |
+
}
|
1804 |
+
$thum_batch = array_chunk($entity_ids,100);
|
1805 |
+
foreach($thum_batch as $key => $value)
|
1806 |
+
{
|
1807 |
+
$this->getConnection()->insert($this->getTableName('klevu_search/image_thumb'),
|
1808 |
+
array(
|
1809 |
+
'batchdata'=>serialize($value)
|
1810 |
+
));
|
1811 |
+
}
|
1812 |
+
}
|
1813 |
+
|
1814 |
+
/**
|
1815 |
+
* Get the batch which are not processed
|
1816 |
+
* @param $id
|
1817 |
+
* @return $this
|
1818 |
+
*/
|
1819 |
+
public function getImageProcessingIds($id)
|
1820 |
+
{
|
1821 |
+
$query = $this->getConnection()->select()
|
1822 |
+
->from($this->getTableName("klevu_search/image_thumb"), array('batchdata'))
|
1823 |
+
->where("id=:id AND is_processed=:is_processed")
|
1824 |
+
->bind(array(
|
1825 |
+
'id' => $id,
|
1826 |
+
'is_processed' => 0,
|
1827 |
+
));
|
1828 |
+
$data = $this->getConnection()->fetchAll($query, $query->getBind());
|
1829 |
+
return $data;
|
1830 |
+
}
|
1831 |
+
/**
|
1832 |
+
* Update the batch which are not processed
|
1833 |
+
* @param $id
|
1834 |
+
* @return $this
|
1835 |
+
*/
|
1836 |
+
public function updateImageProcessingIds($id)
|
1837 |
+
{
|
1838 |
+
$where = $this->getConnection()->quoteInto("id = ?", $id);
|
1839 |
+
$this->getConnection()->update(
|
1840 |
+
$this->getTableName('klevu_search/image_thumb'),
|
1841 |
+
array('is_processed' => '1'),
|
1842 |
+
$where
|
1843 |
+
);
|
1844 |
+
}
|
1845 |
+
|
1846 |
+
|
1847 |
+
/**
|
1848 |
+
* Get ida for debugs
|
1849 |
+
* @return $this
|
1850 |
+
*/
|
1851 |
+
public function debugsIds()
|
1852 |
+
{
|
1853 |
+
$select = $this->getConnection()->select()
|
1854 |
+
->from($this->getTableName("catalog_product_entity"), array('entity_id','updated_at'))->limit(500)->order('updated_at');
|
1855 |
+
$data = $this->getConnection()->fetchAll($select);
|
1856 |
+
return $data;
|
1857 |
+
}
|
1858 |
+
|
1859 |
+
/**
|
1860 |
+
* Get api for debugs
|
1861 |
+
* @return $this
|
1862 |
+
*/
|
1863 |
+
public function getApiDebug()
|
1864 |
+
{
|
1865 |
+
$configs = Mage::getModel('core/config_data')->getCollection()
|
1866 |
+
->addFieldToFilter('path', array("like" => "%rest_api_key%"))->load();
|
1867 |
+
$data = $configs->getData();
|
1868 |
+
return $data[0]['value'];
|
1869 |
+
}
|
1870 |
+
|
1871 |
+
/**
|
1872 |
+
* Run cron externally for debug using js api
|
1873 |
+
* @param $js_api
|
1874 |
+
* @return $this
|
1875 |
+
*/
|
1876 |
+
public function sheduleCronExteranally($rest_api) {
|
1877 |
+
$configs = Mage::getModel('core/config_data')->getCollection()
|
1878 |
+
->addFieldToFilter('value', array("like" => "%$rest_api%"))->load();
|
1879 |
+
$data = $configs->getData();
|
1880 |
+
if(!empty($data[0]['scope_id'])){
|
1881 |
+
$store = Mage::app()->getStore($data[0]['scope_id']);
|
1882 |
+
Mage::getModel('klevu_search/product_sync')
|
1883 |
+
->markAllProductsForUpdate($store)
|
1884 |
+
->schedule();
|
1885 |
+
}
|
1886 |
+
}
|
1887 |
+
/**
|
1888 |
+
* Schedule Image Cron Using Admin action
|
1889 |
+
* @return $this
|
1890 |
+
*/
|
1891 |
+
public function scheduleImageCron($time = "now") {
|
1892 |
+
if (! $time instanceof DateTime) {
|
1893 |
+
$time = new DateTime($time);
|
1894 |
+
} else {
|
1895 |
+
// Don't modify the original parameter
|
1896 |
+
$time = clone $time;
|
1897 |
+
}
|
1898 |
+
$time_str = $time->format("Y-m-d H:i:00");
|
1899 |
+
$before_str = $time->modify("15 minutes ago")->format("Y-m-d H:i:00");
|
1900 |
+
$after_str = $time->modify("30 minutes")->format("Y-m-d H:i:00"); // Modifying the same DateTime object, so it's -15 + 30 = +15 minutes
|
1901 |
+
|
1902 |
+
// Check if Product image cron is not already scheduled to run around (±15 minutes) that time
|
1903 |
+
$collection = Mage::getResourceModel('cron/schedule_collection')
|
1904 |
+
->addFieldToFilter("job_code", 'klevu_search_product_thumb')
|
1905 |
+
->addFieldToFilter("status", Mage_Cron_Model_Schedule::STATUS_PENDING)
|
1906 |
+
->addFieldToFilter("scheduled_at", array(
|
1907 |
+
"from" => $before_str,
|
1908 |
+
"to" => $after_str
|
1909 |
+
));
|
1910 |
+
|
1911 |
+
if ($collection->getSize() == 0) {
|
1912 |
+
$schedule = Mage::getModel('cron/schedule');
|
1913 |
+
$schedule
|
1914 |
+
->setJobCode('klevu_search_product_thumb')
|
1915 |
+
->setCreatedAt($time_str)
|
1916 |
+
->setScheduledAt($time_str)
|
1917 |
+
->setStatus(Mage_Cron_Model_Schedule::STATUS_PENDING)
|
1918 |
+
->save();
|
1919 |
+
}
|
1920 |
+
return $this;
|
1921 |
+
}
|
1922 |
+
|
1923 |
+
/**
|
1924 |
+
* Delete test mode data from product sync
|
1925 |
+
* @return $this
|
1926 |
+
*/
|
1927 |
+
public function deleteTestmodeData($store) {
|
1928 |
+
$condition = array("store_id"=> $store->getId());
|
1929 |
+
$this->getConnection()->delete($this->getTableName("klevu_search/product_sync"),$condition);
|
1930 |
+
}
|
1931 |
+
|
1932 |
+
/**
|
1933 |
+
* Exchange key and value for test mode
|
1934 |
+
* @return $this
|
1935 |
+
*/
|
1936 |
+
public function removeTestMode() {
|
1937 |
+
$stores = Mage::app()->getStores();
|
1938 |
+
foreach ($stores as $store) {
|
1939 |
+
$test_mode = Mage::helper("klevu_search/config")->isTestModeEnabled($store);
|
1940 |
+
if(Mage::helper('klevu_search/config')->isExtensionConfigured($store)) {
|
1941 |
+
if($test_mode){
|
1942 |
+
$final_test_rest_api = Mage::getStoreConfig('klevu_search/general/rest_api_key', $store);
|
1943 |
+
$final_rest_api = Mage::getStoreConfig('klevu_search/general/test_rest_api_key', $store);
|
1944 |
+
Mage::helper('klevu_search/config')->setStoreConfig('klevu_search/general/js_api_key', Mage::getStoreConfig('klevu_search/general/test_js_api_key', $store), $store);
|
1945 |
+
Mage::helper('klevu_search/config')->setStoreConfig('klevu_search/general/rest_api_key', Mage::getStoreConfig('klevu_search/general/test_rest_api_key', $store), $store);
|
1946 |
+
$test_hostname = Mage::getStoreConfig('klevu_search/general/test_hostname', $store);
|
1947 |
+
if(!empty($test_hostname)) {
|
1948 |
+
Mage::helper('klevu_search/config')->setStoreConfig('klevu_search/general/hostname', Mage::getStoreConfig('klevu_search/general/test_hostname', $store), $store);
|
1949 |
+
Mage::helper('klevu_search/config')->setStoreConfig('klevu_search/general/cloud_search_url', Mage::getStoreConfig('klevu_search/general/test_cloud_search_url', $store), $store);
|
1950 |
+
Mage::helper('klevu_search/config')->setStoreConfig('klevu_search/general/analytics_url', Mage::getStoreConfig('klevu_search/general/test_analytics_url', $store), $store);
|
1951 |
+
Mage::helper('klevu_search/config')->setStoreConfig('klevu_search/general/js_url', Mage::getStoreConfig('klevu_search/general/test_js_url', $store), $store);
|
1952 |
+
}
|
1953 |
+
Mage::helper("klevu_search/config")->setTestModeEnabledFlag(0, $store);
|
1954 |
+
//send responsce in kmc
|
1955 |
+
$response = Mage::getModel("klevu_search/api_action_removetestmode")->removeTestMode(array('liveRestApiKey'=>$final_rest_api,'testRestApiKey'=>$final_test_rest_api));
|
1956 |
+
if($response->getMessage()=="success") {
|
1957 |
+
$this->log(Zend_Log::INFO, $response->getMessage());
|
1958 |
+
}
|
1959 |
+
// delete prodcut entry for test mode
|
1960 |
+
Mage::getModel('klevu_search/product_sync')->deleteTestmodeData($store);
|
1961 |
+
//schedual cron for all prodcuts
|
1962 |
+
Mage::getModel('klevu_search/product_sync')
|
1963 |
+
->markAllProductsForUpdate($store)
|
1964 |
+
->schedule();
|
1965 |
+
}
|
1966 |
+
}
|
1967 |
+
}
|
1968 |
+
}
|
1969 |
+
}
|
app/code/community/Klevu/Search/Model/Resource/Notification.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Resource_Notification extends Mage_Core_Model_Mysql4_Abstract {
|
4 |
+
|
5 |
+
protected function _construct() {
|
6 |
+
$this->_init("klevu_search/notification", "id");
|
7 |
+
}
|
8 |
+
}
|
app/code/community/Klevu/Search/Model/Resource/Notification/Collection.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Resource_Notification_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract {
|
4 |
+
|
5 |
+
protected function _construct() {
|
6 |
+
$this->_init("klevu_search/notification");
|
7 |
+
}
|
8 |
+
}
|
app/code/community/Klevu/Search/Model/Session.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_Session extends Mage_Core_Model_Session {
|
4 |
+
|
5 |
+
public function __construct() {
|
6 |
+
$this->init('klevu_search');
|
7 |
+
}
|
8 |
+
}
|
app/code/community/Klevu/Search/Model/Sync.php
ADDED
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class Klevu_Search_Model_Sync extends Varien_Object {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Limit the memory usage of the sync to 80% of the memory
|
7 |
+
* limit. Considering that the minimum memory requirement
|
8 |
+
* for Magento at the time of writing is 256MB, this seems
|
9 |
+
* like a sensible default.
|
10 |
+
*/
|
11 |
+
const MEMORY_LIMIT = 0.8;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Return the cron job code used for the sync model.
|
15 |
+
*
|
16 |
+
* @return string
|
17 |
+
*/
|
18 |
+
abstract function getJobCode();
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Perform the sync.
|
22 |
+
*/
|
23 |
+
abstract function run();
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Run a sync from cron at the specified time. Checks that a cron is not already
|
27 |
+
* scheduled to run in the 15 minute interval before or after the given time first.
|
28 |
+
*
|
29 |
+
* @param DateTime|string $time The scheduled time as a DateTime object or a string
|
30 |
+
* that is going to be passed into DateTime. Default is "now".
|
31 |
+
*
|
32 |
+
* @return $this
|
33 |
+
*/
|
34 |
+
public function schedule($time = "now") {
|
35 |
+
if (! $time instanceof DateTime) {
|
36 |
+
$time = new DateTime($time);
|
37 |
+
} else {
|
38 |
+
// Don't modify the original parameter
|
39 |
+
$time = clone $time;
|
40 |
+
}
|
41 |
+
$time_str = $time->format("Y-m-d H:i:00");
|
42 |
+
$before_str = $time->modify("15 minutes ago")->format("Y-m-d H:i:00");
|
43 |
+
$after_str = $time->modify("30 minutes")->format("Y-m-d H:i:00"); // Modifying the same DateTime object, so it's -15 + 30 = +15 minutes
|
44 |
+
|
45 |
+
// Check if Product Sync is not already scheduled to run around (±15 minutes) that time
|
46 |
+
$collection = Mage::getResourceModel('cron/schedule_collection')
|
47 |
+
->addFieldToFilter("job_code", $this->getJobCode())
|
48 |
+
->addFieldToFilter("status", Mage_Cron_Model_Schedule::STATUS_PENDING)
|
49 |
+
->addFieldToFilter("scheduled_at", array(
|
50 |
+
"from" => $before_str,
|
51 |
+
"to" => $after_str
|
52 |
+
));
|
53 |
+
|
54 |
+
if ($collection->getSize() == 0) {
|
55 |
+
$schedule = Mage::getModel('cron/schedule');
|
56 |
+
$schedule
|
57 |
+
->setJobCode($this->getJobCode())
|
58 |
+
->setCreatedAt($time_str)
|
59 |
+
->setScheduledAt($time_str)
|
60 |
+
->setStatus(Mage_Cron_Model_Schedule::STATUS_PENDING)
|
61 |
+
->save();
|
62 |
+
}
|
63 |
+
|
64 |
+
return $this;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Check if a sync is currently running from cron. A number of running copies to
|
69 |
+
* check for can be specified, which is useful if checking if another copy of sync
|
70 |
+
* is running from sync itself.
|
71 |
+
*
|
72 |
+
* Ignores processes that have been running for more than an hour as they are likely
|
73 |
+
* to have crashed.
|
74 |
+
*
|
75 |
+
* @param int $copies
|
76 |
+
*
|
77 |
+
* @return bool
|
78 |
+
*/
|
79 |
+
public function isRunning($copies = 1) {
|
80 |
+
$time = new Datetime("1 hour ago");
|
81 |
+
$time = $time->format("Y-m-d H:i:00");
|
82 |
+
|
83 |
+
$collection = Mage::getResourceModel('cron/schedule_collection')
|
84 |
+
->addFieldToFilter("job_code", $this->getJobCode())
|
85 |
+
->addFieldToFilter("status", Mage_Cron_Model_Schedule::STATUS_RUNNING)
|
86 |
+
->addFieldToFilter("executed_at", array("gteq" => $time));
|
87 |
+
|
88 |
+
return $collection->getSize() >= $copies;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Check if the current memory usage is below the limit.
|
93 |
+
*
|
94 |
+
* @return bool
|
95 |
+
*/
|
96 |
+
protected function isBelowMemoryLimit() {
|
97 |
+
$helper = Mage::helper('klevu_search');
|
98 |
+
|
99 |
+
$limit = $helper->humanReadableToBytes(ini_get('memory_limit'));
|
100 |
+
$usage = memory_get_usage(true);
|
101 |
+
|
102 |
+
$this->log(Zend_Log::DEBUG, sprintf(
|
103 |
+
"Memory usage: %s of %s.",
|
104 |
+
$helper->bytesToHumanReadable($usage),
|
105 |
+
$helper->bytesToHumanReadable($limit)
|
106 |
+
));
|
107 |
+
|
108 |
+
if ($usage / $limit > static::MEMORY_LIMIT) {
|
109 |
+
return false;
|
110 |
+
} else {
|
111 |
+
return true;
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Check if the memory limit has been reached and reschedule to run
|
117 |
+
* again immediately if so.
|
118 |
+
*
|
119 |
+
* @return bool true if a new process was scheduled, false otherwise.
|
120 |
+
*/
|
121 |
+
protected function rescheduleIfOutOfMemory() {
|
122 |
+
if (!$this->isBelowMemoryLimit()) {
|
123 |
+
$this->log(Zend_Log::INFO, "Memory limit reached. Stopped and rescheduled.");
|
124 |
+
$this->schedule();
|
125 |
+
|
126 |
+
return true;
|
127 |
+
}
|
128 |
+
|
129 |
+
return false;
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Return the table name for the given model entity.
|
134 |
+
*
|
135 |
+
* @param string $entity
|
136 |
+
*
|
137 |
+
* @return string
|
138 |
+
*/
|
139 |
+
protected function getTableName($entity) {
|
140 |
+
return Mage::getModel('core/resource')->getTableName($entity);
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Write a message to the log file.
|
145 |
+
*
|
146 |
+
* @param int $level
|
147 |
+
* @param string $message
|
148 |
+
*
|
149 |
+
* @return $this
|
150 |
+
*/
|
151 |
+
protected function log($level, $message) {
|
152 |
+
Mage::helper('klevu_search')->log($level, sprintf("[%s] %s", $this->getJobCode(), $message));
|
153 |
+
|
154 |
+
return $this;
|
155 |
+
}
|
156 |
+
}
|
app/code/community/Klevu/Search/Model/System/Config/Source/Additional/Attributes.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_System_Config_Source_Additional_Attributes {
|
4 |
+
|
5 |
+
public function toOptionArray() {
|
6 |
+
$helper = Mage::helper('klevu_search');
|
7 |
+
|
8 |
+
return array(
|
9 |
+
array('value' => "brand", 'label' => $helper->__("Brand")),
|
10 |
+
array('value' => "model", 'label' => $helper->__("Model")),
|
11 |
+
array('value' => "color", 'label' => $helper->__("Color")),
|
12 |
+
array('value' => "size" , 'label' => $helper->__("Size"))
|
13 |
+
);
|
14 |
+
}
|
15 |
+
}
|
app/code/community/Klevu/Search/Model/System/Config/Source/Boosting/Attribute.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_System_Config_Source_Boosting_Attribute {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Fetch all integer and decimal attributes and return in as options array.
|
7 |
+
*
|
8 |
+
* @return array
|
9 |
+
*/
|
10 |
+
public function toOptionArray() {
|
11 |
+
$attributes = $this->getAttributeCollection();
|
12 |
+
$options = array(
|
13 |
+
array(
|
14 |
+
'value' => null,
|
15 |
+
'label' => '--- No Attribute Selected ---'
|
16 |
+
)
|
17 |
+
);
|
18 |
+
foreach($attributes as $attribute) {
|
19 |
+
/** @var Mage_Catalog_Model_Resource_Eav_Attribute $attribute */
|
20 |
+
$options[] = array(
|
21 |
+
'value' => $attribute->getAttributeCode(),
|
22 |
+
'label' => $attribute->getAttributeCode()
|
23 |
+
);
|
24 |
+
}
|
25 |
+
|
26 |
+
return $options;
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Get only integer and decimal attributes that are not used by Klevu yet.
|
31 |
+
*
|
32 |
+
* @return Mage_Catalog_Model_Resource_Product_Attribute_Collection
|
33 |
+
*/
|
34 |
+
protected function getAttributeCollection() {
|
35 |
+
/** @var Mage_Catalog_Model_Resource_Product_Attribute_Collection $collection */
|
36 |
+
$collection = Mage::getResourceModel('catalog/product_attribute_collection');
|
37 |
+
|
38 |
+
// We only want integers and decimal attributes.
|
39 |
+
$collection->addFieldToFilter(
|
40 |
+
'backend_type',
|
41 |
+
array(
|
42 |
+
'in' => array(
|
43 |
+
'int',
|
44 |
+
'decimal',
|
45 |
+
'varchar'
|
46 |
+
)
|
47 |
+
)
|
48 |
+
);
|
49 |
+
|
50 |
+
$attributes = Mage::helper('klevu_search/config')->getDefaultMappedAttributes();
|
51 |
+
|
52 |
+
// Exclude attributes used by default (only default int/decimal attributes)
|
53 |
+
$collection->addFieldToFilter(
|
54 |
+
'attribute_code',
|
55 |
+
array(
|
56 |
+
'nin' => array_unique($attributes['magento_attribute'])
|
57 |
+
)
|
58 |
+
);
|
59 |
+
|
60 |
+
return $collection;
|
61 |
+
}
|
62 |
+
}
|
app/code/community/Klevu/Search/Model/System/Config/Source/Frequency.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_System_Config_Source_Frequency {
|
4 |
+
|
5 |
+
const CRON_HOURLY = "0 * * * *";
|
6 |
+
const CRON_EVERY_3_HOURS = "0 */3 * * *";
|
7 |
+
const CRON_EVERY_6_HOURS = "0 */6 * * *";
|
8 |
+
const CRON_EVERY_12_HOURS = "0 */12 * * *";
|
9 |
+
const CRON_DAILY = "0 3 * * *";
|
10 |
+
|
11 |
+
public function toOptionArray() {
|
12 |
+
$helper = Mage::helper("klevu_search");
|
13 |
+
|
14 |
+
return array(
|
15 |
+
array(
|
16 |
+
'label' => $helper->__("Hourly"),
|
17 |
+
'value' => static::CRON_HOURLY
|
18 |
+
),
|
19 |
+
array(
|
20 |
+
'label' => $helper->__("Every %s hours", 3),
|
21 |
+
'value' => static::CRON_EVERY_3_HOURS
|
22 |
+
),
|
23 |
+
array(
|
24 |
+
'label' => $helper->__("Every %s hours", 6),
|
25 |
+
'value' => static::CRON_EVERY_6_HOURS
|
26 |
+
),
|
27 |
+
array(
|
28 |
+
'label' => $helper->__("Every %s hours", 12),
|
29 |
+
'value' => static::CRON_EVERY_12_HOURS
|
30 |
+
),
|
31 |
+
array(
|
32 |
+
'label' => $helper->__("Daily"),
|
33 |
+
'value' => static::CRON_DAILY
|
34 |
+
),
|
35 |
+
);
|
36 |
+
}
|
37 |
+
}
|
app/code/community/Klevu/Search/Model/System/Config/Source/Landingoptions.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_System_Config_Source_Landingoptions {
|
4 |
+
|
5 |
+
const YES = 1;
|
6 |
+
const NO = 0;
|
7 |
+
const KlEVULAND = 2;
|
8 |
+
|
9 |
+
public function toOptionArray() {
|
10 |
+
$helper = Mage::helper("klevu_search");
|
11 |
+
|
12 |
+
return array(
|
13 |
+
array('value' => static::NO, 'label' => $helper->__("Disable")),
|
14 |
+
array('value' => static::KlEVULAND, 'label' => $helper->__("Based on Klevu Template (Recommended)")),
|
15 |
+
array('value' => static::YES, 'label' => $helper->__("Preserves Your Theme Layout**"))
|
16 |
+
|
17 |
+
);
|
18 |
+
}
|
19 |
+
}
|
app/code/community/Klevu/Search/Model/System/Config/Source/Log/Level.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_System_Config_Source_Log_Level {
|
4 |
+
|
5 |
+
public function toOptionArray() {
|
6 |
+
$helper = Mage::helper('klevu_search');
|
7 |
+
|
8 |
+
return array(
|
9 |
+
array('value' => Zend_Log::EMERG, 'label' => $helper->__("Emergency")),
|
10 |
+
array('value' => Zend_Log::ALERT, 'label' => $helper->__("Alert")),
|
11 |
+
array('value' => Zend_Log::CRIT, 'label' => $helper->__("Critical")),
|
12 |
+
array('value' => Zend_Log::ERR, 'label' => $helper->__("Error")),
|
13 |
+
array('value' => Zend_Log::WARN, 'label' => $helper->__("Warning")),
|
14 |
+
array('value' => Zend_Log::NOTICE, 'label' => $helper->__("Notice")),
|
15 |
+
array('value' => Zend_Log::INFO, 'label' => $helper->__("Information")),
|
16 |
+
array('value' => Zend_Log::DEBUG, 'label' => $helper->__("Debug"))
|
17 |
+
);
|
18 |
+
}
|
19 |
+
}
|
app/code/community/Klevu/Search/Model/System/Config/Source/Product/Attributes.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_System_Config_Source_Product_Attributes {
|
4 |
+
|
5 |
+
public function toOptionArray() {
|
6 |
+
$options = array();
|
7 |
+
|
8 |
+
$attributes = $this->getAttributeCollection();
|
9 |
+
foreach ($attributes as $attribute) {
|
10 |
+
/** @var Mage_Catalog_Model_Resource_Eav_Attribute $attribute */
|
11 |
+
$options[] = array(
|
12 |
+
'value' => $attribute->getAttributeCode(),
|
13 |
+
'label' => $attribute->getAttributeCode()
|
14 |
+
);
|
15 |
+
}
|
16 |
+
|
17 |
+
return $options;
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Return a product attribute collection.
|
22 |
+
*
|
23 |
+
* @return Mage_Catalog_Model_Resource_Product_Attribute_Collection
|
24 |
+
*/
|
25 |
+
protected function getAttributeCollection() {
|
26 |
+
/** @var Mage_Catalog_Model_Resource_Product_Attribute_Collection $collection */
|
27 |
+
$collection = Mage::getResourceModel('catalog/product_attribute_collection');
|
28 |
+
// Filter out attributes mapped by default
|
29 |
+
$attributes = Mage::helper('klevu_search/config')->getDefaultMappedAttributes();
|
30 |
+
$collection->addFieldToFilter('attribute_code', array(
|
31 |
+
'nin' => array_unique($attributes['magento_attribute'])
|
32 |
+
));
|
33 |
+
|
34 |
+
return $collection;
|
35 |
+
}
|
36 |
+
}
|
app/code/community/Klevu/Search/Model/System/Config/Source/Yesnoforced.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Model_System_Config_Source_Yesnoforced {
|
4 |
+
|
5 |
+
const YES = 1;
|
6 |
+
const NO = 0;
|
7 |
+
const FORCED = 2;
|
8 |
+
|
9 |
+
public function toOptionArray() {
|
10 |
+
$helper = Mage::helper("klevu_search");
|
11 |
+
|
12 |
+
return array(
|
13 |
+
array('value' => static::YES, 'label' => $helper->__("Yes")),
|
14 |
+
array('value' => static::NO, 'label' => $helper->__("No"))
|
15 |
+
// array('value' => static::FORCED, 'label' => $helper->__("Forced"))
|
16 |
+
);
|
17 |
+
}
|
18 |
+
}
|
app/code/community/Klevu/Search/Test/Config/Base.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Config_Base extends EcomDev_PHPUnit_Test_Case_Config {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
*/
|
8 |
+
public function testClassAlias() {
|
9 |
+
$this->assertBlockAlias("klevu_search/test", "Klevu_Search_Block_Test");
|
10 |
+
$this->assertHelperAlias("klevu_search/test", "Klevu_Search_Helper_Test");
|
11 |
+
$this->assertModelAlias("klevu_search/test", "Klevu_Search_Model_Test");
|
12 |
+
}
|
13 |
+
}
|
app/code/community/Klevu/Search/Test/Controller/CatalogSearch.php
ADDED
@@ -0,0 +1,342 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Controller_CatalogSearch extends EcomDev_PHPUnit_Test_Case_Controller {
|
4 |
+
|
5 |
+
/** @var Klevu_Search_Model_CatalogSearch_Resource_Fulltext_Collection */
|
6 |
+
protected $collection;
|
7 |
+
|
8 |
+
protected function tearDown() {
|
9 |
+
$this->getLayout()->reset();
|
10 |
+
$this->collection = null;
|
11 |
+
Mage::unregister('_singleton/catalogsearch/layer');
|
12 |
+
Mage::unregister('current_layer');
|
13 |
+
Mage::unregister('current_category_filter');
|
14 |
+
|
15 |
+
// Delete all products
|
16 |
+
Mage::getResourceModel('catalog/product_collection')->delete();
|
17 |
+
|
18 |
+
parent::tearDown();
|
19 |
+
}
|
20 |
+
|
21 |
+
protected function setUp() {
|
22 |
+
$this->getLayout()->reset();
|
23 |
+
// Make sure the 'price' attribute is set to is_filterable_in_search
|
24 |
+
$price = $this->getPriceAttribute();
|
25 |
+
$price->setData('is_filterable_in_search', 1);
|
26 |
+
$price->save();
|
27 |
+
|
28 |
+
parent::setUp();
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Run search and make sure the page returns HTTP Code 200
|
33 |
+
* @test
|
34 |
+
* @loadFixture search_results
|
35 |
+
*/
|
36 |
+
public function testSearchResultsPageLoads() {
|
37 |
+
$this->mockAndDispatchSearchResults();
|
38 |
+
// Assert the request was successful.
|
39 |
+
$this->assertResponseHttpCode(200);
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Run search and make sure the layered navigation and search result list block appears
|
44 |
+
* @test
|
45 |
+
* @loadFixture search_results
|
46 |
+
*/
|
47 |
+
public function testExpectedLayoutBlocksAreRendered() {
|
48 |
+
$this->mockAndDispatchSearchResults();
|
49 |
+
// Assert that the left nav (layered navigation) and the search results have been rendered.
|
50 |
+
$this->assertLayoutBlockRendered('catalogsearch.leftnav');
|
51 |
+
$this->assertLayoutBlockRendered('search_result_list');
|
52 |
+
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Run search and check that category and price filters exist
|
57 |
+
* @test
|
58 |
+
* @loadFixture search_results
|
59 |
+
*/
|
60 |
+
public function testLayeredNavigationHasFilters() {
|
61 |
+
$this->mockAndDispatchSearchResults();
|
62 |
+
|
63 |
+
// Load the layered navigation block
|
64 |
+
/** @var Klevu_Search_Block_CatalogSearch_Layer $layer_nav */
|
65 |
+
$layer_nav = $this->app()->getLayout()->getBlock('catalogsearch.leftnav');// Get the category filter block and assert it isn't null.
|
66 |
+
$category_filters_block = $layer_nav->getChild('category_filter');
|
67 |
+
$this->assertNotNull($category_filters_block);
|
68 |
+
|
69 |
+
// Get the category filter items and assert that there was one filter item returned, and it's the category "Shirts"
|
70 |
+
$category_filters = $category_filters_block->getItems();
|
71 |
+
$this->assertCount(1, $category_filters);
|
72 |
+
$this->assertEquals('Test Category', $category_filters[0]->getData('label'));
|
73 |
+
|
74 |
+
$price_filters_block = $layer_nav->getChild('price_filter');
|
75 |
+
$this->assertNotFalse($price_filters_block);
|
76 |
+
|
77 |
+
// Check the price filters are as we expect
|
78 |
+
$price_filters = $price_filters_block->getItems();
|
79 |
+
$this->assertCount(2, $price_filters);
|
80 |
+
$this->assertEquals('0-49', $price_filters[0]->getData('value'));
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Run search and check the results are correct, and in the expected order
|
85 |
+
* @test
|
86 |
+
* @loadFixture search_results
|
87 |
+
*/
|
88 |
+
public function testSearchResultsAreCorrect() {
|
89 |
+
$this->mockApiAndCollection();
|
90 |
+
$collection = $this->collection;
|
91 |
+
// Assert that the number of results is correct.
|
92 |
+
$this->assertEquals(3, $collection->getSize());
|
93 |
+
|
94 |
+
// Assert that the results are in the expected order.
|
95 |
+
$expected_product_ids = array(3,2,1);
|
96 |
+
$actual_product_ids = array();
|
97 |
+
/** @var Mage_Catalog_Model_Product $product */
|
98 |
+
foreach($collection as $product) {
|
99 |
+
$actual_product_ids[] = $product->getId();
|
100 |
+
}
|
101 |
+
|
102 |
+
$this->assertEquals($expected_product_ids, $actual_product_ids);
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Test that a category filter can be applied
|
107 |
+
* @test
|
108 |
+
* @loadFixture search_results
|
109 |
+
*/
|
110 |
+
public function testSearchCategoryFilterIsApplied() {
|
111 |
+
$this->app()->getRequest()->setQuery('cat', '3');
|
112 |
+
$this->mockAndDispatchSearchResults();
|
113 |
+
|
114 |
+
$this->assertCount(1, $this->getAppliedFilters()); // We expect only 1 applied filter.
|
115 |
+
$this->assertEquals("Test Category", $this->getFirstAppliedFilter()->getData('label'));
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Test that a price filter can be applied
|
120 |
+
* @test
|
121 |
+
* @loadFixture search_results
|
122 |
+
*/
|
123 |
+
public function testSearchPriceFilterIsApplied() {
|
124 |
+
$this->app()->getRequest()->setQuery('price', '0-49');
|
125 |
+
$this->mockAndDispatchSearchResults();
|
126 |
+
|
127 |
+
$this->assertCount(1, $this->getAppliedFilters()); // We expect only 1 applied filter.
|
128 |
+
$this->assertEquals(array('0', '49'), $this->getFirstAppliedFilter()->getData('value'));
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Test that both the price and category filter can be applied at the same time
|
133 |
+
* @test
|
134 |
+
* @loadFixture search_results
|
135 |
+
*/
|
136 |
+
public function testMultipleFiltersCanBeApplied() {
|
137 |
+
$this->app()->getRequest()->setQuery(array('price' => '0-49', 'cat' => '3'));
|
138 |
+
$this->mockAndDispatchSearchResults();
|
139 |
+
|
140 |
+
$this->assertCount(2, $this->getAppliedFilters()); // We expect 2 applied filters.
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Test that we can change the sort order so results are in descending order of Price.
|
145 |
+
* @test
|
146 |
+
* @loadFixture search_results
|
147 |
+
*/
|
148 |
+
public function testChangingSortOrderToPriceDesc() {
|
149 |
+
$this->app()->getRequest()->setQuery(array('dir' => 'desc', 'order' => 'price'));
|
150 |
+
$this->mockAndDispatchSearchResults('shirt', 'sorted');
|
151 |
+
$result_block = $this->getSearchResultsBlock();
|
152 |
+
// Set the updated mock collection
|
153 |
+
$result_block->setCollection($this->collection);
|
154 |
+
|
155 |
+
/** @var Klevu_Search_Model_CatalogSearch_Resource_Fulltext_Collection $product_collection */
|
156 |
+
$product_collection = $result_block->getLoadedProductCollection();
|
157 |
+
|
158 |
+
// Expected order of results
|
159 |
+
$expected_product_ids = array(2, 1, 3);
|
160 |
+
$actual_product_ids = array();
|
161 |
+
/** @var Mage_Catalog_Model_Product $product */
|
162 |
+
foreach($product_collection as $product) {
|
163 |
+
$actual_product_ids[] = $product->getId();
|
164 |
+
}
|
165 |
+
$this->assertEquals($expected_product_ids, $actual_product_ids, 'Products are in the wrong order');
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Test that we can access the 2nd page of results and that the expected products show.
|
170 |
+
* @test
|
171 |
+
* @loadFixture search_results
|
172 |
+
*/
|
173 |
+
public function testSecondPageOfResultsExists() {
|
174 |
+
// Default: page size = 9, set the page to page 2, meaning we expect to see results from 10+
|
175 |
+
$this->getRequest()->setQuery('p', '2');
|
176 |
+
// Our response will return the 10th product, our response contains a total result size of 10.
|
177 |
+
$this->mockAndDispatchSearchResults('shirt', 'paged', 9);
|
178 |
+
|
179 |
+
$result_block = $this->getSearchResultsBlock();
|
180 |
+
$result_block->setCollection($this->collection);
|
181 |
+
$toolbar = $result_block->getToolbarBlock();
|
182 |
+
|
183 |
+
$toolbar->setCollection($this->collection);
|
184 |
+
|
185 |
+
//Assert that we can see the 10th item, out of 10 results.
|
186 |
+
$pager_text = version_compare(Mage::getVersion(), "1.9", ">=") ? '10-10 of 10' : 'Items 10 to 10 of 10 total';
|
187 |
+
$this->assertContains($pager_text, $toolbar->toHtml());
|
188 |
+
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Test that when we perform a search which does not return results, the no results message is displayed.
|
193 |
+
* @test
|
194 |
+
* @loadFixture search_results
|
195 |
+
*/
|
196 |
+
public function testNoResults() {
|
197 |
+
$this->mockAndDispatchSearchResults('returnsnothing', 'empty');
|
198 |
+
|
199 |
+
$result_block = $this->getSearchResultsBlock();
|
200 |
+
$result_block->setCollection($this->collection);
|
201 |
+
$result_html = $result_block->toHtml();
|
202 |
+
|
203 |
+
$this->assertContains('There are no products matching the selection.', $result_html);
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Return the search result list block
|
208 |
+
* @return Mage_Catalog_Block_Product_List
|
209 |
+
*/
|
210 |
+
protected function getSearchResultsBlock() {
|
211 |
+
return $this->app()->getLayout()->getBlock('search_result_list');
|
212 |
+
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Get all applied filters
|
216 |
+
* @return array
|
217 |
+
*/
|
218 |
+
protected function getAppliedFilters() {
|
219 |
+
|
220 |
+
/** @var Klevu_Search_Block_CatalogSearch_Layer $layer_nav */
|
221 |
+
$layer_nav = $this->app()->getLayout()->getBlock('catalogsearch.leftnav');
|
222 |
+
return $layer_nav->getLayer()->getState()->getFilters();
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Fetch the first applied filter
|
227 |
+
* @return Mage_Catalog_Model_Layer_Filter_Item
|
228 |
+
*/
|
229 |
+
protected function getFirstAppliedFilter() {
|
230 |
+
$filters = $this->getAppliedFilters();
|
231 |
+
return $filters[0];
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* @param string $query
|
236 |
+
* @return $this
|
237 |
+
* @throws Zend_Controller_Exception
|
238 |
+
*/
|
239 |
+
protected function mockAndDispatchSearchResults($query = 'shirt', $response_type = 'successful', $pagination = 0) {
|
240 |
+
$this->mockApiAndCollection($query, $response_type, $pagination);
|
241 |
+
// Set the search query
|
242 |
+
$this->getRequest()->setQuery('q', $query);
|
243 |
+
|
244 |
+
// Load the search results page
|
245 |
+
return $this->dispatch('catalogsearch/result/index');
|
246 |
+
}
|
247 |
+
|
248 |
+
protected function mockApiAndCollection($query = 'shirt', $response_type = 'successful', $pagination = 0) {
|
249 |
+
// Mock the API Action
|
250 |
+
switch($response_type) {
|
251 |
+
default:
|
252 |
+
case 'successful':
|
253 |
+
$response = $this->getSearchResponse('search_response_success.xml');
|
254 |
+
break;
|
255 |
+
case 'empty':
|
256 |
+
$response = $this->getSearchResponse('search_response_empty.xml');
|
257 |
+
break;
|
258 |
+
case 'sorted':
|
259 |
+
$response = $this->getSearchResponse('search_response_sorted.xml');
|
260 |
+
break;
|
261 |
+
case 'paged':
|
262 |
+
$response = $this->getSearchResponse('search_response_paged.xml');
|
263 |
+
break;
|
264 |
+
}
|
265 |
+
|
266 |
+
$this->replaceApiActionByMock("klevu_search/api_action_idsearch", $response);
|
267 |
+
|
268 |
+
$return_value = array(
|
269 |
+
'ticket' => 'some-api-key',
|
270 |
+
'noOfResults' => 9,
|
271 |
+
'term' => $query,
|
272 |
+
'paginationStartsFrom' => $pagination,
|
273 |
+
'klevuSort' => 'rel',
|
274 |
+
'enableFilters' => 'true',
|
275 |
+
'filterResults' => '',
|
276 |
+
);
|
277 |
+
|
278 |
+
// Mock the klevu search resource collection model, and force the search filters data
|
279 |
+
$this->collection = $this->getResourceModelMock('catalogsearch/fulltext_collection', array('getSearchFilters'));
|
280 |
+
$this->collection->expects($this->any())
|
281 |
+
->method('getSearchFilters')
|
282 |
+
->will($this->returnValue($return_value));
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Create a mock class of the given API action model which will expect to be executed
|
287 |
+
* once and will return the given response. Then replace that model in Magento with
|
288 |
+
* the created mock.
|
289 |
+
*
|
290 |
+
* @param string $alias A grouped class name of the API action model to mock
|
291 |
+
* @param Klevu_Search_Model_Api_Response $response
|
292 |
+
*
|
293 |
+
* @return $this
|
294 |
+
*/
|
295 |
+
protected function replaceApiActionByMock($alias, $response) {
|
296 |
+
$mock = $this->getModelMock($alias, array("execute"));
|
297 |
+
$mock
|
298 |
+
->expects($this->any())
|
299 |
+
->method("execute")
|
300 |
+
->will($this->returnValue($response));
|
301 |
+
|
302 |
+
$this->replaceByMock("model", $alias, $mock);
|
303 |
+
|
304 |
+
|
305 |
+
|
306 |
+
return $this;
|
307 |
+
}
|
308 |
+
|
309 |
+
/**
|
310 |
+
* Return a klevu_search/api_response_message model with a successful response from
|
311 |
+
* a startSession API call.
|
312 |
+
*
|
313 |
+
* @return Klevu_Search_Model_Api_Response_Message
|
314 |
+
*/
|
315 |
+
protected function getSearchResponse($data_file) {
|
316 |
+
$model = Mage::getModel('klevu_search/api_response_search')->setRawResponse(
|
317 |
+
new Zend_Http_Response(200, array(), $this->getDataFileContents($data_file))
|
318 |
+
);
|
319 |
+
|
320 |
+
return $model;
|
321 |
+
|
322 |
+
}
|
323 |
+
|
324 |
+
protected function getDataFileContents($file) {
|
325 |
+
$directory_tree = array(
|
326 |
+
Mage::getModuleDir('', 'Klevu_Search'),
|
327 |
+
'Test',
|
328 |
+
'Model',
|
329 |
+
'Api',
|
330 |
+
'data',
|
331 |
+
$file
|
332 |
+
);
|
333 |
+
|
334 |
+
$file_path = join(DS, $directory_tree);
|
335 |
+
|
336 |
+
return file_get_contents($file_path);
|
337 |
+
}
|
338 |
+
|
339 |
+
protected function getPriceAttribute() {
|
340 |
+
return Mage::getModel('eav/entity_attribute')->loadByCode(Mage_Catalog_Model_Product::ENTITY, 'price');
|
341 |
+
}
|
342 |
+
}
|
app/code/community/Klevu/Search/Test/Controller/CatalogSearch/fixtures/search_results.yaml
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 1
|
3 |
+
default/klevu_search/general/test_mode: 1
|
4 |
+
default/klevu_search/general/test_rest_api_key: test-api-key
|
5 |
+
default/klevu_search/general/test_js_api_key: test-api-key
|
6 |
+
default/klevu_search/product_sync/enabled: 2
|
7 |
+
default/catalog/frontend/grid_per_page_values: 9,15,30
|
8 |
+
default/catalog/frontend/grid_per_page: 9
|
9 |
+
eav:
|
10 |
+
catalog_category:
|
11 |
+
- entity_id: 3
|
12 |
+
parent_id: 2
|
13 |
+
path: 1/2/3
|
14 |
+
position: 2
|
15 |
+
level: 2
|
16 |
+
children_count: 0
|
17 |
+
name: Test Category
|
18 |
+
url_key: test-category
|
19 |
+
is_active: 1
|
20 |
+
is_anchor: 0
|
21 |
+
display_mode: PRODUCTS
|
22 |
+
include_in_menu: 1
|
23 |
+
catalog_product:
|
24 |
+
- entity_id: 1
|
25 |
+
attribute_set_id: 4
|
26 |
+
type_id: simple
|
27 |
+
sku: example1
|
28 |
+
name: Example 1
|
29 |
+
short_description: Example short description
|
30 |
+
description: Example description
|
31 |
+
url_key: example-1
|
32 |
+
weight: null
|
33 |
+
stock:
|
34 |
+
qty: 100.00
|
35 |
+
is_in_stock: 1
|
36 |
+
website_ids:
|
37 |
+
- base # Default website
|
38 |
+
category_ids:
|
39 |
+
- 3 # Default category
|
40 |
+
price: 34
|
41 |
+
tax_class_id: 2
|
42 |
+
status: 1
|
43 |
+
visibility: 4
|
44 |
+
created_at: 2007-08-29 19:56:27
|
45 |
+
updated_at: 2008-06-28 01:57:22
|
46 |
+
- entity_id: 2
|
47 |
+
attribute_set_id: 4
|
48 |
+
type_id: simple
|
49 |
+
sku: example2
|
50 |
+
name: Example 2
|
51 |
+
short_description: Example short description
|
52 |
+
description: Example description
|
53 |
+
url_key: example-2
|
54 |
+
weight: null
|
55 |
+
stock:
|
56 |
+
qty: 100.00
|
57 |
+
is_in_stock: 1
|
58 |
+
website_ids:
|
59 |
+
- base # Default website
|
60 |
+
category_ids:
|
61 |
+
- 3 # Default category
|
62 |
+
price: 34
|
63 |
+
tax_class_id: 2
|
64 |
+
status: 1
|
65 |
+
visibility: 4
|
66 |
+
created_at: 2007-08-29 19:56:27
|
67 |
+
updated_at: 2008-06-28 01:57:22
|
68 |
+
- entity_id: 3
|
69 |
+
attribute_set_id: 4
|
70 |
+
type_id: simple
|
71 |
+
sku: example3
|
72 |
+
name: Example 3
|
73 |
+
short_description: Example short description
|
74 |
+
description: Example description
|
75 |
+
url_key: example-3
|
76 |
+
weight: null
|
77 |
+
stock:
|
78 |
+
qty: 100.00
|
79 |
+
is_in_stock: 1
|
80 |
+
website_ids:
|
81 |
+
- base # Default website
|
82 |
+
category_ids:
|
83 |
+
- 3 # Default category
|
84 |
+
price: 34
|
85 |
+
tax_class_id: 2
|
86 |
+
status: 1
|
87 |
+
visibility: 4
|
88 |
+
created_at: 2007-08-29 19:56:27
|
89 |
+
updated_at: 2008-06-28 01:57:22
|
90 |
+
- entity_id: 10
|
91 |
+
attribute_set_id: 4
|
92 |
+
type_id: simple
|
93 |
+
sku: example10
|
94 |
+
name: Example 10
|
95 |
+
short_description: Example short description
|
96 |
+
description: Example description
|
97 |
+
url_key: example-10
|
98 |
+
weight: null
|
99 |
+
stock:
|
100 |
+
qty: 100.00
|
101 |
+
is_in_stock: 1
|
102 |
+
website_ids:
|
103 |
+
- base # Default website
|
104 |
+
category_ids:
|
105 |
+
- 3 # Default category
|
106 |
+
price: 34
|
107 |
+
tax_class_id: 2
|
108 |
+
status: 1
|
109 |
+
visibility: 4
|
110 |
+
created_at: 2007-08-29 19:56:27
|
111 |
+
updated_at: 2008-06-28 01:57:22
|
112 |
+
- entity_id: 11
|
113 |
+
attribute_set_id: 4
|
114 |
+
type_id: simple
|
115 |
+
sku: example11
|
116 |
+
name: Example 11
|
117 |
+
short_description: Example short description
|
118 |
+
description: Example description
|
119 |
+
url_key: example-11
|
120 |
+
weight: null
|
121 |
+
stock:
|
122 |
+
qty: 100.00
|
123 |
+
is_in_stock: 1
|
124 |
+
website_ids:
|
125 |
+
- base # Default website
|
126 |
+
category_ids:
|
127 |
+
- 3 # Default category
|
128 |
+
price: 34
|
129 |
+
tax_class_id: 2
|
130 |
+
status: 1
|
131 |
+
visibility: 4
|
132 |
+
created_at: 2007-08-29 19:56:27
|
133 |
+
updated_at: 2008-06-28 01:57:22
|
app/code/community/Klevu/Search/Test/Helper/Api.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Klevu_Search_Test_Helper_Api extends EcomDev_PHPUnit_Test_Case {
|
3 |
+
|
4 |
+
const VERSION_NUMBER = '1.1.2';
|
5 |
+
|
6 |
+
public function testGetVersion() {
|
7 |
+
$version = Mage::getConfig()->getModuleConfig('Klevu_Search')->version;
|
8 |
+
$this->assertEquals(self::VERSION_NUMBER, $version);
|
9 |
+
}
|
10 |
+
}
|
app/code/community/Klevu/Search/Test/Helper/Compat.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Helper_Compat extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
/** @var Klevu_Search_Helper_Compat $helper */
|
6 |
+
protected $helper;
|
7 |
+
|
8 |
+
protected function setUp() {
|
9 |
+
parent::setUp();
|
10 |
+
|
11 |
+
$this->helper = Mage::helper("klevu_search/compat");
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @test
|
16 |
+
*/
|
17 |
+
public function testGetProductUrlRewriteSelect() {
|
18 |
+
$this->assertInstanceOf("Varien_Db_Select", $this->helper->getProductUrlRewriteSelect(array(1), 0, 1));
|
19 |
+
}
|
20 |
+
}
|
app/code/community/Klevu/Search/Test/Helper/Config.php
ADDED
@@ -0,0 +1,345 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Helper_Config extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
/** @var Klevu_Search_Helper_Config $helper */
|
6 |
+
protected $helper;
|
7 |
+
|
8 |
+
protected function setUp() {
|
9 |
+
parent::setUp();
|
10 |
+
|
11 |
+
$this->helper = Mage::helper("klevu_search/config");
|
12 |
+
}
|
13 |
+
|
14 |
+
protected function tearDown() {
|
15 |
+
$this->getConfig()->deleteConfig("klevu_search/general/enabled");
|
16 |
+
$this->getConfig()->deleteConfig("klevu_search/general/test_mode");
|
17 |
+
$this->getConfig()->deleteConfig("klevu_search/general/js_api_key");
|
18 |
+
$this->getConfig()->deleteConfig("klevu_search/general/rest_api_key");
|
19 |
+
$this->getConfig()->deleteConfig("klevu_search/general/test_js_api_key");
|
20 |
+
$this->getConfig()->deleteConfig("klevu_search/general/test_rest_api_key");
|
21 |
+
$this->getConfig()->deleteConfig("klevu_search/product_sync/enabled");
|
22 |
+
$this->getConfig()->deleteConfig("klevu_search/product_sync/frequency");
|
23 |
+
$this->getConfig()->deleteConfig("klevu_search/attributes/additional");
|
24 |
+
$this->getConfig()->deleteConfig("klevu_search/order_sync/enabled");
|
25 |
+
$this->getConfig()->deleteConfig("klevu_search/order_sync/frequency");
|
26 |
+
$this->getConfig()->deleteConfig("klevu_search/developer/force_log");
|
27 |
+
$this->getConfig()->deleteConfig("klevu_search/developer/log_level");
|
28 |
+
|
29 |
+
parent::tearDown();
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @test
|
34 |
+
* @loadFixture
|
35 |
+
*/
|
36 |
+
public function testIsExtensionEnabledEnabled() {
|
37 |
+
$this->assertEquals(true, $this->helper->isExtensionEnabled());
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @test
|
42 |
+
* @loadFixture
|
43 |
+
*/
|
44 |
+
public function testIsExtensionEnabledDisabled() {
|
45 |
+
$this->assertEquals(false, $this->helper->isExtensionEnabled());
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @test
|
50 |
+
*/
|
51 |
+
public function testGetTestModeEnabledFlag() {
|
52 |
+
$this->assertEquals(false, $this->helper->getTestModeEnabledFlag(),
|
53 |
+
"Failed asserting that Test Mode flag is disabled by default."
|
54 |
+
);
|
55 |
+
|
56 |
+
$this->getConfig()
|
57 |
+
->saveConfig("klevu_search/general/test_mode", 1)
|
58 |
+
->cleanCache();
|
59 |
+
|
60 |
+
$this->clearConfigCache();
|
61 |
+
|
62 |
+
$this->assertEquals(true, $this->helper->getTestModeEnabledFlag(),
|
63 |
+
"Failed asserting that Test Mode flag returns true when Test Mode is enabled in the config."
|
64 |
+
);
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* @test
|
69 |
+
* @dataProvider dataProvider
|
70 |
+
*/
|
71 |
+
public function testIsTestModeEnabled($test_mode, $is_production_domain, $result) {
|
72 |
+
$this->getConfig()
|
73 |
+
->saveConfig("klevu_search/general/test_mode", $test_mode)
|
74 |
+
->cleanCache();
|
75 |
+
|
76 |
+
$this->clearConfigCache();
|
77 |
+
|
78 |
+
$this->mockIsProductionDomain($is_production_domain);
|
79 |
+
|
80 |
+
$this->assertEquals($result, $this->helper->isTestModeEnabled());
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @test
|
85 |
+
*/
|
86 |
+
public function testGetJsApiKeyProduction() {
|
87 |
+
$api_key = "test-js-api-key";
|
88 |
+
|
89 |
+
$this->mockIsProductionDomain(true);
|
90 |
+
|
91 |
+
$this->assertEquals(null, $this->helper->getJsApiKey());
|
92 |
+
|
93 |
+
$this->getConfig()
|
94 |
+
->saveConfig("klevu_search/general/js_api_key", $api_key)
|
95 |
+
->cleanCache();
|
96 |
+
|
97 |
+
$this->clearConfigCache();
|
98 |
+
|
99 |
+
$this->assertEquals($api_key, $this->helper->getJsApiKey());
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* @test
|
104 |
+
*/
|
105 |
+
public function testGetJsApiKeyStaging() {
|
106 |
+
$api_key = "test-js-api-key";
|
107 |
+
|
108 |
+
$this->mockIsProductionDomain(false);
|
109 |
+
|
110 |
+
$this->assertEquals(null, $this->helper->getJsApiKey());
|
111 |
+
|
112 |
+
$this->getConfig()
|
113 |
+
->saveConfig("klevu_search/general/test_js_api_key", $api_key)
|
114 |
+
->cleanCache();
|
115 |
+
|
116 |
+
$this->clearConfigCache();
|
117 |
+
|
118 |
+
$this->assertEquals($api_key, $this->helper->getJsApiKey());
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* @test
|
123 |
+
*/
|
124 |
+
public function testGetRestApiKeyProduction() {
|
125 |
+
$api_key = "test-rest-api-key";
|
126 |
+
|
127 |
+
$this->mockIsProductionDomain(true);
|
128 |
+
|
129 |
+
$this->assertEquals(null, $this->helper->getRestApiKey());
|
130 |
+
|
131 |
+
$this->getConfig()
|
132 |
+
->saveConfig("klevu_search/general/rest_api_key", $api_key)
|
133 |
+
->cleanCache();
|
134 |
+
|
135 |
+
$this->clearConfigCache();
|
136 |
+
|
137 |
+
$this->assertEquals($api_key, $this->helper->getRestApiKey());
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* @test
|
142 |
+
*/
|
143 |
+
public function testGetRestApiKeyStaging() {
|
144 |
+
$api_key = "test-rest-api-key";
|
145 |
+
|
146 |
+
$this->mockIsProductionDomain(false);
|
147 |
+
|
148 |
+
$this->assertEquals(null, $this->helper->getRestApiKey());
|
149 |
+
|
150 |
+
$this->getConfig()
|
151 |
+
->saveConfig("klevu_search/general/test_rest_api_key", $api_key)
|
152 |
+
->cleanCache();
|
153 |
+
|
154 |
+
$this->clearConfigCache();
|
155 |
+
|
156 |
+
$this->assertEquals($api_key, $this->helper->getRestApiKey());
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* @test
|
161 |
+
*/
|
162 |
+
public function testGetProductSyncEnabledFlagDefault() {
|
163 |
+
$this->assertEquals(2, $this->helper->getProductSyncEnabledFlag());
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* @test
|
168 |
+
* @loadFixture
|
169 |
+
*/
|
170 |
+
public function testGetProductSyncEnabledFlag() {
|
171 |
+
$this->assertEquals(2, $this->helper->getProductSyncEnabledFlag());
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* @test
|
176 |
+
* @dataProvider dataProvider
|
177 |
+
*/
|
178 |
+
public function testIsProductSyncEnabled($is_production_domain, $config_flag, $result) {
|
179 |
+
$data_helper = $this->getHelperMock('klevu_search', array("isProductionDomain"));
|
180 |
+
$data_helper
|
181 |
+
->expects($this->once())
|
182 |
+
->method("isProductionDomain")
|
183 |
+
->will($this->returnValue($is_production_domain));
|
184 |
+
$this->replaceByMock("helper", "klevu_search", $data_helper);
|
185 |
+
|
186 |
+
$this->clearConfigCache();
|
187 |
+
|
188 |
+
$this->getConfig()
|
189 |
+
->saveConfig("klevu_search/product_sync/enabled", $config_flag)
|
190 |
+
->cleanCache();
|
191 |
+
|
192 |
+
$this->assertEquals($result, $this->helper->isProductSyncEnabled());
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* @test
|
197 |
+
*/
|
198 |
+
public function testGetProductSyncFrequencyDefault() {
|
199 |
+
$this->assertEquals("0 * * * *", $this->helper->getProductSyncFrequency());
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* @test
|
204 |
+
* @loadFixture
|
205 |
+
*/
|
206 |
+
public function testGetProductSyncFrequency() {
|
207 |
+
$this->assertEquals("0 */5 * * *", $this->helper->getProductSyncFrequency());
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* @test
|
212 |
+
*/
|
213 |
+
public function testGetAdditionalAttributesMap() {
|
214 |
+
$map = array(
|
215 |
+
"_1" => array("klevu_attribute" => "k_test", "magento_attribute" => "m_test"),
|
216 |
+
"_2" => array("klevu_attribute" => "k_other", "magento_attribute" => "m_something")
|
217 |
+
);
|
218 |
+
|
219 |
+
// Test the default value
|
220 |
+
$this->assertEquals(array(), $this->helper->getAdditionalAttributesMap(), "getAdditionalAttributesMap() did not default to an empty array.");
|
221 |
+
|
222 |
+
$this->getConfig()
|
223 |
+
->saveConfig("klevu_search/attributes/additional", serialize($map))
|
224 |
+
->reinit();
|
225 |
+
|
226 |
+
$this->assertEquals($map, $this->helper->getAdditionalAttributesMap(), "getAdditionalAttributesMap() failed to return the map set.");
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* @test
|
231 |
+
*/
|
232 |
+
public function testGetOrderSyncEnabledFlagDefault() {
|
233 |
+
$this->assertEquals(1, $this->helper->getOrderSyncEnabledFlag());
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* @test
|
238 |
+
* @loadFixture
|
239 |
+
*/
|
240 |
+
public function testGetOrderSyncEnabledFlag() {
|
241 |
+
$this->assertEquals(2, $this->helper->getOrderSyncEnabledFlag());
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* @test
|
246 |
+
* @dataProvider dataProvider
|
247 |
+
*/
|
248 |
+
public function testIsOrderSyncEnabled($is_production_domain, $config_flag, $result) {
|
249 |
+
$data_helper = $this->getHelperMock('klevu_search', array("isProductionDomain"));
|
250 |
+
$data_helper
|
251 |
+
->expects($this->once())
|
252 |
+
->method("isProductionDomain")
|
253 |
+
->will($this->returnValue($is_production_domain));
|
254 |
+
$this->replaceByMock("helper", "klevu_search", $data_helper);
|
255 |
+
|
256 |
+
$this->clearConfigCache();
|
257 |
+
|
258 |
+
$this->getConfig()
|
259 |
+
->saveConfig("klevu_search/order_sync/enabled", $config_flag)
|
260 |
+
->cleanCache();
|
261 |
+
|
262 |
+
$this->assertEquals($result, $this->helper->isOrderSyncEnabled());
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* @test
|
267 |
+
*/
|
268 |
+
public function testGetOrderSyncFrequencyDefault() {
|
269 |
+
$this->assertEquals("0 * * * *", $this->helper->getOrderSyncFrequency());
|
270 |
+
}
|
271 |
+
|
272 |
+
/**
|
273 |
+
* @test
|
274 |
+
* @loadFixture
|
275 |
+
*/
|
276 |
+
public function testGetOrderSyncFrequency() {
|
277 |
+
$this->assertEquals("0 */3 * * *", $this->helper->getOrderSyncFrequency());
|
278 |
+
}
|
279 |
+
|
280 |
+
/**
|
281 |
+
* @test
|
282 |
+
*/
|
283 |
+
public function testIsLoggingForced() {
|
284 |
+
// Test the default value
|
285 |
+
$this->assertEquals(false, $this->helper->isLoggingForced());
|
286 |
+
|
287 |
+
$this->clearConfigCache();
|
288 |
+
|
289 |
+
// Test a set value
|
290 |
+
$this->getConfig()
|
291 |
+
->saveConfig('klevu_search/developer/force_log', true)
|
292 |
+
->cleanCache();
|
293 |
+
|
294 |
+
$this->assertEquals(true, $this->helper->isLoggingForced());
|
295 |
+
}
|
296 |
+
|
297 |
+
public function testGetLogLevel() {
|
298 |
+
// Test the default value
|
299 |
+
$this->assertEquals(Zend_Log::WARN, $this->helper->getLogLevel(), "getLogLevel() returned an incorrect default value.");
|
300 |
+
|
301 |
+
$this->clearConfigCache();
|
302 |
+
|
303 |
+
// Test a set value
|
304 |
+
$this->getConfig()
|
305 |
+
->saveConfig('klevu_search/developer/log_level', Zend_Log::INFO)
|
306 |
+
->cleanCache();
|
307 |
+
|
308 |
+
$this->assertEquals(Zend_Log::INFO, $this->helper->getLogLevel(), "getLogLevel() failed to return the value set.");
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Mock the helper method that checks whether the current domain is a production domain.
|
313 |
+
*
|
314 |
+
* @param bool $result The result to be returned by the method
|
315 |
+
*/
|
316 |
+
protected function mockIsProductionDomain($result = false) {
|
317 |
+
$data_helper = $this->getHelperMock('klevu_search', array("isProductionDomain"));
|
318 |
+
$data_helper
|
319 |
+
->expects($this->any())
|
320 |
+
->method("isProductionDomain")
|
321 |
+
->will($this->returnValue($result));
|
322 |
+
$this->replaceByMock("helper", "klevu_search", $data_helper);
|
323 |
+
}
|
324 |
+
|
325 |
+
protected function getConfig() {
|
326 |
+
return Mage::app()->getConfig();
|
327 |
+
}
|
328 |
+
|
329 |
+
/**
|
330 |
+
* Get around Magento's aggressive caching strategy and actually clear the configuration cache.
|
331 |
+
*/
|
332 |
+
protected function clearConfigCache() {
|
333 |
+
// Flush website and store configuration caches
|
334 |
+
foreach (Mage::app()->getWebsites(true) as $website) {
|
335 |
+
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
|
336 |
+
$website, '_configCache', array()
|
337 |
+
);
|
338 |
+
}
|
339 |
+
foreach (Mage::app()->getStores(true) as $store) {
|
340 |
+
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
|
341 |
+
$store, '_configCache', array()
|
342 |
+
);
|
343 |
+
}
|
344 |
+
}
|
345 |
+
}
|
app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testGetOrderSyncEnabledFlag.yaml
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/order_sync/enabled: 2
|
app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testGetOrderSyncFrequency.yaml
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/order_sync/frequency: 0 */3 * * *
|
app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testGetProductSyncEnabledFlag.yaml
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/product_sync/enabled: 2
|
app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testGetProductSyncFrequency.yaml
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/product_sync/frequency: 0 */5 * * *
|
app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testIsExtensionEnabledDisabled.yaml
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 0
|
app/code/community/Klevu/Search/Test/Helper/Config/fixtures/testIsExtensionEnabledEnabled.yaml
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 1
|
app/code/community/Klevu/Search/Test/Helper/Config/providers/testIsOrderSyncEnabled.yaml
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
is_production_domain: true
|
3 |
+
config_flag: 0 # Disabled
|
4 |
+
order_sync_enabled: false
|
5 |
+
-
|
6 |
+
is_production_domain: true
|
7 |
+
config_flag: 1 # Enabled
|
8 |
+
order_sync_enabled: true
|
9 |
+
-
|
10 |
+
is_production_domain: true
|
11 |
+
config_flag: 2 # Forced
|
12 |
+
order_sync_enabled: true
|
13 |
+
-
|
14 |
+
is_production_domain: false
|
15 |
+
config_flag: 0 # Disabled
|
16 |
+
order_sync_enabled: false
|
17 |
+
-
|
18 |
+
is_production_domain: false
|
19 |
+
config_flag: 1 # Enabled
|
20 |
+
order_sync_enabled: false
|
21 |
+
-
|
22 |
+
is_production_domain: false
|
23 |
+
config_flag: 2 # Forced
|
24 |
+
order_sync_enabled: true
|
app/code/community/Klevu/Search/Test/Helper/Config/providers/testIsProductSyncEnabled.yaml
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
is_production_domain: true
|
3 |
+
config_flag: 0 # Disabled
|
4 |
+
product_sync_enabled: false
|
5 |
+
-
|
6 |
+
is_production_domain: true
|
7 |
+
config_flag: 1 # Enabled
|
8 |
+
product_sync_enabled: true
|
9 |
+
-
|
10 |
+
is_production_domain: true
|
11 |
+
config_flag: 2 # Forced
|
12 |
+
product_sync_enabled: true
|
13 |
+
-
|
14 |
+
is_production_domain: false
|
15 |
+
config_flag: 0 # Disabled
|
16 |
+
product_sync_enabled: false
|
17 |
+
-
|
18 |
+
is_production_domain: false
|
19 |
+
config_flag: 1 # Enabled
|
20 |
+
product_sync_enabled: false
|
21 |
+
-
|
22 |
+
is_production_domain: false
|
23 |
+
config_flag: 2 # Forced
|
24 |
+
product_sync_enabled: true
|
app/code/community/Klevu/Search/Test/Helper/Config/providers/testIsTestModeEnabled.yaml
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
test_mode: 0
|
3 |
+
is_production_domain: 0
|
4 |
+
result: true
|
5 |
+
-
|
6 |
+
test_mode: 1
|
7 |
+
is_production_domain: 0
|
8 |
+
result: true
|
9 |
+
-
|
10 |
+
test_mode: 0
|
11 |
+
is_production_domain: 1
|
12 |
+
result: false
|
13 |
+
-
|
14 |
+
test_mode: 1
|
15 |
+
is_production_domain: 1
|
16 |
+
result: true
|
app/code/community/Klevu/Search/Test/Helper/Data.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Helper_Data extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
/** @var Klevu_Search_Helper_Data $helper */
|
6 |
+
protected $helper;
|
7 |
+
|
8 |
+
protected function setUp() {
|
9 |
+
parent::setUp();
|
10 |
+
|
11 |
+
$this->helper = Mage::helper("klevu_search");
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @test
|
16 |
+
* @dataProvider dataProvider
|
17 |
+
*/
|
18 |
+
public function testGetLanguageFromLocale($input, $output) {
|
19 |
+
$this->assertEquals($output, $this->helper->getLanguageFromLocale($output));
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @test
|
24 |
+
* @dataProvider dataProvider
|
25 |
+
*/
|
26 |
+
public function testIsProductionDomain($domain, $result) {
|
27 |
+
$this->assertEquals(
|
28 |
+
$result,
|
29 |
+
$this->helper->isProductionDomain($domain),
|
30 |
+
sprintf("Domain %s should %s a production domain.", $domain, ($result ? "be" : "NOT be"))
|
31 |
+
);
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @test
|
36 |
+
* @dataProvider dataProvider
|
37 |
+
*/
|
38 |
+
public function testBytesToHumanReadable($input, $output) {
|
39 |
+
$this->assertEquals($output, $this->helper->bytesToHumanReadable($input));
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @test
|
44 |
+
* @dataProvider dataProvider
|
45 |
+
*/
|
46 |
+
public function testHumanReadableToBytes($input, $output) {
|
47 |
+
$this->assertEquals($output, $this->helper->humanReadableToBytes($input));
|
48 |
+
}
|
49 |
+
}
|
app/code/community/Klevu/Search/Test/Helper/Data/providers/testBytesToHumanReadable.yaml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
input: 100
|
3 |
+
output: 100
|
4 |
+
-
|
5 |
+
input: 1024
|
6 |
+
output: 1k
|
7 |
+
-
|
8 |
+
input: 1048576
|
9 |
+
output: 1M
|
10 |
+
-
|
11 |
+
input: 1073741824
|
12 |
+
output: 1G
|
13 |
+
-
|
14 |
+
input: 6815744
|
15 |
+
output: 6.5M
|
16 |
+
-
|
17 |
+
input: 24962496
|
18 |
+
output: 23.81M
|
app/code/community/Klevu/Search/Test/Helper/Data/providers/testGetLanguageFromLocale.yaml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
input: en_GB
|
3 |
+
output: en
|
4 |
+
-
|
5 |
+
input: fr_FR
|
6 |
+
output: fr
|
7 |
+
-
|
8 |
+
input: test
|
9 |
+
output: test
|
10 |
+
-
|
11 |
+
input: en
|
12 |
+
output: en
|
app/code/community/Klevu/Search/Test/Helper/Data/providers/testHumanReadableToBytes.yaml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
input: 100
|
3 |
+
output: 100
|
4 |
+
-
|
5 |
+
input: 1k
|
6 |
+
output: 1024
|
7 |
+
-
|
8 |
+
input: 1M
|
9 |
+
output: 1048576
|
10 |
+
-
|
11 |
+
input: 1G
|
12 |
+
output: 1073741824
|
13 |
+
-
|
14 |
+
input: 6.5M
|
15 |
+
output: 6815744
|
16 |
+
-
|
17 |
+
input: 23.81M
|
18 |
+
output: 24966595
|
app/code/community/Klevu/Search/Test/Helper/Data/providers/testIsProductionDomain.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
- www.klevu.com
|
3 |
+
- true
|
4 |
+
-
|
5 |
+
- klevu.co.uk
|
6 |
+
- true
|
7 |
+
-
|
8 |
+
- staging.klevu.com
|
9 |
+
- false
|
10 |
+
-
|
11 |
+
- klevu.dev
|
12 |
+
- false
|
13 |
+
-
|
14 |
+
- klevu.local
|
15 |
+
- false
|
app/code/community/Klevu/Search/Test/Model/Api/Action.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Action extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
*/
|
8 |
+
public function testExecute() {
|
9 |
+
$response_model = Mage::getModel('klevu_search/api_response');
|
10 |
+
$response_model
|
11 |
+
->setRawResponse(new Zend_Http_Response(200, array(), "Test response"));
|
12 |
+
|
13 |
+
$request_model = $this->getModelMock('klevu_search/api_request', array("send"));
|
14 |
+
$request_model
|
15 |
+
->expects($this->once())
|
16 |
+
->method("send")
|
17 |
+
->will($this->returnValue($response_model));
|
18 |
+
|
19 |
+
$action = Mage::getModel('klevu_search/api_action');
|
20 |
+
$action
|
21 |
+
->setRequest($request_model)
|
22 |
+
->setResponse($response_model);
|
23 |
+
|
24 |
+
$this->assertEquals($response_model, $action->execute());
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @test
|
29 |
+
*/
|
30 |
+
public function testValidate() {
|
31 |
+
$errors = array("Test error", "Another test error");
|
32 |
+
|
33 |
+
$action = $this->getModelMock('klevu_search/api_action', array("validate"));
|
34 |
+
$action
|
35 |
+
->expects($this->once())
|
36 |
+
->method("validate")
|
37 |
+
->will($this->returnValue($errors));
|
38 |
+
|
39 |
+
$request_model = $this->getModelMock('klevu_search/api_request', array("send"));
|
40 |
+
$request_model
|
41 |
+
->expects($this->never())
|
42 |
+
->method("send");
|
43 |
+
|
44 |
+
$action->setRequest($request_model);
|
45 |
+
|
46 |
+
$response = $action->execute();
|
47 |
+
|
48 |
+
$this->assertInstanceOf($this->getGroupedClassName("model", "klevu_search/api_response_invalid"), $response);
|
49 |
+
$this->assertEquals(
|
50 |
+
$errors,
|
51 |
+
$response->getErrors(),
|
52 |
+
"Returned response model does not contain the validation errors expected."
|
53 |
+
);
|
54 |
+
}
|
55 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords.php
ADDED
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Action_Addrecords extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
* @dataProvider dataProvider
|
8 |
+
*/
|
9 |
+
public function testValidateRequiredFields($field) {
|
10 |
+
$parameters = $this->getTestParameters();
|
11 |
+
unset($parameters[$field]);
|
12 |
+
|
13 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
14 |
+
$request
|
15 |
+
->expects($this->never())
|
16 |
+
->method("send");
|
17 |
+
|
18 |
+
$action = Mage::getModel('klevu_search/api_action_addrecords');
|
19 |
+
$action
|
20 |
+
->setRequest($request);
|
21 |
+
|
22 |
+
$response = $action->execute($parameters);
|
23 |
+
|
24 |
+
$this->assertInstanceOf("Klevu_Search_Model_Api_Response_Invalid", $response);
|
25 |
+
|
26 |
+
$this->assertArrayHasKey(
|
27 |
+
$field,
|
28 |
+
$response->getErrors(),
|
29 |
+
sprintf("Failed to assert that an error is returned for %s parameter.", $field)
|
30 |
+
);
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @test
|
35 |
+
* @dataProvider dataProvider
|
36 |
+
*/
|
37 |
+
public function testValidateRequiredFieldsRecords($field) {
|
38 |
+
$parameters = $this->getTestParameters();
|
39 |
+
unset($parameters['records'][0][$field]);
|
40 |
+
|
41 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
42 |
+
$request
|
43 |
+
->expects($this->never())
|
44 |
+
->method("send");
|
45 |
+
|
46 |
+
$action = Mage::getModel('klevu_search/api_action_addrecords');
|
47 |
+
$action
|
48 |
+
->setRequest($request);
|
49 |
+
|
50 |
+
$response = $action->execute($parameters);
|
51 |
+
|
52 |
+
$this->assertInstanceOf(
|
53 |
+
"Klevu_Search_Model_Api_Response_Invalid",
|
54 |
+
$response,
|
55 |
+
sprintf("Failed to assert that validation fails when one of the records is missing a %s field.", $field)
|
56 |
+
);
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @test
|
61 |
+
* @dataProvider dataProvider
|
62 |
+
*/
|
63 |
+
public function testValidateRequiredFieldsRecordsOptional($field) {
|
64 |
+
$parameters = $this->getTestParameters();
|
65 |
+
$parameters['records'][0][$field] = "";
|
66 |
+
|
67 |
+
$response = Mage::getModel('klevu_search/api_response');
|
68 |
+
$response
|
69 |
+
->setRawResponse(new Zend_Http_Response(200, array(), "Test response"));
|
70 |
+
|
71 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
72 |
+
$request
|
73 |
+
->expects($this->once())
|
74 |
+
->method("send")
|
75 |
+
->will($this->returnValue($response));
|
76 |
+
|
77 |
+
$action = Mage::getModel('klevu_search/api_action_addrecords');
|
78 |
+
$action
|
79 |
+
->setRequest($request);
|
80 |
+
|
81 |
+
$this->assertEquals(
|
82 |
+
$response,
|
83 |
+
$action->execute($parameters),
|
84 |
+
sprintf("Failed to assert that validation passes when one of the records is missing the optional %s field.", $field)
|
85 |
+
);
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @test
|
90 |
+
* @dataProvider dataProvider
|
91 |
+
*/
|
92 |
+
public function testValidateRequiredFieldsRecordsEmpty($field) {
|
93 |
+
$parameters = $this->getTestParameters();
|
94 |
+
$parameters['records'][0][$field] = "";
|
95 |
+
|
96 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
97 |
+
$request
|
98 |
+
->expects($this->never())
|
99 |
+
->method("send");
|
100 |
+
|
101 |
+
$action = Mage::getModel('klevu_search/api_action_addrecords');
|
102 |
+
$action
|
103 |
+
->setRequest($request);
|
104 |
+
|
105 |
+
$response = $action->execute($parameters);
|
106 |
+
|
107 |
+
$this->assertInstanceOf(
|
108 |
+
"Klevu_Search_Model_Api_Response_Invalid",
|
109 |
+
$response,
|
110 |
+
sprintf("Failed to assert that validation fails when one of the records as an empty %s field.", $field)
|
111 |
+
);
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* @test
|
116 |
+
* @dataProvider dataProvider
|
117 |
+
*/
|
118 |
+
public function testValidateRequiredFieldsRecordsAllowedEmpty($field) {
|
119 |
+
$parameters = $this->getTestParameters();
|
120 |
+
$parameters['records'][0][$field] = "";
|
121 |
+
|
122 |
+
$response = Mage::getModel('klevu_search/api_response');
|
123 |
+
$response
|
124 |
+
->setRawResponse(new Zend_Http_Response(200, array(), "Test response"));
|
125 |
+
|
126 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
127 |
+
$request
|
128 |
+
->expects($this->once())
|
129 |
+
->method("send")
|
130 |
+
->will($this->returnValue($response));
|
131 |
+
|
132 |
+
$action = Mage::getModel('klevu_search/api_action_addrecords');
|
133 |
+
$action
|
134 |
+
->setRequest($request);
|
135 |
+
|
136 |
+
$this->assertEquals(
|
137 |
+
$response,
|
138 |
+
$action->execute($parameters),
|
139 |
+
sprintf("Failed to assert that validation passes when one of the records has an empty %s field.", $field)
|
140 |
+
);
|
141 |
+
}
|
142 |
+
|
143 |
+
protected function getTestParameters() {
|
144 |
+
return array(
|
145 |
+
'sessionId' => "Klevu-session-1234567890",
|
146 |
+
'records' => array(
|
147 |
+
array(
|
148 |
+
'id' => "1",
|
149 |
+
'name' => "Test Product",
|
150 |
+
'url' => "http://box.klevu.com/",
|
151 |
+
'image' => "http://box.klevu.com/image.jpg",
|
152 |
+
'salePrice' => "19.99",
|
153 |
+
'startPrice' => "15.99",
|
154 |
+
'toPrice' => "29.99",
|
155 |
+
'currency' => "GBP",
|
156 |
+
'shortDesc' => "A test product",
|
157 |
+
'desc' => "A longer description of the test product",
|
158 |
+
'category' => "Tablets",
|
159 |
+
'listCategory' => array("Electronics", "Tablets", "Sale"),
|
160 |
+
'inStock' => "yes",
|
161 |
+
'brand' => "Klevu",
|
162 |
+
'model' => "X-300",
|
163 |
+
'color' => "blue",
|
164 |
+
'size' => "N/A",
|
165 |
+
'weight' => "100",
|
166 |
+
'other' => array(
|
167 |
+
'modes' => array(
|
168 |
+
'label' => 'Modes',
|
169 |
+
'values' => array("fast", "eco", "precise")
|
170 |
+
)
|
171 |
+
)
|
172 |
+
)
|
173 |
+
)
|
174 |
+
);
|
175 |
+
}
|
176 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords/providers/testValidateRequiredFields.yaml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
field: sessionId
|
3 |
+
-
|
4 |
+
field: records
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords/providers/testValidateRequiredFieldsRecords.yaml
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
field: id
|
3 |
+
-
|
4 |
+
field: name
|
5 |
+
-
|
6 |
+
field: url
|
7 |
+
-
|
8 |
+
field: salePrice
|
9 |
+
-
|
10 |
+
field: currency
|
11 |
+
-
|
12 |
+
field: category
|
13 |
+
-
|
14 |
+
field: listCategory
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords/providers/testValidateRequiredFieldsRecordsAllowedEmpty.yaml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
field: category
|
3 |
+
-
|
4 |
+
field: listCategory
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords/providers/testValidateRequiredFieldsRecordsEmpty.yaml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
field: id
|
3 |
+
-
|
4 |
+
field: name
|
5 |
+
-
|
6 |
+
field: url
|
7 |
+
-
|
8 |
+
field: salePrice
|
9 |
+
-
|
10 |
+
field: currency
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Addrecords/providers/testValidateRequiredFieldsRecordsOptional.yaml
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
field: itemGroupId
|
3 |
+
-
|
4 |
+
field: inStock
|
5 |
+
-
|
6 |
+
field: startPrice
|
7 |
+
-
|
8 |
+
field: toPrice
|
9 |
+
-
|
10 |
+
field: brand
|
11 |
+
-
|
12 |
+
field: model
|
13 |
+
-
|
14 |
+
field: color
|
15 |
+
-
|
16 |
+
field: size
|
17 |
+
-
|
18 |
+
field: weight
|
19 |
+
-
|
20 |
+
field: other
|
21 |
+
-
|
22 |
+
field: shortDesc
|
23 |
+
-
|
24 |
+
field: desc
|
25 |
+
-
|
26 |
+
field: image
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Adduser.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Action_Adduser extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
*/
|
8 |
+
public function testValidate() {
|
9 |
+
$parameters = $this->getTestParameters();
|
10 |
+
|
11 |
+
$response = Mage::getModel('klevu_search/api_response');
|
12 |
+
$response->setRawResponse(new Zend_Http_Response(200, array(), "Test response"));
|
13 |
+
|
14 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
15 |
+
$request
|
16 |
+
->expects($this->once())
|
17 |
+
->method("send")
|
18 |
+
->will($this->returnValue($response));
|
19 |
+
|
20 |
+
$action = Mage::getModel('klevu_search/api_action_adduser');
|
21 |
+
$action
|
22 |
+
->setRequest($request);
|
23 |
+
|
24 |
+
$this->assertEquals($response, $action->execute($parameters));
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @test
|
29 |
+
* @dataProvider dataProvider
|
30 |
+
*/
|
31 |
+
public function testValidateRequiredFields($field) {
|
32 |
+
$parameters = $this->getTestParameters();
|
33 |
+
unset($parameters[$field]);
|
34 |
+
|
35 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
36 |
+
$request
|
37 |
+
->expects($this->never())
|
38 |
+
->method("send");
|
39 |
+
|
40 |
+
$action = Mage::getModel('klevu_search/api_action_adduser');
|
41 |
+
$action
|
42 |
+
->setRequest($request);
|
43 |
+
|
44 |
+
$response = $action->execute($parameters);
|
45 |
+
|
46 |
+
$this->assertInstanceOf("Klevu_Search_Model_Api_Response_Invalid", $response);
|
47 |
+
|
48 |
+
$this->assertArrayHasKey(
|
49 |
+
$field,
|
50 |
+
$response->getErrors(),
|
51 |
+
sprintf("Failed to assert that an error is returned for %s parameter.", $field)
|
52 |
+
);
|
53 |
+
}
|
54 |
+
|
55 |
+
protected function getTestParameters() {
|
56 |
+
return array(
|
57 |
+
"email" => "test@klevu.com",
|
58 |
+
"password" => "password1",
|
59 |
+
"url" => "http://www.klevu.com/"
|
60 |
+
);
|
61 |
+
}
|
62 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Adduser/providers/testValidateRequiredFields.yaml
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
field: email
|
3 |
+
-
|
4 |
+
field: password
|
5 |
+
-
|
6 |
+
field: url
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Addwebstore.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Action_Addwebstore extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
*/
|
8 |
+
public function testValidate() {
|
9 |
+
$parameters = $this->getTestParameters();
|
10 |
+
|
11 |
+
$response = Mage::getModel('klevu_search/api_response');
|
12 |
+
$response->setRawResponse(new Zend_Http_Response(200, array(), "Test response"));
|
13 |
+
|
14 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
15 |
+
$request
|
16 |
+
->expects($this->once())
|
17 |
+
->method("send")
|
18 |
+
->will($this->returnValue($response));
|
19 |
+
|
20 |
+
$action = Mage::getModel('klevu_search/api_action_addwebstore');
|
21 |
+
$action
|
22 |
+
->setRequest($request);
|
23 |
+
|
24 |
+
$this->assertEquals($response, $action->execute($parameters));
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @test
|
29 |
+
* @dataProvider dataProvider
|
30 |
+
*/
|
31 |
+
public function testValidateRequiredFields($field) {
|
32 |
+
$parameters = $this->getTestParameters();
|
33 |
+
unset($parameters[$field]);
|
34 |
+
|
35 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
36 |
+
$request
|
37 |
+
->expects($this->never())
|
38 |
+
->method("send");
|
39 |
+
|
40 |
+
$action = Mage::getModel('klevu_search/api_action_addwebstore');
|
41 |
+
$action
|
42 |
+
->setRequest($request);
|
43 |
+
|
44 |
+
$response = $action->execute($parameters);
|
45 |
+
|
46 |
+
$this->assertInstanceOf("Klevu_Search_Model_Api_Response_Invalid", $response);
|
47 |
+
|
48 |
+
$this->assertArrayHasKey(
|
49 |
+
$field,
|
50 |
+
$response->getErrors(),
|
51 |
+
sprintf("Failed to assert that an error is returned for %s parameter.", $field)
|
52 |
+
);
|
53 |
+
}
|
54 |
+
|
55 |
+
protected function getTestParameters() {
|
56 |
+
return array(
|
57 |
+
"customerId" => "42",
|
58 |
+
"testMode" => "true",
|
59 |
+
"storeName" => "Test Store",
|
60 |
+
"language" => "en",
|
61 |
+
"timezone" => "Europe/London",
|
62 |
+
"version" => "1.0.0",
|
63 |
+
"locale" => "en_GB",
|
64 |
+
"country" => "GB"
|
65 |
+
);
|
66 |
+
}
|
67 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Addwebstore/providers/testValidateRequiredFields.yaml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
field: customerId
|
3 |
+
-
|
4 |
+
field: testMode
|
5 |
+
-
|
6 |
+
field: storeName
|
7 |
+
-
|
8 |
+
field: language
|
9 |
+
-
|
10 |
+
field: timezone
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Getuserdetail.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Action_Getuserdetail extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
*/
|
8 |
+
public function testValidate() {
|
9 |
+
$parameters = $this->getTestParameters();
|
10 |
+
|
11 |
+
$response = Mage::getModel('klevu_search/api_response');
|
12 |
+
$response->setRawResponse(new Zend_Http_Response(200, array(), "Test response"));
|
13 |
+
|
14 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
15 |
+
$request
|
16 |
+
->expects($this->once())
|
17 |
+
->method("send")
|
18 |
+
->will($this->returnValue($response));
|
19 |
+
|
20 |
+
$action = Mage::getModel('klevu_search/api_action_getuserdetail');
|
21 |
+
$action
|
22 |
+
->setRequest($request);
|
23 |
+
|
24 |
+
$this->assertEquals($response, $action->execute($parameters));
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @test
|
29 |
+
* @dataProvider dataProvider
|
30 |
+
*/
|
31 |
+
public function testValidateRequiredFields($field) {
|
32 |
+
$parameters = $this->getTestParameters();
|
33 |
+
unset($parameters[$field]);
|
34 |
+
|
35 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
36 |
+
$request
|
37 |
+
->expects($this->never())
|
38 |
+
->method("send");
|
39 |
+
|
40 |
+
$action = Mage::getModel('klevu_search/api_action_getuserdetail');
|
41 |
+
$action
|
42 |
+
->setRequest($request);
|
43 |
+
|
44 |
+
$response = $action->execute($parameters);
|
45 |
+
|
46 |
+
$this->assertInstanceOf("Klevu_Search_Model_Api_Response_Invalid", $response);
|
47 |
+
|
48 |
+
$this->assertArrayHasKey(
|
49 |
+
$field,
|
50 |
+
$response->getErrors(),
|
51 |
+
sprintf("Failed to assert that an error is returned for %s parameter.", $field)
|
52 |
+
);
|
53 |
+
}
|
54 |
+
|
55 |
+
protected function getTestParameters() {
|
56 |
+
return array(
|
57 |
+
'email' => "test@klevu.com",
|
58 |
+
'password' => "password1"
|
59 |
+
);
|
60 |
+
}
|
61 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Getuserdetail/providers/testValidateRequiredFields.yaml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
field: email
|
3 |
+
-
|
4 |
+
field: password
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Idsearch.php
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Action_Idsearch extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Test that validation passes and successful response is received.
|
7 |
+
* @test
|
8 |
+
*/
|
9 |
+
public function testValidate() {
|
10 |
+
$parameters = $this->getTestParameters();
|
11 |
+
|
12 |
+
$response = Mage::getModel('klevu_search/api_response');
|
13 |
+
$response->setRawResponse(new Zend_Http_Response(200, array(), "Test response"));
|
14 |
+
|
15 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
16 |
+
$request
|
17 |
+
->expects($this->once())
|
18 |
+
->method("send")
|
19 |
+
->will($this->returnValue($response));
|
20 |
+
|
21 |
+
$action = Mage::getModel('klevu_search/api_action_idsearch');
|
22 |
+
$action
|
23 |
+
->setRequest($request);
|
24 |
+
|
25 |
+
$this->assertEquals($response, $action->execute($parameters));
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @test
|
30 |
+
* @dataProvider dataProvider
|
31 |
+
*/
|
32 |
+
public function testValidateRequiredFields($field) {
|
33 |
+
$parameters = $this->getTestParameters();
|
34 |
+
unset($parameters[$field]);
|
35 |
+
|
36 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
37 |
+
$request
|
38 |
+
->expects($this->never())
|
39 |
+
->method("send");
|
40 |
+
|
41 |
+
$action = Mage::getModel('klevu_search/api_action_idsearch');
|
42 |
+
$action
|
43 |
+
->setRequest($request);
|
44 |
+
|
45 |
+
$response = $action->execute($parameters);
|
46 |
+
|
47 |
+
$this->assertInstanceOf("Klevu_Search_Model_Api_Response_Invalid", $response);
|
48 |
+
|
49 |
+
$this->assertArrayHasKey(
|
50 |
+
$field,
|
51 |
+
$response->getErrors(),
|
52 |
+
sprintf("Failed to assert that an error is returned for %s parameter.", $field)
|
53 |
+
);
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* @test
|
58 |
+
*/
|
59 |
+
public function testValidationPaginationStartsFromLessThanZero() {
|
60 |
+
$field = 'paginationStartsFrom';
|
61 |
+
$parameters = $this->getTestParameters();
|
62 |
+
$parameters[$field] = -1;
|
63 |
+
|
64 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
65 |
+
$request
|
66 |
+
->expects($this->never())
|
67 |
+
->method("send");
|
68 |
+
|
69 |
+
$action = Mage::getModel('klevu_search/api_action_idsearch');
|
70 |
+
$action
|
71 |
+
->setRequest($request);
|
72 |
+
|
73 |
+
$response = $action->execute($parameters);
|
74 |
+
|
75 |
+
$this->assertInstanceOf("Klevu_Search_Model_Api_Response_Invalid", $response);
|
76 |
+
|
77 |
+
$this->assertArrayHasKey(
|
78 |
+
$field,
|
79 |
+
$response->getErrors(),
|
80 |
+
sprintf("Failed to assert that an error is returned for %s parameter.", $field)
|
81 |
+
);
|
82 |
+
}
|
83 |
+
|
84 |
+
protected function getTestParameters() {
|
85 |
+
return array(
|
86 |
+
'ticket' => 'test-search-api-key',
|
87 |
+
'noOfResults' => 30,
|
88 |
+
'term' => 'computers',
|
89 |
+
'paginationStartsFrom' => 0,
|
90 |
+
'ipAddress' => '127.0.0.1',
|
91 |
+
'klevuSort' => 'rel',
|
92 |
+
'enableFilters' => 1,
|
93 |
+
'filterResults' => ''
|
94 |
+
);
|
95 |
+
}
|
96 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Idsearch/providers/testValidateRequiredFields.yaml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
field: ticket
|
3 |
+
-
|
4 |
+
field: noOfResults
|
5 |
+
-
|
6 |
+
field: term
|
7 |
+
-
|
8 |
+
field: paginationStartsFrom
|
9 |
+
-
|
10 |
+
field: klevuSort
|
11 |
+
-
|
12 |
+
field: enableFilters
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Producttracking.php
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Action_Producttracking extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
*/
|
8 |
+
public function testValidate() {
|
9 |
+
$parameters = $this->getTestParameters();
|
10 |
+
|
11 |
+
$response = Mage::getModel('klevu_search/api_response');
|
12 |
+
$response->setRawResponse(new Zend_Http_Response(200, array(), "Test response"));
|
13 |
+
|
14 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
15 |
+
$request
|
16 |
+
->expects($this->once())
|
17 |
+
->method("send")
|
18 |
+
->will($this->returnValue($response));
|
19 |
+
|
20 |
+
$action = $this->getModel();
|
21 |
+
$action
|
22 |
+
->setRequest($request);
|
23 |
+
|
24 |
+
$this->assertEquals($response, $action->execute($parameters));
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @test
|
29 |
+
* @dataProvider dataProvider
|
30 |
+
*/
|
31 |
+
public function testValidateRequiredFields($field) {
|
32 |
+
$parameters = $this->getTestParameters();
|
33 |
+
unset($parameters[$field]);
|
34 |
+
|
35 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
36 |
+
$request
|
37 |
+
->expects($this->never())
|
38 |
+
->method("send");
|
39 |
+
|
40 |
+
$action = $this->getModel();
|
41 |
+
$action
|
42 |
+
->setRequest($request);
|
43 |
+
|
44 |
+
$response = $action->execute($parameters);
|
45 |
+
|
46 |
+
$this->assertInstanceOf("Klevu_Search_Model_Api_Response_Invalid", $response);
|
47 |
+
|
48 |
+
$this->assertArrayHasKey(
|
49 |
+
$field,
|
50 |
+
$response->getErrors(),
|
51 |
+
sprintf("Failed to assert that an error is returned for %s parameter.", $field)
|
52 |
+
);
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Return the model being tested.
|
57 |
+
*
|
58 |
+
* @return Klevu_Search_Model_Api_Action_Producttracking
|
59 |
+
*/
|
60 |
+
protected function getModel() {
|
61 |
+
return Mage::getModel('klevu_search/api_action_producttracking');
|
62 |
+
}
|
63 |
+
|
64 |
+
protected function getTestParameters() {
|
65 |
+
return array(
|
66 |
+
'klevu_apiKey' => "test-api-key",
|
67 |
+
'klevu_type' => "checkout",
|
68 |
+
'klevu_productId' => 1,
|
69 |
+
'klevu_unit' => 1,
|
70 |
+
'klevu_salePrice' => 100.00,
|
71 |
+
'klevu_currency' => "GBP",
|
72 |
+
'klevu_shopperIP' => "127.0.0.1"
|
73 |
+
);
|
74 |
+
}
|
75 |
+
|
76 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Producttracking/providers/testValidateRequiredFields.yaml
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
field: klevu_apiKey
|
3 |
+
-
|
4 |
+
field: klevu_type
|
5 |
+
-
|
6 |
+
field: klevu_productId
|
7 |
+
-
|
8 |
+
field: klevu_unit
|
9 |
+
-
|
10 |
+
field: klevu_salePrice
|
11 |
+
-
|
12 |
+
field: klevu_currency
|
13 |
+
-
|
14 |
+
field: klevu_shopperIP
|
app/code/community/Klevu/Search/Test/Model/Api/Action/Startsession.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Action_Startsession extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
public function testValidate() {
|
6 |
+
$parameters = array(
|
7 |
+
'api_key' => "dGVzdC1hcGkta2V5"
|
8 |
+
);
|
9 |
+
|
10 |
+
$response = Mage::getModel('klevu_search/api_response');
|
11 |
+
$response->setRawResponse(new Zend_Http_Response(200, array(), "Test response"));
|
12 |
+
|
13 |
+
$request = $this->getModelMock('klevu_search/api_request', array("send"));
|
14 |
+
$request
|
15 |
+
->expects($this->once())
|
16 |
+
->method("send")
|
17 |
+
->will($this->returnValue($response));
|
18 |
+
|
19 |
+
$action = Mage::getModel('klevu_search/api_action_startsession');
|
20 |
+
$action
|
21 |
+
->setRequest($request);
|
22 |
+
|
23 |
+
$this->assertEquals($response, $action->execute($parameters));
|
24 |
+
|
25 |
+
$returned_response = $action->execute(array());
|
26 |
+
|
27 |
+
$this->assertInstanceOf("Klevu_Search_Model_Api_Response_Invalid", $returned_response);
|
28 |
+
$this->assertEquals(array("Missing API key."), $returned_response->getErrors());
|
29 |
+
}
|
30 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Request.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Request extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
* @expectedException Mage_Core_Exception
|
8 |
+
*/
|
9 |
+
public function testSendNoEndpoint() {
|
10 |
+
$model = $this->getModelMock('klevu_search/api_request', array("build"));
|
11 |
+
$model
|
12 |
+
->expects($this->never())
|
13 |
+
->method("build");
|
14 |
+
|
15 |
+
$model->send(); // Should throw an exception
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @test
|
20 |
+
*/
|
21 |
+
public function testSendNoResponse() {
|
22 |
+
$http_client = $this->getMock("Zend_Http_Client", array("request"));
|
23 |
+
$http_client
|
24 |
+
->expects($this->once())
|
25 |
+
->method("request")
|
26 |
+
->will($this->throwException(new Zend_Http_Client_Exception("Test exception")));
|
27 |
+
|
28 |
+
$model = $this->getModelMock('klevu_search/api_request', array("build"));
|
29 |
+
$model
|
30 |
+
->expects($this->once())
|
31 |
+
->method("build")
|
32 |
+
->will($this->returnValue($http_client));
|
33 |
+
|
34 |
+
$model->setEndpoint("http://test.klevu.com/");
|
35 |
+
|
36 |
+
$this->assertInstanceOf("Klevu_Search_Model_Api_Response_Empty", $model->send());
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @test
|
41 |
+
*/
|
42 |
+
public function testSendValidResponse() {
|
43 |
+
$test_raw_response = new Zend_Http_Response(200, array());
|
44 |
+
|
45 |
+
$http_client = $this->getMock("Zend_Http_Client", array("request"));
|
46 |
+
$http_client
|
47 |
+
->expects($this->once())
|
48 |
+
->method("request")
|
49 |
+
->will($this->returnValue($test_raw_response));
|
50 |
+
|
51 |
+
$response_model = $this->getModelMock('klevu_search/api_response', array("setRawResponse"));
|
52 |
+
$response_model
|
53 |
+
->expects($this->once())
|
54 |
+
->method("setRawResponse")
|
55 |
+
->with($this->equalTo($test_raw_response));
|
56 |
+
|
57 |
+
$request_model = $this->getModelMock('klevu_search/api_request', array("build"));
|
58 |
+
$request_model
|
59 |
+
->expects($this->once())
|
60 |
+
->method("build")
|
61 |
+
->will($this->returnValue($http_client));
|
62 |
+
|
63 |
+
$request_model
|
64 |
+
->setEndpoint("http://test.klevu.com/")
|
65 |
+
->setResponseModel($response_model);
|
66 |
+
|
67 |
+
$this->assertInstanceOf("Klevu_Search_Model_Api_Response", $request_model->send());
|
68 |
+
}
|
69 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Request/Xml.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Request_Xml extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
* @dataProvider dataProvider
|
8 |
+
*/
|
9 |
+
public function testGetDataAsXml($data, $xml) {
|
10 |
+
$request = Mage::getModel('klevu_search/api_request_xml');
|
11 |
+
|
12 |
+
$request->setData($data);
|
13 |
+
|
14 |
+
$this->assertEquals($xml, preg_replace("/\n/", "", $request->getDataAsXml()));
|
15 |
+
}
|
16 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Request/Xml/providers/testGetDataAsXml.yaml
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
data:
|
3 |
+
sessionId: Klevu-session-1234567890
|
4 |
+
xml: <?xml version="1.0"?><request><sessionId>Klevu-session-1234567890</sessionId></request>
|
5 |
+
-
|
6 |
+
data:
|
7 |
+
sessionId: Klevu-session-1234567890
|
8 |
+
records:
|
9 |
+
- record:
|
10 |
+
pairs:
|
11 |
+
- pair:
|
12 |
+
key: id
|
13 |
+
value: 1
|
14 |
+
- pair:
|
15 |
+
key: name
|
16 |
+
value: Test Product
|
17 |
+
- record:
|
18 |
+
pairs:
|
19 |
+
- pair:
|
20 |
+
key: id
|
21 |
+
value: 3
|
22 |
+
xml: <?xml version="1.0"?><request><sessionId>Klevu-session-1234567890</sessionId><records><record><pairs><pair><key>id</key><value>1</value></pair><pair><key>name</key><value>Test Product</value></pair></pairs></record><record><pairs><pair><key>id</key><value>3</value></pair></pairs></record></records></request>
|
23 |
+
-
|
24 |
+
data: []
|
25 |
+
xml: <?xml version="1.0"?><request/>
|
app/code/community/Klevu/Search/Test/Model/Api/Response.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Response extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
* @dataProvider dataProvider
|
8 |
+
* @dataProviderFile response_testIsSuccessful.yaml
|
9 |
+
*/
|
10 |
+
public function testIsSuccessful($response_code, $response_data_file, $is_successful) {
|
11 |
+
$response_body = ($response_data_file) ? $this->getDataFileContents($response_data_file) : "";
|
12 |
+
$http_response = new Zend_Http_Response($response_code, array(), $response_body);
|
13 |
+
|
14 |
+
$model = Mage::getModel('klevu_search/api_response');
|
15 |
+
$model->setRawResponse($http_response);
|
16 |
+
|
17 |
+
$this->assertEquals($is_successful, $model->isSuccessful());
|
18 |
+
}
|
19 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Response/Data.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Response_Data extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
* @dataProvider dataProvider
|
8 |
+
*/
|
9 |
+
public function testIsSuccessful($response_code, $response_data_file, $is_successful) {
|
10 |
+
$http_response = new Zend_Http_Response($response_code, array(), $this->getDataFileContents($response_data_file));
|
11 |
+
|
12 |
+
$model = Mage::getModel('klevu_search/api_response_data');
|
13 |
+
$model->setRawResponse($http_response);
|
14 |
+
|
15 |
+
$this->assertEquals($is_successful, $model->isSuccessful());
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @test
|
20 |
+
*/
|
21 |
+
public function testData() {
|
22 |
+
$http_response = new Zend_Http_Response(200, array(), $this->getDataFileContents("data_response_data.xml"));
|
23 |
+
|
24 |
+
$model = Mage::getModel('klevu_search/api_response_data');
|
25 |
+
$model->setRawResponse($http_response);
|
26 |
+
|
27 |
+
$this->assertEquals("test", $model->getTest(), "Failed asserting that data gets set on the response.");
|
28 |
+
$this->assertNull($model->getResponse(), "Failed asserting that 'response' element gets removed from data.");
|
29 |
+
$this->assertEquals("test", $model->getCamelCase(), "Failed asserting that data keys get converted from camel case.");
|
30 |
+
}
|
31 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Response/Data/providers/testIsSuccessful.yaml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
response_code: 200
|
3 |
+
response_data_file: data_response_success.xml
|
4 |
+
is_successful: true
|
5 |
+
-
|
6 |
+
response_code: 200
|
7 |
+
response_data_file: data_response_failure.xml
|
8 |
+
is_successful: false
|
9 |
+
-
|
10 |
+
response_code: 200
|
11 |
+
response_data_file: data_response_no_response.xml
|
12 |
+
is_successful: false
|
app/code/community/Klevu/Search/Test/Model/Api/Response/Empty.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Response_Empty extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
*/
|
8 |
+
public function testIsSuccessful() {
|
9 |
+
$model = Mage::getModel('klevu_search/api_response_empty');
|
10 |
+
|
11 |
+
$this->assertEquals(
|
12 |
+
false,
|
13 |
+
$model->isSuccessful(),
|
14 |
+
"Failed asserting that isSuccessful() returns false when no HTTP response is provided."
|
15 |
+
);
|
16 |
+
|
17 |
+
$model->setRawResponse(new Zend_Http_Response(200, array()));
|
18 |
+
|
19 |
+
$this->assertEquals(
|
20 |
+
false,
|
21 |
+
$model->isSuccessful(),
|
22 |
+
"Failed asserting that isSuccessful() returns false when given a successful HTTP response."
|
23 |
+
);
|
24 |
+
|
25 |
+
$model->setRawResponse(new Zend_Http_Response(500, array()));
|
26 |
+
|
27 |
+
$this->assertEquals(
|
28 |
+
false,
|
29 |
+
$model->isSuccessful(),
|
30 |
+
"Failed asserting that isSuccessful() returns false when given an unsuccessful HTTP response."
|
31 |
+
);
|
32 |
+
}
|
33 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Response/Invalid.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Response_Invalid extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
*/
|
8 |
+
public function testIsSuccessful() {
|
9 |
+
$model = Mage::getModel('klevu_search/api_response_invalid');
|
10 |
+
|
11 |
+
$this->assertEquals(
|
12 |
+
false,
|
13 |
+
$model->isSuccessful(),
|
14 |
+
"Failed asserting that isSuccessful() returns false when no HTTP response is provided."
|
15 |
+
);
|
16 |
+
|
17 |
+
$model->setRawResponse(new Zend_Http_Response(200, array()));
|
18 |
+
|
19 |
+
$this->assertEquals(
|
20 |
+
false,
|
21 |
+
$model->isSuccessful(),
|
22 |
+
"Failed asserting that isSuccessful() returns false when given a successful HTTP response."
|
23 |
+
);
|
24 |
+
|
25 |
+
$model->setRawResponse(new Zend_Http_Response(500, array()));
|
26 |
+
|
27 |
+
$this->assertEquals(
|
28 |
+
false,
|
29 |
+
$model->isSuccessful(),
|
30 |
+
"Failed asserting that isSuccessful() returns false when given an unsuccessful HTTP response."
|
31 |
+
);
|
32 |
+
}
|
33 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Response/Message.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Response_Message extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
* @dataProvider dataProvider
|
8 |
+
*/
|
9 |
+
public function testIsSuccessful($response_code, $response_data_file, $is_successful) {
|
10 |
+
$http_response = new Zend_Http_Response($response_code, array(), $this->getDataFileContents($response_data_file));
|
11 |
+
|
12 |
+
$model = Mage::getModel('klevu_search/api_response_message');
|
13 |
+
$model->setRawResponse($http_response);
|
14 |
+
|
15 |
+
$this->assertEquals($is_successful, $model->isSuccessful());
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @test
|
20 |
+
*/
|
21 |
+
public function testGetSessionId() {
|
22 |
+
$http_response = new Zend_Http_Response(200, array(), $this->getDataFileContents("message_response_session_id.xml"));
|
23 |
+
|
24 |
+
$model = Mage::getModel('klevu_search/api_response_message');
|
25 |
+
$model->setRawResponse($http_response);
|
26 |
+
|
27 |
+
$this->assertEquals("Klevu-session-1234567890", $model->getSessionId());
|
28 |
+
}
|
29 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Response/Message/providers/testIsSuccessful.yaml
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
response_code: 200
|
3 |
+
response_data_file: message_response_success.xml
|
4 |
+
is_successful: true
|
5 |
+
-
|
6 |
+
response_code: 200
|
7 |
+
response_data_file: message_response_failure.xml
|
8 |
+
is_successful: false
|
9 |
+
-
|
10 |
+
response_code: 200
|
11 |
+
response_data_file: message_response_missing_status.xml
|
12 |
+
is_successful: false
|
13 |
+
-
|
14 |
+
response_code: 200
|
15 |
+
response_data_file: message_response_missing_message.xml
|
16 |
+
is_successful: true
|
app/code/community/Klevu/Search/Test/Model/Api/Response/Timezone.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Api_Response_Timezone extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
* @dataProvider dataProvider
|
8 |
+
*/
|
9 |
+
public function testIsSuccessful($response_code, $response_data_file, $is_successful) {
|
10 |
+
$http_response = new Zend_Http_Response($response_code, array(), $this->getDataFileContents($response_data_file));
|
11 |
+
|
12 |
+
$model = Mage::getModel('klevu_search/api_response_timezone');
|
13 |
+
$model->setRawResponse($http_response);
|
14 |
+
|
15 |
+
$this->assertEquals($is_successful, $model->isSuccessful());
|
16 |
+
}
|
17 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/Response/Timezone/providers/testIsSuccessful.yaml
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
response_code: 200
|
3 |
+
response_data_file: timezone_response_no_status.xml
|
4 |
+
is_successful: true
|
5 |
+
-
|
6 |
+
response_code: 200
|
7 |
+
response_data_file: timezone_response_with_success.xml
|
8 |
+
is_successful: true
|
9 |
+
-
|
10 |
+
response_code: 200
|
11 |
+
response_data_file: timezone_response_with_failure.xml
|
12 |
+
is_successful: true
|
13 |
+
-
|
14 |
+
response_code: 200
|
15 |
+
response_data_file: timezone_response_no_data.xml
|
16 |
+
is_successful: false
|
app/code/community/Klevu/Search/Test/Model/Api/Response/providers/response_testIsSuccessful.yaml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
response_code: 200
|
3 |
+
response_data_file: ""
|
4 |
+
is_successful: false
|
5 |
+
-
|
6 |
+
response_code: 500
|
7 |
+
response_data_file: ""
|
8 |
+
is_successful: false
|
9 |
+
-
|
10 |
+
response_code: 200
|
11 |
+
response_data_file: "response_valid.xml"
|
12 |
+
is_successful: true
|
13 |
+
-
|
14 |
+
response_code: 200
|
15 |
+
response_data_file: "response_malformed.xml"
|
16 |
+
is_successful: false
|
17 |
+
-
|
18 |
+
response_code: 200
|
19 |
+
response_data_file: "response_noxml.xml"
|
20 |
+
is_successful: false
|
app/code/community/Klevu/Search/Test/Model/Api/Test/Case.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class Klevu_Search_Test_Model_Api_Test_Case extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
protected function getDataFileContents($file) {
|
6 |
+
$directory_tree = array(
|
7 |
+
Mage::getModuleDir('', 'Klevu_Search'),
|
8 |
+
'Test',
|
9 |
+
'Model',
|
10 |
+
'Api',
|
11 |
+
'data',
|
12 |
+
$file
|
13 |
+
);
|
14 |
+
|
15 |
+
$file_path = join(DS, $directory_tree);
|
16 |
+
|
17 |
+
return file_get_contents($file_path);
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Create a mock class of the given API action model which will expect to be executed
|
22 |
+
* once and will return the given response. Then replace that model in Magento with
|
23 |
+
* the created mock.
|
24 |
+
*
|
25 |
+
* @param string $alias A grouped class name of the API action model to mock
|
26 |
+
* @param Klevu_Search_Model_Api_Response $response
|
27 |
+
*
|
28 |
+
* @return $this
|
29 |
+
*/
|
30 |
+
protected function replaceApiActionByMock($alias, $response) {
|
31 |
+
$mock = $this->getModelMock($alias, array("execute"));
|
32 |
+
$mock
|
33 |
+
->expects($this->once())
|
34 |
+
->method("execute")
|
35 |
+
->will($this->returnValue($response));
|
36 |
+
|
37 |
+
$this->replaceByMock("model", $alias, $mock);
|
38 |
+
|
39 |
+
return $this;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Create a mock class of the given session model, disabling session initialisation, and replace
|
44 |
+
* that model in Magento with the created mock.
|
45 |
+
*
|
46 |
+
* @param string $alias A grouped class name of the session model to mock.
|
47 |
+
*
|
48 |
+
* @return $this
|
49 |
+
*/
|
50 |
+
protected function replaceSessionByMock($alias) {
|
51 |
+
$session_mock = $this->getModelMockBuilder($alias)
|
52 |
+
->disableOriginalConstructor()
|
53 |
+
->setMethods(array("init"))
|
54 |
+
->getMock();
|
55 |
+
|
56 |
+
$session_mock
|
57 |
+
->expects($this->any())
|
58 |
+
->method("init")
|
59 |
+
->will($this->returnSelf());
|
60 |
+
|
61 |
+
$this->replaceByMock("model", $alias, $session_mock);
|
62 |
+
$this->replaceByMock("singleton", $alias, $session_mock);
|
63 |
+
}
|
64 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Api/data/data_response_data.xml
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<response>success</response>
|
3 |
+
<test>test</test>
|
4 |
+
<camelCase>test</camelCase>
|
5 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/data_response_failure.xml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<response>failure</response>
|
3 |
+
<message>Test failure message</message>
|
4 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/data_response_no_response.xml
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<message>Test message</message>
|
3 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/data_response_success.xml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<response>success</response>
|
3 |
+
<customerId>116</customerId>
|
4 |
+
<webstores>
|
5 |
+
<webstore>
|
6 |
+
<jsApiKey>klevu-1396353366396116</jsApiKey>
|
7 |
+
<restApiKey>M5NjM1MzM2NjM5NjExNjpLbGV2dS1nbWFpMjZ0djE2</restApiKey>
|
8 |
+
<storeName>storeName</storeName>
|
9 |
+
<testAccountEnabled>true</testAccountEnabled>
|
10 |
+
</webstore>
|
11 |
+
<webstore>
|
12 |
+
<jsApiKey>klevu-1396353407457116</jsApiKey>
|
13 |
+
<restApiKey>M5NjM1MzQwNzQ1NzExNjpLbGV2dS1ka2hzMjZqYnNx</restApiKey>
|
14 |
+
<storeName>storeName</storeName>
|
15 |
+
<testAccountEnabled>true</testAccountEnabled>
|
16 |
+
</webstore>
|
17 |
+
</webstores>
|
18 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/data_response_success_only.xml
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<response>success</response>
|
3 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/message_response_failure.xml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<message>
|
2 |
+
<status>FAILURE</status>
|
3 |
+
<msg>Failed test status</msg>
|
4 |
+
</message>
|
app/code/community/Klevu/Search/Test/Model/Api/data/message_response_missing_message.xml
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<message>
|
2 |
+
<status>SUCCESS</status>
|
3 |
+
</message>
|
app/code/community/Klevu/Search/Test/Model/Api/data/message_response_missing_status.xml
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<message>
|
2 |
+
<msg>Test response with no status</msg>
|
3 |
+
</message>
|
app/code/community/Klevu/Search/Test/Model/Api/data/message_response_session_id.xml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<message>
|
2 |
+
<status>SUCCESS</status>
|
3 |
+
<sessionId>Klevu-session-1234567890</sessionId>
|
4 |
+
</message>
|
app/code/community/Klevu/Search/Test/Model/Api/data/message_response_success.xml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<message>
|
2 |
+
<status>SUCCESS</status>
|
3 |
+
<msg>Successful test status</msg>
|
4 |
+
</message>
|
app/code/community/Klevu/Search/Test/Model/Api/data/response_malformed.xml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<response>success</response>
|
3 |
+
</message>
|
4 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/response_noxml.xml
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
TEST
|
app/code/community/Klevu/Search/Test/Model/Api/data/response_valid.xml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<response>success</response>
|
3 |
+
<message>Successful test response</message>
|
4 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/search_response_empty.xml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<data>
|
3 |
+
<meta>
|
4 |
+
<totalResultsFound>0</totalResultsFound>
|
5 |
+
<typeOfQuery>WILDCARD_AND</typeOfQuery>
|
6 |
+
<paginationStartFrom>0</paginationStartFrom>
|
7 |
+
<noOfResults>9</noOfResults>
|
8 |
+
</meta>
|
9 |
+
<filters>
|
10 |
+
<filter type="other" label="CATEGORY" key="category">
|
11 |
+
<option name="Default Category " value="category:shirts" count="3" selected="false"/>
|
12 |
+
</filter>
|
13 |
+
<filter type="other" label="PRICE RANGE" key="Price Range">
|
14 |
+
<option name="0 - 49" value="klevu_price:0 - 49" count="3" selected="false" />
|
15 |
+
<option name="0 - 49" value="klevu_price:50 - 99" count="4" selected="false" />
|
16 |
+
</filter>
|
17 |
+
</filters>
|
18 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/search_response_paged.xml
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<data>
|
3 |
+
<result>
|
4 |
+
<id>3</id>
|
5 |
+
<itemGroupId>3</itemGroupId>
|
6 |
+
</result>
|
7 |
+
<meta>
|
8 |
+
<totalResultsFound>10</totalResultsFound>
|
9 |
+
<typeOfQuery>WILDCARD_AND</typeOfQuery>
|
10 |
+
<paginationStartFrom>9</paginationStartFrom>
|
11 |
+
<noOfResults>9</noOfResults>
|
12 |
+
</meta>
|
13 |
+
<filters>
|
14 |
+
<filter type="other" label="CATEGORY" key="category">
|
15 |
+
<option name="Default Category " value="category:shirts" count="3" selected="false"/>
|
16 |
+
</filter>
|
17 |
+
<filter type="other" label="PRICE RANGE" key="Price Range">
|
18 |
+
<option name="0 - 49" value="klevu_price:0 - 49" count="3" selected="false" />
|
19 |
+
<option name="0 - 49" value="klevu_price:50 - 99" count="4" selected="false" />
|
20 |
+
</filter>
|
21 |
+
</filters>
|
22 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/search_response_sorted.xml
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<data>
|
3 |
+
<result>
|
4 |
+
<id>2</id>
|
5 |
+
<itemGroupId>2</itemGroupId>
|
6 |
+
</result>
|
7 |
+
<result>
|
8 |
+
<id>1</id>
|
9 |
+
<itemGroupId>1</itemGroupId>
|
10 |
+
</result>
|
11 |
+
<result>
|
12 |
+
<id>3</id>
|
13 |
+
<itemGroupId>3</itemGroupId>
|
14 |
+
</result>
|
15 |
+
<meta>
|
16 |
+
<totalResultsFound>3</totalResultsFound>
|
17 |
+
<typeOfQuery>WILDCARD_AND</typeOfQuery>
|
18 |
+
<paginationStartFrom>0</paginationStartFrom>
|
19 |
+
<noOfResults>9</noOfResults>
|
20 |
+
</meta>
|
21 |
+
<filters>
|
22 |
+
<filter type="other" label="CATEGORY" key="category">
|
23 |
+
<option name="Default Category " value="category:shirts" count="3" selected="false"/>
|
24 |
+
</filter>
|
25 |
+
<filter type="other" label="PRICE RANGE" key="Price Range">
|
26 |
+
<option name="0 - 49" value="klevu_price:0 - 49" count="3" selected="false" />
|
27 |
+
<option name="0 - 49" value="klevu_price:50 - 99" count="4" selected="false" />
|
28 |
+
</filter>
|
29 |
+
</filters>
|
30 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/search_response_success.xml
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<data>
|
3 |
+
<result>
|
4 |
+
<id>3</id>
|
5 |
+
<itemGroupId>3</itemGroupId>
|
6 |
+
</result>
|
7 |
+
<result>
|
8 |
+
<id>2</id>
|
9 |
+
<itemGroupId>2</itemGroupId>
|
10 |
+
</result>
|
11 |
+
<result>
|
12 |
+
<id>1</id>
|
13 |
+
<itemGroupId>1</itemGroupId>
|
14 |
+
</result>
|
15 |
+
<meta>
|
16 |
+
<totalResultsFound>3</totalResultsFound>
|
17 |
+
<typeOfQuery>WILDCARD_AND</typeOfQuery>
|
18 |
+
<paginationStartFrom>0</paginationStartFrom>
|
19 |
+
<noOfResults>9</noOfResults>
|
20 |
+
</meta>
|
21 |
+
<filters>
|
22 |
+
<filter type="other" label="CATEGORY" key="category">
|
23 |
+
<option name="Test Category " value="category:shirts" count="3" selected="false"/>
|
24 |
+
</filter>
|
25 |
+
<filter type="other" label="PRICE RANGE" key="Price Range">
|
26 |
+
<option name="0 - 49" value="klevu_price:0 - 49" count="3" selected="false" />
|
27 |
+
<option name="0 - 49" value="klevu_price:50 - 99" count="4" selected="false" />
|
28 |
+
</filter>
|
29 |
+
</filters>
|
30 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/startsession_response_success.xml
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
2 |
+
<message>
|
3 |
+
<status>SUCCESS</status>
|
4 |
+
<sessionId>Klevu_251-klevu-139811752368742_1399297005734</sessionId>
|
5 |
+
</message>
|
app/code/community/Klevu/Search/Test/Model/Api/data/timezone_response_no_data.xml
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<response>success</response>
|
3 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/timezone_response_no_status.xml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<timezone>Europe/London</timezone>
|
3 |
+
<timezone>GMT</timezone>
|
4 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/timezone_response_with_failure.xml
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<response>failure</response>
|
3 |
+
<timezone>Europe/London</timezone>
|
4 |
+
<timezone>GMT</timezone>
|
5 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Api/data/timezone_response_with_success.xml
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<data>
|
2 |
+
<response>success</response>
|
3 |
+
<timezone>Europe/London</timezone>
|
4 |
+
<timezone>GMT</timezone>
|
5 |
+
</data>
|
app/code/community/Klevu/Search/Test/Model/Config/Log/Level.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Config_Log_Level extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
*/
|
8 |
+
public function testGetValue() {
|
9 |
+
$model = Mage::getModel('klevu_search/config_log_level');
|
10 |
+
|
11 |
+
// Test the default value
|
12 |
+
$this->assertEquals(Zend_Log::WARN, $model->getValue(), "getValue() returned an incorrect default value.");
|
13 |
+
|
14 |
+
// Test a set value
|
15 |
+
$model->setValue(Zend_Log::INFO);
|
16 |
+
|
17 |
+
$this->assertEquals(Zend_Log::INFO, $model->getValue(), "getValue() didn't return the value set.");
|
18 |
+
}
|
19 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Notification.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Notification extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
protected function tearDown() {
|
6 |
+
$resource = Mage::getModel("core/resource");
|
7 |
+
$resource->getConnection("core_write")->delete($resource->getTableName("klevu_search/notification"));
|
8 |
+
|
9 |
+
parent::tearDown();
|
10 |
+
}
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @test
|
14 |
+
* @loadFixture
|
15 |
+
*/
|
16 |
+
public function testLoad() {
|
17 |
+
$notification = Mage::getModel("klevu_search/notification")->load(1);
|
18 |
+
|
19 |
+
$this->assertEquals(1, $notification->getId());
|
20 |
+
$this->assertEquals("2014-05-13 11:08:00", $notification->getDate());
|
21 |
+
$this->assertEquals("test", $notification->getType());
|
22 |
+
$this->assertEquals("Testing", $notification->getMessage());
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @test
|
27 |
+
*/
|
28 |
+
public function testSave() {
|
29 |
+
$notification = Mage::getModel("klevu_search/notification");
|
30 |
+
|
31 |
+
$notification->setData(array(
|
32 |
+
"type" => "test",
|
33 |
+
"message" => "Testing"
|
34 |
+
));
|
35 |
+
|
36 |
+
$notification->save();
|
37 |
+
|
38 |
+
$this->assertNotNull($notification->getId());
|
39 |
+
|
40 |
+
$result = Mage::getModel("klevu_search/notification")->load($notification->getId());
|
41 |
+
|
42 |
+
$this->assertEquals($result->getId(), $result->getId());
|
43 |
+
$this->assertNotNull($result->getDate());
|
44 |
+
$this->assertEquals("test", $result->getType());
|
45 |
+
$this->assertEquals("Testing", $result->getMessage());
|
46 |
+
}
|
47 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Notification/fixtures/testLoad.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
tables:
|
2 |
+
klevu_search/notification:
|
3 |
+
-
|
4 |
+
id: 1
|
5 |
+
date: 2014-05-13 11:08:00
|
6 |
+
type: test
|
7 |
+
message: Testing
|
app/code/community/Klevu/Search/Test/Model/Observer.php
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Observer extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
public function setUp() {
|
6 |
+
parent::setUp();
|
7 |
+
|
8 |
+
$collection = $this->getProductSyncCronScheduleCollection();
|
9 |
+
foreach ($collection as $item) {
|
10 |
+
$item->delete();
|
11 |
+
}
|
12 |
+
|
13 |
+
$collection = $this->getOrderSyncCronScheduleCollection();
|
14 |
+
foreach ($collection as $item) {
|
15 |
+
$item->delete();
|
16 |
+
}
|
17 |
+
}
|
18 |
+
|
19 |
+
public function tearDown() {
|
20 |
+
$collection = $this->getProductSyncCronScheduleCollection();
|
21 |
+
foreach ($collection as $item) {
|
22 |
+
$item->delete();
|
23 |
+
}
|
24 |
+
|
25 |
+
$resource = Mage::getModel("core/resource");
|
26 |
+
$resource->getConnection("core_write")->delete($resource->getTableName("klevu_search/order_sync"));
|
27 |
+
|
28 |
+
parent::tearDown();
|
29 |
+
}
|
30 |
+
|
31 |
+
public function testScheduleProductSync() {
|
32 |
+
$observer = Mage::getModel("klevu_search/observer");
|
33 |
+
|
34 |
+
$observer->scheduleProductSync(new Varien_Event_Observer());
|
35 |
+
|
36 |
+
$this->assertEquals(1, $this->getProductSyncCronScheduleCollection()->getSize(),
|
37 |
+
"Failed to assert that scheduleProductSync() schedules the Product Sync cron when called.");
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @test
|
42 |
+
* @loadFixture
|
43 |
+
*/
|
44 |
+
public function testScheduleOrderSync() {
|
45 |
+
$model = Mage::getModel("klevu_search/observer");
|
46 |
+
|
47 |
+
$order = Mage::getModel("sales/order")->load(1);
|
48 |
+
$event = new Varien_Event();
|
49 |
+
$event->addData(array(
|
50 |
+
"event_name" => "sales_order_place_after",
|
51 |
+
"order" => $order
|
52 |
+
));
|
53 |
+
$observer = new Varien_Event_Observer();
|
54 |
+
$observer->addData(array("event" => $event));
|
55 |
+
|
56 |
+
$model->scheduleOrderSync($observer);
|
57 |
+
|
58 |
+
$this->assertEquals(array(array("order_item_id" => "2")), $this->getOrderSyncQueue());
|
59 |
+
|
60 |
+
$this->assertEquals(1, $this->getOrderSyncCronScheduleCollection()->getSize(),
|
61 |
+
"Failed to assert that scheduleOrderSync() schedules the Order Sync cron when called."
|
62 |
+
);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Return a cron/schedule collection filtered for Product Sync jobs only.
|
67 |
+
*
|
68 |
+
* @return Mage_Cron_Model_Mysql4_Schedule_Collection
|
69 |
+
*/
|
70 |
+
protected function getProductSyncCronScheduleCollection() {
|
71 |
+
return Mage::getResourceModel("cron/schedule_collection")
|
72 |
+
->addFieldToFilter("job_code", Mage::getModel("klevu_search/product_sync")->getJobCode());
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Return a cron/schedule collection filtered for Order Sync jobs only.
|
77 |
+
*
|
78 |
+
* @return Mage_Cron_Model_Mysql4_Schedule_Collection
|
79 |
+
*/
|
80 |
+
protected function getOrderSyncCronScheduleCollection() {
|
81 |
+
return Mage::getResourceModel("cron/schedule_collection")
|
82 |
+
->addFieldToFilter("job_code", Mage::getModel("klevu_search/order_sync")->getJobCode());
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Return all items in the Order Sync queue.
|
87 |
+
*
|
88 |
+
* @return array
|
89 |
+
*/
|
90 |
+
protected function getOrderSyncQueue() {
|
91 |
+
$resource = Mage::getModel("core/resource");
|
92 |
+
$connection = $resource->getConnection("core_write");
|
93 |
+
return $connection->fetchAll($connection
|
94 |
+
->select()
|
95 |
+
->from($resource->getTableName("klevu_search/order_sync"))
|
96 |
+
);
|
97 |
+
}
|
98 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Observer/fixtures/testScheduleOrderSync.yaml
ADDED
@@ -0,0 +1,320 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 1
|
3 |
+
default/klevu_search/general/test_mode: 1
|
4 |
+
default/klevu_search/general/test_js_api_key: test-api-key
|
5 |
+
default/klevu_search/order_sync/enabled: 2
|
6 |
+
tables:
|
7 |
+
sales_flat_order:
|
8 |
+
-
|
9 |
+
entity_id: 1
|
10 |
+
state: new
|
11 |
+
status: pending
|
12 |
+
coupon_code: null
|
13 |
+
protect_code: bbc820
|
14 |
+
shipping_description: Flat Rate - Fixed
|
15 |
+
is_virtual: 0
|
16 |
+
store_id: 1
|
17 |
+
customer_id: null
|
18 |
+
base_discount_amount: 0
|
19 |
+
base_discount_canceled: null
|
20 |
+
base_discount_invoiced: null
|
21 |
+
base_discount_refunded: null
|
22 |
+
base_grand_total: 139.99
|
23 |
+
base_shipping_amount: 5
|
24 |
+
base_shipping_canceled: null
|
25 |
+
base_shipping_invoiced: null
|
26 |
+
base_shipping_refunded: null
|
27 |
+
base_shipping_tax_amount: 0
|
28 |
+
base_shipping_tax_refunded: null
|
29 |
+
base_subtotal: 134.99
|
30 |
+
base_subtotal_canceled: null
|
31 |
+
base_subtotal_invoiced: null
|
32 |
+
base_subtotal_refunded: null
|
33 |
+
base_tax_amount: 0
|
34 |
+
base_tax_canceled: null
|
35 |
+
base_tax_invoiced: null
|
36 |
+
base_tax_refunded: null
|
37 |
+
base_to_global_rate: 1
|
38 |
+
base_to_order_rate: 1
|
39 |
+
base_total_canceled: null
|
40 |
+
base_total_invoiced: null
|
41 |
+
base_total_invoiced_cost: null
|
42 |
+
base_total_offline_refunded: null
|
43 |
+
base_total_online_refunded: null
|
44 |
+
base_total_paid: null
|
45 |
+
base_total_qty_ordered: null
|
46 |
+
base_total_refunded: null
|
47 |
+
discount_amount: 0
|
48 |
+
discount_canceled: null
|
49 |
+
discount_invoiced: null
|
50 |
+
discount_refunded: null
|
51 |
+
grand_total: 139.99
|
52 |
+
shipping_amount: 5
|
53 |
+
shipping_canceled: null
|
54 |
+
shipping_invoiced: null
|
55 |
+
shipping_refunded: null
|
56 |
+
shipping_tax_amount: 0
|
57 |
+
shipping_tax_refunded: null
|
58 |
+
store_to_base_rate: 1
|
59 |
+
store_to_order_rate: 1
|
60 |
+
subtotal: 134.99
|
61 |
+
subtotal_canceled: null
|
62 |
+
subtotal_invoiced: null
|
63 |
+
subtotal_refunded: null
|
64 |
+
tax_amount: 0
|
65 |
+
tax_canceled: null
|
66 |
+
tax_invoiced: null
|
67 |
+
tax_refunded: null
|
68 |
+
total_canceled: null
|
69 |
+
total_invoiced: null
|
70 |
+
total_offline_refunded: null
|
71 |
+
total_online_refunded: null
|
72 |
+
total_paid: null
|
73 |
+
total_qty_ordered: 1
|
74 |
+
total_refunded: null
|
75 |
+
can_ship_partially: null
|
76 |
+
can_ship_partially_item: null
|
77 |
+
customer_is_guest: 1
|
78 |
+
customer_note_notify: 1
|
79 |
+
billing_address_id: 1
|
80 |
+
customer_group_id: 0
|
81 |
+
edit_increment: null
|
82 |
+
email_sent: 1
|
83 |
+
forced_shipment_with_invoice: null
|
84 |
+
gift_message_id: null
|
85 |
+
payment_auth_expiration: null
|
86 |
+
paypal_ipn_customer_notified: null
|
87 |
+
quote_address_id: null
|
88 |
+
quote_id: 3
|
89 |
+
shipping_address_id: 2
|
90 |
+
adjustment_negative: null
|
91 |
+
adjustment_positive: null
|
92 |
+
base_adjustment_negative: null
|
93 |
+
base_adjustment_positive: null
|
94 |
+
base_shipping_discount_amount: 0
|
95 |
+
base_subtotal_incl_tax: 134.99
|
96 |
+
base_total_due: null
|
97 |
+
payment_authorization_amount: null
|
98 |
+
shipping_discount_amount: 0
|
99 |
+
subtotal_incl_tax: 134.99
|
100 |
+
total_due: null
|
101 |
+
weight: 3
|
102 |
+
customer_dob: null
|
103 |
+
increment_id: 100000001
|
104 |
+
applied_rule_ids: null
|
105 |
+
base_currency_code: GBP
|
106 |
+
customer_email: tomas.gerulaitis@meanbee.com
|
107 |
+
customer_firstname: Tomas
|
108 |
+
customer_lastname: Gerulaitis
|
109 |
+
customer_middlename: null
|
110 |
+
customer_prefix: null
|
111 |
+
customer_suffix: null
|
112 |
+
customer_taxvat: null
|
113 |
+
discount_description: null
|
114 |
+
ext_customer_id: null
|
115 |
+
ext_order_id: null
|
116 |
+
global_currency_code: GBP
|
117 |
+
hold_before_state: null
|
118 |
+
hold_before_status: null
|
119 |
+
order_currency_code: GBP
|
120 |
+
original_increment_id: null
|
121 |
+
relation_child_id: null
|
122 |
+
relation_child_real_id: null
|
123 |
+
relation_parent_id: null
|
124 |
+
relation_parent_real_id: null
|
125 |
+
remote_ip: 127.0.0.1
|
126 |
+
shipping_method: flatrate_flatrate
|
127 |
+
store_currency_code: GBP
|
128 |
+
store_name: Main Website, Main Store, English
|
129 |
+
x_forwarded_for: null
|
130 |
+
customer_note: null
|
131 |
+
created_at: 2014-05-15 16:05:21
|
132 |
+
updated_at: 2014-05-15 16:05:21
|
133 |
+
total_item_count: 1
|
134 |
+
customer_gender: null
|
135 |
+
base_custbalance_amount: null
|
136 |
+
currency_base_id: null
|
137 |
+
currency_code: null
|
138 |
+
currency_rate: null
|
139 |
+
custbalance_amount: null
|
140 |
+
is_hold: null
|
141 |
+
is_multi_payment: null
|
142 |
+
real_order_id: null
|
143 |
+
tax_percent: null
|
144 |
+
tracking_numbers: null
|
145 |
+
hidden_tax_amount: 0
|
146 |
+
base_hidden_tax_amount: 0
|
147 |
+
shipping_hidden_tax_amount: 0
|
148 |
+
base_shipping_hidden_tax_amnt: 0
|
149 |
+
hidden_tax_invoiced: null
|
150 |
+
base_hidden_tax_invoiced: null
|
151 |
+
hidden_tax_refunded: null
|
152 |
+
base_hidden_tax_refunded: null
|
153 |
+
shipping_incl_tax: 5
|
154 |
+
base_shipping_incl_tax: 5
|
155 |
+
coupon_rule_name: null
|
156 |
+
sales_flat_order_item:
|
157 |
+
-
|
158 |
+
item_id: 1
|
159 |
+
order_id: 1
|
160 |
+
parent_item_id: null
|
161 |
+
quote_item_id: 1
|
162 |
+
store_id: 1
|
163 |
+
created_at: 2014-05-15 16:05:21
|
164 |
+
updated_at: 2014-05-15 16:05:21
|
165 |
+
product_id: 93
|
166 |
+
product_type: configurable
|
167 |
+
product_options: a:6:{s:15:"info_buyRequest";a:6:{s:4:"uenc";s:100:"aHR0cDovL3NreXdhcnAubG9jYWwvbWVhbmJlZS9rbGV2dS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1sP19fX1NJRD1V";s:7:"product";s:2:"93";s:8:"form_key";s:16:"L9pfTdY6fCBMRa3z";s:15:"related_product";s:0:"";s:15:"super_attribute";a:1:{i:502;s:2:"41";}s:3:"qty";s:1:"1";}s:15:"attributes_info";a:1:{i:0;a:2:{s:5:"label";s:9:"Shoe Size";s:5:"value";s:1:"8";}}s:11:"simple_name";s:30:"ASICS® Men's GEL-Kayano® XII";s:10:"simple_sku";s:5:"asc_8";s:20:"product_calculations";i:1;s:13:"shipment_type";i:0;}
|
168 |
+
weight: 3
|
169 |
+
is_virtual: 0
|
170 |
+
sku: asc_8
|
171 |
+
name: ASICS® Men's GEL-Kayano® XII
|
172 |
+
description: null
|
173 |
+
applied_rule_ids: null
|
174 |
+
additional_data: null
|
175 |
+
free_shipping: 0
|
176 |
+
is_qty_decimal: 0
|
177 |
+
no_discount: 0
|
178 |
+
qty_backordered: null
|
179 |
+
qty_canceled: 0
|
180 |
+
qty_invoiced: 0
|
181 |
+
qty_ordered: 1
|
182 |
+
qty_refunded: 0
|
183 |
+
qty_shipped: 0
|
184 |
+
base_cost: 29.99
|
185 |
+
price: 134.99
|
186 |
+
base_price: 134.99
|
187 |
+
original_price: 134.99
|
188 |
+
base_original_price: 134.99
|
189 |
+
tax_percent: 0
|
190 |
+
tax_amount: 0
|
191 |
+
base_tax_amount: 0
|
192 |
+
tax_invoiced: 0
|
193 |
+
base_tax_invoiced: 0
|
194 |
+
discount_percent: 0
|
195 |
+
discount_amount: 0
|
196 |
+
base_discount_amount: 0
|
197 |
+
discount_invoiced: 0
|
198 |
+
base_discount_invoiced: 0
|
199 |
+
amount_refunded: 0
|
200 |
+
base_amount_refunded: 0
|
201 |
+
row_total: 134.99
|
202 |
+
base_row_total: 134.99
|
203 |
+
row_invoiced: 0
|
204 |
+
base_row_invoiced: 0
|
205 |
+
row_weight: 3
|
206 |
+
gift_message_id: null
|
207 |
+
gift_message_available: null
|
208 |
+
base_tax_before_discount: null
|
209 |
+
tax_before_discount: null
|
210 |
+
weee_tax_applied: a:0:{}
|
211 |
+
weee_tax_applied_amount: 0
|
212 |
+
weee_tax_applied_row_amount: 0
|
213 |
+
base_weee_tax_applied_amount: 0
|
214 |
+
base_weee_tax_applied_row_amnt: 0
|
215 |
+
weee_tax_disposition: 0
|
216 |
+
weee_tax_row_disposition: 0
|
217 |
+
base_weee_tax_disposition: 0
|
218 |
+
base_weee_tax_row_disposition: 0
|
219 |
+
ext_order_item_id: null
|
220 |
+
locked_do_invoice: null
|
221 |
+
locked_do_ship: null
|
222 |
+
price_incl_tax: 134.99
|
223 |
+
base_price_incl_tax: 134.99
|
224 |
+
row_total_incl_tax: 134.99
|
225 |
+
base_row_total_incl_tax: 134.99
|
226 |
+
hidden_tax_amount: 0
|
227 |
+
base_hidden_tax_amount: 0
|
228 |
+
hidden_tax_invoiced: null
|
229 |
+
base_hidden_tax_invoiced: null
|
230 |
+
hidden_tax_refunded: null
|
231 |
+
base_hidden_tax_refunded: null
|
232 |
+
is_nominal: 0
|
233 |
+
tax_canceled: null
|
234 |
+
hidden_tax_canceled: null
|
235 |
+
tax_refunded: null
|
236 |
+
base_tax_refunded: null
|
237 |
+
discount_refunded: null
|
238 |
+
base_discount_refunded: null
|
239 |
+
-
|
240 |
+
item_id: 2
|
241 |
+
order_id: 1
|
242 |
+
parent_item_id: 1
|
243 |
+
quote_item_id: 2
|
244 |
+
store_id: 1
|
245 |
+
created_at: 2014-05-15 16:05:21
|
246 |
+
updated_at: 2014-05-15 16:05:21
|
247 |
+
product_id: 30
|
248 |
+
product_type: simple
|
249 |
+
product_options: a:1:{s:15:"info_buyRequest";a:6:{s:4:"uenc";s:100:"aHR0cDovL3NreXdhcnAubG9jYWwvbWVhbmJlZS9rbGV2dS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1sP19fX1NJRD1V";s:7:"product";s:2:"93";s:8:"form_key";s:16:"L9pfTdY6fCBMRa3z";s:15:"related_product";s:0:"";s:15:"super_attribute";a:1:{i:502;s:2:"41";}s:3:"qty";s:1:"1";}}
|
250 |
+
weight: 3
|
251 |
+
is_virtual: 0
|
252 |
+
sku: asc_8
|
253 |
+
name: ASICS® Men's GEL-Kayano® XII
|
254 |
+
description: null
|
255 |
+
applied_rule_ids: null
|
256 |
+
additional_data: null
|
257 |
+
free_shipping: 0
|
258 |
+
is_qty_decimal: 0
|
259 |
+
no_discount: 0
|
260 |
+
qty_backordered: null
|
261 |
+
qty_canceled: 0
|
262 |
+
qty_invoiced: 0
|
263 |
+
qty_ordered: 1
|
264 |
+
qty_refunded: 0
|
265 |
+
qty_shipped: 0
|
266 |
+
base_cost: 29.99
|
267 |
+
price: 0
|
268 |
+
base_price: 0
|
269 |
+
original_price: 0
|
270 |
+
base_original_price: null
|
271 |
+
tax_percent: 0
|
272 |
+
tax_amount: 0
|
273 |
+
base_tax_amount: 0
|
274 |
+
tax_invoiced: 0
|
275 |
+
base_tax_invoiced: 0
|
276 |
+
discount_percent: 0
|
277 |
+
discount_amount: 0
|
278 |
+
base_discount_amount: 0
|
279 |
+
discount_invoiced: 0
|
280 |
+
base_discount_invoiced: 0
|
281 |
+
amount_refunded: 0
|
282 |
+
base_amount_refunded: 0
|
283 |
+
row_total: 0
|
284 |
+
base_row_total: 0
|
285 |
+
row_invoiced: 0
|
286 |
+
base_row_invoiced: 0
|
287 |
+
row_weight: 0
|
288 |
+
gift_message_id: null
|
289 |
+
gift_message_available: null
|
290 |
+
base_tax_before_discount: null
|
291 |
+
tax_before_discount: null
|
292 |
+
weee_tax_applied: a:0:{}
|
293 |
+
weee_tax_applied_amount: 0
|
294 |
+
weee_tax_applied_row_amount: 0
|
295 |
+
base_weee_tax_applied_amount: 0
|
296 |
+
base_weee_tax_applied_row_amnt: null
|
297 |
+
weee_tax_disposition: 0
|
298 |
+
weee_tax_row_disposition: 0
|
299 |
+
base_weee_tax_disposition: 0
|
300 |
+
base_weee_tax_row_disposition: 0
|
301 |
+
ext_order_item_id: null
|
302 |
+
locked_do_invoice: null
|
303 |
+
locked_do_ship: null
|
304 |
+
price_incl_tax: null
|
305 |
+
base_price_incl_tax: null
|
306 |
+
row_total_incl_tax: null
|
307 |
+
base_row_total_incl_tax: null
|
308 |
+
hidden_tax_amount: null
|
309 |
+
base_hidden_tax_amount: null
|
310 |
+
hidden_tax_invoiced: null
|
311 |
+
base_hidden_tax_invoiced: null
|
312 |
+
hidden_tax_refunded: null
|
313 |
+
base_hidden_tax_refunded: null
|
314 |
+
is_nominal: 0
|
315 |
+
tax_canceled: null
|
316 |
+
hidden_tax_canceled: null
|
317 |
+
tax_refunded: null
|
318 |
+
base_tax_refunded: null
|
319 |
+
discount_refunded: null
|
320 |
+
base_discount_refunded: null
|
app/code/community/Klevu/Search/Test/Model/Order/Sync.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Order_Sync extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
protected function tearDown() {
|
6 |
+
$resource = Mage::getModel("core/resource");
|
7 |
+
$connection = $resource->getConnection("core_write");
|
8 |
+
|
9 |
+
$connection->delete($resource->getTableName("klevu_search/order_sync"));
|
10 |
+
|
11 |
+
parent::tearDown();
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @test
|
16 |
+
* @loadFixture
|
17 |
+
*/
|
18 |
+
public function testAddOrderToQueue() {
|
19 |
+
$order = Mage::getModel("sales/order");
|
20 |
+
$order->load(1);
|
21 |
+
|
22 |
+
$model = Mage::getModel("klevu_search/order_sync");
|
23 |
+
$model->addOrderToQueue($order);
|
24 |
+
|
25 |
+
$this->assertEquals(array(array("order_item_id" => "2")), $this->getOrderSyncTableContents(),
|
26 |
+
"Failed asserting that addOrderToQueue() adds the child configurable item to Order Sync queue."
|
27 |
+
);
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @test
|
32 |
+
* @loadFixture
|
33 |
+
*/
|
34 |
+
public function testClearQueue() {
|
35 |
+
$model = Mage::getModel("klevu_search/order_sync");
|
36 |
+
|
37 |
+
$model->clearQueue(1);
|
38 |
+
|
39 |
+
$this->assertEquals(array(array("order_item_id" => "3")), $this->getOrderSyncTableContents(),
|
40 |
+
"Failed asserting that clearQueue() only removes order items for the store given."
|
41 |
+
);
|
42 |
+
|
43 |
+
$model->clearQueue();
|
44 |
+
|
45 |
+
$this->assertEmpty($this->getOrderSyncTableContents(),
|
46 |
+
"Failed asserting that clearQueue() removes all items if no store is given."
|
47 |
+
);
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @test
|
52 |
+
* @loadFixture
|
53 |
+
*/
|
54 |
+
public function testRun() {
|
55 |
+
$this->replaceApiActionByMock(
|
56 |
+
"klevu_search/api_action_producttracking",
|
57 |
+
Mage::getModel("klevu_search/api_response_data")->setRawResponse(
|
58 |
+
new Zend_Http_Response(200, array(), $this->getDataFileContents("data_response_success_only.xml"))
|
59 |
+
)
|
60 |
+
);
|
61 |
+
|
62 |
+
$model = $this->getModelMock("klevu_search/order_sync", array("isRunning", "isBelowMemoryLimit"));
|
63 |
+
$model
|
64 |
+
->expects($this->any())
|
65 |
+
->method("isRunning")
|
66 |
+
->will($this->returnValue(false));
|
67 |
+
$model
|
68 |
+
->expects($this->any())
|
69 |
+
->method("isBelowMemoryLimit")
|
70 |
+
->will($this->returnValue(true));
|
71 |
+
|
72 |
+
$model->run();
|
73 |
+
|
74 |
+
$this->assertEmpty($this->getOrderSyncTableContents(),
|
75 |
+
"Failed asserting that order item gets removed from the sync queue."
|
76 |
+
);
|
77 |
+
}
|
78 |
+
|
79 |
+
protected function getOrderSyncTableContents($where = null) {
|
80 |
+
$resource = Mage::getModel("core/resource");
|
81 |
+
$connection = $resource->getConnection("core_write");
|
82 |
+
|
83 |
+
$select = $connection->select()->from($resource->getTableName("klevu_search/order_sync"));
|
84 |
+
if ($where) {
|
85 |
+
$select->where($where);
|
86 |
+
}
|
87 |
+
|
88 |
+
return $connection->fetchAll($select);
|
89 |
+
}
|
90 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Order/Sync/fixtures/testAddOrderToQueue.yaml
ADDED
@@ -0,0 +1,319 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 1
|
3 |
+
default/klevu_search/general/js_api_key: test-api-key
|
4 |
+
default/klevu_search/order_sync/enabled: 2
|
5 |
+
tables:
|
6 |
+
sales_flat_order:
|
7 |
+
-
|
8 |
+
entity_id: 1
|
9 |
+
state: new
|
10 |
+
status: pending
|
11 |
+
coupon_code: null
|
12 |
+
protect_code: bbc820
|
13 |
+
shipping_description: Flat Rate - Fixed
|
14 |
+
is_virtual: 0
|
15 |
+
store_id: 1
|
16 |
+
customer_id: null
|
17 |
+
base_discount_amount: 0
|
18 |
+
base_discount_canceled: null
|
19 |
+
base_discount_invoiced: null
|
20 |
+
base_discount_refunded: null
|
21 |
+
base_grand_total: 139.99
|
22 |
+
base_shipping_amount: 5
|
23 |
+
base_shipping_canceled: null
|
24 |
+
base_shipping_invoiced: null
|
25 |
+
base_shipping_refunded: null
|
26 |
+
base_shipping_tax_amount: 0
|
27 |
+
base_shipping_tax_refunded: null
|
28 |
+
base_subtotal: 134.99
|
29 |
+
base_subtotal_canceled: null
|
30 |
+
base_subtotal_invoiced: null
|
31 |
+
base_subtotal_refunded: null
|
32 |
+
base_tax_amount: 0
|
33 |
+
base_tax_canceled: null
|
34 |
+
base_tax_invoiced: null
|
35 |
+
base_tax_refunded: null
|
36 |
+
base_to_global_rate: 1
|
37 |
+
base_to_order_rate: 1
|
38 |
+
base_total_canceled: null
|
39 |
+
base_total_invoiced: null
|
40 |
+
base_total_invoiced_cost: null
|
41 |
+
base_total_offline_refunded: null
|
42 |
+
base_total_online_refunded: null
|
43 |
+
base_total_paid: null
|
44 |
+
base_total_qty_ordered: null
|
45 |
+
base_total_refunded: null
|
46 |
+
discount_amount: 0
|
47 |
+
discount_canceled: null
|
48 |
+
discount_invoiced: null
|
49 |
+
discount_refunded: null
|
50 |
+
grand_total: 139.99
|
51 |
+
shipping_amount: 5
|
52 |
+
shipping_canceled: null
|
53 |
+
shipping_invoiced: null
|
54 |
+
shipping_refunded: null
|
55 |
+
shipping_tax_amount: 0
|
56 |
+
shipping_tax_refunded: null
|
57 |
+
store_to_base_rate: 1
|
58 |
+
store_to_order_rate: 1
|
59 |
+
subtotal: 134.99
|
60 |
+
subtotal_canceled: null
|
61 |
+
subtotal_invoiced: null
|
62 |
+
subtotal_refunded: null
|
63 |
+
tax_amount: 0
|
64 |
+
tax_canceled: null
|
65 |
+
tax_invoiced: null
|
66 |
+
tax_refunded: null
|
67 |
+
total_canceled: null
|
68 |
+
total_invoiced: null
|
69 |
+
total_offline_refunded: null
|
70 |
+
total_online_refunded: null
|
71 |
+
total_paid: null
|
72 |
+
total_qty_ordered: 1
|
73 |
+
total_refunded: null
|
74 |
+
can_ship_partially: null
|
75 |
+
can_ship_partially_item: null
|
76 |
+
customer_is_guest: 1
|
77 |
+
customer_note_notify: 1
|
78 |
+
billing_address_id: 1
|
79 |
+
customer_group_id: 0
|
80 |
+
edit_increment: null
|
81 |
+
email_sent: 1
|
82 |
+
forced_shipment_with_invoice: null
|
83 |
+
gift_message_id: null
|
84 |
+
payment_auth_expiration: null
|
85 |
+
paypal_ipn_customer_notified: null
|
86 |
+
quote_address_id: null
|
87 |
+
quote_id: 3
|
88 |
+
shipping_address_id: 2
|
89 |
+
adjustment_negative: null
|
90 |
+
adjustment_positive: null
|
91 |
+
base_adjustment_negative: null
|
92 |
+
base_adjustment_positive: null
|
93 |
+
base_shipping_discount_amount: 0
|
94 |
+
base_subtotal_incl_tax: 134.99
|
95 |
+
base_total_due: null
|
96 |
+
payment_authorization_amount: null
|
97 |
+
shipping_discount_amount: 0
|
98 |
+
subtotal_incl_tax: 134.99
|
99 |
+
total_due: null
|
100 |
+
weight: 3
|
101 |
+
customer_dob: null
|
102 |
+
increment_id: 100000001
|
103 |
+
applied_rule_ids: null
|
104 |
+
base_currency_code: GBP
|
105 |
+
customer_email: tomas.gerulaitis@meanbee.com
|
106 |
+
customer_firstname: Tomas
|
107 |
+
customer_lastname: Gerulaitis
|
108 |
+
customer_middlename: null
|
109 |
+
customer_prefix: null
|
110 |
+
customer_suffix: null
|
111 |
+
customer_taxvat: null
|
112 |
+
discount_description: null
|
113 |
+
ext_customer_id: null
|
114 |
+
ext_order_id: null
|
115 |
+
global_currency_code: GBP
|
116 |
+
hold_before_state: null
|
117 |
+
hold_before_status: null
|
118 |
+
order_currency_code: GBP
|
119 |
+
original_increment_id: null
|
120 |
+
relation_child_id: null
|
121 |
+
relation_child_real_id: null
|
122 |
+
relation_parent_id: null
|
123 |
+
relation_parent_real_id: null
|
124 |
+
remote_ip: 127.0.0.1
|
125 |
+
shipping_method: flatrate_flatrate
|
126 |
+
store_currency_code: GBP
|
127 |
+
store_name: Main Website, Main Store, English
|
128 |
+
x_forwarded_for: null
|
129 |
+
customer_note: null
|
130 |
+
created_at: 2014-05-15 16:05:21
|
131 |
+
updated_at: 2014-05-15 16:05:21
|
132 |
+
total_item_count: 1
|
133 |
+
customer_gender: null
|
134 |
+
base_custbalance_amount: null
|
135 |
+
currency_base_id: null
|
136 |
+
currency_code: null
|
137 |
+
currency_rate: null
|
138 |
+
custbalance_amount: null
|
139 |
+
is_hold: null
|
140 |
+
is_multi_payment: null
|
141 |
+
real_order_id: null
|
142 |
+
tax_percent: null
|
143 |
+
tracking_numbers: null
|
144 |
+
hidden_tax_amount: 0
|
145 |
+
base_hidden_tax_amount: 0
|
146 |
+
shipping_hidden_tax_amount: 0
|
147 |
+
base_shipping_hidden_tax_amnt: 0
|
148 |
+
hidden_tax_invoiced: null
|
149 |
+
base_hidden_tax_invoiced: null
|
150 |
+
hidden_tax_refunded: null
|
151 |
+
base_hidden_tax_refunded: null
|
152 |
+
shipping_incl_tax: 5
|
153 |
+
base_shipping_incl_tax: 5
|
154 |
+
coupon_rule_name: null
|
155 |
+
sales_flat_order_item:
|
156 |
+
-
|
157 |
+
item_id: 1
|
158 |
+
order_id: 1
|
159 |
+
parent_item_id: null
|
160 |
+
quote_item_id: 1
|
161 |
+
store_id: 1
|
162 |
+
created_at: 2014-05-15 16:05:21
|
163 |
+
updated_at: 2014-05-15 16:05:21
|
164 |
+
product_id: 93
|
165 |
+
product_type: configurable
|
166 |
+
product_options: a:6:{s:15:"info_buyRequest";a:6:{s:4:"uenc";s:100:"aHR0cDovL3NreXdhcnAubG9jYWwvbWVhbmJlZS9rbGV2dS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1sP19fX1NJRD1V";s:7:"product";s:2:"93";s:8:"form_key";s:16:"L9pfTdY6fCBMRa3z";s:15:"related_product";s:0:"";s:15:"super_attribute";a:1:{i:502;s:2:"41";}s:3:"qty";s:1:"1";}s:15:"attributes_info";a:1:{i:0;a:2:{s:5:"label";s:9:"Shoe Size";s:5:"value";s:1:"8";}}s:11:"simple_name";s:30:"ASICS® Men's GEL-Kayano® XII";s:10:"simple_sku";s:5:"asc_8";s:20:"product_calculations";i:1;s:13:"shipment_type";i:0;}
|
167 |
+
weight: 3
|
168 |
+
is_virtual: 0
|
169 |
+
sku: asc_8
|
170 |
+
name: ASICS® Men's GEL-Kayano® XII
|
171 |
+
description: null
|
172 |
+
applied_rule_ids: null
|
173 |
+
additional_data: null
|
174 |
+
free_shipping: 0
|
175 |
+
is_qty_decimal: 0
|
176 |
+
no_discount: 0
|
177 |
+
qty_backordered: null
|
178 |
+
qty_canceled: 0
|
179 |
+
qty_invoiced: 0
|
180 |
+
qty_ordered: 1
|
181 |
+
qty_refunded: 0
|
182 |
+
qty_shipped: 0
|
183 |
+
base_cost: 29.99
|
184 |
+
price: 134.99
|
185 |
+
base_price: 134.99
|
186 |
+
original_price: 134.99
|
187 |
+
base_original_price: 134.99
|
188 |
+
tax_percent: 0
|
189 |
+
tax_amount: 0
|
190 |
+
base_tax_amount: 0
|
191 |
+
tax_invoiced: 0
|
192 |
+
base_tax_invoiced: 0
|
193 |
+
discount_percent: 0
|
194 |
+
discount_amount: 0
|
195 |
+
base_discount_amount: 0
|
196 |
+
discount_invoiced: 0
|
197 |
+
base_discount_invoiced: 0
|
198 |
+
amount_refunded: 0
|
199 |
+
base_amount_refunded: 0
|
200 |
+
row_total: 134.99
|
201 |
+
base_row_total: 134.99
|
202 |
+
row_invoiced: 0
|
203 |
+
base_row_invoiced: 0
|
204 |
+
row_weight: 3
|
205 |
+
gift_message_id: null
|
206 |
+
gift_message_available: null
|
207 |
+
base_tax_before_discount: null
|
208 |
+
tax_before_discount: null
|
209 |
+
weee_tax_applied: a:0:{}
|
210 |
+
weee_tax_applied_amount: 0
|
211 |
+
weee_tax_applied_row_amount: 0
|
212 |
+
base_weee_tax_applied_amount: 0
|
213 |
+
base_weee_tax_applied_row_amnt: 0
|
214 |
+
weee_tax_disposition: 0
|
215 |
+
weee_tax_row_disposition: 0
|
216 |
+
base_weee_tax_disposition: 0
|
217 |
+
base_weee_tax_row_disposition: 0
|
218 |
+
ext_order_item_id: null
|
219 |
+
locked_do_invoice: null
|
220 |
+
locked_do_ship: null
|
221 |
+
price_incl_tax: 134.99
|
222 |
+
base_price_incl_tax: 134.99
|
223 |
+
row_total_incl_tax: 134.99
|
224 |
+
base_row_total_incl_tax: 134.99
|
225 |
+
hidden_tax_amount: 0
|
226 |
+
base_hidden_tax_amount: 0
|
227 |
+
hidden_tax_invoiced: null
|
228 |
+
base_hidden_tax_invoiced: null
|
229 |
+
hidden_tax_refunded: null
|
230 |
+
base_hidden_tax_refunded: null
|
231 |
+
is_nominal: 0
|
232 |
+
tax_canceled: null
|
233 |
+
hidden_tax_canceled: null
|
234 |
+
tax_refunded: null
|
235 |
+
base_tax_refunded: null
|
236 |
+
discount_refunded: null
|
237 |
+
base_discount_refunded: null
|
238 |
+
-
|
239 |
+
item_id: 2
|
240 |
+
order_id: 1
|
241 |
+
parent_item_id: 1
|
242 |
+
quote_item_id: 2
|
243 |
+
store_id: 1
|
244 |
+
created_at: 2014-05-15 16:05:21
|
245 |
+
updated_at: 2014-05-15 16:05:21
|
246 |
+
product_id: 30
|
247 |
+
product_type: simple
|
248 |
+
product_options: a:1:{s:15:"info_buyRequest";a:6:{s:4:"uenc";s:100:"aHR0cDovL3NreXdhcnAubG9jYWwvbWVhbmJlZS9rbGV2dS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1sP19fX1NJRD1V";s:7:"product";s:2:"93";s:8:"form_key";s:16:"L9pfTdY6fCBMRa3z";s:15:"related_product";s:0:"";s:15:"super_attribute";a:1:{i:502;s:2:"41";}s:3:"qty";s:1:"1";}}
|
249 |
+
weight: 3
|
250 |
+
is_virtual: 0
|
251 |
+
sku: asc_8
|
252 |
+
name: ASICS® Men's GEL-Kayano® XII
|
253 |
+
description: null
|
254 |
+
applied_rule_ids: null
|
255 |
+
additional_data: null
|
256 |
+
free_shipping: 0
|
257 |
+
is_qty_decimal: 0
|
258 |
+
no_discount: 0
|
259 |
+
qty_backordered: null
|
260 |
+
qty_canceled: 0
|
261 |
+
qty_invoiced: 0
|
262 |
+
qty_ordered: 1
|
263 |
+
qty_refunded: 0
|
264 |
+
qty_shipped: 0
|
265 |
+
base_cost: 29.99
|
266 |
+
price: 0
|
267 |
+
base_price: 0
|
268 |
+
original_price: 0
|
269 |
+
base_original_price: null
|
270 |
+
tax_percent: 0
|
271 |
+
tax_amount: 0
|
272 |
+
base_tax_amount: 0
|
273 |
+
tax_invoiced: 0
|
274 |
+
base_tax_invoiced: 0
|
275 |
+
discount_percent: 0
|
276 |
+
discount_amount: 0
|
277 |
+
base_discount_amount: 0
|
278 |
+
discount_invoiced: 0
|
279 |
+
base_discount_invoiced: 0
|
280 |
+
amount_refunded: 0
|
281 |
+
base_amount_refunded: 0
|
282 |
+
row_total: 0
|
283 |
+
base_row_total: 0
|
284 |
+
row_invoiced: 0
|
285 |
+
base_row_invoiced: 0
|
286 |
+
row_weight: 0
|
287 |
+
gift_message_id: null
|
288 |
+
gift_message_available: null
|
289 |
+
base_tax_before_discount: null
|
290 |
+
tax_before_discount: null
|
291 |
+
weee_tax_applied: a:0:{}
|
292 |
+
weee_tax_applied_amount: 0
|
293 |
+
weee_tax_applied_row_amount: 0
|
294 |
+
base_weee_tax_applied_amount: 0
|
295 |
+
base_weee_tax_applied_row_amnt: null
|
296 |
+
weee_tax_disposition: 0
|
297 |
+
weee_tax_row_disposition: 0
|
298 |
+
base_weee_tax_disposition: 0
|
299 |
+
base_weee_tax_row_disposition: 0
|
300 |
+
ext_order_item_id: null
|
301 |
+
locked_do_invoice: null
|
302 |
+
locked_do_ship: null
|
303 |
+
price_incl_tax: null
|
304 |
+
base_price_incl_tax: null
|
305 |
+
row_total_incl_tax: null
|
306 |
+
base_row_total_incl_tax: null
|
307 |
+
hidden_tax_amount: null
|
308 |
+
base_hidden_tax_amount: null
|
309 |
+
hidden_tax_invoiced: null
|
310 |
+
base_hidden_tax_invoiced: null
|
311 |
+
hidden_tax_refunded: null
|
312 |
+
base_hidden_tax_refunded: null
|
313 |
+
is_nominal: 0
|
314 |
+
tax_canceled: null
|
315 |
+
hidden_tax_canceled: null
|
316 |
+
tax_refunded: null
|
317 |
+
base_tax_refunded: null
|
318 |
+
discount_refunded: null
|
319 |
+
base_discount_refunded: null
|
app/code/community/Klevu/Search/Test/Model/Order/Sync/fixtures/testClearQueue.yaml
ADDED
@@ -0,0 +1,563 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
scope:
|
2 |
+
store:
|
3 |
+
-
|
4 |
+
store_id: 2
|
5 |
+
website_id: 1
|
6 |
+
group_id: 1
|
7 |
+
code: test
|
8 |
+
name: Test Store
|
9 |
+
is_active: 1
|
10 |
+
config:
|
11 |
+
default/klevu_search/general/enabled: 1
|
12 |
+
default/klevu_search/general/js_api_key: test-api-key
|
13 |
+
default/klevu_search/order_sync/enabled: 2
|
14 |
+
tables:
|
15 |
+
sales_flat_order:
|
16 |
+
-
|
17 |
+
entity_id: 1
|
18 |
+
state: new
|
19 |
+
status: pending
|
20 |
+
coupon_code: null
|
21 |
+
protect_code: bbc820
|
22 |
+
shipping_description: Flat Rate - Fixed
|
23 |
+
is_virtual: 0
|
24 |
+
store_id: 1
|
25 |
+
customer_id: null
|
26 |
+
base_discount_amount: 0
|
27 |
+
base_discount_canceled: null
|
28 |
+
base_discount_invoiced: null
|
29 |
+
base_discount_refunded: null
|
30 |
+
base_grand_total: 139.99
|
31 |
+
base_shipping_amount: 5
|
32 |
+
base_shipping_canceled: null
|
33 |
+
base_shipping_invoiced: null
|
34 |
+
base_shipping_refunded: null
|
35 |
+
base_shipping_tax_amount: 0
|
36 |
+
base_shipping_tax_refunded: null
|
37 |
+
base_subtotal: 134.99
|
38 |
+
base_subtotal_canceled: null
|
39 |
+
base_subtotal_invoiced: null
|
40 |
+
base_subtotal_refunded: null
|
41 |
+
base_tax_amount: 0
|
42 |
+
base_tax_canceled: null
|
43 |
+
base_tax_invoiced: null
|
44 |
+
base_tax_refunded: null
|
45 |
+
base_to_global_rate: 1
|
46 |
+
base_to_order_rate: 1
|
47 |
+
base_total_canceled: null
|
48 |
+
base_total_invoiced: null
|
49 |
+
base_total_invoiced_cost: null
|
50 |
+
base_total_offline_refunded: null
|
51 |
+
base_total_online_refunded: null
|
52 |
+
base_total_paid: null
|
53 |
+
base_total_qty_ordered: null
|
54 |
+
base_total_refunded: null
|
55 |
+
discount_amount: 0
|
56 |
+
discount_canceled: null
|
57 |
+
discount_invoiced: null
|
58 |
+
discount_refunded: null
|
59 |
+
grand_total: 139.99
|
60 |
+
shipping_amount: 5
|
61 |
+
shipping_canceled: null
|
62 |
+
shipping_invoiced: null
|
63 |
+
shipping_refunded: null
|
64 |
+
shipping_tax_amount: 0
|
65 |
+
shipping_tax_refunded: null
|
66 |
+
store_to_base_rate: 1
|
67 |
+
store_to_order_rate: 1
|
68 |
+
subtotal: 134.99
|
69 |
+
subtotal_canceled: null
|
70 |
+
subtotal_invoiced: null
|
71 |
+
subtotal_refunded: null
|
72 |
+
tax_amount: 0
|
73 |
+
tax_canceled: null
|
74 |
+
tax_invoiced: null
|
75 |
+
tax_refunded: null
|
76 |
+
total_canceled: null
|
77 |
+
total_invoiced: null
|
78 |
+
total_offline_refunded: null
|
79 |
+
total_online_refunded: null
|
80 |
+
total_paid: null
|
81 |
+
total_qty_ordered: 1
|
82 |
+
total_refunded: null
|
83 |
+
can_ship_partially: null
|
84 |
+
can_ship_partially_item: null
|
85 |
+
customer_is_guest: 1
|
86 |
+
customer_note_notify: 1
|
87 |
+
billing_address_id: 1
|
88 |
+
customer_group_id: 0
|
89 |
+
edit_increment: null
|
90 |
+
email_sent: 1
|
91 |
+
forced_shipment_with_invoice: null
|
92 |
+
gift_message_id: null
|
93 |
+
payment_auth_expiration: null
|
94 |
+
paypal_ipn_customer_notified: null
|
95 |
+
quote_address_id: null
|
96 |
+
quote_id: 3
|
97 |
+
shipping_address_id: 2
|
98 |
+
adjustment_negative: null
|
99 |
+
adjustment_positive: null
|
100 |
+
base_adjustment_negative: null
|
101 |
+
base_adjustment_positive: null
|
102 |
+
base_shipping_discount_amount: 0
|
103 |
+
base_subtotal_incl_tax: 134.99
|
104 |
+
base_total_due: null
|
105 |
+
payment_authorization_amount: null
|
106 |
+
shipping_discount_amount: 0
|
107 |
+
subtotal_incl_tax: 134.99
|
108 |
+
total_due: null
|
109 |
+
weight: 3
|
110 |
+
customer_dob: null
|
111 |
+
increment_id: 100000001
|
112 |
+
applied_rule_ids: null
|
113 |
+
base_currency_code: GBP
|
114 |
+
customer_email: tomas.gerulaitis@meanbee.com
|
115 |
+
customer_firstname: Tomas
|
116 |
+
customer_lastname: Gerulaitis
|
117 |
+
customer_middlename: null
|
118 |
+
customer_prefix: null
|
119 |
+
customer_suffix: null
|
120 |
+
customer_taxvat: null
|
121 |
+
discount_description: null
|
122 |
+
ext_customer_id: null
|
123 |
+
ext_order_id: null
|
124 |
+
global_currency_code: GBP
|
125 |
+
hold_before_state: null
|
126 |
+
hold_before_status: null
|
127 |
+
order_currency_code: GBP
|
128 |
+
original_increment_id: null
|
129 |
+
relation_child_id: null
|
130 |
+
relation_child_real_id: null
|
131 |
+
relation_parent_id: null
|
132 |
+
relation_parent_real_id: null
|
133 |
+
remote_ip: 127.0.0.1
|
134 |
+
shipping_method: flatrate_flatrate
|
135 |
+
store_currency_code: GBP
|
136 |
+
store_name: Main Website, Main Store, English
|
137 |
+
x_forwarded_for: null
|
138 |
+
customer_note: null
|
139 |
+
created_at: 2014-05-15 16:05:21
|
140 |
+
updated_at: 2014-05-15 16:05:21
|
141 |
+
total_item_count: 1
|
142 |
+
customer_gender: null
|
143 |
+
base_custbalance_amount: null
|
144 |
+
currency_base_id: null
|
145 |
+
currency_code: null
|
146 |
+
currency_rate: null
|
147 |
+
custbalance_amount: null
|
148 |
+
is_hold: null
|
149 |
+
is_multi_payment: null
|
150 |
+
real_order_id: null
|
151 |
+
tax_percent: null
|
152 |
+
tracking_numbers: null
|
153 |
+
hidden_tax_amount: 0
|
154 |
+
base_hidden_tax_amount: 0
|
155 |
+
shipping_hidden_tax_amount: 0
|
156 |
+
base_shipping_hidden_tax_amnt: 0
|
157 |
+
hidden_tax_invoiced: null
|
158 |
+
base_hidden_tax_invoiced: null
|
159 |
+
hidden_tax_refunded: null
|
160 |
+
base_hidden_tax_refunded: null
|
161 |
+
shipping_incl_tax: 5
|
162 |
+
base_shipping_incl_tax: 5
|
163 |
+
coupon_rule_name: null
|
164 |
+
-
|
165 |
+
entity_id: 2
|
166 |
+
state: new
|
167 |
+
status: pending
|
168 |
+
coupon_code: null
|
169 |
+
protect_code: 58acbb
|
170 |
+
shipping_description: Flat Rate - Fixed
|
171 |
+
is_virtual: 0
|
172 |
+
store_id: 2
|
173 |
+
customer_id: null
|
174 |
+
base_discount_amount: 0
|
175 |
+
base_discount_canceled: null
|
176 |
+
base_discount_invoiced: null
|
177 |
+
base_discount_refunded: null
|
178 |
+
base_grand_total: 166.94
|
179 |
+
base_shipping_amount: 5
|
180 |
+
base_shipping_canceled: null
|
181 |
+
base_shipping_invoiced: null
|
182 |
+
base_shipping_refunded: null
|
183 |
+
base_shipping_tax_amount: 0
|
184 |
+
base_shipping_tax_refunded: null
|
185 |
+
base_subtotal: 161.94
|
186 |
+
base_subtotal_canceled: null
|
187 |
+
base_subtotal_invoiced: null
|
188 |
+
base_subtotal_refunded: null
|
189 |
+
base_tax_amount: 0
|
190 |
+
base_tax_canceled: null
|
191 |
+
base_tax_invoiced: null
|
192 |
+
base_tax_refunded: null
|
193 |
+
base_to_global_rate: 1
|
194 |
+
base_to_order_rate: 1
|
195 |
+
base_total_canceled: null
|
196 |
+
base_total_invoiced: null
|
197 |
+
base_total_invoiced_cost: null
|
198 |
+
base_total_offline_refunded: null
|
199 |
+
base_total_online_refunded: null
|
200 |
+
base_total_paid: null
|
201 |
+
base_total_qty_ordered: null
|
202 |
+
base_total_refunded: null
|
203 |
+
discount_amount: 0
|
204 |
+
discount_canceled: null
|
205 |
+
discount_invoiced: null
|
206 |
+
discount_refunded: null
|
207 |
+
grand_total: 166.94
|
208 |
+
shipping_amount: 5
|
209 |
+
shipping_canceled: null
|
210 |
+
shipping_invoiced: null
|
211 |
+
shipping_refunded: null
|
212 |
+
shipping_tax_amount: 0
|
213 |
+
shipping_tax_refunded: null
|
214 |
+
store_to_base_rate: 1
|
215 |
+
store_to_order_rate: 1
|
216 |
+
subtotal: 161.94
|
217 |
+
subtotal_canceled: null
|
218 |
+
subtotal_invoiced: null
|
219 |
+
subtotal_refunded: null
|
220 |
+
tax_amount: 0
|
221 |
+
tax_canceled: null
|
222 |
+
tax_invoiced: null
|
223 |
+
tax_refunded: null
|
224 |
+
total_canceled: null
|
225 |
+
total_invoiced: null
|
226 |
+
total_offline_refunded: null
|
227 |
+
total_online_refunded: null
|
228 |
+
total_paid: null
|
229 |
+
total_qty_ordered: 1
|
230 |
+
total_refunded: null
|
231 |
+
can_ship_partially: null
|
232 |
+
can_ship_partially_item: null
|
233 |
+
customer_is_guest: 1
|
234 |
+
customer_note_notify: 1
|
235 |
+
billing_address_id: 3
|
236 |
+
customer_group_id: 0
|
237 |
+
edit_increment: null
|
238 |
+
email_sent: 1
|
239 |
+
forced_shipment_with_invoice: null
|
240 |
+
gift_message_id: null
|
241 |
+
payment_auth_expiration: null
|
242 |
+
paypal_ipn_customer_notified: null
|
243 |
+
quote_address_id: null
|
244 |
+
quote_id: 4
|
245 |
+
shipping_address_id: 4
|
246 |
+
adjustment_negative: null
|
247 |
+
adjustment_positive: null
|
248 |
+
base_adjustment_negative: null
|
249 |
+
base_adjustment_positive: null
|
250 |
+
base_shipping_discount_amount: 0
|
251 |
+
base_subtotal_incl_tax: 161.94
|
252 |
+
base_total_due: null
|
253 |
+
payment_authorization_amount: null
|
254 |
+
shipping_discount_amount: 0
|
255 |
+
subtotal_incl_tax: 161.94
|
256 |
+
total_due: null
|
257 |
+
weight: 2
|
258 |
+
customer_dob: null
|
259 |
+
increment_id: 300000001
|
260 |
+
applied_rule_ids: null
|
261 |
+
base_currency_code: GBP
|
262 |
+
customer_email: tomas.gerulaitis@meanbee.com
|
263 |
+
customer_firstname: Tomas
|
264 |
+
customer_lastname: Gerulaitis
|
265 |
+
customer_middlename: null
|
266 |
+
customer_prefix: null
|
267 |
+
customer_suffix: null
|
268 |
+
customer_taxvat: null
|
269 |
+
discount_description: null
|
270 |
+
ext_customer_id: null
|
271 |
+
ext_order_id: null
|
272 |
+
global_currency_code: GBP
|
273 |
+
hold_before_state: null
|
274 |
+
hold_before_status: null
|
275 |
+
order_currency_code: GBP
|
276 |
+
original_increment_id: null
|
277 |
+
relation_child_id: null
|
278 |
+
relation_child_real_id: null
|
279 |
+
relation_parent_id: null
|
280 |
+
relation_parent_real_id: null
|
281 |
+
remote_ip: 127.0.0.1
|
282 |
+
shipping_method: flatrate_flatrate
|
283 |
+
store_currency_code: GBP
|
284 |
+
store_name: Main Website, Main Store, French
|
285 |
+
x_forwarded_for: null
|
286 |
+
customer_note: null
|
287 |
+
created_at: 2014-05-26 12:14:20
|
288 |
+
updated_at: 2014-05-26 12:14:20
|
289 |
+
total_item_count: 1
|
290 |
+
customer_gender: null
|
291 |
+
base_custbalance_amount: null
|
292 |
+
currency_base_id: null
|
293 |
+
currency_code: null
|
294 |
+
currency_rate: null
|
295 |
+
custbalance_amount: null
|
296 |
+
is_hold: null
|
297 |
+
is_multi_payment: null
|
298 |
+
real_order_id: null
|
299 |
+
tax_percent: null
|
300 |
+
tracking_numbers: null
|
301 |
+
hidden_tax_amount: 0
|
302 |
+
base_hidden_tax_amount: 0
|
303 |
+
shipping_hidden_tax_amount: 0
|
304 |
+
base_shipping_hidden_tax_amnt: 0
|
305 |
+
hidden_tax_invoiced: null
|
306 |
+
base_hidden_tax_invoiced: null
|
307 |
+
hidden_tax_refunded: null
|
308 |
+
base_hidden_tax_refunded: null
|
309 |
+
shipping_incl_tax: 5
|
310 |
+
base_shipping_incl_tax: 5
|
311 |
+
coupon_rule_name: null
|
312 |
+
sales_flat_order_item:
|
313 |
+
-
|
314 |
+
item_id: 1
|
315 |
+
order_id: 1
|
316 |
+
parent_item_id: null
|
317 |
+
quote_item_id: 1
|
318 |
+
store_id: 1
|
319 |
+
created_at: 2014-05-15 16:05:21
|
320 |
+
updated_at: 2014-05-15 16:05:21
|
321 |
+
product_id: 93
|
322 |
+
product_type: configurable
|
323 |
+
product_options: a:6:{s:15:"info_buyRequest";a:6:{s:4:"uenc";s:100:"aHR0cDovL3NreXdhcnAubG9jYWwvbWVhbmJlZS9rbGV2dS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1sP19fX1NJRD1V";s:7:"product";s:2:"93";s:8:"form_key";s:16:"L9pfTdY6fCBMRa3z";s:15:"related_product";s:0:"";s:15:"super_attribute";a:1:{i:502;s:2:"41";}s:3:"qty";s:1:"1";}s:15:"attributes_info";a:1:{i:0;a:2:{s:5:"label";s:9:"Shoe Size";s:5:"value";s:1:"8";}}s:11:"simple_name";s:30:"ASICS® Men's GEL-Kayano® XII";s:10:"simple_sku";s:5:"asc_8";s:20:"product_calculations";i:1;s:13:"shipment_type";i:0;}
|
324 |
+
weight: 3
|
325 |
+
is_virtual: 0
|
326 |
+
sku: asc_8
|
327 |
+
name: ASICS® Men's GEL-Kayano® XII
|
328 |
+
description: null
|
329 |
+
applied_rule_ids: null
|
330 |
+
additional_data: null
|
331 |
+
free_shipping: 0
|
332 |
+
is_qty_decimal: 0
|
333 |
+
no_discount: 0
|
334 |
+
qty_backordered: null
|
335 |
+
qty_canceled: 0
|
336 |
+
qty_invoiced: 0
|
337 |
+
qty_ordered: 1
|
338 |
+
qty_refunded: 0
|
339 |
+
qty_shipped: 0
|
340 |
+
base_cost: 29.99
|
341 |
+
price: 134.99
|
342 |
+
base_price: 134.99
|
343 |
+
original_price: 134.99
|
344 |
+
base_original_price: 134.99
|
345 |
+
tax_percent: 0
|
346 |
+
tax_amount: 0
|
347 |
+
base_tax_amount: 0
|
348 |
+
tax_invoiced: 0
|
349 |
+
base_tax_invoiced: 0
|
350 |
+
discount_percent: 0
|
351 |
+
discount_amount: 0
|
352 |
+
base_discount_amount: 0
|
353 |
+
discount_invoiced: 0
|
354 |
+
base_discount_invoiced: 0
|
355 |
+
amount_refunded: 0
|
356 |
+
base_amount_refunded: 0
|
357 |
+
row_total: 134.99
|
358 |
+
base_row_total: 134.99
|
359 |
+
row_invoiced: 0
|
360 |
+
base_row_invoiced: 0
|
361 |
+
row_weight: 3
|
362 |
+
gift_message_id: null
|
363 |
+
gift_message_available: null
|
364 |
+
base_tax_before_discount: null
|
365 |
+
tax_before_discount: null
|
366 |
+
weee_tax_applied: a:0:{}
|
367 |
+
weee_tax_applied_amount: 0
|
368 |
+
weee_tax_applied_row_amount: 0
|
369 |
+
base_weee_tax_applied_amount: 0
|
370 |
+
base_weee_tax_applied_row_amnt: 0
|
371 |
+
weee_tax_disposition: 0
|
372 |
+
weee_tax_row_disposition: 0
|
373 |
+
base_weee_tax_disposition: 0
|
374 |
+
base_weee_tax_row_disposition: 0
|
375 |
+
ext_order_item_id: null
|
376 |
+
locked_do_invoice: null
|
377 |
+
locked_do_ship: null
|
378 |
+
price_incl_tax: 134.99
|
379 |
+
base_price_incl_tax: 134.99
|
380 |
+
row_total_incl_tax: 134.99
|
381 |
+
base_row_total_incl_tax: 134.99
|
382 |
+
hidden_tax_amount: 0
|
383 |
+
base_hidden_tax_amount: 0
|
384 |
+
hidden_tax_invoiced: null
|
385 |
+
base_hidden_tax_invoiced: null
|
386 |
+
hidden_tax_refunded: null
|
387 |
+
base_hidden_tax_refunded: null
|
388 |
+
is_nominal: 0
|
389 |
+
tax_canceled: null
|
390 |
+
hidden_tax_canceled: null
|
391 |
+
tax_refunded: null
|
392 |
+
base_tax_refunded: null
|
393 |
+
discount_refunded: null
|
394 |
+
base_discount_refunded: null
|
395 |
+
-
|
396 |
+
item_id: 2
|
397 |
+
order_id: 1
|
398 |
+
parent_item_id: 1
|
399 |
+
quote_item_id: 2
|
400 |
+
store_id: 1
|
401 |
+
created_at: 2014-05-15 16:05:21
|
402 |
+
updated_at: 2014-05-15 16:05:21
|
403 |
+
product_id: 30
|
404 |
+
product_type: simple
|
405 |
+
product_options: a:1:{s:15:"info_buyRequest";a:6:{s:4:"uenc";s:100:"aHR0cDovL3NreXdhcnAubG9jYWwvbWVhbmJlZS9rbGV2dS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1sP19fX1NJRD1V";s:7:"product";s:2:"93";s:8:"form_key";s:16:"L9pfTdY6fCBMRa3z";s:15:"related_product";s:0:"";s:15:"super_attribute";a:1:{i:502;s:2:"41";}s:3:"qty";s:1:"1";}}
|
406 |
+
weight: 3
|
407 |
+
is_virtual: 0
|
408 |
+
sku: asc_8
|
409 |
+
name: ASICS® Men's GEL-Kayano® XII
|
410 |
+
description: null
|
411 |
+
applied_rule_ids: null
|
412 |
+
additional_data: null
|
413 |
+
free_shipping: 0
|
414 |
+
is_qty_decimal: 0
|
415 |
+
no_discount: 0
|
416 |
+
qty_backordered: null
|
417 |
+
qty_canceled: 0
|
418 |
+
qty_invoiced: 0
|
419 |
+
qty_ordered: 1
|
420 |
+
qty_refunded: 0
|
421 |
+
qty_shipped: 0
|
422 |
+
base_cost: 29.99
|
423 |
+
price: 0
|
424 |
+
base_price: 0
|
425 |
+
original_price: 0
|
426 |
+
base_original_price: null
|
427 |
+
tax_percent: 0
|
428 |
+
tax_amount: 0
|
429 |
+
base_tax_amount: 0
|
430 |
+
tax_invoiced: 0
|
431 |
+
base_tax_invoiced: 0
|
432 |
+
discount_percent: 0
|
433 |
+
discount_amount: 0
|
434 |
+
base_discount_amount: 0
|
435 |
+
discount_invoiced: 0
|
436 |
+
base_discount_invoiced: 0
|
437 |
+
amount_refunded: 0
|
438 |
+
base_amount_refunded: 0
|
439 |
+
row_total: 0
|
440 |
+
base_row_total: 0
|
441 |
+
row_invoiced: 0
|
442 |
+
base_row_invoiced: 0
|
443 |
+
row_weight: 0
|
444 |
+
gift_message_id: null
|
445 |
+
gift_message_available: null
|
446 |
+
base_tax_before_discount: null
|
447 |
+
tax_before_discount: null
|
448 |
+
weee_tax_applied: a:0:{}
|
449 |
+
weee_tax_applied_amount: 0
|
450 |
+
weee_tax_applied_row_amount: 0
|
451 |
+
base_weee_tax_applied_amount: 0
|
452 |
+
base_weee_tax_applied_row_amnt: null
|
453 |
+
weee_tax_disposition: 0
|
454 |
+
weee_tax_row_disposition: 0
|
455 |
+
base_weee_tax_disposition: 0
|
456 |
+
base_weee_tax_row_disposition: 0
|
457 |
+
ext_order_item_id: null
|
458 |
+
locked_do_invoice: null
|
459 |
+
locked_do_ship: null
|
460 |
+
price_incl_tax: null
|
461 |
+
base_price_incl_tax: null
|
462 |
+
row_total_incl_tax: null
|
463 |
+
base_row_total_incl_tax: null
|
464 |
+
hidden_tax_amount: null
|
465 |
+
base_hidden_tax_amount: null
|
466 |
+
hidden_tax_invoiced: null
|
467 |
+
base_hidden_tax_invoiced: null
|
468 |
+
hidden_tax_refunded: null
|
469 |
+
base_hidden_tax_refunded: null
|
470 |
+
is_nominal: 0
|
471 |
+
tax_canceled: null
|
472 |
+
hidden_tax_canceled: null
|
473 |
+
tax_refunded: null
|
474 |
+
base_tax_refunded: null
|
475 |
+
discount_refunded: null
|
476 |
+
base_discount_refunded: null
|
477 |
+
-
|
478 |
+
item_id: 3
|
479 |
+
order_id: 2
|
480 |
+
parent_item_id: null
|
481 |
+
quote_item_id: 3
|
482 |
+
store_id: 2
|
483 |
+
created_at: 2014-05-26 12:14:20
|
484 |
+
updated_at: 2014-05-26 12:14:20
|
485 |
+
product_id: 46
|
486 |
+
product_type: simple
|
487 |
+
product_options: a:1:{s:15:"info_buyRequest";a:5:{s:4:"uenc";s:120:"aHR0cDovL3NreXdhcnAubG9jYWwvbWVhbmJlZS9rbGV2dS9vbHltcHVzLXN0eWx1cy03NTAtNy0xbXAtZGlnaXRhbC1jYW1lcmEuaHRtbD9fX19TSUQ9VQ,,";s:7:"product";s:2:"46";s:8:"form_key";s:16:"zmyiLczPG2zL8kLs";s:15:"related_product";s:0:"";s:3:"qty";s:1:"0";}}
|
488 |
+
weight: 2
|
489 |
+
is_virtual: 0
|
490 |
+
sku: 750
|
491 |
+
name: Olympus Stylus 750 7.1MP Digital Camera
|
492 |
+
description: null
|
493 |
+
applied_rule_ids: null
|
494 |
+
additional_data: null
|
495 |
+
free_shipping: 0
|
496 |
+
is_qty_decimal: 0
|
497 |
+
no_discount: 0
|
498 |
+
qty_backordered: null
|
499 |
+
qty_canceled: 0
|
500 |
+
qty_invoiced: 0
|
501 |
+
qty_ordered: 1
|
502 |
+
qty_refunded: 0
|
503 |
+
qty_shipped: 0
|
504 |
+
base_cost: 29.99
|
505 |
+
price: 161.94
|
506 |
+
base_price: 161.94
|
507 |
+
original_price: 161.94
|
508 |
+
base_original_price: 161.94
|
509 |
+
tax_percent: 0
|
510 |
+
tax_amount: 0
|
511 |
+
base_tax_amount: 0
|
512 |
+
tax_invoiced: 0
|
513 |
+
base_tax_invoiced: 0
|
514 |
+
discount_percent: 0
|
515 |
+
discount_amount: 0
|
516 |
+
base_discount_amount: 0
|
517 |
+
discount_invoiced: 0
|
518 |
+
base_discount_invoiced: 0
|
519 |
+
amount_refunded: 0
|
520 |
+
base_amount_refunded: 0
|
521 |
+
row_total: 161.94
|
522 |
+
base_row_total: 161.94
|
523 |
+
row_invoiced: 0
|
524 |
+
base_row_invoiced: 0
|
525 |
+
row_weight: 2
|
526 |
+
gift_message_id: null
|
527 |
+
gift_message_available: null
|
528 |
+
base_tax_before_discount: null
|
529 |
+
tax_before_discount: null
|
530 |
+
weee_tax_applied: a:0:{}
|
531 |
+
weee_tax_applied_amount: 0
|
532 |
+
weee_tax_applied_row_amount: 0
|
533 |
+
base_weee_tax_applied_amount: 0
|
534 |
+
base_weee_tax_applied_row_amnt: 0
|
535 |
+
weee_tax_disposition: 0
|
536 |
+
weee_tax_row_disposition: 0
|
537 |
+
base_weee_tax_disposition: 0
|
538 |
+
base_weee_tax_row_disposition: 0
|
539 |
+
ext_order_item_id: null
|
540 |
+
locked_do_invoice: null
|
541 |
+
locked_do_ship: null
|
542 |
+
price_incl_tax: 161.94
|
543 |
+
base_price_incl_tax: 161.94
|
544 |
+
row_total_incl_tax: 161.94
|
545 |
+
base_row_total_incl_tax: 161.94
|
546 |
+
hidden_tax_amount: 0
|
547 |
+
base_hidden_tax_amount: 0
|
548 |
+
hidden_tax_invoiced: null
|
549 |
+
base_hidden_tax_invoiced: null
|
550 |
+
hidden_tax_refunded: null
|
551 |
+
base_hidden_tax_refunded: null
|
552 |
+
is_nominal: 0
|
553 |
+
tax_canceled: null
|
554 |
+
hidden_tax_canceled: null
|
555 |
+
tax_refunded: null
|
556 |
+
base_tax_refunded: null
|
557 |
+
discount_refunded: null
|
558 |
+
base_discount_refunded: null
|
559 |
+
klevu_search/order_sync:
|
560 |
+
-
|
561 |
+
order_item_id: 2
|
562 |
+
-
|
563 |
+
order_item_id: 3
|
app/code/community/Klevu/Search/Test/Model/Order/Sync/fixtures/testRun.yaml
ADDED
@@ -0,0 +1,323 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 1
|
3 |
+
default/klevu_search/general/test_mode: 1
|
4 |
+
default/klevu_search/general/test_js_api_key: test-api-key
|
5 |
+
default/klevu_search/order_sync/enabled: 2
|
6 |
+
tables:
|
7 |
+
sales_flat_order:
|
8 |
+
-
|
9 |
+
entity_id: 1
|
10 |
+
state: new
|
11 |
+
status: pending
|
12 |
+
coupon_code: null
|
13 |
+
protect_code: bbc820
|
14 |
+
shipping_description: Flat Rate - Fixed
|
15 |
+
is_virtual: 0
|
16 |
+
store_id: 1
|
17 |
+
customer_id: null
|
18 |
+
base_discount_amount: 0
|
19 |
+
base_discount_canceled: null
|
20 |
+
base_discount_invoiced: null
|
21 |
+
base_discount_refunded: null
|
22 |
+
base_grand_total: 139.99
|
23 |
+
base_shipping_amount: 5
|
24 |
+
base_shipping_canceled: null
|
25 |
+
base_shipping_invoiced: null
|
26 |
+
base_shipping_refunded: null
|
27 |
+
base_shipping_tax_amount: 0
|
28 |
+
base_shipping_tax_refunded: null
|
29 |
+
base_subtotal: 134.99
|
30 |
+
base_subtotal_canceled: null
|
31 |
+
base_subtotal_invoiced: null
|
32 |
+
base_subtotal_refunded: null
|
33 |
+
base_tax_amount: 0
|
34 |
+
base_tax_canceled: null
|
35 |
+
base_tax_invoiced: null
|
36 |
+
base_tax_refunded: null
|
37 |
+
base_to_global_rate: 1
|
38 |
+
base_to_order_rate: 1
|
39 |
+
base_total_canceled: null
|
40 |
+
base_total_invoiced: null
|
41 |
+
base_total_invoiced_cost: null
|
42 |
+
base_total_offline_refunded: null
|
43 |
+
base_total_online_refunded: null
|
44 |
+
base_total_paid: null
|
45 |
+
base_total_qty_ordered: null
|
46 |
+
base_total_refunded: null
|
47 |
+
discount_amount: 0
|
48 |
+
discount_canceled: null
|
49 |
+
discount_invoiced: null
|
50 |
+
discount_refunded: null
|
51 |
+
grand_total: 139.99
|
52 |
+
shipping_amount: 5
|
53 |
+
shipping_canceled: null
|
54 |
+
shipping_invoiced: null
|
55 |
+
shipping_refunded: null
|
56 |
+
shipping_tax_amount: 0
|
57 |
+
shipping_tax_refunded: null
|
58 |
+
store_to_base_rate: 1
|
59 |
+
store_to_order_rate: 1
|
60 |
+
subtotal: 134.99
|
61 |
+
subtotal_canceled: null
|
62 |
+
subtotal_invoiced: null
|
63 |
+
subtotal_refunded: null
|
64 |
+
tax_amount: 0
|
65 |
+
tax_canceled: null
|
66 |
+
tax_invoiced: null
|
67 |
+
tax_refunded: null
|
68 |
+
total_canceled: null
|
69 |
+
total_invoiced: null
|
70 |
+
total_offline_refunded: null
|
71 |
+
total_online_refunded: null
|
72 |
+
total_paid: null
|
73 |
+
total_qty_ordered: 1
|
74 |
+
total_refunded: null
|
75 |
+
can_ship_partially: null
|
76 |
+
can_ship_partially_item: null
|
77 |
+
customer_is_guest: 1
|
78 |
+
customer_note_notify: 1
|
79 |
+
billing_address_id: 1
|
80 |
+
customer_group_id: 0
|
81 |
+
edit_increment: null
|
82 |
+
email_sent: 1
|
83 |
+
forced_shipment_with_invoice: null
|
84 |
+
gift_message_id: null
|
85 |
+
payment_auth_expiration: null
|
86 |
+
paypal_ipn_customer_notified: null
|
87 |
+
quote_address_id: null
|
88 |
+
quote_id: 3
|
89 |
+
shipping_address_id: 2
|
90 |
+
adjustment_negative: null
|
91 |
+
adjustment_positive: null
|
92 |
+
base_adjustment_negative: null
|
93 |
+
base_adjustment_positive: null
|
94 |
+
base_shipping_discount_amount: 0
|
95 |
+
base_subtotal_incl_tax: 134.99
|
96 |
+
base_total_due: null
|
97 |
+
payment_authorization_amount: null
|
98 |
+
shipping_discount_amount: 0
|
99 |
+
subtotal_incl_tax: 134.99
|
100 |
+
total_due: null
|
101 |
+
weight: 3
|
102 |
+
customer_dob: null
|
103 |
+
increment_id: 100000001
|
104 |
+
applied_rule_ids: null
|
105 |
+
base_currency_code: GBP
|
106 |
+
customer_email: tomas.gerulaitis@meanbee.com
|
107 |
+
customer_firstname: Tomas
|
108 |
+
customer_lastname: Gerulaitis
|
109 |
+
customer_middlename: null
|
110 |
+
customer_prefix: null
|
111 |
+
customer_suffix: null
|
112 |
+
customer_taxvat: null
|
113 |
+
discount_description: null
|
114 |
+
ext_customer_id: null
|
115 |
+
ext_order_id: null
|
116 |
+
global_currency_code: GBP
|
117 |
+
hold_before_state: null
|
118 |
+
hold_before_status: null
|
119 |
+
order_currency_code: GBP
|
120 |
+
original_increment_id: null
|
121 |
+
relation_child_id: null
|
122 |
+
relation_child_real_id: null
|
123 |
+
relation_parent_id: null
|
124 |
+
relation_parent_real_id: null
|
125 |
+
remote_ip: 127.0.0.1
|
126 |
+
shipping_method: flatrate_flatrate
|
127 |
+
store_currency_code: GBP
|
128 |
+
store_name: Main Website, Main Store, English
|
129 |
+
x_forwarded_for: null
|
130 |
+
customer_note: null
|
131 |
+
created_at: 2014-05-15 16:05:21
|
132 |
+
updated_at: 2014-05-15 16:05:21
|
133 |
+
total_item_count: 1
|
134 |
+
customer_gender: null
|
135 |
+
base_custbalance_amount: null
|
136 |
+
currency_base_id: null
|
137 |
+
currency_code: null
|
138 |
+
currency_rate: null
|
139 |
+
custbalance_amount: null
|
140 |
+
is_hold: null
|
141 |
+
is_multi_payment: null
|
142 |
+
real_order_id: null
|
143 |
+
tax_percent: null
|
144 |
+
tracking_numbers: null
|
145 |
+
hidden_tax_amount: 0
|
146 |
+
base_hidden_tax_amount: 0
|
147 |
+
shipping_hidden_tax_amount: 0
|
148 |
+
base_shipping_hidden_tax_amnt: 0
|
149 |
+
hidden_tax_invoiced: null
|
150 |
+
base_hidden_tax_invoiced: null
|
151 |
+
hidden_tax_refunded: null
|
152 |
+
base_hidden_tax_refunded: null
|
153 |
+
shipping_incl_tax: 5
|
154 |
+
base_shipping_incl_tax: 5
|
155 |
+
coupon_rule_name: null
|
156 |
+
sales_flat_order_item:
|
157 |
+
-
|
158 |
+
item_id: 1
|
159 |
+
order_id: 1
|
160 |
+
parent_item_id: null
|
161 |
+
quote_item_id: 1
|
162 |
+
store_id: 1
|
163 |
+
created_at: 2014-05-15 16:05:21
|
164 |
+
updated_at: 2014-05-15 16:05:21
|
165 |
+
product_id: 93
|
166 |
+
product_type: configurable
|
167 |
+
product_options: a:6:{s:15:"info_buyRequest";a:6:{s:4:"uenc";s:100:"aHR0cDovL3NreXdhcnAubG9jYWwvbWVhbmJlZS9rbGV2dS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1sP19fX1NJRD1V";s:7:"product";s:2:"93";s:8:"form_key";s:16:"L9pfTdY6fCBMRa3z";s:15:"related_product";s:0:"";s:15:"super_attribute";a:1:{i:502;s:2:"41";}s:3:"qty";s:1:"1";}s:15:"attributes_info";a:1:{i:0;a:2:{s:5:"label";s:9:"Shoe Size";s:5:"value";s:1:"8";}}s:11:"simple_name";s:30:"ASICS® Men's GEL-Kayano® XII";s:10:"simple_sku";s:5:"asc_8";s:20:"product_calculations";i:1;s:13:"shipment_type";i:0;}
|
168 |
+
weight: 3
|
169 |
+
is_virtual: 0
|
170 |
+
sku: asc_8
|
171 |
+
name: ASICS® Men's GEL-Kayano® XII
|
172 |
+
description: null
|
173 |
+
applied_rule_ids: null
|
174 |
+
additional_data: null
|
175 |
+
free_shipping: 0
|
176 |
+
is_qty_decimal: 0
|
177 |
+
no_discount: 0
|
178 |
+
qty_backordered: null
|
179 |
+
qty_canceled: 0
|
180 |
+
qty_invoiced: 0
|
181 |
+
qty_ordered: 1
|
182 |
+
qty_refunded: 0
|
183 |
+
qty_shipped: 0
|
184 |
+
base_cost: 29.99
|
185 |
+
price: 134.99
|
186 |
+
base_price: 134.99
|
187 |
+
original_price: 134.99
|
188 |
+
base_original_price: 134.99
|
189 |
+
tax_percent: 0
|
190 |
+
tax_amount: 0
|
191 |
+
base_tax_amount: 0
|
192 |
+
tax_invoiced: 0
|
193 |
+
base_tax_invoiced: 0
|
194 |
+
discount_percent: 0
|
195 |
+
discount_amount: 0
|
196 |
+
base_discount_amount: 0
|
197 |
+
discount_invoiced: 0
|
198 |
+
base_discount_invoiced: 0
|
199 |
+
amount_refunded: 0
|
200 |
+
base_amount_refunded: 0
|
201 |
+
row_total: 134.99
|
202 |
+
base_row_total: 134.99
|
203 |
+
row_invoiced: 0
|
204 |
+
base_row_invoiced: 0
|
205 |
+
row_weight: 3
|
206 |
+
gift_message_id: null
|
207 |
+
gift_message_available: null
|
208 |
+
base_tax_before_discount: null
|
209 |
+
tax_before_discount: null
|
210 |
+
weee_tax_applied: a:0:{}
|
211 |
+
weee_tax_applied_amount: 0
|
212 |
+
weee_tax_applied_row_amount: 0
|
213 |
+
base_weee_tax_applied_amount: 0
|
214 |
+
base_weee_tax_applied_row_amnt: 0
|
215 |
+
weee_tax_disposition: 0
|
216 |
+
weee_tax_row_disposition: 0
|
217 |
+
base_weee_tax_disposition: 0
|
218 |
+
base_weee_tax_row_disposition: 0
|
219 |
+
ext_order_item_id: null
|
220 |
+
locked_do_invoice: null
|
221 |
+
locked_do_ship: null
|
222 |
+
price_incl_tax: 134.99
|
223 |
+
base_price_incl_tax: 134.99
|
224 |
+
row_total_incl_tax: 134.99
|
225 |
+
base_row_total_incl_tax: 134.99
|
226 |
+
hidden_tax_amount: 0
|
227 |
+
base_hidden_tax_amount: 0
|
228 |
+
hidden_tax_invoiced: null
|
229 |
+
base_hidden_tax_invoiced: null
|
230 |
+
hidden_tax_refunded: null
|
231 |
+
base_hidden_tax_refunded: null
|
232 |
+
is_nominal: 0
|
233 |
+
tax_canceled: null
|
234 |
+
hidden_tax_canceled: null
|
235 |
+
tax_refunded: null
|
236 |
+
base_tax_refunded: null
|
237 |
+
discount_refunded: null
|
238 |
+
base_discount_refunded: null
|
239 |
+
-
|
240 |
+
item_id: 2
|
241 |
+
order_id: 1
|
242 |
+
parent_item_id: 1
|
243 |
+
quote_item_id: 2
|
244 |
+
store_id: 1
|
245 |
+
created_at: 2014-05-15 16:05:21
|
246 |
+
updated_at: 2014-05-15 16:05:21
|
247 |
+
product_id: 30
|
248 |
+
product_type: simple
|
249 |
+
product_options: a:1:{s:15:"info_buyRequest";a:6:{s:4:"uenc";s:100:"aHR0cDovL3NreXdhcnAubG9jYWwvbWVhbmJlZS9rbGV2dS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1sP19fX1NJRD1V";s:7:"product";s:2:"93";s:8:"form_key";s:16:"L9pfTdY6fCBMRa3z";s:15:"related_product";s:0:"";s:15:"super_attribute";a:1:{i:502;s:2:"41";}s:3:"qty";s:1:"1";}}
|
250 |
+
weight: 3
|
251 |
+
is_virtual: 0
|
252 |
+
sku: asc_8
|
253 |
+
name: ASICS® Men's GEL-Kayano® XII
|
254 |
+
description: null
|
255 |
+
applied_rule_ids: null
|
256 |
+
additional_data: null
|
257 |
+
free_shipping: 0
|
258 |
+
is_qty_decimal: 0
|
259 |
+
no_discount: 0
|
260 |
+
qty_backordered: null
|
261 |
+
qty_canceled: 0
|
262 |
+
qty_invoiced: 0
|
263 |
+
qty_ordered: 1
|
264 |
+
qty_refunded: 0
|
265 |
+
qty_shipped: 0
|
266 |
+
base_cost: 29.99
|
267 |
+
price: 0
|
268 |
+
base_price: 0
|
269 |
+
original_price: 0
|
270 |
+
base_original_price: null
|
271 |
+
tax_percent: 0
|
272 |
+
tax_amount: 0
|
273 |
+
base_tax_amount: 0
|
274 |
+
tax_invoiced: 0
|
275 |
+
base_tax_invoiced: 0
|
276 |
+
discount_percent: 0
|
277 |
+
discount_amount: 0
|
278 |
+
base_discount_amount: 0
|
279 |
+
discount_invoiced: 0
|
280 |
+
base_discount_invoiced: 0
|
281 |
+
amount_refunded: 0
|
282 |
+
base_amount_refunded: 0
|
283 |
+
row_total: 0
|
284 |
+
base_row_total: 0
|
285 |
+
row_invoiced: 0
|
286 |
+
base_row_invoiced: 0
|
287 |
+
row_weight: 0
|
288 |
+
gift_message_id: null
|
289 |
+
gift_message_available: null
|
290 |
+
base_tax_before_discount: null
|
291 |
+
tax_before_discount: null
|
292 |
+
weee_tax_applied: a:0:{}
|
293 |
+
weee_tax_applied_amount: 0
|
294 |
+
weee_tax_applied_row_amount: 0
|
295 |
+
base_weee_tax_applied_amount: 0
|
296 |
+
base_weee_tax_applied_row_amnt: null
|
297 |
+
weee_tax_disposition: 0
|
298 |
+
weee_tax_row_disposition: 0
|
299 |
+
base_weee_tax_disposition: 0
|
300 |
+
base_weee_tax_row_disposition: 0
|
301 |
+
ext_order_item_id: null
|
302 |
+
locked_do_invoice: null
|
303 |
+
locked_do_ship: null
|
304 |
+
price_incl_tax: null
|
305 |
+
base_price_incl_tax: null
|
306 |
+
row_total_incl_tax: null
|
307 |
+
base_row_total_incl_tax: null
|
308 |
+
hidden_tax_amount: null
|
309 |
+
base_hidden_tax_amount: null
|
310 |
+
hidden_tax_invoiced: null
|
311 |
+
base_hidden_tax_invoiced: null
|
312 |
+
hidden_tax_refunded: null
|
313 |
+
base_hidden_tax_refunded: null
|
314 |
+
is_nominal: 0
|
315 |
+
tax_canceled: null
|
316 |
+
hidden_tax_canceled: null
|
317 |
+
tax_refunded: null
|
318 |
+
base_tax_refunded: null
|
319 |
+
discount_refunded: null
|
320 |
+
base_discount_refunded: null
|
321 |
+
klevu_order_sync:
|
322 |
+
-
|
323 |
+
order_item_id: 2
|
app/code/community/Klevu/Search/Test/Model/Product/Sync.php
ADDED
@@ -0,0 +1,275 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Product_Sync extends Klevu_Search_Test_Model_Api_Test_Case {
|
4 |
+
|
5 |
+
protected function tearDown() {
|
6 |
+
$resource = Mage::getModel('core/resource');
|
7 |
+
|
8 |
+
$resource->getConnection("core_write")->delete($resource->getTableName("klevu_search/product_sync"));
|
9 |
+
|
10 |
+
Mage::getResourceModel('catalog/product_collection')->delete();
|
11 |
+
|
12 |
+
parent::tearDown();
|
13 |
+
}
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @test
|
17 |
+
* @loadFixture
|
18 |
+
* @doNotIndexAll
|
19 |
+
*/
|
20 |
+
public function testRun() {
|
21 |
+
$this->reindexAll();
|
22 |
+
|
23 |
+
$this->replaceApiActionByMock("klevu_search/api_action_startsession", $this->getSuccessfulSessionResponse());
|
24 |
+
|
25 |
+
$model = $this->getModelMock("klevu_search/product_sync", array(
|
26 |
+
"isBelowMemoryLimit", "deleteProducts", "updateProducts", "addProducts"
|
27 |
+
));
|
28 |
+
$model
|
29 |
+
->expects($this->any())
|
30 |
+
->method("isBelowMemoryLimit")
|
31 |
+
->will($this->returnValue(true));
|
32 |
+
$model
|
33 |
+
->expects($this->once())
|
34 |
+
->method("deleteProducts")
|
35 |
+
->with(array(
|
36 |
+
array("product_id" => "130", "parent_id" => "0"),
|
37 |
+
array("product_id" => "201", "parent_id" => "202"),
|
38 |
+
array("product_id" => "211", "parent_id" => "212")
|
39 |
+
))
|
40 |
+
->will($this->returnValue(true));
|
41 |
+
$model
|
42 |
+
->expects($this->once())
|
43 |
+
->method("updateProducts")
|
44 |
+
->with(array(
|
45 |
+
array("product_id" => "133", "parent_id" => "0"),
|
46 |
+
array("product_id" => "134", "parent_id" => "0"),
|
47 |
+
array("product_id" => "203", "parent_id" => "204"),
|
48 |
+
array("product_id" => "205", "parent_id" => "206")
|
49 |
+
))
|
50 |
+
->will($this->returnValue(true));
|
51 |
+
$model
|
52 |
+
->expects($this->once())
|
53 |
+
->method("addProducts")
|
54 |
+
->with(array(
|
55 |
+
array("product_id" => "132", "parent_id" => "0"),
|
56 |
+
array("product_id" => "207", "parent_id" => "209"),
|
57 |
+
array("product_id" => "208", "parent_id" => "209")
|
58 |
+
))
|
59 |
+
->will($this->returnValue(true));
|
60 |
+
|
61 |
+
$model->run();
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @test
|
66 |
+
* @loadFixture
|
67 |
+
* @doNotIndexAll
|
68 |
+
*/
|
69 |
+
public function testDeleteProducts() {
|
70 |
+
$this->reindexAll();
|
71 |
+
|
72 |
+
$this->replaceApiActionByMock("klevu_search/api_action_startsession", $this->getSuccessfulSessionResponse());
|
73 |
+
$this->replaceApiActionByMock("klevu_search/api_action_deleterecords", $this->getSuccessfulMessageResponse());
|
74 |
+
|
75 |
+
Mage::getModel('klevu_search/product_sync')->run();
|
76 |
+
|
77 |
+
$this->assertEquals(array(), $this->getProductSyncTableContents());
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* @test
|
82 |
+
* @loadFixture
|
83 |
+
* @doNotIndexAll
|
84 |
+
*/
|
85 |
+
public function testUpdateProducts() {
|
86 |
+
$this->reindexAll();
|
87 |
+
|
88 |
+
$this->replaceApiActionByMock("klevu_search/api_action_startsession", $this->getSuccessfulSessionResponse());
|
89 |
+
$this->replaceApiActionByMock("klevu_search/api_action_updaterecords", $this->getSuccessfulMessageResponse());
|
90 |
+
|
91 |
+
$this->replaceSessionByMock("core/session");
|
92 |
+
$this->replaceSessionByMock("customer/session");
|
93 |
+
|
94 |
+
Mage::getModel('klevu_search/product_sync')->run();
|
95 |
+
|
96 |
+
$contents = $this->getProductSyncTableContents('last_synced_at > "2008-06-27 01:57:22"');
|
97 |
+
|
98 |
+
$this->assertTrue((is_array($contents) && count($contents) == 1));
|
99 |
+
$this->assertEquals("133", $contents[0]['product_id']);
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* @test
|
104 |
+
* @loadFixture
|
105 |
+
* @doNotIndexAll
|
106 |
+
*/
|
107 |
+
public function testAddProducts() {
|
108 |
+
$this->reindexAll();
|
109 |
+
|
110 |
+
$this->replaceApiActionByMock("klevu_search/api_action_startsession", $this->getSuccessfulSessionResponse());
|
111 |
+
$this->replaceApiActionByMock("klevu_search/api_action_addrecords", $this->getSuccessfulMessageResponse());
|
112 |
+
|
113 |
+
$this->replaceSessionByMock("core/session");
|
114 |
+
$this->replaceSessionByMock("customer/session");
|
115 |
+
|
116 |
+
Mage::getModel('klevu_search/product_sync')->run();
|
117 |
+
|
118 |
+
$contents = $this->getProductSyncTableContents();
|
119 |
+
|
120 |
+
$this->assertTrue((is_array($contents) && count($contents) == 1));
|
121 |
+
$this->assertEquals("133", $contents[0]['product_id']);
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* @test
|
126 |
+
* @loadFixture
|
127 |
+
*/
|
128 |
+
public function testClearAllProducts() {
|
129 |
+
$model = Mage::getModel("klevu_search/product_sync");
|
130 |
+
|
131 |
+
$model->clearAllProducts(1);
|
132 |
+
|
133 |
+
$contents = $this->getProductSyncTableContents();
|
134 |
+
|
135 |
+
$this->assertTrue(
|
136 |
+
is_array($contents) && count($contents) == 1 && $contents[0]['product_id'] == 2,
|
137 |
+
"Failed asserting that clearAllProducts() only removes products for the given store."
|
138 |
+
);
|
139 |
+
|
140 |
+
$model->clearAllProducts();
|
141 |
+
|
142 |
+
$contents = $this->getProductSyncTableContents();
|
143 |
+
|
144 |
+
$this->assertTrue(
|
145 |
+
empty($contents),
|
146 |
+
"Failed asserting that clearAllProducts() removes products for all stores."
|
147 |
+
);
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* @test
|
152 |
+
*/
|
153 |
+
public function testAutomaticAttributes() {
|
154 |
+
$model = Mage::getModel("klevu_search/product_sync");
|
155 |
+
|
156 |
+
$automatic_attributes = $model->getAutomaticAttributes();
|
157 |
+
|
158 |
+
$expected_attributes = $this->getExpectedAutomaticAttributes();
|
159 |
+
|
160 |
+
$this->assertEquals($expected_attributes, $automatic_attributes);
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Return a klevu_search/api_response_message model with a successful response from
|
165 |
+
* a startSession API call.
|
166 |
+
*
|
167 |
+
* @return Klevu_Search_Model_Api_Response_Message
|
168 |
+
*/
|
169 |
+
protected function getSuccessfulSessionResponse() {
|
170 |
+
$model = Mage::getModel('klevu_search/api_response_message')->setRawResponse(
|
171 |
+
new Zend_Http_Response(200, array(), $this->getDataFileContents("startsession_response_success.xml"))
|
172 |
+
);
|
173 |
+
|
174 |
+
return $model;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Return a klevu_search/api_response_message model with a successful response.
|
179 |
+
*
|
180 |
+
* @return Klevu_Search_Model_Api_Response_Message
|
181 |
+
*/
|
182 |
+
protected function getSuccessfulMessageResponse() {
|
183 |
+
$model = Mage::getModel('klevu_search/api_response_message')->setRawResponse(
|
184 |
+
new Zend_Http_Response(200, array(), $this->getDataFileContents("message_response_success.xml"))
|
185 |
+
);
|
186 |
+
|
187 |
+
return $model;
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Return the contents of the Product Sync table.
|
192 |
+
*
|
193 |
+
* @param string $where The where clause to use in the database query
|
194 |
+
*
|
195 |
+
* @return array
|
196 |
+
*/
|
197 |
+
protected function getProductSyncTableContents($where = null) {
|
198 |
+
$resource = Mage::getModel('core/resource');
|
199 |
+
$connection = $resource->getConnection("core_write");
|
200 |
+
|
201 |
+
$select = $connection->select()->from($resource->getTableName('klevu_search/product_sync'));
|
202 |
+
if ($where) {
|
203 |
+
$select->where($where);
|
204 |
+
}
|
205 |
+
|
206 |
+
return $connection->fetchAll($select);
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Run all of the indexers.
|
211 |
+
*
|
212 |
+
* @return $this
|
213 |
+
*/
|
214 |
+
protected function reindexAll() {
|
215 |
+
$indexer = Mage::getSingleton('index/indexer');
|
216 |
+
|
217 |
+
// Delete all index events
|
218 |
+
$index_events = Mage::getResourceModel("index/event_collection");
|
219 |
+
foreach ($index_events as $event) {
|
220 |
+
/** @var Mage_Index_Model_Event $event */
|
221 |
+
$event->delete();
|
222 |
+
}
|
223 |
+
|
224 |
+
// Remove the stores cache from the category product index
|
225 |
+
if ($process = $indexer->getProcessByCode("catalog_category_product")) {
|
226 |
+
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
|
227 |
+
$process->getIndexer()->getResource(), "_storesInfo", null
|
228 |
+
);
|
229 |
+
}
|
230 |
+
|
231 |
+
$processes = $indexer->getProcessesCollection();
|
232 |
+
|
233 |
+
// Reset all the indexers
|
234 |
+
foreach ($processes as $process) {
|
235 |
+
/** @var Mage_Index_Model_Process $process */
|
236 |
+
if ($process->hasData('runed_reindexall')) {
|
237 |
+
$process->setData('runed_reindexall', false);
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
// Run all indexers
|
242 |
+
foreach ($processes as $process) {
|
243 |
+
/** @var Mage_Index_Model_Process $process */
|
244 |
+
$process->reindexEverything();
|
245 |
+
}
|
246 |
+
|
247 |
+
return $this;
|
248 |
+
}
|
249 |
+
|
250 |
+
protected function getExpectedAutomaticAttributes() {
|
251 |
+
return array(
|
252 |
+
array(
|
253 |
+
'klevu_attribute' => 'name',
|
254 |
+
'magento_attribute' => 'name'),
|
255 |
+
array(
|
256 |
+
'klevu_attribute' => 'image',
|
257 |
+
'magento_attribute' => 'image'),
|
258 |
+
array(
|
259 |
+
'klevu_attribute' => 'desc',
|
260 |
+
'magento_attribute' => 'description'),
|
261 |
+
array(
|
262 |
+
'klevu_attribute' => 'shortDesc',
|
263 |
+
'magento_attribute' => 'short_description'),
|
264 |
+
array(
|
265 |
+
'klevu_attribute' => 'salePrice',
|
266 |
+
'magento_attribute' => 'price'),
|
267 |
+
array(
|
268 |
+
'klevu_attribute' => 'salePrice',
|
269 |
+
'magento_attribute' => 'tax_class_id'),
|
270 |
+
array(
|
271 |
+
'klevu_attribute' => 'weight',
|
272 |
+
'magento_attribute' => 'weight'),
|
273 |
+
);
|
274 |
+
}
|
275 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Product/Sync/fixtures/testAddProducts.yaml
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 1
|
3 |
+
default/klevu_search/general/test_mode: 1
|
4 |
+
default/klevu_search/general/test_rest_api_key: test-api-key
|
5 |
+
default/klevu_search/product_sync/enabled: 2
|
6 |
+
eav:
|
7 |
+
catalog_product:
|
8 |
+
-
|
9 |
+
entity_id: 133
|
10 |
+
attribute_set_id: 4
|
11 |
+
type_id: simple
|
12 |
+
sku: ac9003
|
13 |
+
name: Universal Camera Case
|
14 |
+
short_description: A stylish digital camera demands stylish protection. This leather carrying case will defend your camera from the dings and scratches of travel and everyday use while looking smart all the time.
|
15 |
+
description: A stylish digital camera demands stylish protection. This leather carrying case will defend your camera from the dings and scratches of travel and everyday use while looking smart all the time.
|
16 |
+
url_key: universal-camera-case
|
17 |
+
image: /u/n/universal-camera-case.jpg
|
18 |
+
weight: null
|
19 |
+
stock:
|
20 |
+
qty: 100.00
|
21 |
+
is_in_stock: 1
|
22 |
+
website_ids:
|
23 |
+
- 1 # Default website
|
24 |
+
category_ids:
|
25 |
+
- 2 # Default category
|
26 |
+
price: 34
|
27 |
+
tax_class_id: 2
|
28 |
+
status: 1
|
29 |
+
visibility: 4
|
30 |
+
created_at: 2007-08-29 19:56:27
|
31 |
+
updated_at: 2008-06-28 01:57:22
|
app/code/community/Klevu/Search/Test/Model/Product/Sync/fixtures/testClearAllProducts.yaml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 1
|
3 |
+
default/klevu_search/general/test_mode: 1
|
4 |
+
default/klevu_search/general/test_rest_api_key: test-api-key
|
5 |
+
default/klevu_search/product_sync/enabled: 2
|
6 |
+
tables:
|
7 |
+
klevu_search/product_sync:
|
8 |
+
-
|
9 |
+
product_id: 1
|
10 |
+
parent_id: 0
|
11 |
+
store_id: 1
|
12 |
+
test_mode: 1
|
13 |
+
last_synced_at: 2008-08-10 13:36:29
|
14 |
+
-
|
15 |
+
product_id: 2
|
16 |
+
parent_id: 0
|
17 |
+
store_id: 2
|
18 |
+
test_mode: 1
|
19 |
+
last_synced_at: 2008-08-10 13:36:29
|
20 |
+
|
app/code/community/Klevu/Search/Test/Model/Product/Sync/fixtures/testDeleteProducts.yaml
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 1
|
3 |
+
default/klevu_search/general/test_mode: 1
|
4 |
+
default/klevu_search/general/test_rest_api_key: test-api-key
|
5 |
+
default/klevu_search/product_sync/enabled: 2
|
6 |
+
tables:
|
7 |
+
klevu_search/product_sync:
|
8 |
+
-
|
9 |
+
product_id: 130
|
10 |
+
parent_id: 0
|
11 |
+
store_id: 1
|
12 |
+
test_mode: 1
|
13 |
+
last_synced_at: 2008-08-10 13:36:29
|
app/code/community/Klevu/Search/Test/Model/Product/Sync/fixtures/testRun.yaml
ADDED
@@ -0,0 +1,425 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 1
|
3 |
+
default/klevu_search/general/test_mode: 1
|
4 |
+
default/klevu_search/general/test_rest_api_key: test-api-key
|
5 |
+
default/klevu_search/product_sync/enabled: 2
|
6 |
+
eav:
|
7 |
+
catalog_product:
|
8 |
+
-
|
9 |
+
entity_id: 132
|
10 |
+
attribute_set_id: 4
|
11 |
+
type_id: simple
|
12 |
+
sku: ac674
|
13 |
+
name: SLR Camera Tripod
|
14 |
+
short_description: Sturdy, lightweight tripods are designed to meet the needs of amateur and professional photographers and videographers.
|
15 |
+
description: Sturdy, lightweight tripods are designed to meet the needs of amateur and professional photographers and videographers.
|
16 |
+
url_key: slr-camera-tripod
|
17 |
+
image: /s/l/slr-camera-tripod.jpg
|
18 |
+
weight: 42
|
19 |
+
stock:
|
20 |
+
qty: 100.00
|
21 |
+
is_in_stock: 1
|
22 |
+
website_ids:
|
23 |
+
- 1 # Default website
|
24 |
+
category_ids:
|
25 |
+
- 2 # Default category
|
26 |
+
price: 99
|
27 |
+
tax_class_id: 2
|
28 |
+
status: 1
|
29 |
+
visibility: 4
|
30 |
+
created_at: 2007-08-29 19:53:55
|
31 |
+
updated_at: 2008-08-08 15:05:45
|
32 |
+
-
|
33 |
+
entity_id: 133
|
34 |
+
attribute_set_id: 4
|
35 |
+
type_id: simple
|
36 |
+
sku: ac9003
|
37 |
+
name: Universal Camera Case
|
38 |
+
short_description: A stylish digital camera demands stylish protection. This leather carrying case will defend your camera from the dings and scratches of travel and everyday use while looking smart all the time.
|
39 |
+
description: A stylish digital camera demands stylish protection. This leather carrying case will defend your camera from the dings and scratches of travel and everyday use while looking smart all the time.
|
40 |
+
url_key: universal-camera-case
|
41 |
+
image: /u/n/universal-camera-case.jpg
|
42 |
+
weight: null
|
43 |
+
stock:
|
44 |
+
qty: 100.00
|
45 |
+
is_in_stock: 1
|
46 |
+
website_ids:
|
47 |
+
- 1 # Default website
|
48 |
+
category_ids:
|
49 |
+
- 2 # Default category
|
50 |
+
price: 34
|
51 |
+
tax_class_id: 2
|
52 |
+
status: 1
|
53 |
+
visibility: 4
|
54 |
+
created_at: 2007-08-29 19:56:27
|
55 |
+
updated_at: 2008-06-28 01:57:22
|
56 |
+
-
|
57 |
+
entity_id: 134
|
58 |
+
attribute_set_id: 4
|
59 |
+
type_id: simple
|
60 |
+
sku: ac-66332
|
61 |
+
name: Universal Camera Charger
|
62 |
+
short_description: Features foldable Flat Pin for Easy Storage/ Slim/ Lightweight Design and Smart Charging LED Indicator.
|
63 |
+
description: Features foldable Flat Pin for Easy Storage/ Slim/ Lightweight Design and Smart Charging LED Indicator.
|
64 |
+
url_key: universal-camera-charger
|
65 |
+
image: /u/n/universal-camera-charger.jpg
|
66 |
+
weight: 5
|
67 |
+
stock:
|
68 |
+
qty: 100.00
|
69 |
+
is_in_stock: 1
|
70 |
+
website_ids:
|
71 |
+
- 1 # Default website
|
72 |
+
category_ids:
|
73 |
+
- 2 # Default category
|
74 |
+
price: 19
|
75 |
+
tax_class_id: 2
|
76 |
+
status: 1
|
77 |
+
visibility: 4
|
78 |
+
created_at: 2007-08-29 19:59:29
|
79 |
+
updated_at: 2008-06-28 01:57:16
|
80 |
+
-
|
81 |
+
entity_id: 138
|
82 |
+
attribute_set_id: 4
|
83 |
+
type_id: simple
|
84 |
+
sku: apevia-black
|
85 |
+
name: Apevia Black X-Cruiser Case ATX Mid-Tower Case (Default)
|
86 |
+
short_description: This magnificent new case features 2 x 80mm built-in fans with space for 2 optional fans. The Aspire X-Cruiser features front temperature gauge, front fan speed controller and gauge, and front volume controller and gauge. It also features USB2.0, Firewire and audio ports. The superior cooling solution that X-Cruiser delivers can only be found in very few of the expensive chassis in the market.
|
87 |
+
description: This superb, multi-functional Aspire X-Cruiser mid tower case is designed to follow Intel's recommendations to achieve the highest level of thermal performance. This gorgeous case outperforms most of the expensive chassis in the market, boasts an abundance of innovative features, yet carries a very affordable price tag. The Aspire X-Cruiser is fully loaded with everything you could possibly imagine that a great gaming case could have. With a built-in air duct on the side panel to funnel cool air towards the CPU, the fan-less X-Cruiser is specially designed to bring out the best performance in systems based on high-end processors.
|
88 |
+
url_key: apevia-black-x-cruiser-case-atx-mid-tower-case
|
89 |
+
image: /a/p/apevia-black-x-cruiser-case-atx-mid-tower-case-default.jpg
|
90 |
+
weight: 10
|
91 |
+
stock:
|
92 |
+
qty: 100.00
|
93 |
+
is_in_stock: 1
|
94 |
+
website_ids:
|
95 |
+
- 1 # Default website
|
96 |
+
category_ids:
|
97 |
+
- 2 # Default category
|
98 |
+
price: 150
|
99 |
+
tax_class_id: 1
|
100 |
+
status: 1
|
101 |
+
visibility: 4
|
102 |
+
created_at: 2008-07-25 00:52:03
|
103 |
+
updated_at: 2008-08-08 13:36:29
|
104 |
+
-
|
105 |
+
entity_id: 139
|
106 |
+
attribute_set_id: 4
|
107 |
+
type_id: simple
|
108 |
+
sku: nzxtlexa
|
109 |
+
name: NZXT Lexa Silver Aluminum ATX Mid-Tower Case (Default)
|
110 |
+
short_description: The Lexa boasts a ridgid, but light weight aluminum chassis. The Lexa's high-air-flow design, while quiet, ensures cooling options for the more ambitious computing enthusiasts. Three thermal probes provide temperature readings to the illuminated LCD display for monitoring your systems core components. The Lexa ships with a rugged carrying strap with protective window cover for easy single-handed transportation.
|
111 |
+
description: Introducing the next advancement in case design and technology, the Lexa. Designed from ground up to be symmetrical, the Lexa is representative of the modern lifestyle design cues of today. The Lexa's minimalist and classy design fits perfectly under the NZXT Classic Series line.
|
112 |
+
url_key: nzxt-lexa-silver-aluminum-atx-mid-tower-case
|
113 |
+
image: /n/z/nzxt-lexa-silver-aluminum-atx-mid-tower-case-default.jpg
|
114 |
+
weight: 10
|
115 |
+
stock:
|
116 |
+
qty: 100.00
|
117 |
+
is_in_stock: 1
|
118 |
+
website_ids:
|
119 |
+
- 1 # Default website
|
120 |
+
category_ids:
|
121 |
+
- 2 # Default category
|
122 |
+
price: 199.99
|
123 |
+
tax_class_id: 1
|
124 |
+
status: 1
|
125 |
+
visibility: 4
|
126 |
+
created_at: 2008-07-25 00:54:41
|
127 |
+
updated_at: 2008-07-25 00:54:41
|
128 |
+
-
|
129 |
+
entity_id: 201
|
130 |
+
attribute_set_id: 4
|
131 |
+
type_id: simple
|
132 |
+
sku: delete-simple
|
133 |
+
name: Delete Simple Product
|
134 |
+
short_description: Delete Simple Product
|
135 |
+
description: delete Simple Product
|
136 |
+
url_key: delete-simple
|
137 |
+
website_ids:
|
138 |
+
- 1 # Default website
|
139 |
+
category_ids:
|
140 |
+
- 2 # Default category
|
141 |
+
price: 19.99
|
142 |
+
tax_class_id: 2
|
143 |
+
status: 1
|
144 |
+
visibility: 1
|
145 |
+
color: 4
|
146 |
+
created_at: 2014-05-21 12:00:00
|
147 |
+
updated_at: 2014-05-21 12:00:00
|
148 |
+
-
|
149 |
+
entity_id: 202
|
150 |
+
attribute_set_id: 4
|
151 |
+
type_id: configurable
|
152 |
+
sku: delete
|
153 |
+
name: Delete Configurable Product
|
154 |
+
short_description: Delete Configurable Product
|
155 |
+
description: Delete Configurable Product
|
156 |
+
url_key: delete
|
157 |
+
super_attributes:
|
158 |
+
- color
|
159 |
+
configurable_children:
|
160 |
+
- 201
|
161 |
+
website_ids:
|
162 |
+
- 1 # Default website
|
163 |
+
category_ids:
|
164 |
+
- 2 # Default category
|
165 |
+
price: 19.99
|
166 |
+
tax_class_id: 2
|
167 |
+
status: 1
|
168 |
+
visibility: 1
|
169 |
+
created_at: 2014-05-21 12:00:00
|
170 |
+
updated_at: 2014-05-21 12:00:00
|
171 |
+
-
|
172 |
+
entity_id: 203
|
173 |
+
attribute_set_id: 4
|
174 |
+
type_id: simple
|
175 |
+
sku: update-parent-simple
|
176 |
+
name: Update Parent Simple Product
|
177 |
+
short_description: Update Parent Simple Product
|
178 |
+
description: Update Parent Simple Product
|
179 |
+
url_key: update-parent-simple
|
180 |
+
website_ids:
|
181 |
+
- 1 # Default website
|
182 |
+
category_ids:
|
183 |
+
- 2 # Default category
|
184 |
+
price: 19.99
|
185 |
+
tax_class_id: 2
|
186 |
+
status: 1
|
187 |
+
visibility: 1
|
188 |
+
color: 4
|
189 |
+
created_at: 2014-05-20 09:00:00
|
190 |
+
updated_at: 2014-05-20 09:00:00
|
191 |
+
-
|
192 |
+
entity_id: 204
|
193 |
+
attribute_set_id: 4
|
194 |
+
type_id: configurable
|
195 |
+
sku: update-parent
|
196 |
+
name: Update Parent Configurable Product
|
197 |
+
short_description: Update Parent Configurable Product
|
198 |
+
description: Update Parent Configurable Product
|
199 |
+
url_key: update-parent
|
200 |
+
super_attributes:
|
201 |
+
- color
|
202 |
+
configurable_children:
|
203 |
+
- 203
|
204 |
+
website_ids:
|
205 |
+
- 1 # Default website
|
206 |
+
category_ids:
|
207 |
+
- 2 # Default category
|
208 |
+
price: 19.99
|
209 |
+
tax_class_id: 2
|
210 |
+
status: 1
|
211 |
+
visibility: 4
|
212 |
+
created_at: 2014-05-20 09:00:00
|
213 |
+
updated_at: 2014-05-21 09:00:00
|
214 |
+
-
|
215 |
+
entity_id: 205
|
216 |
+
attribute_set_id: 4
|
217 |
+
type_id: simple
|
218 |
+
sku: update-child-simple
|
219 |
+
name: Update Child Simple Product
|
220 |
+
short_description: Update Child Simple Product
|
221 |
+
description: Update Child Simple Product
|
222 |
+
url_key: update-child-simple
|
223 |
+
website_ids:
|
224 |
+
- 1 # Default website
|
225 |
+
category_ids:
|
226 |
+
- 2 # Default category
|
227 |
+
price: 19.99
|
228 |
+
tax_class_id: 2
|
229 |
+
status: 1
|
230 |
+
visibility: 1
|
231 |
+
color: 4
|
232 |
+
created_at: 2014-05-20 09:00:00
|
233 |
+
updated_at: 2014-05-21 09:00:00
|
234 |
+
-
|
235 |
+
entity_id: 206
|
236 |
+
attribute_set_id: 4
|
237 |
+
type_id: configurable
|
238 |
+
sku: update-child
|
239 |
+
name: Update Child Configurable Product
|
240 |
+
short_description: Update Child Configurable Product
|
241 |
+
description: Update Child Configurable Product
|
242 |
+
url_key: update-child
|
243 |
+
super_attributes:
|
244 |
+
- color
|
245 |
+
configurable_children:
|
246 |
+
- 205
|
247 |
+
website_ids:
|
248 |
+
- 1 # Default website
|
249 |
+
category_ids:
|
250 |
+
- 2 # Default category
|
251 |
+
price: 19.99
|
252 |
+
tax_class_id: 2
|
253 |
+
status: 1
|
254 |
+
visibility: 4
|
255 |
+
created_at: 2014-05-20 09:00:00
|
256 |
+
updated_at: 2014-05-20 09:00:00
|
257 |
+
-
|
258 |
+
entity_id: 207
|
259 |
+
attribute_set_id: 4
|
260 |
+
type_id: simple
|
261 |
+
sku: add-simple-1
|
262 |
+
name: Add Simple Product 1
|
263 |
+
short_description: Add Simple Product 1
|
264 |
+
description: Add Simple Product 1
|
265 |
+
url_key: add-simple-1
|
266 |
+
website_ids:
|
267 |
+
- 1 # Default website
|
268 |
+
category_ids:
|
269 |
+
- 2 # Default category
|
270 |
+
price: 19.99
|
271 |
+
tax_class_id: 2
|
272 |
+
status: 1
|
273 |
+
visibility: 1
|
274 |
+
color: 4
|
275 |
+
created_at: 2014-05-20 09:00:00
|
276 |
+
updated_at: 2014-05-21 09:00:00
|
277 |
+
-
|
278 |
+
entity_id: 208
|
279 |
+
attribute_set_id: 4
|
280 |
+
type_id: simple
|
281 |
+
sku: add-simple-2
|
282 |
+
name: Add Simple Product 2
|
283 |
+
short_description: Add Simple Product 2
|
284 |
+
description: Add Simple Product 2
|
285 |
+
url_key: add-simple-2
|
286 |
+
website_ids:
|
287 |
+
- 1 # Default website
|
288 |
+
category_ids:
|
289 |
+
- 2 # Default category
|
290 |
+
price: 29.99
|
291 |
+
tax_class_id: 2
|
292 |
+
status: 1
|
293 |
+
visibility: 1
|
294 |
+
color: 3
|
295 |
+
created_at: 2014-05-20 09:00:00
|
296 |
+
updated_at: 2014-05-21 09:00:00
|
297 |
+
-
|
298 |
+
entity_id: 209
|
299 |
+
attribute_set_id: 4
|
300 |
+
type_id: configurable
|
301 |
+
sku: add
|
302 |
+
name: Add Configurable Product
|
303 |
+
short_description: Add Configurable Product
|
304 |
+
description: Add Configurable Product
|
305 |
+
url_key: add
|
306 |
+
super_attributes:
|
307 |
+
- color
|
308 |
+
configurable_children:
|
309 |
+
- 207
|
310 |
+
- 208
|
311 |
+
website_ids:
|
312 |
+
- 1 # Default website
|
313 |
+
category_ids:
|
314 |
+
- 2 # Default category
|
315 |
+
price: 19.99
|
316 |
+
tax_class_id: 2
|
317 |
+
status: 1
|
318 |
+
visibility: 4
|
319 |
+
created_at: 2014-05-20 09:00:00
|
320 |
+
updated_at: 2014-05-20 09:00:00
|
321 |
+
-
|
322 |
+
entity_id: 210
|
323 |
+
attribute_set_id: 4
|
324 |
+
type_id: simple
|
325 |
+
sku: delete-deleted-child-simple
|
326 |
+
name: Delete Deleted Child Simple Product
|
327 |
+
short_description: Delete Deleted Child Simple Product
|
328 |
+
description: Delete Deleted Child Simple Product
|
329 |
+
url_key: delete-deleted-child-simple
|
330 |
+
website_ids:
|
331 |
+
- 1 # Default website
|
332 |
+
category_ids:
|
333 |
+
- 2 # Default category
|
334 |
+
price: 19.99
|
335 |
+
tax_class_id: 2
|
336 |
+
status: 1
|
337 |
+
visibility: 1
|
338 |
+
color: 4
|
339 |
+
created_at: 2014-05-21 12:00:00
|
340 |
+
updated_at: 2014-05-21 12:00:00
|
341 |
+
-
|
342 |
+
entity_id: 212
|
343 |
+
attribute_set_id: 4
|
344 |
+
type_id: configurable
|
345 |
+
sku: delete-deleted-child
|
346 |
+
name: Delete Deleted Child Configurable Product
|
347 |
+
short_description: Delete Deleted Child Configurable Product
|
348 |
+
description: Delete Deleted Child Configurable Product
|
349 |
+
url_key: delete-deleted-child
|
350 |
+
super_attributes:
|
351 |
+
- color
|
352 |
+
configurable_children:
|
353 |
+
- 210
|
354 |
+
website_ids:
|
355 |
+
- 1 # Default website
|
356 |
+
category_ids:
|
357 |
+
- 2 # Default category
|
358 |
+
price: 19.99
|
359 |
+
tax_class_id: 2
|
360 |
+
status: 1
|
361 |
+
visibility: 4
|
362 |
+
created_at: 2014-05-21 12:00:00
|
363 |
+
updated_at: 2014-05-21 12:00:00
|
364 |
+
tables:
|
365 |
+
klevu_search/product_sync:
|
366 |
+
-
|
367 |
+
product_id: 130
|
368 |
+
parent_id: 0
|
369 |
+
store_id: 1
|
370 |
+
test_mode: 1
|
371 |
+
last_synced_at: 2008-08-10 13:36:29
|
372 |
+
-
|
373 |
+
product_id: 133
|
374 |
+
parent_id: 0
|
375 |
+
store_id: 1
|
376 |
+
test_mode: 1
|
377 |
+
last_synced_at: 2008-06-27 01:57:22
|
378 |
+
-
|
379 |
+
product_id: 134
|
380 |
+
parent_id: 0
|
381 |
+
store_id: 1
|
382 |
+
test_mode: 1
|
383 |
+
last_synced_at: 2008-06-27 01:57:16
|
384 |
+
-
|
385 |
+
product_id: 138
|
386 |
+
parent_id: 0
|
387 |
+
store_id: 1
|
388 |
+
test_mode: 1
|
389 |
+
last_synced_at: 2008-08-10 13:36:29
|
390 |
+
-
|
391 |
+
product_id: 139
|
392 |
+
parent_id: 0
|
393 |
+
store_id: 1
|
394 |
+
test_mode: 1
|
395 |
+
last_synced_at: 2008-08-10 13:36:29
|
396 |
+
-
|
397 |
+
product_id: 201
|
398 |
+
parent_id: 202
|
399 |
+
store_id: 1
|
400 |
+
test_mode: 1
|
401 |
+
last_synced_at: 2014-05-21 12:00:00
|
402 |
+
-
|
403 |
+
product_id: 203
|
404 |
+
parent_id: 204
|
405 |
+
store_id: 1
|
406 |
+
test_mode: 1
|
407 |
+
last_synced_at: 2014-05-20 12:00:00
|
408 |
+
-
|
409 |
+
product_id: 205
|
410 |
+
parent_id: 206
|
411 |
+
store_id: 1
|
412 |
+
test_mode: 1
|
413 |
+
last_synced_at: 2014-05-20 12:00:00
|
414 |
+
-
|
415 |
+
product_id: 210
|
416 |
+
parent_id: 212
|
417 |
+
store_id: 1
|
418 |
+
test_mode: 1
|
419 |
+
last_synced_at: 2014-05-21 12:00:00
|
420 |
+
-
|
421 |
+
product_id: 211
|
422 |
+
parent_id: 212
|
423 |
+
store_id: 1
|
424 |
+
test_mode: 1
|
425 |
+
last_synced_at: 2014-05-21 12:00:00
|
app/code/community/Klevu/Search/Test/Model/Product/Sync/fixtures/testUpdateProducts.yaml
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
config:
|
2 |
+
default/klevu_search/general/enabled: 1
|
3 |
+
default/klevu_search/general/test_mode: 1
|
4 |
+
default/klevu_search/general/test_rest_api_key: test-api-key
|
5 |
+
default/klevu_search/product_sync/enabled: 2
|
6 |
+
eav:
|
7 |
+
catalog_product:
|
8 |
+
-
|
9 |
+
entity_id: 133
|
10 |
+
attribute_set_id: 4
|
11 |
+
type_id: simple
|
12 |
+
sku: ac9003
|
13 |
+
name: Universal Camera Case
|
14 |
+
short_description: A stylish digital camera demands stylish protection. This leather carrying case will defend your camera from the dings and scratches of travel and everyday use while looking smart all the time.
|
15 |
+
description: A stylish digital camera demands stylish protection. This leather carrying case will defend your camera from the dings and scratches of travel and everyday use while looking smart all the time.
|
16 |
+
url_key: universal-camera-case
|
17 |
+
image: /u/n/universal-camera-case.jpg
|
18 |
+
weight: null
|
19 |
+
stock:
|
20 |
+
qty: 100.00
|
21 |
+
is_in_stock: 1
|
22 |
+
website_ids:
|
23 |
+
- 1 # Default website
|
24 |
+
category_ids:
|
25 |
+
- 2 # Default category
|
26 |
+
price: 34
|
27 |
+
tax_class_id: 2
|
28 |
+
status: 1
|
29 |
+
visibility: 4
|
30 |
+
created_at: 2007-08-29 19:56:27
|
31 |
+
updated_at: 2008-06-28 01:57:22
|
32 |
+
tables:
|
33 |
+
klevu_search/product_sync:
|
34 |
+
-
|
35 |
+
product_id: 133
|
36 |
+
parent_id: 0
|
37 |
+
store_id: 1
|
38 |
+
test_mode: 1
|
39 |
+
last_synced_at: 2008-06-27 01:57:22
|
app/code/community/Klevu/Search/Test/Model/Sync.php
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_Sync extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
const TEST_JOB_CODE = "klevu_search_test_job";
|
6 |
+
|
7 |
+
protected function tearDown() {
|
8 |
+
$collection = $this->getTestCronScheduleCollection();
|
9 |
+
foreach ($collection as $item) {
|
10 |
+
$item->delete();
|
11 |
+
}
|
12 |
+
|
13 |
+
parent::tearDown();
|
14 |
+
}
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @test
|
18 |
+
* @dataProvider dataProvider
|
19 |
+
*/
|
20 |
+
public function testSchedule($time) {
|
21 |
+
$model = $this->getTestModel();
|
22 |
+
|
23 |
+
$time = new DateTime($time);
|
24 |
+
|
25 |
+
$model->schedule($time);
|
26 |
+
|
27 |
+
$collection = $this->getTestCronScheduleCollection();
|
28 |
+
|
29 |
+
$this->assertEquals(1, $collection->getSize());
|
30 |
+
|
31 |
+
$schedule = $collection->getFirstItem();
|
32 |
+
|
33 |
+
$this->assertEquals($time->format("Y-m-d H:i:00"), $schedule->getScheduledAt());
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @test
|
38 |
+
*/
|
39 |
+
public function testAlreadyScheduled() {
|
40 |
+
$model = $this->getTestModel();
|
41 |
+
$connection = Mage::getModel('core/resource')->getConnection("core_write");
|
42 |
+
$count_sql = $this->getTestCronScheduleCollection()->getSelectCountSql();
|
43 |
+
|
44 |
+
$time = new DateTime("now");
|
45 |
+
|
46 |
+
$model->schedule($time);
|
47 |
+
$this->assertEquals(1, $connection->fetchOne($count_sql),
|
48 |
+
"Failed to assert that schedule() adds a cron entry to the schedule.");
|
49 |
+
|
50 |
+
$before = clone $time;
|
51 |
+
$before->modify("15 minutes ago");
|
52 |
+
$model->schedule($before);
|
53 |
+
$this->assertEquals(1, $connection->fetchOne($count_sql),
|
54 |
+
"Failed to assert that schedule() does not add a new cron entry if one is already scheduled for up to 15 minutes later.");
|
55 |
+
|
56 |
+
$after = clone $time;
|
57 |
+
$after->modify("15 minutes");
|
58 |
+
$model->schedule($after);
|
59 |
+
$this->assertEquals(1, $connection->fetchOne($count_sql),
|
60 |
+
"Failed to assert that schedule() does not add a new cron entry if one is already scheduled for up to 15 minutes earlier.");
|
61 |
+
|
62 |
+
$before->modify("5 minutes ago");
|
63 |
+
$model->schedule($before);
|
64 |
+
$this->assertEquals(2, $connection->fetchOne($count_sql),
|
65 |
+
"Failed to assert that schedule() can add a new cron entry 20 minutes before an existing one.");
|
66 |
+
|
67 |
+
$after->modify("5 minutes");
|
68 |
+
$model->schedule($after);
|
69 |
+
$this->assertEquals(3, $connection->fetchOne($count_sql),
|
70 |
+
"Failed to assert that schedule() can add a new cron entry 20 minutes after an existing one.");
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* @test
|
75 |
+
*/
|
76 |
+
public function testIsRunning() {
|
77 |
+
$model = $this->getTestModel();
|
78 |
+
|
79 |
+
$now = new DateTime();
|
80 |
+
$now = $now->format("Y-m-d H:i:00");
|
81 |
+
|
82 |
+
$schedule = Mage::getModel('cron/schedule');
|
83 |
+
$schedule
|
84 |
+
->setJobCode(static::TEST_JOB_CODE)
|
85 |
+
->setCreatedAt($now)
|
86 |
+
->setScheduledAt($now)
|
87 |
+
->setExecutedAt($now)
|
88 |
+
->setStatus(Mage_Cron_Model_Schedule::STATUS_RUNNING)
|
89 |
+
->save();
|
90 |
+
|
91 |
+
$this->assertTrue($model->isRunning(), "Failed to assert that isRunning() returns true when there's a sync cron running.");
|
92 |
+
$this->assertFalse($model->isRunning(2), "Failed to assert that isRunning(2) returns false when there's only one cron running.");
|
93 |
+
|
94 |
+
|
95 |
+
$schedule = Mage::getModel('cron/schedule');
|
96 |
+
$schedule
|
97 |
+
->setJobCode(static::TEST_JOB_CODE)
|
98 |
+
->setCreatedAt($now)
|
99 |
+
->setScheduledAt($now)
|
100 |
+
->setExecutedAt($now)
|
101 |
+
->setStatus(Mage_Cron_Model_Schedule::STATUS_RUNNING)
|
102 |
+
->save();
|
103 |
+
|
104 |
+
$this->assertTrue($model->isRunning(2), "Failed to assert that isRunning(2) returns true when there's 2 sync crons running.");
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Return a Mock fo the klevu_search/sync model for testing.
|
109 |
+
*
|
110 |
+
* @return PHPUnit_Framework_MockObject_MockObject
|
111 |
+
*/
|
112 |
+
protected function getTestModel() {
|
113 |
+
$mock = $this->getMockForAbstractClass(Mage::app()->getConfig()->getModelClassName("klevu_search/sync"));
|
114 |
+
$mock
|
115 |
+
->expects($this->any())
|
116 |
+
->method("getJobCode")
|
117 |
+
->will($this->returnValue(static::TEST_JOB_CODE));
|
118 |
+
return $mock;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Return a cron/schedule collection filtered for test jobs only.
|
123 |
+
*
|
124 |
+
* @return Mage_Cron_Model_Mysql4_Schedule_Collection
|
125 |
+
*/
|
126 |
+
protected function getTestCronScheduleCollection() {
|
127 |
+
return Mage::getResourceModel('cron/schedule_collection')
|
128 |
+
->addFieldToFilter("job_code", static::TEST_JOB_CODE);
|
129 |
+
}
|
130 |
+
}
|
app/code/community/Klevu/Search/Test/Model/Sync/providers/testSchedule.yaml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
time: now
|
3 |
+
-
|
4 |
+
time: 2014-05-14 12:00:00
|
app/code/community/Klevu/Search/Test/Model/System/Config/Source/Test.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Test_Model_System_Config_Source_Test extends EcomDev_PHPUnit_Test_Case {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @test
|
7 |
+
* @dataProvider dataProvider
|
8 |
+
*/
|
9 |
+
public function testIsValidSourceModel($alias) {
|
10 |
+
$model = Mage::getModel($alias);
|
11 |
+
|
12 |
+
$this->assertTrue($model !== false, sprintf("Model with alias %s not found.", $alias));
|
13 |
+
$this->assertTrue(method_exists($model, "toOptionArray"), "toOptionArray() method doesn't exist.");
|
14 |
+
|
15 |
+
$options = $model->toOptionArray();
|
16 |
+
|
17 |
+
$this->assertTrue(is_array($options), "toOptionArray() did not return an array.");
|
18 |
+
|
19 |
+
foreach ($options as $option) {
|
20 |
+
$this->assertTrue(is_array($option), sprintf("Each option must be an array, instead got: %s", print_r($option, true)));
|
21 |
+
|
22 |
+
$this->assertArrayHasKey("label", $option, sprintf("Each option must have a label, instead got: %s", print_r($option, true)));
|
23 |
+
$this->assertArrayHasKey("value", $option, sprintf("Each option must have a value, instead got: %s", print_r($option, true)));
|
24 |
+
}
|
25 |
+
}
|
26 |
+
}
|
app/code/community/Klevu/Search/Test/Model/System/Config/Source/Test/providers/testIsValidSourceModel.yaml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-
|
2 |
+
- klevu_search/system_config_source_yesnoforced
|
3 |
+
-
|
4 |
+
- klevu_search/system_config_source_frequency
|
5 |
+
-
|
6 |
+
- klevu_search/system_config_source_log_level
|
7 |
+
-
|
8 |
+
- klevu_search/system_config_source_additional_attributes
|
9 |
+
-
|
10 |
+
- klevu_search/system_config_source_product_attributes
|
app/code/community/Klevu/Search/controllers/Adminhtml/Klevu/NotificationsController.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Adminhtml_Klevu_NotificationsController extends Mage_Adminhtml_Controller_Action {
|
4 |
+
|
5 |
+
public function dismissAction() {
|
6 |
+
$id = intval($this->getRequest()->getParam("id"));
|
7 |
+
|
8 |
+
$notification = Mage::getModel('klevu_search/notification')->load($id);
|
9 |
+
|
10 |
+
if ($notification->getId()) {
|
11 |
+
$notification->delete();
|
12 |
+
} else {
|
13 |
+
Mage::getSingleton("adminhtml/session")->addError("Unable to dismiss Klevu notification as it does not exist.");
|
14 |
+
}
|
15 |
+
|
16 |
+
return $this->_redirectReferer($this->getUrl("adminhtml/dashboard"));
|
17 |
+
}
|
18 |
+
}
|
app/code/community/Klevu/Search/controllers/Adminhtml/Klevu/Search/WizardController.php
ADDED
@@ -0,0 +1,214 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Adminhtml_Klevu_Search_WizardController extends Mage_Adminhtml_Controller_Action {
|
4 |
+
|
5 |
+
public function configure_userAction() {
|
6 |
+
$this->loadLayout();
|
7 |
+
$this->initLayoutMessages('klevu_search/session');
|
8 |
+
$this->renderLayout();
|
9 |
+
}
|
10 |
+
|
11 |
+
public function configure_user_postAction() {
|
12 |
+
$request = $this->getRequest();
|
13 |
+
|
14 |
+
if (!$request->isPost() || !$request->isAjax()) {
|
15 |
+
return $this->_redirect('adminhtml/dashboard');
|
16 |
+
}
|
17 |
+
|
18 |
+
$api = Mage::helper("klevu_search/api");
|
19 |
+
$session = Mage::getSingleton('klevu_search/session');
|
20 |
+
|
21 |
+
if ($request->getPost("klevu_existing_email")) {
|
22 |
+
$result = $api->getUser(
|
23 |
+
$request->getPost("klevu_existing_email"),
|
24 |
+
$request->getPost("klevu_existing_password")
|
25 |
+
);
|
26 |
+
} else {
|
27 |
+
$klevu_new_email = $request->getPost("klevu_new_email");
|
28 |
+
$klevu_new_password = $request->getPost("klevu_new_password");
|
29 |
+
$userPlan = $request->getPost("userPlan");
|
30 |
+
$klevu_new_url = $request->getPost("klevu_new_url");
|
31 |
+
$merchantEmail = $request->getPost("merchantEmail");
|
32 |
+
$contactNo = $request->getPost("countyCode")."-".$request->getPost("contactNo");
|
33 |
+
if(!empty($klevu_new_email) && !empty($klevu_new_password) && !empty($userPlan) && !empty($klevu_new_url)
|
34 |
+
&& !empty($merchantEmail) ) {
|
35 |
+
$result = $api->createUser(
|
36 |
+
$request->getPost("klevu_new_email"),
|
37 |
+
$request->getPost("klevu_new_password"),
|
38 |
+
$request->getPost("userPlan"),
|
39 |
+
$request->getPost("klevu_new_url"),
|
40 |
+
$request->getPost("merchantEmail"),
|
41 |
+
$contactNo
|
42 |
+
);
|
43 |
+
} else {
|
44 |
+
$session->addError(Mage::helper("klevu_search")->__("Missing details in the form. Please check."));
|
45 |
+
return $this->_forward("configure_user");
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
if ($result["success"]) {
|
50 |
+
$session->setConfiguredCustomerId($result["customer_id"]);
|
51 |
+
if (isset($result["message"])) {
|
52 |
+
$session->addSuccess(Mage::helper("klevu_search")->__($result["message"]));
|
53 |
+
}
|
54 |
+
return $this->_forward("configure_store");
|
55 |
+
} else {
|
56 |
+
$session->addError(Mage::helper("klevu_search")->__($result["message"]));
|
57 |
+
return $this->_forward("configure_user");
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
public function configure_storeAction() {
|
62 |
+
$request = $this->getRequest();
|
63 |
+
|
64 |
+
if (!$request->isAjax()) {
|
65 |
+
return $this->_redirect("adminhtml/dashboard");
|
66 |
+
}
|
67 |
+
|
68 |
+
$session = Mage::getSingleton("klevu_search/session");
|
69 |
+
|
70 |
+
if (!$session->getConfiguredCustomerId()) {
|
71 |
+
$session->addError(Mage::helper("klevu_search")->__("You must configure a user first."));
|
72 |
+
return $this->_redirect("*/*/configure_user");
|
73 |
+
}
|
74 |
+
|
75 |
+
$this->loadLayout();
|
76 |
+
$this->initLayoutMessages('klevu_search/session');
|
77 |
+
$this->renderLayout();
|
78 |
+
}
|
79 |
+
|
80 |
+
public function configure_store_postAction() {
|
81 |
+
$request = $this->getRequest();
|
82 |
+
|
83 |
+
if (!$request->isPost() || !$request->isAjax()) {
|
84 |
+
return $this->_redirect("adminhtml/dashboard");
|
85 |
+
}
|
86 |
+
|
87 |
+
$config = Mage::helper("klevu_search/config");
|
88 |
+
$api = Mage::helper("klevu_search/api");
|
89 |
+
$session = Mage::getSingleton('klevu_search/session');
|
90 |
+
$customer_id = $session->getConfiguredCustomerId();
|
91 |
+
|
92 |
+
if (!$customer_id) {
|
93 |
+
$session->addError(Mage::helper("klevu_search")->__("You must configure a user first."));
|
94 |
+
return $this->_redirect("*/*/configure_user");
|
95 |
+
}
|
96 |
+
|
97 |
+
$store_code = $request->getPost("store");
|
98 |
+
if (strlen($store_code) == 0) {
|
99 |
+
$session->addError(Mage::helper("klevu_search")->__("Must select a store"));
|
100 |
+
return $this->_forward("configure_store");
|
101 |
+
}
|
102 |
+
|
103 |
+
try {
|
104 |
+
$store = Mage::app()->getStore($store_code);
|
105 |
+
} catch (Mage_Core_Model_Store_Exception $e) {
|
106 |
+
$session->addError(Mage::helper("klevu_search")->__("Selected store does not exist."));
|
107 |
+
return $this->_forward("configure_store");
|
108 |
+
}
|
109 |
+
|
110 |
+
// Setup the live and test Webstores
|
111 |
+
foreach (array(false) as $test_mode) {
|
112 |
+
$result = $api->createWebstore($customer_id, $store, $test_mode);
|
113 |
+
if ($result["success"]) {
|
114 |
+
$config->setJsApiKey($result["webstore"]->getJsApiKey(), $store, $test_mode);
|
115 |
+
$config->setRestApiKey($result["webstore"]->getRestApiKey(), $store, $test_mode);
|
116 |
+
$config->setHostname($result["webstore"]->getHostedOn(), $store, $test_mode);
|
117 |
+
$config->setCloudSearchUrl($result['webstore']->getCloudSearchUrl(), $store, $test_mode);
|
118 |
+
$config->setAnalyticsUrl($result['webstore']->getAnalyticsUrl(), $store, $test_mode);
|
119 |
+
$config->setJsUrl($result['webstore']->getJsUrl(), $store, $test_mode);
|
120 |
+
$config->setRestHostname($result['webstore']->getRestHostname(), $store, $test_mode);
|
121 |
+
if (isset($result["message"])) {
|
122 |
+
$session->addSuccess(Mage::helper("klevu_search")->__($result["message"]));
|
123 |
+
}
|
124 |
+
} else {
|
125 |
+
$session->addError(Mage::helper("klevu_search")->__($result["message"]));
|
126 |
+
return $this->_forward("configure_store");
|
127 |
+
}
|
128 |
+
}
|
129 |
+
|
130 |
+
|
131 |
+
$config->setTaxEnabledFlag($request->getPost("tax_enable"), $store);
|
132 |
+
|
133 |
+
// Clear Product Sync and Order Sync data for the newly configured store
|
134 |
+
Mage::getModel("klevu_search/product_sync")->clearAllProducts($store);
|
135 |
+
Mage::getModel("klevu_search/order_sync")->clearQueue($store);
|
136 |
+
|
137 |
+
$session->setConfiguredStoreCode($store_code);
|
138 |
+
|
139 |
+
$session->addSuccess("Store configured successfully. Saved API credentials.");
|
140 |
+
|
141 |
+
// Schedule a Product Sync
|
142 |
+
Mage::getModel("klevu_search/product_sync")->schedule();
|
143 |
+
|
144 |
+
$this->loadLayout();
|
145 |
+
$this->initLayoutMessages("klevu_search/session");
|
146 |
+
$this->renderLayout();
|
147 |
+
return;
|
148 |
+
}
|
149 |
+
|
150 |
+
public function configure_attributesAction() {
|
151 |
+
|
152 |
+
$request = $this->getRequest();
|
153 |
+
|
154 |
+
if (!$request->isAjax()) {
|
155 |
+
return $this->_redirect("adminhtml/dashboard");
|
156 |
+
}
|
157 |
+
|
158 |
+
$session = Mage::getSingleton("klevu_search/session");
|
159 |
+
|
160 |
+
if (!$session->getConfiguredCustomerId()) {
|
161 |
+
$session->addError(Mage::helper("klevu_search")->__("You must configure a user first."));
|
162 |
+
return $this->_redirect("*/*/configure_user");
|
163 |
+
}
|
164 |
+
|
165 |
+
if (!$session->getConfiguredStoreCode()) {
|
166 |
+
$session->addError(Mage::helper("klevu_search")->__("Must select a store"));
|
167 |
+
return $this->_redirect("*/*/configure_store");
|
168 |
+
}
|
169 |
+
|
170 |
+
$this->loadLayout();
|
171 |
+
$this->initLayoutMessages('klevu_search/session');
|
172 |
+
$this->renderLayout();
|
173 |
+
}
|
174 |
+
|
175 |
+
public function configure_attributes_postAction() {
|
176 |
+
|
177 |
+
$request = $this->getRequest();
|
178 |
+
|
179 |
+
if (!$request->isPost() || !$request->isAjax()) {
|
180 |
+
return $this->_redirect("adminhtml/dashboard");
|
181 |
+
}
|
182 |
+
|
183 |
+
$session = Mage::getSingleton("klevu_search/session");
|
184 |
+
|
185 |
+
if (!$session->getConfiguredCustomerId()) {
|
186 |
+
$session->addError(Mage::helper("klevu_search")->__("You must configure a user first."));
|
187 |
+
return $this->_redirect("*/*/configure_user");
|
188 |
+
}
|
189 |
+
|
190 |
+
if (!$session->getConfiguredStoreCode()) {
|
191 |
+
$session->addError(Mage::helper("klevu_search")->__("Must select a store"));
|
192 |
+
return $this->_redirect("*/*/configure_store");
|
193 |
+
}
|
194 |
+
|
195 |
+
if ($attributes = $request->getPost("attributes")) {
|
196 |
+
$store = Mage::app()->getStore($session->getConfiguredStoreCode());
|
197 |
+
|
198 |
+
Mage::helper("klevu_search/config")->setAdditionalAttributesMap($attributes, $store);
|
199 |
+
|
200 |
+
$session->addSuccess(Mage::helper("klevu_search")->__("Attributes configured successfully. Attribute mappings saved to System Configuration."));
|
201 |
+
|
202 |
+
// Schedule a Product Sync
|
203 |
+
Mage::getModel("klevu_search/product_sync")->schedule();
|
204 |
+
|
205 |
+
$this->loadLayout();
|
206 |
+
$this->initLayoutMessages("klevu_search/session");
|
207 |
+
$this->renderLayout();
|
208 |
+
return;
|
209 |
+
} else {
|
210 |
+
$session->addError(Mage::helper("klevu_search")->__("Missing attributes!"));
|
211 |
+
//return $this->_forward("configure_attributes");
|
212 |
+
}
|
213 |
+
}
|
214 |
+
}
|
app/code/community/Klevu/Search/controllers/Adminhtml/Klevu/SearchController.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Klevu_Search_Adminhtml_Klevu_SearchController extends Mage_Adminhtml_Controller_Action {
|
4 |
+
|
5 |
+
public function sync_allAction() {
|
6 |
+
$store = $this->getRequest()->getParam("store");
|
7 |
+
|
8 |
+
if ($store !== null) {
|
9 |
+
try {
|
10 |
+
$store = Mage::app()->getStore($store);
|
11 |
+
} catch (Mage_Core_Model_Store_Exception $e) {
|
12 |
+
Mage::getSingleton("adminhtml/session")->addError($this->__("Selected store could not be found!"));
|
13 |
+
return $this->_redirectReferer("adminhtml/dashboard");
|
14 |
+
}
|
15 |
+
}
|
16 |
+
|
17 |
+
if (Mage::helper('klevu_search/config')->isProductSyncEnabled()) {
|
18 |
+
Mage::getModel('klevu_search/product_sync')
|
19 |
+
->markAllProductsForUpdate($store)
|
20 |
+
->schedule();
|
21 |
+
|
22 |
+
if ($store) {
|
23 |
+
Mage::helper("klevu_search")->log(Zend_Log::INFO, sprintf("Product Sync scheduled to re-sync ALL products in %s (%s).",
|
24 |
+
$store->getWebsite()->getName(),
|
25 |
+
$store->getName()
|
26 |
+
));
|
27 |
+
|
28 |
+
Mage::getSingleton("adminhtml/session")->addSuccess($this->__("Klevu Search Product Sync scheduled to be run on the next cron run for ALL products in %s (%s).",
|
29 |
+
$store->getWebsite()->getName(),
|
30 |
+
$store->getName()
|
31 |
+
));
|
32 |
+
} else {
|
33 |
+
Mage::helper("klevu_search")->log(Zend_Log::INFO, "Product Sync scheduled to re-sync ALL products.");
|
34 |
+
|
35 |
+
Mage::getSingleton('adminhtml/session')->addSuccess($this->__("Klevu Search Product Sync scheduled to be run on the next cron run for ALL products."));
|
36 |
+
}
|
37 |
+
} else {
|
38 |
+
Mage::getSingleton('adminhtml/session')->addError($this->__("Klevu Search Product Sync is disabled."));
|
39 |
+
}
|
40 |
+
|
41 |
+
return $this->_redirectReferer("adminhtml/dashboard");
|
42 |
+
}
|
43 |
+
|
44 |
+
public function manual_syncAction() {
|
45 |
+
Mage::getModel("klevu_search/product_sync")->runManually();
|
46 |
+
|
47 |
+
return $this->_redirectReferer("adminhtml/dashboard");
|
48 |
+
}
|
49 |
+
/**
|
50 |
+
* Get the product ids for thumbnails and schedual the cron.
|
51 |
+
*/
|
52 |
+
public function generate_thumbnailAction() {
|
53 |
+
try {
|
54 |
+
Mage::getModel('klevu_search/product_sync')->getEntityIds();
|
55 |
+
Mage::getModel('klevu_search/product_sync')->scheduleImageCron();
|
56 |
+
Mage::getSingleton('adminhtml/session')->addSuccess($this->__("Klevu thumbnails generation task scheduled to be run on the next cron run."));
|
57 |
+
}
|
58 |
+
catch (Exception $e) {
|
59 |
+
Mage::logException($e);
|
60 |
+
Mage::getSingleton('adminhtml/session')->addError($this->__("Unable to generate product images. Please try later."));
|
61 |
+
}
|
62 |
+
return $this->_redirectReferer("adminhtml/dashboard");
|
63 |
+
}
|
64 |
+
}
|
app/code/community/Klevu/Search/controllers/SearchController.php
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Klevu FrontEnd Controller
|
4 |
+
*/
|
5 |
+
class Klevu_Search_SearchController extends Mage_Core_Controller_Front_Action {
|
6 |
+
/**
|
7 |
+
* Genarate thumbnail using multiple curl request action
|
8 |
+
*/
|
9 |
+
public function indexAction() {
|
10 |
+
try {
|
11 |
+
$id = Mage::app()->getRequest()->getParam('id');
|
12 |
+
$data = Mage::getModel('klevu_search/product_sync')->getImageProcessingIds($id);
|
13 |
+
foreach(unserialize($data[0]['batchdata']) as $key => $value) {
|
14 |
+
$product = Mage::getModel('catalog/product')->load($value);
|
15 |
+
$image = $product->getImage();
|
16 |
+
if((!empty($image)) && ($image!= "no_selection")) {
|
17 |
+
Mage::getModel('klevu_search/product_sync')->thumbImage($product->getImage());
|
18 |
+
}
|
19 |
+
}
|
20 |
+
Mage::getModel('klevu_search/product_sync')->updateImageProcessingIds($id);
|
21 |
+
}
|
22 |
+
catch(Exception $e) {
|
23 |
+
Mage::helper('klevu_search')->log(Zend_Log::DEBUG, sprintf("Image Error:\n%s", $e->getMessage()));
|
24 |
+
}
|
25 |
+
|
26 |
+
}
|
27 |
+
|
28 |
+
public function runexternalylogAction()
|
29 |
+
{
|
30 |
+
$this->loadLayout();
|
31 |
+
$this->renderLayout();
|
32 |
+
}
|
33 |
+
/**
|
34 |
+
* Send different logs to klevu server to debug the data
|
35 |
+
*/
|
36 |
+
public function runexternalyAction(){
|
37 |
+
try {
|
38 |
+
$debugapi = Mage::getModel('klevu_search/product_sync')->getApiDebug();
|
39 |
+
$content="";
|
40 |
+
if($this->getRequest()->getParam('debug') == "klevu") {
|
41 |
+
// get last 500 lines from klevu log
|
42 |
+
$path = Mage::getBaseDir("log")."/Klevu_Search.log";
|
43 |
+
if($this->getRequest()->getParam('lines')) {
|
44 |
+
$line = $this->getRequest()->getParam('lines');
|
45 |
+
}else {
|
46 |
+
$line = 100;
|
47 |
+
}
|
48 |
+
$content.= $this->getLastlines($path,$line,true);
|
49 |
+
|
50 |
+
//send php and magento version
|
51 |
+
$content.= "</br>".'****Current Magento version on store:'.Mage::getVersion()."</br>";
|
52 |
+
$content.= "</br>".'****Current PHP version on store:'. phpversion()."</br>";
|
53 |
+
|
54 |
+
//send cron and logfile data
|
55 |
+
$cron = Mage::getBaseDir()."/cron.php";
|
56 |
+
$cronfile = file_get_contents($cron);
|
57 |
+
$content.= nl2br(htmlspecialchars($content)).nl2br(htmlspecialchars($cronfile));
|
58 |
+
$response = Mage::getModel("klevu_search/api_action_debuginfo")->debugKlevu(array('apiKey'=>$debugapi,'klevuLog'=>$content,'type'=>'log_file'));
|
59 |
+
if($response->getMessage()=="success") {
|
60 |
+
Mage::getSingleton('core/session')->addSuccess("Klevu search log sent.");
|
61 |
+
}
|
62 |
+
|
63 |
+
$content = serialize(Mage::getModel('klevu_search/product_sync')->debugsIds());
|
64 |
+
$response = Mage::getModel("klevu_search/api_action_debuginfo")->debugKlevu(array('apiKey'=>$debugapi,'klevuLog'=>$content,'type'=>'product_table'));
|
65 |
+
|
66 |
+
if($response->getMessage()=="success") {
|
67 |
+
Mage::getSingleton('core/session')->addSuccess("Status of indexing queue sent.");
|
68 |
+
}else {
|
69 |
+
Mage::getSingleton('core/session')->addSuccess($response->getMessage());
|
70 |
+
}
|
71 |
+
//send index status data
|
72 |
+
$content ="";
|
73 |
+
$allIndex= Mage::getSingleton('index/indexer')->getProcessesCollection();
|
74 |
+
foreach ($allIndex as $index) {
|
75 |
+
$content .= $index->getIndexerCode().":".$index->getStatus().'<br>';
|
76 |
+
}
|
77 |
+
$response = Mage::getModel("klevu_search/api_action_debuginfo")->debugKlevu(array('apiKey'=>$debugapi,'klevuLog'=>$content,'type'=>'index'));
|
78 |
+
if($response->getMessage()=="success") {
|
79 |
+
Mage::getSingleton('core/session')->addSuccess("Status of magento indices sent.");
|
80 |
+
}else {
|
81 |
+
Mage::getSingleton('core/session')->addSuccess($response->getMessage());
|
82 |
+
}
|
83 |
+
Mage::helper('klevu_search')->log(Zend_Log::DEBUG, sprintf("klevu debug data was sent to klevu server successfully."));
|
84 |
+
}
|
85 |
+
$rest_api = $this->getRequest()->getParam('api');
|
86 |
+
if(!empty($rest_api)) {
|
87 |
+
Mage::getModel('klevu_search/product_sync')->sheduleCronExteranally($rest_api);
|
88 |
+
Mage::getSingleton('core/session')->addSuccess("Cron scheduled externally.");
|
89 |
+
}
|
90 |
+
$this->_redirect('klevu/search/runexternalylog');
|
91 |
+
|
92 |
+
}
|
93 |
+
catch(Exception $e) {
|
94 |
+
Mage::helper('klevu_search')->log(Zend_Log::DEBUG, sprintf("Product Synchronization was Run externally:\n%s", $e->getMessage()));
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
function getLastlines($filepath, $lines, $adaptive = true) {
|
99 |
+
// Open file
|
100 |
+
$f = @fopen($filepath, "rb");
|
101 |
+
if ($f === false) return false;
|
102 |
+
// Sets buffer size
|
103 |
+
if (!$adaptive) $buffer = 4096;
|
104 |
+
else $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096));
|
105 |
+
// Jump to last character
|
106 |
+
fseek($f, -1, SEEK_END);
|
107 |
+
// Read it and adjust line number if necessary
|
108 |
+
// (Otherwise the result would be wrong if file doesn't end with a blank line)
|
109 |
+
if (fread($f, 1) != "\n") $lines -= 1;
|
110 |
+
// Start reading
|
111 |
+
$output = '';
|
112 |
+
$chunk = '';
|
113 |
+
// While we would like more
|
114 |
+
while (ftell($f) > 0 && $lines >= 0) {
|
115 |
+
// Figure out how far back we should jump
|
116 |
+
$seek = min(ftell($f), $buffer);
|
117 |
+
// Do the jump (backwards, relative to where we are)
|
118 |
+
fseek($f, -$seek, SEEK_CUR);
|
119 |
+
// Read a chunk and prepend it to our output
|
120 |
+
$output = ($chunk = fread($f, $seek)) . $output;
|
121 |
+
// Jump back to where we started reading
|
122 |
+
fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);
|
123 |
+
// Decrease our line counter
|
124 |
+
$lines -= substr_count($chunk, "\n");
|
125 |
+
}
|
126 |
+
// While we have too many lines
|
127 |
+
// (Because of buffer size we might have read too many)
|
128 |
+
while ($lines++ < 0) {
|
129 |
+
// Find first newline and remove all text before that
|
130 |
+
$output = substr($output, strpos($output, "\n") + 1);
|
131 |
+
}
|
132 |
+
// Close file and return
|
133 |
+
fclose($f);
|
134 |
+
return trim($output);
|
135 |
+
}
|
136 |
+
|
137 |
+
|
138 |
+
|
139 |
+
}
|
app/code/community/Klevu/Search/etc/adminhtml.xml
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<acl>
|
4 |
+
<resources>
|
5 |
+
<admin>
|
6 |
+
<children>
|
7 |
+
<klevu_search translate="title" module="klevu_search">
|
8 |
+
<title>Klevu Search</title>
|
9 |
+
<sort_order>100</sort_order>
|
10 |
+
</klevu_search>
|
11 |
+
<system>
|
12 |
+
<children>
|
13 |
+
<config>
|
14 |
+
<children>
|
15 |
+
<klevu_search translate="title" module="klevu_search">
|
16 |
+
<title>Klevu Search Section</title>
|
17 |
+
</klevu_search>
|
18 |
+
</children>
|
19 |
+
</config>
|
20 |
+
</children>
|
21 |
+
</system>
|
22 |
+
</children>
|
23 |
+
</admin>
|
24 |
+
</resources>
|
25 |
+
</acl>
|
26 |
+
</config>
|
app/code/community/Klevu/Search/etc/config.xml
ADDED
@@ -0,0 +1,285 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Klevu_Search>
|
5 |
+
<version>1.1.13</version>
|
6 |
+
</Klevu_Search>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<blocks>
|
10 |
+
<klevu_search>
|
11 |
+
<class>Klevu_Search_Block</class>
|
12 |
+
</klevu_search>
|
13 |
+
</blocks>
|
14 |
+
<helpers>
|
15 |
+
<klevu_search>
|
16 |
+
<class>Klevu_Search_Helper</class>
|
17 |
+
</klevu_search>
|
18 |
+
</helpers>
|
19 |
+
<models>
|
20 |
+
<klevu_search>
|
21 |
+
<class>Klevu_Search_Model</class>
|
22 |
+
<resourceModel>klevu_search_resource</resourceModel>
|
23 |
+
</klevu_search>
|
24 |
+
<klevu_search_resource>
|
25 |
+
<class>Klevu_Search_Model_Resource</class>
|
26 |
+
<entities>
|
27 |
+
<notification>
|
28 |
+
<table>klevu_notification</table>
|
29 |
+
</notification>
|
30 |
+
<product_sync>
|
31 |
+
<table>klevu_product_sync</table>
|
32 |
+
</product_sync>
|
33 |
+
<order_sync>
|
34 |
+
<table>klevu_order_sync</table>
|
35 |
+
</order_sync>
|
36 |
+
<image_thumb>
|
37 |
+
<table>klevu_image_thumb</table>
|
38 |
+
</image_thumb>
|
39 |
+
</entities>
|
40 |
+
</klevu_search_resource>
|
41 |
+
</models>
|
42 |
+
<resources>
|
43 |
+
<klevu_search_setup>
|
44 |
+
<setup>
|
45 |
+
<module>Klevu_Search</module>
|
46 |
+
</setup>
|
47 |
+
</klevu_search_setup>
|
48 |
+
</resources>
|
49 |
+
<events>
|
50 |
+
<admin_system_config_changed_section_klevu_search>
|
51 |
+
<observers>
|
52 |
+
<klevu_search_removetest>
|
53 |
+
<type>singleton</type>
|
54 |
+
<class>klevu_search/observer</class>
|
55 |
+
<method>removeTest</method>
|
56 |
+
</klevu_search_removetest>
|
57 |
+
</observers>
|
58 |
+
</admin_system_config_changed_section_klevu_search>
|
59 |
+
<controller_action_predispatch_catalogsearch_result_index>
|
60 |
+
<observers>
|
61 |
+
<klevu_search_landing_page>
|
62 |
+
<type>singleton</type>
|
63 |
+
<class>klevu_search/observer</class>
|
64 |
+
<method>applyLandingPageModelRewrites</method>
|
65 |
+
</klevu_search_landing_page>
|
66 |
+
</observers>
|
67 |
+
</controller_action_predispatch_catalogsearch_result_index>
|
68 |
+
<after_reindex_process_catalog_category_product>
|
69 |
+
<observers>
|
70 |
+
<klevu_search_product_sync>
|
71 |
+
<type>singleton</type>
|
72 |
+
<class>klevu_search/observer</class>
|
73 |
+
<method>scheduleProductSync</method>
|
74 |
+
</klevu_search_product_sync>
|
75 |
+
</observers>
|
76 |
+
</after_reindex_process_catalog_category_product>
|
77 |
+
<after_reindex_process_catalog_product_price>
|
78 |
+
<observers>
|
79 |
+
<klevu_search_product_sync>
|
80 |
+
<type>singleton</type>
|
81 |
+
<class>klevu_search/observer</class>
|
82 |
+
<method>scheduleProductSync</method>
|
83 |
+
</klevu_search_product_sync>
|
84 |
+
</observers>
|
85 |
+
</after_reindex_process_catalog_product_price>
|
86 |
+
<after_reindex_process_catalog_url>
|
87 |
+
<observers>
|
88 |
+
<klevu_search_product_sync>
|
89 |
+
<type>singleton</type>
|
90 |
+
<class>klevu_search/observer</class>
|
91 |
+
<method>scheduleProductSync</method>
|
92 |
+
</klevu_search_product_sync>
|
93 |
+
</observers>
|
94 |
+
</after_reindex_process_catalog_url>
|
95 |
+
<catalog_inventory_stock_item_save_commit_after>
|
96 |
+
<observers>
|
97 |
+
<klevu_search_product_sync>
|
98 |
+
<type>singleton</type>
|
99 |
+
<class>klevu_search/observer</class>
|
100 |
+
<method>scheduleProductSync</method>
|
101 |
+
</klevu_search_product_sync>
|
102 |
+
</observers>
|
103 |
+
</catalog_inventory_stock_item_save_commit_after>
|
104 |
+
<catalog_product_save_commit_after>
|
105 |
+
<observers>
|
106 |
+
<klevu_search_product_sync>
|
107 |
+
<type>singleton</type>
|
108 |
+
<class>klevu_search/observer</class>
|
109 |
+
<method>scheduleProductSync</method>
|
110 |
+
</klevu_search_product_sync>
|
111 |
+
<catalog_product_media_save_before_event>
|
112 |
+
<type>singleton</type>
|
113 |
+
<class>klevu_search/observer</class>
|
114 |
+
<method>createThumb</method>
|
115 |
+
</catalog_product_media_save_before_event>
|
116 |
+
</observers>
|
117 |
+
</catalog_product_save_commit_after>
|
118 |
+
<catalog_product_delete_commit_after>
|
119 |
+
<observers>
|
120 |
+
<klevu_search_product_sync>
|
121 |
+
<type>singleton</type>
|
122 |
+
<class>klevu_search/observer</class>
|
123 |
+
<method>scheduleProductSync</method>
|
124 |
+
</klevu_search_product_sync>
|
125 |
+
</observers>
|
126 |
+
</catalog_product_delete_commit_after>
|
127 |
+
<catalog_entity_attribute_save_commit_after>
|
128 |
+
<observers>
|
129 |
+
<klevu_search_product_sync>
|
130 |
+
<type>singleton</type>
|
131 |
+
<class>klevu_search/observer</class>
|
132 |
+
<method>syncAllProducts</method>
|
133 |
+
</klevu_search_product_sync>
|
134 |
+
</observers>
|
135 |
+
</catalog_entity_attribute_save_commit_after>
|
136 |
+
<category_move>
|
137 |
+
<observers>
|
138 |
+
<klevu_search_product_sync>
|
139 |
+
<type>singleton</type>
|
140 |
+
<class>klevu_search/observer</class>
|
141 |
+
<method>scheduleProductSync</method>
|
142 |
+
</klevu_search_product_sync>
|
143 |
+
</observers>
|
144 |
+
</category_move>
|
145 |
+
<sales_order_place_after>
|
146 |
+
<observers>
|
147 |
+
<klevu_search_order_sync>
|
148 |
+
<type>singleton</type>
|
149 |
+
<class>klevu_search/observer</class>
|
150 |
+
<method>scheduleOrderSync</method>
|
151 |
+
</klevu_search_order_sync>
|
152 |
+
<klevu_search_product_sync>
|
153 |
+
<type>singleton</type>
|
154 |
+
<class>klevu_search/observer</class>
|
155 |
+
<method>scheduleProductSync</method>
|
156 |
+
</klevu_search_product_sync>
|
157 |
+
</observers>
|
158 |
+
</sales_order_place_after>
|
159 |
+
<catalog_product_attribute_update_before>
|
160 |
+
<observers>
|
161 |
+
<klevu_search_product_sync>
|
162 |
+
<type>singleton</type>
|
163 |
+
<class>klevu_search/observer</class>
|
164 |
+
<method>setProductsToSync</method>
|
165 |
+
</klevu_search_product_sync>
|
166 |
+
</observers>
|
167 |
+
</catalog_product_attribute_update_before>
|
168 |
+
</events>
|
169 |
+
</global>
|
170 |
+
<admin>
|
171 |
+
<routers>
|
172 |
+
<adminhtml>
|
173 |
+
<args>
|
174 |
+
<modules>
|
175 |
+
<klevu_search before="Mage_Adminhtml">Klevu_Search_Adminhtml</klevu_search>
|
176 |
+
</modules>
|
177 |
+
</args>
|
178 |
+
</adminhtml>
|
179 |
+
</routers>
|
180 |
+
</admin>
|
181 |
+
<adminhtml>
|
182 |
+
<layout>
|
183 |
+
<updates>
|
184 |
+
<klevu_search>
|
185 |
+
<file>klevu/search.xml</file>
|
186 |
+
</klevu_search>
|
187 |
+
</updates>
|
188 |
+
</layout>
|
189 |
+
</adminhtml>
|
190 |
+
<frontend>
|
191 |
+
<layout>
|
192 |
+
<updates>
|
193 |
+
<klevu_search>
|
194 |
+
<file>klevu/search.xml</file>
|
195 |
+
</klevu_search>
|
196 |
+
</updates>
|
197 |
+
</layout>
|
198 |
+
<routers>
|
199 |
+
<klevu_search>
|
200 |
+
<use>standard</use>
|
201 |
+
<args>
|
202 |
+
<module>Klevu_Search</module>
|
203 |
+
<frontName>klevu</frontName>
|
204 |
+
</args>
|
205 |
+
</klevu_search>
|
206 |
+
</routers>
|
207 |
+
</frontend>
|
208 |
+
<crontab>
|
209 |
+
<jobs>
|
210 |
+
<klevu_search_clear_cron_check>
|
211 |
+
<run>
|
212 |
+
<model>klevu_search/cron::clearCronCheckNotification</model>
|
213 |
+
</run>
|
214 |
+
</klevu_search_clear_cron_check>
|
215 |
+
<klevu_search_product_sync>
|
216 |
+
<schedule>
|
217 |
+
<config_path>klevu_search/product_sync/frequency</config_path>
|
218 |
+
</schedule>
|
219 |
+
<run>
|
220 |
+
<model>klevu_search/product_sync::run</model>
|
221 |
+
</run>
|
222 |
+
</klevu_search_product_sync>
|
223 |
+
<klevu_search_order_sync>
|
224 |
+
<schedule>
|
225 |
+
<config_path>klevu_search/order_sync/frequency</config_path>
|
226 |
+
</schedule>
|
227 |
+
<run>
|
228 |
+
<model>klevu_search/order_sync::run</model>
|
229 |
+
</run>
|
230 |
+
</klevu_search_order_sync>
|
231 |
+
<klevu_search_product_thumb>
|
232 |
+
<schedule>
|
233 |
+
<config_path>klevu_search/product_sync/frequency</config_path>
|
234 |
+
</schedule>
|
235 |
+
<run>
|
236 |
+
<model>klevu_search/product_sync::generateThumbParrallel</model>
|
237 |
+
</run>
|
238 |
+
</klevu_search_product_thumb>
|
239 |
+
</jobs>
|
240 |
+
</crontab>
|
241 |
+
<default>
|
242 |
+
<klevu_search>
|
243 |
+
<general>
|
244 |
+
<enabled>0</enabled>
|
245 |
+
<test_mode>0</test_mode>
|
246 |
+
<hostname>box.klevu.com</hostname>
|
247 |
+
<rest_hostname>rest.klevu.com</rest_hostname>
|
248 |
+
<test_hostname>box.klevu.com</test_hostname>
|
249 |
+
<test_cloud_search_url>eucs.klevu.com</test_cloud_search_url>
|
250 |
+
<cloud_search_url>eucs.klevu.com</cloud_search_url>
|
251 |
+
<analytics_url>stats.klevu.com</analytics_url>
|
252 |
+
<test_analytics_url>stats.klevu.com</test_analytics_url>
|
253 |
+
<js_url>js.klevu.com</js_url>
|
254 |
+
<test_js_url>js.klevu.com</test_js_url>
|
255 |
+
</general>
|
256 |
+
<product_sync>
|
257 |
+
<enabled>1</enabled>
|
258 |
+
<frequency>0 * * * *</frequency>
|
259 |
+
<last_run>Never</last_run>
|
260 |
+
</product_sync>
|
261 |
+
<searchlanding>
|
262 |
+
<landenabled>2</landenabled>
|
263 |
+
</searchlanding>
|
264 |
+
<order_sync>
|
265 |
+
<enabled>1</enabled>
|
266 |
+
<frequency>0 * * * *</frequency>
|
267 |
+
<last_run>Never</last_run>
|
268 |
+
</order_sync>
|
269 |
+
<developer>
|
270 |
+
<force_log>1</force_log>
|
271 |
+
<!-- Log level default is set in the backend model and getter as it uses Zend_Log constants -->
|
272 |
+
</developer>
|
273 |
+
<order_sync>
|
274 |
+
<enabled>1</enabled>
|
275 |
+
</order_sync>
|
276 |
+
</klevu_search>
|
277 |
+
</default>
|
278 |
+
<phpunit>
|
279 |
+
<suite>
|
280 |
+
<modules>
|
281 |
+
<Klevu_Search/>
|
282 |
+
</modules>
|
283 |
+
</suite>
|
284 |
+
</phpunit>
|
285 |
+
</config>
|
app/code/community/Klevu/Search/etc/system.xml
ADDED
@@ -0,0 +1,342 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<sections>
|
4 |
+
<klevu_search translate="label" module="klevu_search">
|
5 |
+
<label>Klevu Search</label>
|
6 |
+
<tab>catalog</tab>
|
7 |
+
<sort_order>50</sort_order>
|
8 |
+
<show_in_default>1</show_in_default>
|
9 |
+
<show_in_website>1</show_in_website>
|
10 |
+
<show_in_store>1</show_in_store>
|
11 |
+
<groups>
|
12 |
+
<information translate="label">
|
13 |
+
<label>Information</label>
|
14 |
+
<sort_order>1</sort_order>
|
15 |
+
<expanded>1</expanded>
|
16 |
+
<frontend_model>klevu_search/adminhtml_form_information</frontend_model>
|
17 |
+
<show_in_default>1</show_in_default>
|
18 |
+
<show_in_website>1</show_in_website>
|
19 |
+
<show_in_store>1</show_in_store>
|
20 |
+
</information>
|
21 |
+
<general translate="label">
|
22 |
+
<label>General Settings</label>
|
23 |
+
<sort_order>100</sort_order>
|
24 |
+
<expanded>1</expanded>
|
25 |
+
<show_in_default>1</show_in_default>
|
26 |
+
<show_in_website>1</show_in_website>
|
27 |
+
<show_in_store>1</show_in_store>
|
28 |
+
<fields>
|
29 |
+
<enabled translate="label">
|
30 |
+
<label>Enable on Frontend</label>
|
31 |
+
<frontend_type>select</frontend_type>
|
32 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
33 |
+
<sort_order>100</sort_order>
|
34 |
+
<show_in_default>1</show_in_default>
|
35 |
+
<show_in_website>1</show_in_website>
|
36 |
+
<show_in_store>1</show_in_store>
|
37 |
+
</enabled>
|
38 |
+
<js_api_key translate="label comment">
|
39 |
+
<label>JS API Key</label>
|
40 |
+
<comment><![CDATA[This API key is used for searches in the frontend.]]></comment>
|
41 |
+
<frontend_type>text</frontend_type>
|
42 |
+
<sort_order>121</sort_order>
|
43 |
+
<show_in_default>0</show_in_default>
|
44 |
+
<show_in_website>0</show_in_website>
|
45 |
+
<show_in_store>1</show_in_store>
|
46 |
+
</js_api_key>
|
47 |
+
<rest_api_key translate="label comment">
|
48 |
+
<label>REST API Key</label>
|
49 |
+
<comment><![CDATA[This API key is used for syncing product information in the backend.]]></comment>
|
50 |
+
<sort_order>122</sort_order>
|
51 |
+
<show_in_default>0</show_in_default>
|
52 |
+
<show_in_website>0</show_in_website>
|
53 |
+
<show_in_store>1</show_in_store>
|
54 |
+
</rest_api_key>
|
55 |
+
<wizard translate="button_label">
|
56 |
+
<label></label>
|
57 |
+
<frontend_model>klevu_search/adminhtml_wizard_config_button</frontend_model>
|
58 |
+
<sort_order>130</sort_order>
|
59 |
+
<show_in_default>1</show_in_default>
|
60 |
+
<show_in_website>1</show_in_website>
|
61 |
+
<show_in_store>1</show_in_store>
|
62 |
+
</wizard>
|
63 |
+
<hostname translate="label comment">
|
64 |
+
<label>Hostname</label>
|
65 |
+
<comment><![CDATA[This Hostname is used for sending API requests to Klevu]]></comment>
|
66 |
+
<sort_order>132</sort_order>
|
67 |
+
<show_in_default>0</show_in_default>
|
68 |
+
<show_in_website>0</show_in_website>
|
69 |
+
<show_in_store>1</show_in_store>
|
70 |
+
</hostname>
|
71 |
+
<rest_hostname translate="label comment">
|
72 |
+
<label>Product Synchronization URL</label>
|
73 |
+
<comment><![CDATA[This Hostname is used for sending product synchronization API requests to Klevu]]></comment>
|
74 |
+
<sort_order>132</sort_order>
|
75 |
+
<show_in_default>0</show_in_default>
|
76 |
+
<show_in_website>0</show_in_website>
|
77 |
+
<show_in_store>1</show_in_store>
|
78 |
+
</rest_hostname>
|
79 |
+
<cloud_search_url translate="label comment">
|
80 |
+
<label>Cloud Search URL</label>
|
81 |
+
<comment><![CDATA[The Cloud Search URL is used for sending search API requests to Klevu]]></comment>
|
82 |
+
<sort_order>132</sort_order>
|
83 |
+
<show_in_default>0</show_in_default>
|
84 |
+
<show_in_website>0</show_in_website>
|
85 |
+
<show_in_store>1</show_in_store>
|
86 |
+
</cloud_search_url>
|
87 |
+
<analytics_url translate="label comment">
|
88 |
+
<label>Analytics URL</label>
|
89 |
+
<comment><![CDATA[The Analytics URL is used when reporting search terms and click to Klevu]]></comment>
|
90 |
+
<sort_order>132</sort_order>
|
91 |
+
<show_in_default>0</show_in_default>
|
92 |
+
<show_in_website>0</show_in_website>
|
93 |
+
<show_in_store>1</show_in_store>
|
94 |
+
</analytics_url>
|
95 |
+
<js_url translate="label comment">
|
96 |
+
<label>JS URL</label>
|
97 |
+
<comment><![CDATA[The JS URL is used for getting Klevu's Javascript file]]></comment>
|
98 |
+
<sort_order>132</sort_order>
|
99 |
+
<show_in_default>0</show_in_default>
|
100 |
+
<show_in_website>0</show_in_website>
|
101 |
+
<show_in_store>1</show_in_store>
|
102 |
+
</js_url>
|
103 |
+
|
104 |
+
</fields>
|
105 |
+
</general>
|
106 |
+
<searchlanding translate="label">
|
107 |
+
<label>Search Result Page Settings</label>
|
108 |
+
<sort_order>101</sort_order>
|
109 |
+
<expanded>1</expanded>
|
110 |
+
<show_in_default>1</show_in_default>
|
111 |
+
<show_in_website>1</show_in_website>
|
112 |
+
<show_in_store>1</show_in_store>
|
113 |
+
<fields>
|
114 |
+
<landenabled translate="label">
|
115 |
+
<label>Search Result Page</label>
|
116 |
+
<comment><![CDATA[** "Preserves Your Theme Layout" option preserves layout of your theme.
|
117 |
+
]]></comment>
|
118 |
+
<frontend_type>select</frontend_type>
|
119 |
+
<source_model>klevu_search/system_config_source_landingoptions</source_model>
|
120 |
+
<sort_order>100</sort_order>
|
121 |
+
<show_in_default>1</show_in_default>
|
122 |
+
<show_in_website>1</show_in_website>
|
123 |
+
<show_in_store>1</show_in_store>
|
124 |
+
</landenabled>
|
125 |
+
</fields>
|
126 |
+
</searchlanding>
|
127 |
+
<product_sync translate="label">
|
128 |
+
<label>Product Sync Settings</label>
|
129 |
+
<sort_order>200</sort_order>
|
130 |
+
<show_in_default>1</show_in_default>
|
131 |
+
<show_in_website>1</show_in_website>
|
132 |
+
<show_in_store>1</show_in_store>
|
133 |
+
<fields>
|
134 |
+
<enabled translate="label comment">
|
135 |
+
<label>Enable Product Sync</label>
|
136 |
+
<comment><![CDATA[Enable Product Sync]]></comment>
|
137 |
+
<frontend_type>select</frontend_type>
|
138 |
+
<source_model>klevu_search/system_config_source_yesnoforced</source_model>
|
139 |
+
<sort_order>100</sort_order>
|
140 |
+
<show_in_default>1</show_in_default>
|
141 |
+
<show_in_website>1</show_in_website>
|
142 |
+
<show_in_store>1</show_in_store>
|
143 |
+
</enabled>
|
144 |
+
<frequency translate="label">
|
145 |
+
<label>Frequency</label>
|
146 |
+
<frontend_type>select</frontend_type>
|
147 |
+
<source_model>klevu_search/system_config_source_frequency</source_model>
|
148 |
+
<sort_order>200</sort_order>
|
149 |
+
<show_in_default>1</show_in_default>
|
150 |
+
<show_in_website>0</show_in_website>
|
151 |
+
<show_in_store>0</show_in_store>
|
152 |
+
</frequency>
|
153 |
+
<last_run translate="label">
|
154 |
+
<label>Last Run</label>
|
155 |
+
<frontend_model>klevu_search/adminhtml_form_field_store_level_label</frontend_model>
|
156 |
+
<sort_order>300</sort_order>
|
157 |
+
<show_in_default>1</show_in_default>
|
158 |
+
<show_in_website>1</show_in_website>
|
159 |
+
<show_in_store>1</show_in_store>
|
160 |
+
</last_run>
|
161 |
+
<sync_button>
|
162 |
+
<label></label>
|
163 |
+
<frontend_model>klevu_search/adminhtml_form_field_sync_button</frontend_model>
|
164 |
+
<sort_order>400</sort_order>
|
165 |
+
<show_in_default>1</show_in_default>
|
166 |
+
<show_in_website>1</show_in_website>
|
167 |
+
<show_in_store>1</show_in_store>
|
168 |
+
</sync_button>
|
169 |
+
</fields>
|
170 |
+
</product_sync>
|
171 |
+
<attributes translate="label">
|
172 |
+
<label>Product Attribute Mappings</label>
|
173 |
+
<sort_order>300</sort_order>
|
174 |
+
<show_in_default>1</show_in_default>
|
175 |
+
<show_in_website>1</show_in_website>
|
176 |
+
<show_in_store>1</show_in_store>
|
177 |
+
<fields>
|
178 |
+
<additional translate="label comment">
|
179 |
+
<label>Additional Attributes</label>
|
180 |
+
<comment><![CDATA[Here you can set optional product attributes sent to Klevu by mapping them to your Magento attributes. If you specify multiple mappings for the same Klevu attribute, only the first mapping found on the product sent will be used.]]></comment>
|
181 |
+
<frontend_model>klevu_search/adminhtml_form_field_attribute_mappings</frontend_model>
|
182 |
+
<backend_model>adminhtml/system_config_backend_serialized_array</backend_model>
|
183 |
+
<sort_order>300</sort_order>
|
184 |
+
<show_in_default>0</show_in_default>
|
185 |
+
<show_in_website>0</show_in_website>
|
186 |
+
<show_in_store>0</show_in_store>
|
187 |
+
</additional>
|
188 |
+
<automatic translate="label comment">
|
189 |
+
<label>Automatic Attribute Mappings</label>
|
190 |
+
<comment><![CDATA[These product attributes are automatically mapped and synced to Klevu. The attributes configured as to be used in the search results layered navigation are mapped with the "Other" attribute above.]]></comment>
|
191 |
+
<frontend_model>klevu_search/adminhtml_form_field_automatic_attribute_mappings</frontend_model>
|
192 |
+
<backend_model>adminhtml/system_config_backend_serialized_array</backend_model>
|
193 |
+
<sort_order>400</sort_order>
|
194 |
+
<show_in_default>0</show_in_default>
|
195 |
+
<show_in_website>0</show_in_website>
|
196 |
+
<show_in_store>0</show_in_store>
|
197 |
+
</automatic>
|
198 |
+
<boosting translate="label comment">
|
199 |
+
<label>Boosting Attribute</label>
|
200 |
+
<comment><![CDATA[Select the attribute you wish to use as the Boosting attribute in Klevu. The Boosting attribute is a decimal or integer product attribute which allows you to manually boost certain products. All products have a default score of 1, to promote a product simply give the product a score higher than 1, to demote give a score lower than 1 (i.e. 0.1)]]></comment>
|
201 |
+
<frontend_type>select</frontend_type>
|
202 |
+
<source_model>klevu_search/system_config_source_boosting_attribute</source_model>
|
203 |
+
<sort_order>500</sort_order>
|
204 |
+
<show_in_default>0</show_in_default>
|
205 |
+
<show_in_website>0</show_in_website>
|
206 |
+
<show_in_store>1</show_in_store>
|
207 |
+
</boosting>
|
208 |
+
<other translate="label comment">
|
209 |
+
<label>Other Attributes To Index</label>
|
210 |
+
<comment><![CDATA[Select all other attributes you would like Klevu to index and use to improve search results.</br>Please make sure to resynchronize products by clicking on the "Sync All Products for This Store" under the "Product Sync Settings".]]></comment>
|
211 |
+
<frontend_type>multiselect</frontend_type>
|
212 |
+
<source_model>klevu_search/system_config_source_product_attributes</source_model>
|
213 |
+
<can_be_empty>1</can_be_empty>
|
214 |
+
<sort_order>600</sort_order>
|
215 |
+
<show_in_default>0</show_in_default>
|
216 |
+
<show_in_website>0</show_in_website>
|
217 |
+
<show_in_store>1</show_in_store>
|
218 |
+
</other>
|
219 |
+
</fields>
|
220 |
+
</attributes>
|
221 |
+
<order_sync translate="label">
|
222 |
+
<label>Order Sync Settings</label>
|
223 |
+
<sort_order>400</sort_order>
|
224 |
+
<show_in_default>1</show_in_default>
|
225 |
+
<show_in_default>1</show_in_default>
|
226 |
+
<show_in_store>1</show_in_store>
|
227 |
+
<fields>
|
228 |
+
<enabled translate="label comment">
|
229 |
+
<label>Enable Order Sync</label>
|
230 |
+
<comment><![CDATA[Enable Order Sync]]></comment>
|
231 |
+
<frontend_type>select</frontend_type>
|
232 |
+
<source_model>klevu_search/system_config_source_yesnoforced</source_model>
|
233 |
+
<sort_order>100</sort_order>
|
234 |
+
<show_in_default>1</show_in_default>
|
235 |
+
<show_in_website>1</show_in_website>
|
236 |
+
<show_in_store>1</show_in_store>
|
237 |
+
</enabled>
|
238 |
+
<frequency translate="label">
|
239 |
+
<label>Frequency</label>
|
240 |
+
<frontend_type>select</frontend_type>
|
241 |
+
<source_model>klevu_search/system_config_source_frequency</source_model>
|
242 |
+
<sort_order>200</sort_order>
|
243 |
+
<show_in_default>1</show_in_default>
|
244 |
+
<show_in_website>0</show_in_website>
|
245 |
+
<show_in_store>0</show_in_store>
|
246 |
+
</frequency>
|
247 |
+
<last_run translate="label">
|
248 |
+
<label>Last Run</label>
|
249 |
+
<frontend_type>label</frontend_type>
|
250 |
+
<sort_order>300</sort_order>
|
251 |
+
<show_in_default>1</show_in_default>
|
252 |
+
<show_in_website>0</show_in_website>
|
253 |
+
<show_in_store>0</show_in_store>
|
254 |
+
</last_run>
|
255 |
+
</fields>
|
256 |
+
</order_sync>
|
257 |
+
<tax_setting translate="label">
|
258 |
+
<label>Tax Settings</label>
|
259 |
+
<sort_order>400</sort_order>
|
260 |
+
<show_in_default>0</show_in_default>
|
261 |
+
<show_in_website>0</show_in_website>
|
262 |
+
<show_in_store>1</show_in_store>
|
263 |
+
<fields>
|
264 |
+
<enabled translate="label comment">
|
265 |
+
<label>Include Tax in Price</label>
|
266 |
+
<comment><![CDATA[Please make sure to resynchronize products by clicking on the "Sync All Products for This Store" under the "Product Sync Settings".]]></comment>
|
267 |
+
<frontend_type>select</frontend_type>
|
268 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
269 |
+
<sort_order>100</sort_order>
|
270 |
+
<show_in_default>0</show_in_default>
|
271 |
+
<show_in_website>0</show_in_website>
|
272 |
+
<show_in_store>1</show_in_store>
|
273 |
+
</enabled>
|
274 |
+
|
275 |
+
</fields>
|
276 |
+
</tax_setting>
|
277 |
+
<developer translate="label">
|
278 |
+
<label>Developer Settings</label>
|
279 |
+
<sort_order>900</sort_order>
|
280 |
+
<show_in_default>1</show_in_default>
|
281 |
+
<show_in_website>0</show_in_website>
|
282 |
+
<show_in_store>0</show_in_store>
|
283 |
+
<fields>
|
284 |
+
<force_log translate="label comment">
|
285 |
+
<label>Force Logging</label>
|
286 |
+
<comment><![CDATA[Use this setting to override default Magento log settings and enable logging. Log messages are saved in Klevu_Search.log]]></comment>
|
287 |
+
<frontend_type>select</frontend_type>
|
288 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
289 |
+
<sort_order>300</sort_order>
|
290 |
+
<show_in_default>1</show_in_default>
|
291 |
+
<show_in_website>0</show_in_website>
|
292 |
+
<show_in_store>0</show_in_store>
|
293 |
+
</force_log>
|
294 |
+
<log_level translate="label">
|
295 |
+
<label>Log level</label>
|
296 |
+
<frontend_type>select</frontend_type>
|
297 |
+
<source_model>klevu_search/system_config_source_log_level</source_model>
|
298 |
+
<backend_model>klevu_search/config_log_level</backend_model>
|
299 |
+
<sort_order>310</sort_order>
|
300 |
+
<show_in_default>1</show_in_default>
|
301 |
+
<show_in_website>0</show_in_website>
|
302 |
+
<show_in_store>0</show_in_store>
|
303 |
+
</log_level>
|
304 |
+
<sendlog translate="label">
|
305 |
+
<label>Send Log</label>
|
306 |
+
<comment><![CDATA[When you click on the "Send Log" Button above, the following information is submitted to the Klevu team: your magento and php version numbers; status of your product indices and the last few lines of Klevu_Search.log file.]]></comment>
|
307 |
+
<frontend_type>button</frontend_type>
|
308 |
+
<frontend_model>klevu_search/adminhtml_form_field_image_log</frontend_model>
|
309 |
+
<sort_order>311</sort_order>
|
310 |
+
<show_in_default>1</show_in_default>
|
311 |
+
<show_in_website>0</show_in_website>
|
312 |
+
<show_in_store>0</show_in_store>
|
313 |
+
</sendlog>
|
314 |
+
</fields>
|
315 |
+
</developer>
|
316 |
+
<image translate="label">
|
317 |
+
<label>Generate Thumbnail Image</label>
|
318 |
+
<sort_order>901</sort_order>
|
319 |
+
<expanded>1</expanded>
|
320 |
+
<show_in_default>1</show_in_default>
|
321 |
+
<show_in_website>0</show_in_website>
|
322 |
+
<show_in_store>0</show_in_store>
|
323 |
+
<fields>
|
324 |
+
<image_thumb translate="label">
|
325 |
+
<label>Product Thumbnails</label>
|
326 |
+
<comment><![CDATA[Click here to create thumbnails for all your product images. Once the process
|
327 |
+
has finnished, please synchronize all your products again (see Product
|
328 |
+
Synchronization Settings). This is to make sure Klevu Search uses the newly
|
329 |
+
created thumbnails instead of the original product images.]]></comment>
|
330 |
+
<frontend_type>button</frontend_type>
|
331 |
+
<frontend_model>klevu_search/adminhtml_form_field_image_button</frontend_model>
|
332 |
+
<sort_order>310</sort_order>
|
333 |
+
<show_in_default>1</show_in_default>
|
334 |
+
<show_in_website>0</show_in_website>
|
335 |
+
<show_in_store>0</show_in_store>
|
336 |
+
</image_thumb>
|
337 |
+
</fields>
|
338 |
+
</image>
|
339 |
+
</groups>
|
340 |
+
</klevu_search>
|
341 |
+
</sections>
|
342 |
+
</config>
|
app/code/community/Klevu/Search/sql/klevu_search_setup/mysql4-data-upgrade-1.1.1-1.1.2.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Add all of the attributes mapped in "Additional Attributes" section to the
|
4 |
+
* "Other Attributes to Index" section
|
5 |
+
*/
|
6 |
+
|
7 |
+
/** @var Mage_Core_Model_Resource_Setup $installer */
|
8 |
+
$installer = $this;
|
9 |
+
|
10 |
+
$installer->startSetup();
|
11 |
+
|
12 |
+
$mage_config = Mage::getConfig();
|
13 |
+
$klevu_config = Mage::helper("klevu_search/config");
|
14 |
+
|
15 |
+
foreach (Mage::app()->getStores() as $store) {
|
16 |
+
/** @var Mage_Core_Model_Store $store */
|
17 |
+
$additional_attributes = $klevu_config->getAdditionalAttributesMap($store);
|
18 |
+
|
19 |
+
if (count($additional_attributes) == 0) {
|
20 |
+
continue;
|
21 |
+
}
|
22 |
+
|
23 |
+
$other_attributes = $klevu_config->getOtherAttributesToIndex($store);
|
24 |
+
|
25 |
+
foreach ($additional_attributes as $mapping) {
|
26 |
+
$other_attributes[] = $mapping["magento_attribute"];
|
27 |
+
}
|
28 |
+
|
29 |
+
$other_attributes = array_unique($other_attributes);
|
30 |
+
|
31 |
+
if (count($other_attributes) == 0) {
|
32 |
+
continue;
|
33 |
+
}
|
34 |
+
|
35 |
+
$other_attributes = implode(",", $other_attributes);
|
36 |
+
|
37 |
+
$scope_id = $mage_config->getNode(sprintf(Klevu_Search_Helper_Config::XML_PATH_STORE_ID, $store->getCode()));
|
38 |
+
if ($scope_id !== null) {
|
39 |
+
$scope_id = (int) $scope_id;
|
40 |
+
|
41 |
+
$mage_config->saveConfig(Klevu_Search_Helper_Config::XML_PATH_ATTRIBUTES_OTHER, $other_attributes, "stores", $scope_id);
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
$mage_config->reinit();
|
46 |
+
|
47 |
+
$image_thumb_table = $installer->getTable('klevu_search/image_thumb');
|
48 |
+
$installer->run("DROP TABLE IF EXISTS `{$image_thumb_table}`");
|
49 |
+
$installer->run("
|
50 |
+
CREATE TABLE `{$image_thumb_table}` (
|
51 |
+
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
52 |
+
`batchdata` text NOT NULL,
|
53 |
+
`date` timestamp NOT NULL default CURRENT_TIMESTAMP,
|
54 |
+
`is_processed` int(10) NOT NULL,
|
55 |
+
PRIMARY KEY (`id`)
|
56 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
57 |
+
");
|
58 |
+
|
59 |
+
|
60 |
+
$installer->endSetup();
|
app/code/community/Klevu/Search/sql/klevu_search_setup/mysql4-data-upgrade-1.1.7-1.1.8.php
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Add all of the attributes mapped in "Additional Attributes" section to the
|
5 |
+
* "Other Attributes to Index" section
|
6 |
+
*/
|
7 |
+
|
8 |
+
/** @var Mage_Core_Model_Resource_Setup $installer */
|
9 |
+
$installer = $this;
|
10 |
+
$installer->startSetup();
|
11 |
+
$content = '<div class="kuContainer">
|
12 |
+
<div id="loader" style="text-align: center;"><img src="{{skin url=images/klevu/ku-loader.gif}}" alt="search" /></div>
|
13 |
+
<div class="kuProListing" id="kuProListing" style="display:none;">
|
14 |
+
<div class="kuNoRecordFound" id="kuNoRecordFound" style="display:none;">
|
15 |
+
<p>No matching products found for "red awef"</p>
|
16 |
+
</div>
|
17 |
+
<div class="kuFilters" id="kuFilters">
|
18 |
+
</div><!-- End of kuFilters -->
|
19 |
+
|
20 |
+
<div class="kuResultList" id="kuResultListBlock">
|
21 |
+
<div class="kuListHeader">
|
22 |
+
<div class="kuTotResults" id="kuTotResults"></div>
|
23 |
+
<div class="kuSortingOpt">
|
24 |
+
<div class="kuSortby">
|
25 |
+
<label id="klevuSortLbl">Sort by:</label>
|
26 |
+
<select name="kuSortby" id="kuSortby" onchange="klevu_changeSortingOptionsForLandigPage(this.value);">
|
27 |
+
<option value="rel" id="klevuRelSort" >Relevance</option>
|
28 |
+
<option value="lth" id="klevuLthSort">Price: Low to high</option>
|
29 |
+
<option value="htl" id="klevuHtlSort">Price: High to low</option>
|
30 |
+
</select>
|
31 |
+
</div>
|
32 |
+
|
33 |
+
<div class="kuView">
|
34 |
+
<a class="kuGridviewBtn" id="gridViewBtn" onclick="setKuView('."'grid'".');">
|
35 |
+
<span class="icon-gridview"> </span>
|
36 |
+
</a>
|
37 |
+
<a class="kuListviewBtn kuCurrent" id="listViewBtn" onclick="setKuView('."'list'".');">
|
38 |
+
<span class="icon-listview"> </span>
|
39 |
+
</a>
|
40 |
+
</div>
|
41 |
+
|
42 |
+
<div class="kuPerPage">
|
43 |
+
<label id="klevuItemsPerPage">Items per page:</label>
|
44 |
+
<select onchange="klevu_changeItemsPerPage(this.value);" id="noOfRecords1">
|
45 |
+
<option>12</option>
|
46 |
+
<option>24</option>
|
47 |
+
<option>36</option>
|
48 |
+
</select>
|
49 |
+
</div>
|
50 |
+
|
51 |
+
<div class="kuPagination" id="kuPagination1">
|
52 |
+
</div>
|
53 |
+
|
54 |
+
<div class="kuClearLeft"></div>
|
55 |
+
</div>
|
56 |
+
|
57 |
+
</div>
|
58 |
+
<div class="kuListView" id="kuResultsView">
|
59 |
+
|
60 |
+
</div>
|
61 |
+
<div class="kuBottomPagi">
|
62 |
+
<div class="kuPerPage">
|
63 |
+
<label id="klevuItemsPerPageFooter">Items per page:</label>
|
64 |
+
<select onchange="klevu_changeItemsPerPage(this.value);" id="noOfRecords2">
|
65 |
+
<option>12</option>
|
66 |
+
<option>24</option>
|
67 |
+
<option>36</option>
|
68 |
+
</select>
|
69 |
+
</div>
|
70 |
+
<div class="kuPagination" id="kuPagination2">
|
71 |
+
|
72 |
+
</div>
|
73 |
+
<div class="kuClearLeft"></div>
|
74 |
+
</div>
|
75 |
+
|
76 |
+
|
77 |
+
</div>
|
78 |
+
<div class="klevu-clear-both"></div>
|
79 |
+
</div><!-- End of kuProListing -->
|
80 |
+
</div><!-- End of klevu-container -->
|
81 |
+
<input type="hidden" name="noOfRecords" id="noOfRecords" value="12"/>
|
82 |
+
<input type="hidden" name="startPos" id="startPos" value="0"/>
|
83 |
+
<input type="hidden" name="totalResultsFound" id="totalResultsFound" value="0"/>
|
84 |
+
<input type="hidden" name="searchedKeyword" id="searchedKeyword" value=""/>
|
85 |
+
<input type="hidden" name="totalPages" id="totalPages" value="0"/>
|
86 |
+
<script type="text/javascript" src="https://box.klevu.com/klevu-js-v1/js-1-1/klevu-landing.js">
|
87 |
+
</script>
|
88 |
+
<script type="text/javascript">// <![CDATA[
|
89 |
+
document.getElementById("searchedKeyword").value= klevu_getParamValue("q");
|
90 |
+
// ]]></script>';
|
91 |
+
//if you want one block for each store view, get the store collection
|
92 |
+
$stores = Mage::getModel('core/store')->getCollection()->addFieldToFilter('store_id', array('gt'=>0))->getAllIds();
|
93 |
+
// add static block
|
94 |
+
$block = Mage::getModel('cms/block');
|
95 |
+
$block->setTitle('Klevu Search Landing Page Block');
|
96 |
+
$block->setIdentifier('klevu-search-landing-page-block-html');
|
97 |
+
$block->setStores(array(0));
|
98 |
+
$block->setIsActive(1);
|
99 |
+
$block->setContent($content);
|
100 |
+
$block->save();
|
101 |
+
|
102 |
+
// add cms page
|
103 |
+
$cmsPage = array(
|
104 |
+
'title' => 'Search results',
|
105 |
+
'root_template' => 'one_column',
|
106 |
+
'identifier' => 'search-result',
|
107 |
+
'is_active' => 1,
|
108 |
+
'stores' => array(0),
|
109 |
+
'content' => '{{block type="cms/block" block_id="klevu-search-landing-page-block-html"}}',
|
110 |
+
);
|
111 |
+
|
112 |
+
Mage::getModel('cms/page')->setData($cmsPage)->save();
|
113 |
+
$installer->endSetup();
|
app/code/community/Klevu/Search/sql/klevu_search_setup/mysql4-install-1.0.0.php
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/** @var Mage_Core_Model_Resource_Setup $installer */
|
3 |
+
$installer = $this;
|
4 |
+
|
5 |
+
$installer->startSetup();
|
6 |
+
|
7 |
+
$connection = $installer->getConnection();
|
8 |
+
|
9 |
+
|
10 |
+
|
11 |
+
$notifications_table = $installer->getTable('klevu_search/notification');
|
12 |
+
|
13 |
+
$installer->run("DROP TABLE IF EXISTS `{$notifications_table}`");
|
14 |
+
|
15 |
+
$installer->run("
|
16 |
+
CREATE TABLE `{$notifications_table}` (
|
17 |
+
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
18 |
+
`date` timestamp NOT NULL default CURRENT_TIMESTAMP,
|
19 |
+
`type` varchar(32) NOT NULL,
|
20 |
+
`message` text NOT NULL,
|
21 |
+
PRIMARY KEY (`id`)
|
22 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
23 |
+
");
|
24 |
+
|
25 |
+
// Add a notification to setup cron and a cron job to clear
|
26 |
+
// the notification the next time cron runs
|
27 |
+
$installer->getConnection()->insert($notifications_table, array(
|
28 |
+
"type" => "cron_check",
|
29 |
+
"message" => Mage::helper("klevu_search")->__('Klevu Search relies on cron for normal operations. Please check that you have Magento cron set up correctly. You can find instructions on how to set up Magento Cron <a target="_blank" href="https://klevusearch.freshdesk.com/support/solutions/articles/5000518493-how-do-i-setup-a-cron-">here</a>.')
|
30 |
+
));
|
31 |
+
|
32 |
+
$now = date_create("now")->format("Y-m-d H:i:00");
|
33 |
+
|
34 |
+
$schedule = Mage::getModel("cron/schedule");
|
35 |
+
$schedule
|
36 |
+
->setJobCode("klevu_search_clear_cron_check")
|
37 |
+
->setCreatedAt($now)
|
38 |
+
->setScheduledAt($now)
|
39 |
+
->setStatus(Mage_Cron_Model_Schedule::STATUS_PENDING)
|
40 |
+
->save();
|
41 |
+
|
42 |
+
|
43 |
+
|
44 |
+
$product_sync_table = $installer->getTable('klevu_search/product_sync');
|
45 |
+
|
46 |
+
// Pre-existing sync data is of no use, so drop the existing
|
47 |
+
// table before recreating it
|
48 |
+
$installer->run("DROP TABLE IF EXISTS `{$product_sync_table}`");
|
49 |
+
|
50 |
+
$installer->run("
|
51 |
+
CREATE TABLE `{$product_sync_table}` (
|
52 |
+
`product_id` int(10) unsigned NOT NULL,
|
53 |
+
`parent_id` int(10) unsigned NOT NULL DEFAULT 0,
|
54 |
+
`store_id` smallint(5) unsigned NOT NULL,
|
55 |
+
`test_mode` int(1) NOT NULL DEFAULT 0,
|
56 |
+
`last_synced_at` timestamp NOT NULL default CURRENT_TIMESTAMP,
|
57 |
+
PRIMARY KEY (`product_id`, `parent_id`, `store_id`, `test_mode`)
|
58 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
59 |
+
");
|
60 |
+
|
61 |
+
|
62 |
+
|
63 |
+
$order_sync_table = $installer->getTable('klevu_search/order_sync');
|
64 |
+
|
65 |
+
$installer->run("DROP TABLE IF EXISTS `{$order_sync_table}`");
|
66 |
+
|
67 |
+
$installer->run("
|
68 |
+
CREATE TABLE `{$order_sync_table}` (
|
69 |
+
`order_item_id` int(10) unsigned NOT NULL,
|
70 |
+
PRIMARY KEY (`order_item_id`)
|
71 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
72 |
+
");
|
73 |
+
|
74 |
+
|
75 |
+
|
76 |
+
$installer->endSetup();
|
app/design/adminhtml/default/default/layout/klevu/search.xml
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout version="0.1.0">
|
3 |
+
|
4 |
+
<default>
|
5 |
+
<reference name="head">
|
6 |
+
<action method="addItem"><type>skin_css</type><name>klevu/search/notifications.css</name></action>
|
7 |
+
</reference>
|
8 |
+
<reference name="notifications">
|
9 |
+
<block type="klevu_search/adminhtml_notifications" name="klevu_notifications"
|
10 |
+
template="klevu/search/notifications.phtml"/>
|
11 |
+
</reference>
|
12 |
+
</default>
|
13 |
+
|
14 |
+
<adminhtml_catalog_product_index>
|
15 |
+
<reference name="products_list">
|
16 |
+
<action method="addButton" ifconfig="klevu_search/product_sync/enabled">
|
17 |
+
<name>klevu_search_sync_all</name>
|
18 |
+
<data helper="klevu_search/getSyncAllButtonData"/>
|
19 |
+
</action>
|
20 |
+
</reference>
|
21 |
+
</adminhtml_catalog_product_index>
|
22 |
+
|
23 |
+
<adminhtml_system_config_edit>
|
24 |
+
<update handle="editor" />
|
25 |
+
<reference name="head">
|
26 |
+
<action method="addItem"><type>skin_css</type><name>klevu/search/wizard.css</name></action>
|
27 |
+
<action method="addItem"><type>js</type><name>klevu/search/lib/Wizard.js</name></action>
|
28 |
+
</reference>
|
29 |
+
</adminhtml_system_config_edit>
|
30 |
+
|
31 |
+
<adminhtml_klevu_search_wizard_configure_user>
|
32 |
+
<remove name="root"/>
|
33 |
+
<block type="klevu_search/adminhtml_wizard_configure_user" name="configure_user"
|
34 |
+
template="klevu/search/wizard/configure/user.phtml" output="toHtml">
|
35 |
+
<block type="core/messages" name="messages" as="messages" />
|
36 |
+
</block>
|
37 |
+
</adminhtml_klevu_search_wizard_configure_user>
|
38 |
+
|
39 |
+
<adminhtml_klevu_search_wizard_configure_store>
|
40 |
+
<remove name="root" />
|
41 |
+
<block type="klevu_search/adminhtml_wizard_configure_store" name="configure_store"
|
42 |
+
template="klevu/search/wizard/configure/store.phtml" output="toHtml">
|
43 |
+
<block type="core/messages" name="messages" as="messages" />
|
44 |
+
</block>
|
45 |
+
</adminhtml_klevu_search_wizard_configure_store>
|
46 |
+
|
47 |
+
<adminhtml_klevu_search_wizard_configure_attributes>
|
48 |
+
<remove name="root" />
|
49 |
+
<block type="klevu_search/adminhtml_wizard_configure_attributes" name="configure_attributes"
|
50 |
+
template="klevu/search/wizard/configure/attributes.phtml" output="toHtml">
|
51 |
+
<block type="core/messages" name="messages" as="messages"/>
|
52 |
+
</block>
|
53 |
+
</adminhtml_klevu_search_wizard_configure_attributes>
|
54 |
+
|
55 |
+
<adminhtml_klevu_search_wizard_configure_store_post>
|
56 |
+
<remove name="root"/>
|
57 |
+
<block type="adminhtml/template" name="configure_attributes_post" template="klevu/search/wizard/complete.phtml" output="toHtml">
|
58 |
+
<block type="core/messages" name="messages" as="messages" />
|
59 |
+
</block>
|
60 |
+
</adminhtml_klevu_search_wizard_configure_store_post>
|
61 |
+
</layout>
|
app/design/adminhtml/default/default/template/klevu/search/form/field/array_readonly.phtml
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** Template copied from: app/design/adminhtml/default/default/template/system/config/form/field/array.phtml */ ?>
|
2 |
+
|
3 |
+
<?php
|
4 |
+
$_htmlId = $this->getHtmlId() ? $this->getHtmlId() : '_' . uniqid();
|
5 |
+
?>
|
6 |
+
|
7 |
+
<div class="grid" id="grid<?php echo $_htmlId ?>">
|
8 |
+
<table cellpadding="0" cellspacing="0" class="border">
|
9 |
+
<tbody>
|
10 |
+
|
11 |
+
<tr class="headings" id="headings<?php echo $_htmlId ?>">
|
12 |
+
<?php foreach ($this->_columns as $columnName => $column):?>
|
13 |
+
<th><?php echo $column['label'] ?></th>
|
14 |
+
<?php endforeach;?>
|
15 |
+
</tr>
|
16 |
+
<?php foreach ($this->getArrayRows() as $_row): ?>
|
17 |
+
<tr>
|
18 |
+
<?php foreach ($this->_columns as $columnName => $column): ?>
|
19 |
+
<td><?php echo $_row->getData($columnName) ?></td>
|
20 |
+
<?php endforeach ?>
|
21 |
+
</tr>
|
22 |
+
<?php endforeach ?>
|
23 |
+
</tbody>
|
24 |
+
</table>
|
25 |
+
</div>
|
app/design/adminhtml/default/default/template/klevu/search/form/field/sync/button.phtml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Klevu_Search_Block_Adminhtml_Form_Field_Sync_Button $this */ ?>
|
2 |
+
<button id="<?php echo $this->getHtmlId() ?>" class="scalable" type="button">
|
3 |
+
<span><?php echo $this->__($this->getButtonLabel()) ?></span>
|
4 |
+
</button>
|
5 |
+
<script type="text/javascript">
|
6 |
+
$("<?php echo $this->getHtmlId() ?>").observe("click", function () {
|
7 |
+
setLocation("<?php echo $this->getDestinationUrl() ?>");
|
8 |
+
});
|
9 |
+
</script>
|
app/design/adminhtml/default/default/template/klevu/search/form/field/sync/logbutton.phtml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Klevu_Search_Block_Adminhtml_Form_Field_Sync_Button $this */ ?>
|
2 |
+
<button id="<?php echo $this->getHtmlId() ?>" class="scalable" type="button">
|
3 |
+
<span><?php echo $this->__($this->getButtonLabel()) ?></span>
|
4 |
+
</button>
|
5 |
+
<script type="text/javascript">
|
6 |
+
$("<?php echo $this->getHtmlId() ?>").observe("click", function () {
|
7 |
+
window.open('<?php echo $this->getDestinationUrl() ?>','_blank');
|
8 |
+
});
|
9 |
+
</script>
|
app/design/adminhtml/default/default/template/klevu/search/form/information.phtml
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Klevu_Search_Block_Adminhtml_Form_Information $this */ ?>
|
2 |
+
<p><?php echo $this->__("Installed Version: {$this->getVersion()}") ?></br></p>
|
3 |
+
<p><b><?php echo $this->__("Prerequisites:") ?></b></br>
|
4 |
+
<?php echo $this->__("1. Ensure cron is running > (<a href='http://www.klevu.com/support/setup-cron.html' target='_blank'>click here</a> for more information on setting up a cron)") ?></br>
|
5 |
+
<?php echo $this->__("2. Indices are uptodate (System > Index Management)") ?></br>
|
6 |
+
<?php echo $this->__("3. Products should be enabled and have the visibility set to catalog and search.") ?></p>
|
7 |
+
<p><b><?php echo $this->__(" Klevu Merchant Centre: <a href='https://box.klevu.com' target='_blank'>https://box.klevu.com</a>");?></b></p>
|
8 |
+
<p><?php echo $this->__("Login into Klevu Merchant Centre account to customize Klevu Search. You can
|
9 |
+
change look and feel of your search results, setup product promotions, monitor
|
10 |
+
search activity, upgrade your account and many more.");?></p>
|
11 |
+
<p><b><?php echo $this->__("FAQs and Troubleshooting: <a href='http://www.klevu.com/support/support-home.html' target='_blank'>click here</a>");?></b></p>
|
app/design/adminhtml/default/default/template/klevu/search/notifications.phtml
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Klevu_Search_Block_Adminhtml_Notifications $this */ ?>
|
2 |
+
<?php $notifications = $this->getNotifications(); ?>
|
3 |
+
<?php foreach ($notifications as $notification): ?>
|
4 |
+
<div class="klevu-notification notification-global">
|
5 |
+
<strong><?php echo $this->__("Klevu Search") ?>:</strong> [<?php echo $notification->getDate() ?>] <?php echo $notification->getMessage() ?>
|
6 |
+
<a class="dismiss" href="<?php echo $this->getDismissUrl($notification) ?>"><?php echo $this->__("Dismiss") ?></a>
|
7 |
+
</div>
|
8 |
+
<?php endforeach; ?>
|
app/design/adminhtml/default/default/template/klevu/search/wizard/complete.phtml
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Mage_Core_Block_Template $this */ ?>
|
2 |
+
<div class="content-header">
|
3 |
+
<h3>Complete</h3>
|
4 |
+
</div>
|
5 |
+
<?php echo $this->getChildHtml('messages') ?>
|
6 |
+
<p><?php echo $this->__("You have completed Klevu Search Configuration Wizard.") ?></p>
|
7 |
+
<p><?php echo $this->__("Please click the \"Finish and Sync\" button below to synchronise your products to Klevu. Afterwards, the products will be automatically resynchronised periodically as well as when any information changes.") ?></p>
|
8 |
+
<p><?php echo $this->__("Klevu Search will be automatically enabled on frontend after the first synchronisation completes. Afterwards, you can manually control that using the \"Enable on Frontend\" flag on the System Configuration page.") ?></p>
|
9 |
+
<p class="warning"><b><?php echo $this->__("Warning") ?>:</b> <?php echo $this->__("Product synchronisation takes time. Please do not close or refresh the page after clicking the button until the page finishes loading.") ?></p>
|
10 |
+
<div class="button-set">
|
11 |
+
<button id="sync-button"><span><?php echo $this->__("Finish and Sync") ?></span></button>
|
12 |
+
</div>
|
13 |
+
<script type="text/javascript">
|
14 |
+
$("sync-button").observe("click", function (e) {
|
15 |
+
window.location = "<?php echo $this->getUrl("adminhtml/klevu_search/manual_sync") ?>";
|
16 |
+
});
|
17 |
+
</script>
|
app/design/adminhtml/default/default/template/klevu/search/wizard/config/button.phtml
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Klevu_Search_Block_Adminhtml_Wizard_Config_Button $this */ ?>
|
2 |
+
<button id="<?php echo $this->getHtmlId() ?>" class="scalable" type="button">
|
3 |
+
<span><?php echo $this->__("Start Configuration Wizard") ?></span>
|
4 |
+
</button>
|
5 |
+
<script type="text/javascript">
|
6 |
+
$("<?php echo $this->getHtmlId() ?>").observe("click", function () {
|
7 |
+
new Klevu.Search.Wizard({
|
8 |
+
url: "<?php echo $this->getWizardUrl() ?>"
|
9 |
+
});
|
10 |
+
});
|
11 |
+
</script>
|
app/design/adminhtml/default/default/template/klevu/search/wizard/configure/attributes.phtml
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Klevu_Search_Block_Adminhtml_Wizard_Configure_Attributes $this */ ?>
|
2 |
+
<div class="content-header">
|
3 |
+
<h3>Configure Attributes</h3>
|
4 |
+
</div>
|
5 |
+
<?php echo $this->getChildHtml('messages') ?>
|
6 |
+
<form id="klevu_search_wizard_configure_attributes_form" action="<?php echo $this->getFormActionUrl() ?>" method="POST">
|
7 |
+
<input type="hidden" name="form_key" value="<?php echo $this->getFormKey() ?>" />
|
8 |
+
<p><?php echo $this->__("Klevu Search uses most of the standard Magento product attributes for search. However, if you have any custom attributes that you want to be used in search or want to use any additional filters, such as color or size, you can map them below by selecting the Klevu attribute you want to define and the Magento attribute that it should map to.") ?></p>
|
9 |
+
<fieldset class="fieldset">
|
10 |
+
<table cellspacing="0" class="form-list">
|
11 |
+
<tbody>
|
12 |
+
<tr>
|
13 |
+
<td class="label"></td>
|
14 |
+
<td class="value"><?php echo $this->getAttributeMappingsHtml() ?></td>
|
15 |
+
</tr>
|
16 |
+
</tbody>
|
17 |
+
</table>
|
18 |
+
</fieldset>
|
19 |
+
<div class="button-set">
|
20 |
+
<button type="submit"><span><?php echo $this->__("Continue") ?></span></button>
|
21 |
+
</div>
|
22 |
+
</form>
|
app/design/adminhtml/default/default/template/klevu/search/wizard/configure/store.phtml
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Klevu_Search_Block_Adminhtml_Wizard_Configure_Store $this */ ?>
|
2 |
+
<?php $store = $this->getStore() ?>
|
3 |
+
<div class="content-header">
|
4 |
+
<h3>Configure Store</h3>
|
5 |
+
</div>
|
6 |
+
<?php echo $this->getChildHtml('messages') ?>
|
7 |
+
<form id="klevu_search_wizard_configure_store_form" action="<?php echo $this->getFormActionUrl() ?>" method="POST">
|
8 |
+
<input type="hidden" name="form_key" value="<?php echo $this->getFormKey() ?>" />
|
9 |
+
<p><?php echo $this->__("Select a Magento store you want to configure Klevu search for.") ?></p>
|
10 |
+
<fieldset class="fieldset">
|
11 |
+
<table cellspacing="0" class="form-list">
|
12 |
+
<tbody>
|
13 |
+
<tr>
|
14 |
+
<td class="label"><label for="store"><?php echo $this->__("Magento store:") ?></label></td>
|
15 |
+
<td class="value">
|
16 |
+
<select name="store">
|
17 |
+
<option value=""></option>
|
18 |
+
<?php $data = $this->getStoreSelectData() ?>
|
19 |
+
<?php foreach ($data as $website => $groups): ?>
|
20 |
+
<optgroup label="<?php echo $this->escapeHtml($website) ?>"></optgroup>
|
21 |
+
<?php foreach ($groups as $group => $stores): ?>
|
22 |
+
<optgroup label=" <?php echo $this->escapeHtml($group) ?>">
|
23 |
+
<?php foreach ($stores as $store): ?>
|
24 |
+
<?php /** @var Mage_Core_Model_Store $store */ ?>
|
25 |
+
<option value="<?php echo $store->getCode() ?>"> <?php echo $this->escapeHtml($store->getName()) ?></option>
|
26 |
+
<?php endforeach; ?>
|
27 |
+
</optgroup>
|
28 |
+
<?php endforeach; ?>
|
29 |
+
<?php endforeach; ?>
|
30 |
+
</select>
|
31 |
+
</td>
|
32 |
+
</tr>
|
33 |
+
|
34 |
+
<tr>
|
35 |
+
<td class="label"><label for="tax_enable"><?php echo $this->__("Want to include tax in price:") ?></label></td>
|
36 |
+
<td class="value">
|
37 |
+
<select name="tax_enable" id="tax_enable">
|
38 |
+
<option value="0" selected="selected"><?php echo $this->__("No") ?></option>
|
39 |
+
<option value="1"><?php echo $this->__("Yes") ?></option>
|
40 |
+
</select>
|
41 |
+
</td>
|
42 |
+
</tr>
|
43 |
+
</tbody>
|
44 |
+
</table>
|
45 |
+
</fieldset>
|
46 |
+
<div class="button-set">
|
47 |
+
<button type="submit"><span><?php echo $this->__("Continue") ?></span></button>
|
48 |
+
</div>
|
49 |
+
</form>
|
app/design/adminhtml/default/default/template/klevu/search/wizard/configure/user.phtml
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Klevu_Search_Block_Adminhtml_Wizard_Configure_User $this */ ?>
|
2 |
+
<?php echo $this->getChildHtml('messages') ?>
|
3 |
+
|
4 |
+
<form id="klevu_search_wizard_configure_user_form" action="<?php echo $this->getFormActionUrl() ?>" method="POST">
|
5 |
+
<input type="hidden" name="form_key" value="<?php echo $this->getFormKey() ?>" />
|
6 |
+
|
7 |
+
<fieldset class="fieldset">
|
8 |
+
<table cellspacing="0" class="form-list" style="width:100%;">
|
9 |
+
<tbody>
|
10 |
+
<tr>
|
11 |
+
<td>
|
12 |
+
<table class="klevu_signup_form">
|
13 |
+
<tr>
|
14 |
+
<td colspan="2">
|
15 |
+
<div class="content-header">
|
16 |
+
<h3>Register New User</h3>
|
17 |
+
</div>
|
18 |
+
<p><?php echo $this->__("Fill out the form below to create a new Klevu user to use with this Magento installation:") ?></p>
|
19 |
+
</td>
|
20 |
+
</tr>
|
21 |
+
<tr>
|
22 |
+
<td class="label"><label for="klevu_new_email"><?php echo $this->__("Primary Email:") ?><span class="required"> <em>*</em></span></label>
|
23 |
+
</td>
|
24 |
+
<td class="value"><input type="text" name="klevu_new_email" id="klevu_new_email" class="input-text " />
|
25 |
+
<p class="note">For login and technical support</p></td>
|
26 |
+
</tr>
|
27 |
+
<tr>
|
28 |
+
<td class="label"><label for="merchantEmail"><?php echo $this->__("Retailer Email:") ?><span class="required"> <em>*</em></span></label></td>
|
29 |
+
<td class="value"><input type="text" name="merchantEmail" id="merchantEmail" class="input-text" /><p class="note">
|
30 |
+
For search insights and billing</p></td>
|
31 |
+
</tr>
|
32 |
+
<tr>
|
33 |
+
<td class="label"><label for="klevu_new_password"><?php echo $this->__("Password:") ?><span class="required"> <em>*</em></span></label></td>
|
34 |
+
<td class="value"><input type="password" name="klevu_new_password" id="klevu_new_password" class="input-text" />
|
35 |
+
</td>
|
36 |
+
</tr>
|
37 |
+
<tr>
|
38 |
+
<td class="label"><label for="userPlan"><?php echo $this->__("Choose Your Plan:") ?><span class="required"> <em>*</em></span></label></td>
|
39 |
+
<td class="value">
|
40 |
+
<input type="radio" name="userPlan" value="free"> Free
|
41 |
+
<input type="radio" name="userPlan" checked="checked" value="trial"> PRO trial
|
42 |
+
<a href="#" onClick="checkplan();">what's included?</a>
|
43 |
+
<p class="note">If your store exceeds the guidelines of FREE edition, then PRO trial will be enabled.</p>
|
44 |
+
</td>
|
45 |
+
</tr>
|
46 |
+
|
47 |
+
<tr>
|
48 |
+
<td class="label"><label for="contactNo"> <?php echo $this->__("Phone Number:") ?><span class="required"> </span></label></td>
|
49 |
+
<td class="value"><input type="text" placeholder="Country code" name="countyCode" id="countyCode" class="input-text" value="<?php echo $this->getCountyCode() ?>" /> <input type="text" name="contactNo" id="contactNo" class="input-text" value="<?php echo $this->getContactNo() ?>" /></td>
|
50 |
+
</tr>
|
51 |
+
|
52 |
+
<tr>
|
53 |
+
<td class="label"><label for="klevu_new_url"> <?php echo $this->__("Store URL:") ?><span class="required"> <em>*</em></span></label></td>
|
54 |
+
<td class="value"><input type="text" name="klevu_new_url" id="klevu_new_url" class="input-text" value="<?php echo $this->getStoreUrl() ?>" /></td>
|
55 |
+
</tr>
|
56 |
+
|
57 |
+
<tr>
|
58 |
+
<td class="label"></td>
|
59 |
+
<td class="value" style="padding-right: 26px;">
|
60 |
+
<div class="button-set">
|
61 |
+
<button type="submit"><span><?php echo $this->__("Register") ?></span></button>
|
62 |
+
</div>
|
63 |
+
</td>
|
64 |
+
</tr>
|
65 |
+
</table>
|
66 |
+
</td>
|
67 |
+
<td>
|
68 |
+
<table class="klevu_signup_form">
|
69 |
+
<tr>
|
70 |
+
<td colspan="2">
|
71 |
+
<div class="content-header">
|
72 |
+
<h3>Already Registered?</h3>
|
73 |
+
</div>
|
74 |
+
<p><?php echo $this->__("If you have an account with Klevu, please log in:") ?></p>
|
75 |
+
</td>
|
76 |
+
</tr>
|
77 |
+
<tr>
|
78 |
+
<td class="label"><label for="klevu_existing_email"><?php echo $this->__("Primary Email:") ?><span class="required"> <em>*</em></span></label></td>
|
79 |
+
<td class="value"><input type="text" name="klevu_existing_email" id="klevu_existing_email" class="input-text" /></td>
|
80 |
+
</tr>
|
81 |
+
<tr>
|
82 |
+
<td class="label"><label for="klevu_existing_password"><?php echo $this->__("Password:") ?><span class="required"> <em>*</em></span></label></td>
|
83 |
+
<td class="value"><input type="password" name="klevu_existing_password" id="klevu_existing_password" class="input-text" /></td>
|
84 |
+
</tr>
|
85 |
+
<tr>
|
86 |
+
<td class="label"></td>
|
87 |
+
<td class="value">
|
88 |
+
<div class="button-set">
|
89 |
+
<button type="submit"><span><?php echo $this->__("Login") ?></span></button>
|
90 |
+
</div>
|
91 |
+
</td>
|
92 |
+
</tr>
|
93 |
+
|
94 |
+
</table>
|
95 |
+
|
96 |
+
</td>
|
97 |
+
</tr>
|
98 |
+
|
99 |
+
|
100 |
+
|
101 |
+
|
102 |
+
</tbody>
|
103 |
+
</table>
|
104 |
+
</fieldset>
|
105 |
+
</form>
|
106 |
+
|
app/design/adminhtml/default/default/template/klevu/search/wizard/form/field/array.phtml
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** Template copied from: app/design/adminhtml/default/default/template/system/config/form/field/array.phtml */ ?>
|
2 |
+
<?php
|
3 |
+
$_htmlId = $this->getHtmlId() ? $this->getHtmlId() : '_' . uniqid();
|
4 |
+
|
5 |
+
$_colspan = 2;
|
6 |
+
if (!$this->_addAfter) {
|
7 |
+
$_colspan -= 1;
|
8 |
+
}
|
9 |
+
$_colspan = $_colspan > 1 ? 'colspan="' . $_colspan . '"' : '';
|
10 |
+
?>
|
11 |
+
|
12 |
+
<div class="grid" id="grid<?php echo $_htmlId ?>">
|
13 |
+
<table cellpadding="0" cellspacing="0" class="border">
|
14 |
+
<tbody>
|
15 |
+
|
16 |
+
<tr class="headings" id="headings<?php echo $_htmlId ?>">
|
17 |
+
<?php foreach ($this->_columns as $columnName => $column):?>
|
18 |
+
<th><?php echo $column['label'] ?></th>
|
19 |
+
<?php endforeach;?>
|
20 |
+
<th <?php echo $_colspan?>></th>
|
21 |
+
</tr>
|
22 |
+
|
23 |
+
<tr id="addRow<?php echo $_htmlId ?>">
|
24 |
+
<td colspan="<?php echo count($this->_columns) ?>"></td>
|
25 |
+
<td <?php echo $_colspan?>>
|
26 |
+
<button style="" onclick="" class="scalable add" type="button" id="addToEndBtn<?php echo $_htmlId ?>">
|
27 |
+
<span><span><span><?php echo $this->_addButtonLabel ?></span></span></span>
|
28 |
+
</button>
|
29 |
+
</td>
|
30 |
+
</tr>
|
31 |
+
|
32 |
+
</tbody>
|
33 |
+
</table>
|
34 |
+
<input type="hidden" name="<?php echo $this->getElement()->getName() ?>[__empty]" value="" />
|
35 |
+
</div>
|
36 |
+
<div id="empty<?php echo $_htmlId ?>">
|
37 |
+
<button style="" onclick="" class="scalable add" type="button" id="emptyAddBtn<?php echo $_htmlId ?>">
|
38 |
+
<span><span><span><?php echo $this->_addButtonLabel ?></span></span></span>
|
39 |
+
</button>
|
40 |
+
</div>
|
41 |
+
|
42 |
+
<script type="text/javascript">
|
43 |
+
//<![CDATA[
|
44 |
+
// create row creator
|
45 |
+
// Make sure it's in the global scope
|
46 |
+
window.arrayRow<?php echo $_htmlId ?> = {
|
47 |
+
// define row prototypeJS template
|
48 |
+
template : new Template(
|
49 |
+
'<tr id="#{_id}">'
|
50 |
+
<?php foreach ($this->_columns as $columnName => $column):?>
|
51 |
+
+'<td>'
|
52 |
+
+'<?php echo $this->_renderCellTemplate($columnName)?>'
|
53 |
+
+'<\/td>'
|
54 |
+
<?php endforeach;?>
|
55 |
+
<?php if ($this->_addAfter):?>
|
56 |
+
+'<td><button onclick="" class="scalable add" type="button" id="addAfterBtn#{_id}"><span><span><span><?php echo Mage::helper('adminhtml')->__('Add after') ?><\/span><\/span><\/span><\/button><\/td>'
|
57 |
+
<?php endif;?>
|
58 |
+
+'<td><button onclick="arrayRow<?php echo $_htmlId ?>.del(\'#{_id}\')" class="scalable delete" type="button"><span><span><span><?php echo Mage::helper('adminhtml')->__('Delete') ?><\/span><\/span><\/span><\/button><\/td>'
|
59 |
+
+'<\/tr>'
|
60 |
+
),
|
61 |
+
|
62 |
+
rowsCount : 0,
|
63 |
+
|
64 |
+
add : function(templateData, insertAfterId)
|
65 |
+
{
|
66 |
+
// generate default template data
|
67 |
+
if ('' == templateData) {
|
68 |
+
var d = new Date();
|
69 |
+
var templateData = {
|
70 |
+
<?php foreach ($this->_columns as $columnName => $column):?>
|
71 |
+
<?php echo $columnName ?> : '',
|
72 |
+
<?php endforeach;?>
|
73 |
+
_id : '_' + d.getTime() + '_' + d.getMilliseconds()
|
74 |
+
};
|
75 |
+
}
|
76 |
+
|
77 |
+
// insert before last row
|
78 |
+
if ('' == insertAfterId) {
|
79 |
+
Element.insert($('addRow<?php echo $_htmlId ?>'), {before: this.template.evaluate(templateData)});
|
80 |
+
}
|
81 |
+
// insert after specified row
|
82 |
+
else {
|
83 |
+
Element.insert($(insertAfterId), {after: this.template.evaluate(templateData)});
|
84 |
+
}
|
85 |
+
|
86 |
+
<?php if ($this->_addAfter):?>
|
87 |
+
Event.observe('addAfterBtn' + templateData._id, 'click', this.add.bind(this, '', templateData._id));
|
88 |
+
<?php endif;?>
|
89 |
+
|
90 |
+
this.rowsCount += 1;
|
91 |
+
},
|
92 |
+
|
93 |
+
del : function(rowId)
|
94 |
+
{
|
95 |
+
$(rowId).remove();
|
96 |
+
this.rowsCount -= 1;
|
97 |
+
if (0 == this.rowsCount) {
|
98 |
+
this.showButtonOnly();
|
99 |
+
}
|
100 |
+
},
|
101 |
+
|
102 |
+
showButtonOnly : function()
|
103 |
+
{
|
104 |
+
$('grid<?php echo $_htmlId ?>').hide();
|
105 |
+
$('empty<?php echo $_htmlId ?>').show();
|
106 |
+
}
|
107 |
+
}
|
108 |
+
|
109 |
+
// bind add action to "Add" button in last row
|
110 |
+
Event.observe('addToEndBtn<?php echo $_htmlId ?>', 'click', arrayRow<?php echo $_htmlId ?>.add.bind(arrayRow<?php echo $_htmlId ?>, '', ''));
|
111 |
+
|
112 |
+
// add existing rows
|
113 |
+
<?php
|
114 |
+
$_addAfterId = "headings{$_htmlId}";
|
115 |
+
foreach ($this->getArrayRows() as $_rowId => $_row) {
|
116 |
+
echo "arrayRow{$_htmlId}.add(" . $_row->toJson() . ", '{$_addAfterId}');\n";
|
117 |
+
$_addAfterId = $_rowId;
|
118 |
+
}
|
119 |
+
?>
|
120 |
+
|
121 |
+
// initialize standalone button
|
122 |
+
$('empty<?php echo $_htmlId ?>').hide();
|
123 |
+
Event.observe('emptyAddBtn<?php echo $_htmlId ?>', 'click', function () {
|
124 |
+
$('grid<?php echo $_htmlId ?>').show();
|
125 |
+
$('empty<?php echo $_htmlId ?>').hide();
|
126 |
+
arrayRow<?php echo $_htmlId ?>.add('', '');
|
127 |
+
});
|
128 |
+
|
129 |
+
// if no rows, hide grid and show button only
|
130 |
+
<?php if (!$this->getArrayRows()):?>
|
131 |
+
arrayRow<?php echo $_htmlId ?>.showButtonOnly();
|
132 |
+
<?php endif;?>
|
133 |
+
|
134 |
+
// toggle the grid, if element is disabled (depending on scope)
|
135 |
+
<?php if ($this->getElement()->getDisabled()):?>
|
136 |
+
toggleValueElements({checked:true}, $('grid<?php echo $_htmlId ?>').parentNode);
|
137 |
+
<?php endif;?>
|
138 |
+
//]]>
|
139 |
+
</script>
|
app/design/frontend/base/default/layout/klevu/search.xml
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout version="0.1.0">
|
3 |
+
<default>
|
4 |
+
<reference name="head">
|
5 |
+
<action method="addCss"><stylesheet>css/klevu/klevu-landing-page-style.css</stylesheet></action>
|
6 |
+
<action method="addCss"><stylesheet>css/klevu/klevu-landing-responsive.css</stylesheet></action>
|
7 |
+
</reference>
|
8 |
+
<reference name="before_body_end">
|
9 |
+
<block type="core/template" name="klevu.search.form_js" template="klevu/search/form_js.phtml"/>
|
10 |
+
</reference>
|
11 |
+
</default>
|
12 |
+
<catalog_product_view>
|
13 |
+
<reference name="before_body_end">
|
14 |
+
<block type="klevu_search/catalog_product_tracking" name="klevu_search.catalog.product.tracking" template="klevu/search/product_tracking.phtml" />
|
15 |
+
</reference>
|
16 |
+
</catalog_product_view>
|
17 |
+
<klevu_search_runexternalylog>
|
18 |
+
<label>Klevu Log</label>
|
19 |
+
<remove name="right"/>
|
20 |
+
<remove name="left"/>
|
21 |
+
<reference name="root">
|
22 |
+
<action method="setTemplate"><template>page/1column.phtml</template></action>
|
23 |
+
</reference>
|
24 |
+
<reference name="content">
|
25 |
+
<block type="core/template" name="klevulog" template="klevu/klevulog.phtml"/>
|
26 |
+
</reference>
|
27 |
+
</klevu_search_runexternalylog>
|
28 |
+
</layout>
|
app/design/frontend/base/default/template/klevu/search/form_js.phtml
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Mage_Core_Block_Template $this */ ?>
|
2 |
+
<?php $config = Mage::helper('klevu_search/config'); ?>
|
3 |
+
<?php $helper = Mage::helper('klevu_search'); ?>
|
4 |
+
<?php if ($config->isExtensionConfigured()): ?>
|
5 |
+
<script type="text/javascript">
|
6 |
+
<?php
|
7 |
+
if ($config->isLandingEnabled()==0){ ?>
|
8 |
+
(function () {
|
9 |
+
// Remove Magento event observers from the search box
|
10 |
+
// No Redirection of landing page
|
11 |
+
var search_input = $('search');
|
12 |
+
search_input.stopObserving('click');
|
13 |
+
search_input.stopObserving('keydown');
|
14 |
+
search_input.form.stopObserving('submit');
|
15 |
+
search_input.form.observe('submit', function (e) {
|
16 |
+
Event.stop(e);
|
17 |
+
klevu_autoSuggest($('search').value, e);
|
18 |
+
return false;
|
19 |
+
});
|
20 |
+
})();
|
21 |
+
<?php } else if($config->isLandingEnabled()==2) { ?>
|
22 |
+
(function () {
|
23 |
+
// Remove Magento event observers from the search box
|
24 |
+
// Redirect to klevu js page
|
25 |
+
var search_input = $('search');
|
26 |
+
search_input.stopObserving('click');
|
27 |
+
search_input.stopObserving('keydown');
|
28 |
+
search_input.form.observe('submit', function (e) {
|
29 |
+
Event.stop(e);
|
30 |
+
document.location='<?php echo Mage::getBaseUrl(); ?>' + "search-result?q="+$('search').value;
|
31 |
+
return false;
|
32 |
+
});
|
33 |
+
|
34 |
+
})();
|
35 |
+
var klevu_showQuickSearchOnEnter=false;
|
36 |
+
<?php } else if($config->isLandingEnabled()==1) { ?>
|
37 |
+
(function () {
|
38 |
+
// Remove Magento event observers from the search box
|
39 |
+
// default magetno layout landing page
|
40 |
+
var search_input = $('search');
|
41 |
+
search_input.stopObserving('click');
|
42 |
+
search_input.stopObserving('keydown');
|
43 |
+
})();
|
44 |
+
var klevu_showQuickSearchOnEnter=false;
|
45 |
+
<?php } ?>
|
46 |
+
// call store js
|
47 |
+
var klevu_apiKey = '<?php echo $config->getJsApiKey() ?>',
|
48 |
+
searchTextBoxName = 'search',
|
49 |
+
klevu_lang = '<?php echo $helper->getStoreLanguage() ?>',
|
50 |
+
klevu_result_top_margin = '',
|
51 |
+
klevu_result_left_margin = '';
|
52 |
+
(function () { var ws = document.createElement('script'),kl_protocol =("https:"===document.location.protocol?"https://":"http://"); ws.type = 'text/javascript'; ws.async = true; ws.src = kl_protocol+'<?php echo $config->getJsUrl() ?>/klevu-js-v1/js/klevu-webstore.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ws, s); })();
|
53 |
+
</script>
|
54 |
+
|
55 |
+
<?php endif; ?>
|
app/design/frontend/base/default/template/klevu/search/klevulog.phtml
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Mage_Core_Block_Template $this */
|
2 |
+
echo "hi";
|
3 |
+
exit;
|
4 |
+
?>
|
5 |
+
<div id="messages_product_view">
|
6 |
+
<?php echo $this->getMessagesBlock()->getGroupedHtml(); ?>
|
7 |
+
</div>
|
app/design/frontend/base/default/template/klevu/search/product_tracking.phtml
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php /** @var Klevu_Search_Block_Catalog_Product_Tracking $this */ ?>
|
2 |
+
<?php $config = Mage::helper('klevu_search/config'); ?>
|
3 |
+
<?php if ($config->isExtensionConfigured()): ?>
|
4 |
+
<script type="text/javascript">
|
5 |
+
(function() {
|
6 |
+
var referrer, search_term, klevu_search_product_tracking;
|
7 |
+
referrer = document.referrer;
|
8 |
+
search_term = referrer.toQueryParams().q;
|
9 |
+
|
10 |
+
if (referrer.indexOf('catalogsearch/result') > -1 && search_term) {
|
11 |
+
klevu_search_product_tracking = <?php echo $this->getJsonTrackingData() ?>;
|
12 |
+
klevu_search_product_tracking.klevu_term = search_term;
|
13 |
+
|
14 |
+
// Send the ajax request
|
15 |
+
new Ajax.Request('//<?php echo $config->getAnalyticsUrl() ?>/analytics/productTracking', {
|
16 |
+
method: "GET",
|
17 |
+
parameters: klevu_search_product_tracking,
|
18 |
+
|
19 |
+
// We need to remove the AJAX headers so the request does not get preflighted and break cross-origin request policy
|
20 |
+
onCreate: function(response) {
|
21 |
+
var t = response.transport;
|
22 |
+
t.setRequestHeader = t.setRequestHeader.wrap(function(original, k, v) {
|
23 |
+
if (/^(accept|accept-language|content-language)$/i.test(k))
|
24 |
+
return original(k, v);
|
25 |
+
if (/^content-type$/i.test(k) &&
|
26 |
+
/^(application\/x-www-form-urlencoded|multipart\/form-data|text\/plain)(;.+)?$/i.test(v))
|
27 |
+
return original(k, v);
|
28 |
+
return;
|
29 |
+
});
|
30 |
+
}
|
31 |
+
});
|
32 |
+
}
|
33 |
+
})();
|
34 |
+
</script>
|
35 |
+
<?php endif; ?>
|
app/etc/modules/Klevu_Search.xml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Klevu_Search>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
</Klevu_Search>
|
8 |
+
</modules>
|
9 |
+
</config>
|
js/klevu/search/lib/Wizard.js
ADDED
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
;'use strict';
|
2 |
+
|
3 |
+
if (!window.Klevu) window.Klevu = {};
|
4 |
+
if (!window.Klevu.Search) window.Klevu.Search = {};
|
5 |
+
|
6 |
+
(function () {
|
7 |
+
/**
|
8 |
+
* This class controls a popup Klevu Search Configuration Wizard window
|
9 |
+
* in System Configuration.
|
10 |
+
*/
|
11 |
+
var Wizard = Class.create({
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Create a new Wizard.
|
15 |
+
*
|
16 |
+
* @constructor
|
17 |
+
* @param options An Object containing any of the following configuration options:
|
18 |
+
* id - the DOM id to use for the Wizard window (default: klevu_search_wizard)
|
19 |
+
* title - the Wizard window title (default: Klevu Search Configuration Wizard)
|
20 |
+
* url - the initial Wizard URL to load
|
21 |
+
* onChange - a callback function to be called after every time Wizard window
|
22 |
+
* content is updated with the Window content DOM as a parameter.
|
23 |
+
*/
|
24 |
+
initialize: function (options) {
|
25 |
+
var self = this;
|
26 |
+
|
27 |
+
self.config = Object.extend({
|
28 |
+
id: "klevu_search_wizard",
|
29 |
+
title: "Klevu Search Configuration Wizard",
|
30 |
+
url: null,
|
31 |
+
onChange: null
|
32 |
+
}, options || {});
|
33 |
+
|
34 |
+
self.load();
|
35 |
+
},
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Request the given URL through AJAX and display the response in the Wizard window.
|
39 |
+
*
|
40 |
+
* @param url
|
41 |
+
*/
|
42 |
+
load: function (url) {
|
43 |
+
var self = this;
|
44 |
+
|
45 |
+
url = url || this.config.url;
|
46 |
+
|
47 |
+
if (url) {
|
48 |
+
self.display();
|
49 |
+
new Ajax.Updater(self.dialog.content, url, {
|
50 |
+
evalScripts: true,
|
51 |
+
onComplete: self.onChangeCallback.bind(self)
|
52 |
+
});
|
53 |
+
}
|
54 |
+
},
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Submit the given form through AJAX and display the response in the Wizard window.
|
58 |
+
*
|
59 |
+
* @param form
|
60 |
+
*/
|
61 |
+
submit: function (form) {
|
62 |
+
var self = this;
|
63 |
+
|
64 |
+
self.display();
|
65 |
+
new Ajax.Updater(self.dialog.content, form.action, {
|
66 |
+
method: form.method,
|
67 |
+
parameters: form.serialize(),
|
68 |
+
evalScripts: true,
|
69 |
+
onComplete: self.onChangeCallback.bind(self)
|
70 |
+
});
|
71 |
+
},
|
72 |
+
|
73 |
+
/**
|
74 |
+
* A callback function executed after content is updated in the Wizard window.
|
75 |
+
* Calls the user-defined callback at the end.
|
76 |
+
*/
|
77 |
+
onChangeCallback: function () {
|
78 |
+
var self = this;
|
79 |
+
|
80 |
+
var content = self.dialog.getContent();
|
81 |
+
|
82 |
+
// Overwrite submit on any forms in the content
|
83 |
+
content.select('form').each(function (form) {
|
84 |
+
form.observe('submit', function (event) {
|
85 |
+
self.submit(this);
|
86 |
+
Event.stop(event);
|
87 |
+
});
|
88 |
+
});
|
89 |
+
|
90 |
+
// Call the user-defined callback
|
91 |
+
if (self.config.onChange) {
|
92 |
+
self.config.onChange(content);
|
93 |
+
}
|
94 |
+
},
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Display the Wizard window.
|
98 |
+
*/
|
99 |
+
display: function () {
|
100 |
+
var self = this;
|
101 |
+
|
102 |
+
if (self.dialog && $(self.config.id) && typeof(Windows) != 'undefined') {
|
103 |
+
Windows.focus(self.config.id);
|
104 |
+
} else {
|
105 |
+
self.dialog = Dialog.info('<div class="loading">Loading...</div>', {
|
106 |
+
id: self.config.id,
|
107 |
+
className: "magento",
|
108 |
+
windowClassName: "popup-window",
|
109 |
+
title: self.config.title,
|
110 |
+
width: 1000,
|
111 |
+
// height: 450, Height is set to auto in css, with min-height: 450px
|
112 |
+
top: 50,
|
113 |
+
zIndex: 300, // Above content, but below the AJAX spinner, which is at 500 by default
|
114 |
+
recenterAuto: true,
|
115 |
+
draggable: true,
|
116 |
+
resizable: false,
|
117 |
+
closable: true,
|
118 |
+
showEffect: Element.show,
|
119 |
+
hideEffect: Element.hide,
|
120 |
+
onClose: self.close,
|
121 |
+
options: {}
|
122 |
+
});
|
123 |
+
}
|
124 |
+
},
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Close the Wizard window.
|
128 |
+
*
|
129 |
+
* @param dialog The dialog window to close
|
130 |
+
*/
|
131 |
+
close: function(dialog) {
|
132 |
+
var self = this;
|
133 |
+
|
134 |
+
if (!dialog) {
|
135 |
+
dialog = self.dialog;
|
136 |
+
}
|
137 |
+
|
138 |
+
if (dialog) {
|
139 |
+
dialog.close();
|
140 |
+
}
|
141 |
+
|
142 |
+
// Reload the page after close as it may have changed some information on the page
|
143 |
+
window.location.reload();
|
144 |
+
}
|
145 |
+
});
|
146 |
+
|
147 |
+
window.Klevu.Search.Wizard = Wizard;
|
148 |
+
})();
|
149 |
+
|
150 |
+
function showPopup(sUrl) {
|
151 |
+
oPopup = new Window({
|
152 |
+
id:'popup_window',
|
153 |
+
className: 'magento',
|
154 |
+
url: sUrl,
|
155 |
+
title: "Klevu Search Pro Features",
|
156 |
+
width: 980,
|
157 |
+
height: 600,
|
158 |
+
minimizable: false,
|
159 |
+
maximizable: false,
|
160 |
+
showEffectOptions: {
|
161 |
+
duration: 0.4
|
162 |
+
},
|
163 |
+
hideEffectOptions:{
|
164 |
+
duration: 0.4
|
165 |
+
},
|
166 |
+
destroyOnClose: true
|
167 |
+
});
|
168 |
+
oPopup.setZIndex(100);
|
169 |
+
oPopup.showCenter(true);
|
170 |
+
}
|
171 |
+
|
172 |
+
function closePopup() {
|
173 |
+
Windows.close('popup_window');
|
174 |
+
}
|
175 |
+
|
176 |
+
function checkplan()
|
177 |
+
{
|
178 |
+
showPopup("http://www.klevu.com/magento-free-vs-pro.html");
|
179 |
+
}
|
package.xml
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>Klevu_SmartSearch</name>
|
4 |
+
<version>1.1.13</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://klevu.com">Commercial</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Klevu Search replaces the default Magento search functiontality with a intelligent, dynamic, lightning fast search provided by Klevu.</summary>
|
10 |
+
<description>Klevu Search is a search extension which takes over the Magento search box and seamlessly integrates it with the Klevu Search engine. Klevu Search offers several advantages, including:
|
11 |
+
Lightning fast search - Shoppers see instantly what they want.
|
12 |
+
Trend mining - Shoppers trends are always up in the results.
|
13 |
+
Intelligent boosting - Just select products you want to promote, no need to manually enter keywords.
|
14 |
+
Dynamic filters - Shoppers get excellent shopping experience.
|
15 |
+
Search as you type - Shoppers see results even with long keywords.
|
16 |
+
Actionable insights - Drive traffic by learning from shoppers' search patterns.</description>
|
17 |
+
<notes>- Attributes change
|
18 |
+
</notes>
|
19 |
+
<authors><author><name>Klevu</name><user>Klevu</user><email>niraj.aswani@klevu.com</email></author></authors>
|
20 |
+
<date>2015-03-11</date>
|
21 |
+
<time>12:36:01</time>
|
22 |
+
<contents><target name="mageetc"><dir name="modules"><file name="Klevu_Search.xml" hash="49674c121481f67bcfc2f31bb21e5aaf"/></dir></target><target name="magecommunity"><dir name="Klevu"><dir name="Search"><dir name="Block"><dir name="Adminhtml"><dir name="Form"><dir name="Field"><dir name="Attribute"><file name="Mappings.php" hash="293c4d19663fa3aad76c17287fec2114"/></dir><dir name="Automatic"><dir name="Attribute"><file name="Mappings.php" hash="b0d192bd03319957d09f34d510914a2f"/></dir></dir><dir name="Html"><file name="Select.php" hash="adc22272b93deb46b524f46f7000972f"/></dir><dir name="Image"><file name="Button.php" hash="bebde12b67a3fd9717e0fb3a1b489bfb"/><file name="Log.php" hash="b74aaef7b0f94f0e775d0da6491316af"/></dir><dir name="Store"><dir name="Level"><file name="Label.php" hash="c2a77e64a2decb8abd101f15b4ea3e3f"/></dir></dir><dir name="Sync"><file name="Button.php" hash="a6f8f69290f84f0ecd731585b3cca0e7"/></dir></dir><file name="Information.php" hash="b422d8aa8524b4277f2b4013e90379a0"/></dir><file name="Notifications.php" hash="9fc2511a89e04cb2c9ce86fc7c3684cd"/><dir name="Wizard"><dir name="Config"><file name="Button.php" hash="d17ba7640d5777612ab9fb27f85aa5c9"/></dir><dir name="Configure"><file name="Attributes.php" hash="3801cd4ebb45b3d29cfbacf830af2874"/><file name="Store.php" hash="a5e900bf91db47115ce54497669fd384"/><file name="User.php" hash="f353da92a383854f419333e842380273"/></dir></dir></dir><dir name="Catalog"><dir name="Product"><file name="Tracking.php" hash="a472d4caf068d12f9151d0ed282293e4"/></dir></dir></dir><dir name="Helper"><file name="Api.php" hash="72588aad499bee2c3a543a8a558a8a90"/><file name="Compat.php" hash="3726862a4576a53c5a44dda59a1e9a86"/><file name="Config.php" hash="04f3028dd50c1e6e16df2d5c2f588f47"/><file name="Data.php" hash="22e73727ba0b0f2575da81b04eb2e4c4"/></dir><dir name="Model"><dir name="Api"><dir name="Action"><file name="Addrecords.php" hash="36ee2cb10481d4b223c02e7a339482bd"/><file name="Adduser.php" hash="d8b6e6d37fe6ce522747fd6951c8e9df"/><file name="Addwebstore.php" hash="ea33f2c7032682a6ec2bdb8324cdaf0e"/><file name="Debuginfo.php" hash="dd92df091719aa73eca07a08d9681d42"/><file name="Deleterecords.php" hash="0e404db0aab2c58ff90a4e7e4fe73818"/><file name="Gettimezone.php" hash="4bb572b68f42236d765f8194e413b1ca"/><file name="Getuserdetail.php" hash="849a0f04bfdbf39ae75a2627d26717ca"/><file name="Idsearch.php" hash="9244fbdf1e67beea19c99ad0a014d0fc"/><file name="Producttracking.php" hash="50dacac910b7a68b035078771e9f8ff6"/><file name="Removetestmode.php" hash="bd2e7ecf6c233b1430e2989b2b62000f"/><file name="Startsession.php" hash="14edcef879dce92c76a9c78d4106fc6c"/><file name="Updaterecords.php" hash="9e99ce8da72a030b10e9af8353233427"/></dir><file name="Action.php" hash="792f3fe4348f7d13bdf09562ec0d8b59"/><dir name="Request"><file name="Get.php" hash="2d6f510d4dcc171b8e44322b76a49f93"/><file name="Post.php" hash="a46b484a50ced15e2c02deb16bbeb6bb"/><file name="Xml.php" hash="73b3f04d29c2bd79c470d7b81cfc0390"/></dir><file name="Request.php" hash="7f15814e8a01982499563e0e056d2d52"/><dir name="Response"><file name="Data.php" hash="9dbe8e28a501feacb07a6ce2bcc4deb8"/><file name="Empty.php" hash="5988ec43c1756cf4acfedb212787b2b9"/><file name="Invalid.php" hash="8287280c3b99f64e08cf54a0bf65e4a1"/><file name="Message.php" hash="5b6d717c75014e798e619e3df2008d29"/><file name="Search.php" hash="96b9bdef60811c4d994cb457f0d355a9"/><file name="Timezone.php" hash="ffa4d48e42fa52d2c928e202c2af61fd"/></dir><file name="Response.php" hash="b2c244001dedd653e1f0953d6bf25e0e"/></dir><dir name="Catalog"><dir name="Model"><file name="Config.php" hash="57ae55e3cea3dd1b4c60dafcb06d5efd"/></dir></dir><dir name="CatalogSearch"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="104ac92f6ef59879b593a9f1baffd562"/><file name="Category.php" hash="d30670c5ca616dcb0c3f0dd2ffbb97ba"/><file name="Price.php" hash="4ca1e56183364670fb39a88ea5666c13"/></dir></dir><dir name="Resource"><dir name="Fulltext"><file name="Collection.php" hash="b80bc1ff2e539c4ff54ba9b04a53bae6"/></dir><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="d675e50ad7c5277b9ca4100770ac16d3"/></dir></dir></dir></dir><dir name="Config"><dir name="Log"><file name="Level.php" hash="ef07b22f48c4ca72066bf90a1cf9ac27"/></dir></dir><file name="Cron.php" hash="0936cc2667e056182668c9f61fc171bc"/><file name="Notification.php" hash="771d45868668c5b925e3bf2202482b43"/><file name="Observer.php" hash="a4eedf47b7194cd56aa0b7cc069fb691"/><dir name="Order"><file name="Sync.php" hash="e8af97ae357bfa1380e9f733d88efd5c"/></dir><dir name="Product"><file name="Sync.php" hash="4f3fcd3df423aa085fe209dd51e8876e"/></dir><dir name="Resource"><dir name="Notification"><file name="Collection.php" hash="936a242678b1c89853149e9dc77b6aff"/></dir><file name="Notification.php" hash="f3206c5286bf6ccb4df268c54fcff0f5"/></dir><file name="Session.php" hash="a4ab94b093ba8a414fbfa031f0d2cabe"/><file name="Sync.php" hash="f9f6f4d1251d493944ab13f1467d5257"/><dir name="System"><dir name="Config"><dir name="Source"><dir name="Additional"><file name="Attributes.php" hash="d91e1af65488d647b035fbb100a4eb1d"/></dir><dir name="Boosting"><file name="Attribute.php" hash="52a633242ff145d8f3b74c6a573c303e"/></dir><file name="Frequency.php" hash="5866e9d92476cdaa8a5f27c5fa0dc48b"/><file name="Landingoptions.php" hash="058c81eb9faec57f6c77db697ff3279e"/><dir name="Log"><file name="Level.php" hash="ba2bee63eb18b966db6beade72293036"/></dir><dir name="Product"><file name="Attributes.php" hash="f99ced41d6504f1570a703e66743dd0b"/></dir><file name="Yesnoforced.php" hash="0cf0e7842afae56af0caf92c9490295b"/></dir></dir></dir></dir><dir name="Test"><dir name="Config"><file name="Base.php" hash="a1a8faa15e50cd1d394bc79ca94f712b"/></dir><dir name="Controller"><dir name="CatalogSearch"><dir name="fixtures"><file name="search_results.yaml" hash="29bfca0b08d91f8acc4f7114f1e40475"/></dir></dir><file name="CatalogSearch.php" hash="7f8d9583333f5ad7a383a994816aa7a5"/></dir><dir name="Helper"><file name="Api.php" hash="74864f6af98fbbf64cf2e83e0ff25389"/><file name="Compat.php" hash="8bae993e0da8f368eb50689f271446a5"/><dir name="Config"><dir name="fixtures"><file name="testGetOrderSyncEnabledFlag.yaml" hash="998fd5ff61adf624336ba054e1898754"/><file name="testGetOrderSyncFrequency.yaml" hash="52dffcad75b15761a695eb451b99c751"/><file name="testGetProductSyncEnabledFlag.yaml" hash="431cf53b919d319bee1444c88c53d399"/><file name="testGetProductSyncFrequency.yaml" hash="004e62dfa22c9abfd8dcf56c92270e19"/><file name="testIsExtensionEnabledDisabled.yaml" hash="5d706b347b4f32f87dc8eb4dd6102148"/><file name="testIsExtensionEnabledEnabled.yaml" hash="52c9eb8a4fad4d8f3ba25c68d35977f3"/></dir><dir name="providers"><file name="testIsOrderSyncEnabled.yaml" hash="8239d8d0835b3fc555ac22906acd96da"/><file name="testIsProductSyncEnabled.yaml" hash="71e7c11155746f8add52a5b3704f4113"/><file name="testIsTestModeEnabled.yaml" hash="f727b557a1a13f0e98b576e3a067690b"/></dir></dir><file name="Config.php" hash="6a29543849d2b606f20f792018124b23"/><dir name="Data"><dir name="providers"><file name="testBytesToHumanReadable.yaml" hash="7cdb8705e108715abc63fa2cfd81626b"/><file name="testGetLanguageFromLocale.yaml" hash="c301f8dc090142627f6af4e4222b7708"/><file name="testHumanReadableToBytes.yaml" hash="dd89ae5b6705cfcfbf42ba64432c0f0a"/><file name="testIsProductionDomain.yaml" hash="f88ef0f80073fdb9cbdbd020348527a7"/></dir></dir><file name="Data.php" hash="93bb38ec55380a6ec7d79008496cac34"/></dir><dir name="Model"><dir name="Api"><dir name="Action"><dir name="Addrecords"><dir name="providers"><file name="testValidateRequiredFields.yaml" hash="26eea8bfc58c60e4a2f07dcbddc2e6fd"/><file name="testValidateRequiredFieldsRecords.yaml" hash="590b7ec9b7c33debb740b8c6c6db717f"/><file name="testValidateRequiredFieldsRecordsAllowedEmpty.yaml" hash="f82933b3d219491015cef39a214543bd"/><file name="testValidateRequiredFieldsRecordsEmpty.yaml" hash="d5dcd5aad682db42b1352c35b8905d47"/><file name="testValidateRequiredFieldsRecordsOptional.yaml" hash="25092bb84ba311815ca33971a388256e"/></dir></dir><file name="Addrecords.php" hash="14f5c217fac3f82957f54916fa29b387"/><dir name="Adduser"><dir name="providers"><file name="testValidateRequiredFields.yaml" hash="841f068ff3ffd8081ccc91e8675f998c"/></dir></dir><file name="Adduser.php" hash="5189f29f08c4ed30d9b6ac83429de3d0"/><dir name="Addwebstore"><dir name="providers"><file name="testValidateRequiredFields.yaml" hash="e52324b58b76d2d63cfa83ee228e1b31"/></dir></dir><file name="Addwebstore.php" hash="fbeac1b8adc5df45ef08a0a3331e5fbc"/><dir name="Getuserdetail"><dir name="providers"><file name="testValidateRequiredFields.yaml" hash="297df49838c47536bc9ee928b27470b2"/></dir></dir><file name="Getuserdetail.php" hash="4733d1ec7fd5b3b765aa88f182adf390"/><dir name="Idsearch"><dir name="providers"><file name="testValidateRequiredFields.yaml" hash="f36c1a1a1e6d1f5a2d3a59d8d349036e"/></dir></dir><file name="Idsearch.php" hash="0f572e9621086df59e53c55054e3f9d7"/><dir name="Producttracking"><dir name="providers"><file name="testValidateRequiredFields.yaml" hash="8749e326906367a0d0c26128ca944d0b"/></dir></dir><file name="Producttracking.php" hash="c41b1cb2e23bb00d83703d5f1775d31e"/><file name="Startsession.php" hash="e952ec0fd56d4a4603f73e297fd219c4"/></dir><file name="Action.php" hash="14ce7e11eb3acfda2dfea539c8f5254b"/><dir name="Request"><dir name="Xml"><dir name="providers"><file name="testGetDataAsXml.yaml" hash="4aa16e3557481444ba39775ee0b99d29"/></dir></dir><file name="Xml.php" hash="279a5defe0c933540e9635455590d8b1"/></dir><file name="Request.php" hash="b0cbdfe6a023d0479dc1b1c7fc6869c0"/><dir name="Response"><dir name="Data"><dir name="providers"><file name="testIsSuccessful.yaml" hash="f085922f4329b3d6b19c1e0010d3ca22"/></dir></dir><file name="Data.php" hash="1ab05c7225658f54bd31f0c205d05a2b"/><file name="Empty.php" hash="9933c42aa9ff06977ca3e53d2de15857"/><file name="Invalid.php" hash="bb68f25a053b7e5fc024bce0f5286fcb"/><dir name="Message"><dir name="providers"><file name="testIsSuccessful.yaml" hash="d53562002270a0c4b58ca94733309a21"/></dir></dir><file name="Message.php" hash="135c0d136fa9d0e86158407fc59294c3"/><dir name="Timezone"><dir name="providers"><file name="testIsSuccessful.yaml" hash="67f35e7ee5081689a1eddb867ae6256d"/></dir></dir><file name="Timezone.php" hash="f9cb063ef1f506f656a25c6206899eb3"/><dir name="providers"><file name="response_testIsSuccessful.yaml" hash="ac214d5ebf1eccb89e8fa85e8e3cbb75"/></dir></dir><file name="Response.php" hash="dbcce43ccb2cdf47bce5c05fcf27e759"/><dir name="Test"><file name="Case.php" hash="ec6d3169b9e2bd26655687124be779dd"/></dir><dir name="data"><file name="data_response_data.xml" hash="cd2e5d3dcac402828b9e5f0b0b637c76"/><file name="data_response_failure.xml" hash="ba677628e68149e0283729c1c8e5e86a"/><file name="data_response_no_response.xml" hash="98944f0eda050221de59100f4b22f030"/><file name="data_response_success.xml" hash="e92d1cfcd4461dc8d3fcabe1f902b40b"/><file name="data_response_success_only.xml" hash="276055d04a3f112efe9e6f1c337d7699"/><file name="message_response_failure.xml" hash="ab63c55523b26bd53ea6abf426dd11f5"/><file name="message_response_missing_message.xml" hash="4a43490eda6f33804ca400da2f9cdac1"/><file name="message_response_missing_status.xml" hash="39103fec18a0be88e4ff00a8149c8ad4"/><file name="message_response_session_id.xml" hash="415f25f79a3795ae70b983504cbb784f"/><file name="message_response_success.xml" hash="3ac53566b3d187cb81eb04d40a195c50"/><file name="response_malformed.xml" hash="bfeb4e75829a42082a7935a8e7be491e"/><file name="response_noxml.xml" hash="2debfdcf79f03e4a65a667d21ef9de14"/><file name="response_valid.xml" hash="c915992330f0e4bd37bb629637139f98"/><file name="search_response_empty.xml" hash="601298402d21f3626052634cbbb0ae72"/><file name="search_response_paged.xml" hash="04203807a1d6df787c54afd84690a50e"/><file name="search_response_sorted.xml" hash="c3ee65658a56f65334417328c7fbdcac"/><file name="search_response_success.xml" hash="fea4e59e7ae6e68b387729e320d5f49c"/><file name="startsession_response_success.xml" hash="1865ee2da80359e5a84914c56cae2c8d"/><file name="timezone_response_no_data.xml" hash="276055d04a3f112efe9e6f1c337d7699"/><file name="timezone_response_no_status.xml" hash="bd695479b03e3607196f01f627af4a45"/><file name="timezone_response_with_failure.xml" hash="69a6b1fa7b2cf087d85be162064525b0"/><file name="timezone_response_with_success.xml" hash="e6888eca066741675d228ba1397b5554"/></dir></dir><dir name="Config"><dir name="Log"><file name="Level.php" hash="2032f568dc75c8a5ff63c7daaf8bd049"/></dir></dir><dir name="Notification"><dir name="fixtures"><file name="testLoad.yaml" hash="305afce09851bb40e8c990c138aff162"/></dir></dir><file name="Notification.php" hash="889ec647dbdb938741cfc75e1baa2bc2"/><dir name="Observer"><dir name="fixtures"><file name="testScheduleOrderSync.yaml" hash="9dc706c72f13c3dbf43add1b23d1edce"/></dir></dir><file name="Observer.php" hash="f47e6187bcc7f738f40865a5db663467"/><dir name="Order"><dir name="Sync"><dir name="fixtures"><file name="testAddOrderToQueue.yaml" hash="9fd8654cffa0c5e5ad8140825a116601"/><file name="testClearQueue.yaml" hash="2413c55c5e3f05e15668fbe7edbe0bb0"/><file name="testRun.yaml" hash="b0b694cbdbfbbd97880254841f57fcf9"/></dir></dir><file name="Sync.php" hash="d2166272904e003b6bea3862f66e0235"/></dir><dir name="Product"><dir name="Sync"><dir name="fixtures"><file name="testAddProducts.yaml" hash="3059d9bfa5e611542384f2177b693d0c"/><file name="testClearAllProducts.yaml" hash="7420a73a3db174f74f825a9267f9be96"/><file name="testDeleteProducts.yaml" hash="fdac9c823890a3308fa83564df2b2531"/><file name="testRun.yaml" hash="1890501df756f0e8813d66f5726cbbc8"/><file name="testUpdateProducts.yaml" hash="796f71e44f79c5e5bb14f8d860bcbcd5"/></dir></dir><file name="Sync.php" hash="bb0455f3b8ce4988f4da8e66d90a9ef8"/></dir><dir name="Sync"><dir name="providers"><file name="testSchedule.yaml" hash="97f1043c42eb74162ae97941dc920d8f"/></dir></dir><file name="Sync.php" hash="8c091e168e251761be7fb1d1d2149305"/><dir name="System"><dir name="Config"><dir name="Source"><dir name="Test"><dir name="providers"><file name="testIsValidSourceModel.yaml" hash="cfedc94014707ee5586dd212b4d1ee16"/></dir></dir><file name="Test.php" hash="3e915599d4f76a2fbbb20aed9ffdf968"/></dir></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Klevu"><file name="NotificationsController.php" hash="e6a8f7ee4ca5463bb9b3df5fa901b6b1"/><dir name="Search"><file name="WizardController.php" hash="5de993f8afaa30dcabbbaeb255503383"/></dir><file name="SearchController.php" hash="fc8669460e70f2a7cca27714faaf15d5"/></dir></dir><file name="SearchController.php" hash="1cd14cf045fedd2957a2bfd6de4b6080"/></dir><dir name="etc"><file name="adminhtml.xml" hash="938a66de5c0de1d096d7c0cb97e980cd"/><file name="config.xml" hash="937c87d26206813274c7f4d6090e3ef3"/><file name="system.xml" hash="26bc11cf684cc93977735cfa4bff4fa9"/></dir><dir name="sql"><dir name="klevu_search_setup"><file name="mysql4-data-upgrade-1.1.1-1.1.2.php" hash="28513b00d6ee4ac0a2bd0716484ff687"/><file name="mysql4-data-upgrade-1.1.7-1.1.8.php" hash="dd74fc5c8209647d87b5757a0fad6805"/><file name="mysql4-install-1.0.0.php" hash="860c1991c2ebf804f939598e9932edf5"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="klevu"><dir name="search"><dir name="form"><dir name="field"><file name="array_readonly.phtml" hash="d3a3be4cf22f89d84bd73121a1adfa86"/><dir name="sync"><file name="button.phtml" hash="0459f187b2b98a9ff5a9433875b465e1"/><file name="logbutton.phtml" hash="d31dd881015319d78d9fb2b83874f296"/></dir></dir><file name="information.phtml" hash="971e5e3e0823a740774164f58e00084e"/></dir><file name="notifications.phtml" hash="090714ca57b11d24769c1baa1bcd4615"/><dir name="wizard"><file name="complete.phtml" hash="aeca8d1a3335b461f5e6bcbba08c22b6"/><dir name="config"><file name="button.phtml" hash="b1644ee569882b05c2d8cb2f1eecddbc"/></dir><dir name="configure"><file name="attributes.phtml" hash="d54f0a86e78390fbe66825d0771aad25"/><file name="store.phtml" hash="1345462de285ecfe0bbe5ae8c422cbe6"/><file name="user.phtml" hash="0dfc281b7e98f3d7338ece082f2dc1ec"/></dir><dir name="form"><dir name="field"><file name="array.phtml" hash="ccdccab02fbd9cfc2145f094d5e12a2e"/></dir></dir></dir></dir></dir></dir><dir name="layout"><dir name="klevu"><file name="search.xml" hash="f385a7290bad22fb212b440afa82d2a7"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><dir name="klevu"><file name="search.xml" hash="71f813aa8775943a17220ddc3c4b9a41"/></dir></dir><dir name="template"><dir name="klevu"><dir name="search"><file name="form_js.phtml" hash="0f685e77647449b5a752a6c90b8fd4b8"/><file name="klevulog.phtml" hash="4dfa41e3747b2281e66b949ff03d46e2"/><file name="product_tracking.phtml" hash="5f81bca7273a3f1197217b6e0015083e"/></dir></dir></dir></dir></dir></dir></target><target name="mageweb"><dir name="js"><dir name="klevu"><dir name="search"><dir name="lib"><file name="Wizard.js" hash="67e9ae1996da43d6e419853a1e096419"/></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="klevu"><dir name="search"><file name="notifications.css" hash="80954cfc49bb2bc45d2eafb7c28cedad"/><file name="wizard.css" hash="824f735715f3ed97ce98414b9895e46b"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><dir name="klevu"><file name="klevu-landing-page-style.css" hash="b80caca63061ae1e1be4ec63d31b4260"/><file name="klevu-landing-responsive.css" hash="811e1bfece09ba7d5529fec850963ac6"/></dir></dir><dir name="images"><dir name="klevu"><file name="btn-gridview.png" hash="c3dd97f4f53e1dfe34b6c5b6b4237b8a"/><file name="btn-listview.png" hash="00aaaa62d67e252248d6075f53b04f7f"/><file name="ku-loader.gif" hash="6050f5bcf455cc8f0332dd65e72f8e52"/></dir></dir></dir></dir></dir></target></contents>
|
23 |
+
<compatible/>
|
24 |
+
<dependencies><required><php><min>5.3.0</min><max>5.6.0</max></php></required></dependencies>
|
25 |
+
</package>
|
skin/adminhtml/default/default/klevu/search/notifications.css
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.klevu-notification:before,
|
2 |
+
.klevu-notification:after {
|
3 |
+
content: " ";
|
4 |
+
display: table;
|
5 |
+
clear: both;
|
6 |
+
}
|
7 |
+
.klevu-notification .dismiss {
|
8 |
+
float: right;
|
9 |
+
}
|
10 |
+
|
skin/adminhtml/default/default/klevu/search/wizard.css
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#klevu_search_wizard .magento_content {
|
2 |
+
height: auto !important;
|
3 |
+
min-height: 450px;
|
4 |
+
}
|
5 |
+
|
6 |
+
#klevu_search_wizard .divider {
|
7 |
+
height: auto;
|
8 |
+
text-align: center;
|
9 |
+
font-weight: bold;
|
10 |
+
background: none;
|
11 |
+
}
|
12 |
+
|
13 |
+
#klevu_search_wizard .loading {
|
14 |
+
margin: 50px 20px;
|
15 |
+
text-align: center;
|
16 |
+
}
|
17 |
+
|
18 |
+
#klevu_search_wizard .warning {
|
19 |
+
margin: 30px 0;
|
20 |
+
}
|
21 |
+
|
22 |
+
#klevu_search_wizard #klevu_search_wizard_select_store_form .form-list {
|
23 |
+
margin: 0 auto;
|
24 |
+
}
|
25 |
+
|
26 |
+
#klevu_search_wizard p.error-msg {
|
27 |
+
min-height: 23px;
|
28 |
+
padding: 8px 8px 2px 32px;
|
29 |
+
}
|
30 |
+
|
31 |
+
#klevu_search_wizard .button-set {
|
32 |
+
margin: 10px 5px;
|
33 |
+
}
|
34 |
+
|
35 |
+
#klevu_search_wizard .button-set:before,
|
36 |
+
#klevu_search_wizard .button-set:after {
|
37 |
+
content: ' ';
|
38 |
+
display: table;
|
39 |
+
}
|
40 |
+
|
41 |
+
#klevu_search_wizard .button-set:after {
|
42 |
+
clear: both;
|
43 |
+
}
|
44 |
+
|
45 |
+
#klevu_search_wizard .button-set button,
|
46 |
+
#klevu_search_wizard .button-set a {
|
47 |
+
float: right;
|
48 |
+
margin-left: 10px;
|
49 |
+
}
|
50 |
+
|
51 |
+
#klevu_search_wizard_configure_attributes_form .fieldset div.grid {
|
52 |
+
max-height: 250px;
|
53 |
+
overflow: scroll;
|
54 |
+
}
|
55 |
+
|
56 |
+
#klevu_search_wizard_summary_form .configuration-changes {
|
57 |
+
margin: 10px 40px;
|
58 |
+
}
|
59 |
+
|
60 |
+
#klevu_search_wizard_summary_form .configuration-changes {
|
61 |
+
margin: 10px 0;
|
62 |
+
}
|
63 |
+
|
64 |
+
#klevu_search_wizard_summary_form .configuration-changes li div {
|
65 |
+
font-weight: bold;
|
66 |
+
}
|
67 |
+
|
68 |
+
#klevu_search_wizard_summary_form .configuration-changes li dl {
|
69 |
+
margin-left: 20px;
|
70 |
+
}
|
71 |
+
|
72 |
+
#klevu_search_wizard_summary_form .configuration-changes li dt,
|
73 |
+
#klevu_search_wizard_summary_form .configuration-changes li dd {
|
74 |
+
float: left;
|
75 |
+
}
|
76 |
+
|
77 |
+
#klevu_search_wizard_summary_form .configuration-changes li dt {
|
78 |
+
clear: left;
|
79 |
+
width: 150px;
|
80 |
+
}
|
81 |
+
|
82 |
+
#klevu_search_wizard_summary_form .configuration-changes dl:before,
|
83 |
+
#klevu_search_wizard_summary_form .configuration-changes dl:after {
|
84 |
+
content: " ";
|
85 |
+
display: table;
|
86 |
+
clear: both;
|
87 |
+
}
|
88 |
+
|
89 |
+
.klevu_signup_form td.label{
|
90 |
+
width: 130px !important;
|
91 |
+
}
|
92 |
+
|
93 |
+
.klevu_signup_form td.label label{
|
94 |
+
width: 130px !important;
|
95 |
+
}
|
96 |
+
|
97 |
+
.klevu_signup_form #countyCode{
|
98 |
+
width:74px;
|
99 |
+
text-align:right;
|
100 |
+
}
|
101 |
+
|
102 |
+
.klevu_signup_form #contactNo{
|
103 |
+
width:190px;
|
104 |
+
text-align:right;
|
105 |
+
}
|
skin/frontend/base/default/css/klevu/klevu-landing-page-style.css
ADDED
@@ -0,0 +1,618 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* CSS of Klevu Search Result Landing Page */
|
2 |
+
|
3 |
+
/* klevu container for fix width layout*/
|
4 |
+
|
5 |
+
.kuContainer{
|
6 |
+
width:100%;
|
7 |
+
margin:0 auto;
|
8 |
+
font-family:inherit;
|
9 |
+
font-size:12px;
|
10 |
+
}
|
11 |
+
|
12 |
+
/* klevu container for fluid layout*/
|
13 |
+
.kuProListing{
|
14 |
+
margin-top:20px;
|
15 |
+
margin-bottom:20px;
|
16 |
+
}
|
17 |
+
|
18 |
+
/* klevu filters */
|
19 |
+
.kuFilters{
|
20 |
+
float:left;
|
21 |
+
width:23%;
|
22 |
+
border:1px solid #ddd;
|
23 |
+
}
|
24 |
+
|
25 |
+
/* set the height of each filter*/
|
26 |
+
.kuFilterBox{
|
27 |
+
height:150px;
|
28 |
+
overflow:hidden;
|
29 |
+
}
|
30 |
+
|
31 |
+
/* heading of filters i.e brand, color */
|
32 |
+
.kuFilterHead{
|
33 |
+
padding: 8px;
|
34 |
+
font-weight: bold;
|
35 |
+
font-size: 12px;
|
36 |
+
text-align: left;
|
37 |
+
background-color: #eee;
|
38 |
+
border-bottom: 1px solid #ddd;
|
39 |
+
}
|
40 |
+
|
41 |
+
/* down arrow div in filters */
|
42 |
+
.kuShowOpt{
|
43 |
+
text-align:center;
|
44 |
+
padding:3px;
|
45 |
+
position:relative;
|
46 |
+
}
|
47 |
+
|
48 |
+
/* up arrow div in filters */
|
49 |
+
.kuHideOpt{
|
50 |
+
text-align:center;
|
51 |
+
padding:3px;
|
52 |
+
}
|
53 |
+
|
54 |
+
.kuShowOpt img, .kuHideOpt img{
|
55 |
+
width:auto !important;
|
56 |
+
display:inline-block !important;
|
57 |
+
}
|
58 |
+
|
59 |
+
/* down & up arrow link color in filters */
|
60 |
+
.kuShowOpt a,.kuHideOpt a{
|
61 |
+
color:#4d7abf;
|
62 |
+
text-decoration:none;
|
63 |
+
}
|
64 |
+
|
65 |
+
/* set list for filters */
|
66 |
+
.kuFilterNames ul{
|
67 |
+
margin:0px;
|
68 |
+
padding:0px;
|
69 |
+
margin-top:10px;
|
70 |
+
margin-left:0px !important;
|
71 |
+
}
|
72 |
+
|
73 |
+
/* style for each values in filter */
|
74 |
+
.kuFilterNames ul li{
|
75 |
+
list-style:none;
|
76 |
+
text-align:left;
|
77 |
+
width:99%;
|
78 |
+
display:inline-table;
|
79 |
+
margin:0px;
|
80 |
+
padding-left:0px;
|
81 |
+
margin-left:0px !important;
|
82 |
+
}
|
83 |
+
|
84 |
+
.kuFilterNames ul li a{
|
85 |
+
display: block;
|
86 |
+
position: relative;
|
87 |
+
overflow: hidden;
|
88 |
+
margin: 0 5px;
|
89 |
+
line-height:24px;
|
90 |
+
padding-left: 5px;
|
91 |
+
padding-right: 5px;
|
92 |
+
font-size: 13px;
|
93 |
+
text-decoration: none;
|
94 |
+
cursor: pointer;
|
95 |
+
font-style:normal;
|
96 |
+
}
|
97 |
+
|
98 |
+
/* set background color on hover of filter */
|
99 |
+
.kuFilterNames ul li a:hover{
|
100 |
+
background-color:#eee;
|
101 |
+
cursor: pointer;
|
102 |
+
}
|
103 |
+
|
104 |
+
/* set background color for selected filter */
|
105 |
+
.kuFilterNames ul li.kuSelected a{
|
106 |
+
background-color:#616161;
|
107 |
+
color: #fff;
|
108 |
+
}
|
109 |
+
|
110 |
+
/* label for the filter */
|
111 |
+
.kuFilterNames ul li a span.kuFilterLabel{
|
112 |
+
float:left;
|
113 |
+
width:86%;
|
114 |
+
margin:0px;
|
115 |
+
padding:0px;
|
116 |
+
font-weight:normal;
|
117 |
+
}
|
118 |
+
|
119 |
+
/* total nos of results available for filter */
|
120 |
+
.kuFilterNames ul li a span.kuFilterTotal{
|
121 |
+
float:right;
|
122 |
+
width:13%;
|
123 |
+
text-align:right;
|
124 |
+
}
|
125 |
+
|
126 |
+
/* shows cancel button if filter is selected */
|
127 |
+
.kuFilterNames ul li a span.kuFilterCancel{
|
128 |
+
float:right;
|
129 |
+
width:13%;
|
130 |
+
text-align:right;
|
131 |
+
font-size:10px;
|
132 |
+
}
|
133 |
+
|
134 |
+
/* klevu results box */
|
135 |
+
.kuResultList{
|
136 |
+
float:right;
|
137 |
+
width:75%;
|
138 |
+
}
|
139 |
+
|
140 |
+
/* div for Sorting, pagination, change result view icons*/
|
141 |
+
.kuSortHeader{
|
142 |
+
padding:10px;
|
143 |
+
margin:5px;
|
144 |
+
padding-top: 0px;
|
145 |
+
margin-top: 0px;
|
146 |
+
}
|
147 |
+
|
148 |
+
/* div to display total no of results */
|
149 |
+
.kuTotResults{
|
150 |
+
text-align:left;
|
151 |
+
margin-bottom:10px;
|
152 |
+
line-height:24px;
|
153 |
+
font-weight:bold;
|
154 |
+
font-size:14px;
|
155 |
+
}
|
156 |
+
|
157 |
+
.kuSortingOpt{
|
158 |
+
background-color:#eee;
|
159 |
+
border:1px solid #ddd;
|
160 |
+
padding:5px;
|
161 |
+
}
|
162 |
+
|
163 |
+
/* div to display sorting dropdown */
|
164 |
+
.kuSortby{
|
165 |
+
float:left;
|
166 |
+
width:25%;
|
167 |
+
}
|
168 |
+
|
169 |
+
/* label of sorting dropdown */
|
170 |
+
.kuSortby label{
|
171 |
+
display:inline;
|
172 |
+
}
|
173 |
+
|
174 |
+
/* sorting dropdown */
|
175 |
+
.kuSortby select{
|
176 |
+
display:inline;
|
177 |
+
height:25px;
|
178 |
+
width:100px;
|
179 |
+
}
|
180 |
+
|
181 |
+
/* div to display icons to change the view of result (grid/view) */
|
182 |
+
.kuView{
|
183 |
+
float:left;
|
184 |
+
width:15%;
|
185 |
+
text-align:center;
|
186 |
+
}
|
187 |
+
|
188 |
+
/* display GRID view icon */
|
189 |
+
.kuView .kuGridviewBtn{
|
190 |
+
background: #ededed url(../../images/klevu/btn-gridview.png) no-repeat 0 0;
|
191 |
+
cursor:pointer;
|
192 |
+
}
|
193 |
+
|
194 |
+
/* display LIST view icon */
|
195 |
+
.kuView .kuListviewBtn{
|
196 |
+
background: #ededed url(../../images/klevu/btn-listview.png) no-repeat 0 0;
|
197 |
+
cursor:pointer;
|
198 |
+
}
|
199 |
+
|
200 |
+
/* set width and height of view icons box*/
|
201 |
+
.kuView a{
|
202 |
+
display: inline-block;
|
203 |
+
border: 1px solid #D9D9D9;
|
204 |
+
width: 44px;
|
205 |
+
height: 27px;
|
206 |
+
margin-right: -4px;
|
207 |
+
text-align: center;
|
208 |
+
vertical-align: middle;
|
209 |
+
overflow: hidden;
|
210 |
+
}
|
211 |
+
|
212 |
+
/* changing background position on hover of GRID/LIST view icons */
|
213 |
+
.kuView a:hover{
|
214 |
+
border-color: #BBB;
|
215 |
+
background-position:0 -30px;
|
216 |
+
text-decoration: none;
|
217 |
+
}
|
218 |
+
|
219 |
+
/* change background position to set current view */
|
220 |
+
.kuView a.kuCurrent{
|
221 |
+
background-position:0 -60px;
|
222 |
+
border-color: #BBB;
|
223 |
+
}
|
224 |
+
|
225 |
+
/* dropdown to select no of results per page*/
|
226 |
+
.kuPerPage{
|
227 |
+
float:left;
|
228 |
+
width:23%;
|
229 |
+
margin-left:10px;
|
230 |
+
text-align:right;
|
231 |
+
}
|
232 |
+
|
233 |
+
.kuPerPage select{
|
234 |
+
width:54px !important;
|
235 |
+
height:25px;
|
236 |
+
}
|
237 |
+
|
238 |
+
/* div for pagination */
|
239 |
+
.kuPagination{
|
240 |
+
width:33%;
|
241 |
+
float:left;
|
242 |
+
margin-left:10px;
|
243 |
+
text-align:right;
|
244 |
+
}
|
245 |
+
|
246 |
+
/* style to display page nos in line */
|
247 |
+
.kuPagination a{
|
248 |
+
border: 1px solid #ddd;
|
249 |
+
margin:0px;
|
250 |
+
position: relative;
|
251 |
+
display: inline-block;
|
252 |
+
background:#eee;
|
253 |
+
padding:4px;
|
254 |
+
padding-left:8px;
|
255 |
+
padding-right:8px;
|
256 |
+
color: #444;
|
257 |
+
cursor: pointer;
|
258 |
+
text-decoration:none;
|
259 |
+
}
|
260 |
+
|
261 |
+
/* style on hover of page links */
|
262 |
+
.kuPagination a:hover{
|
263 |
+
background: #dadada;
|
264 |
+
}
|
265 |
+
|
266 |
+
/* style to show current page */
|
267 |
+
.kuPagination a.kuCurrent{
|
268 |
+
background: #fff;
|
269 |
+
-webkit-box-shadow:none;
|
270 |
+
-moz-box-shadow:none;
|
271 |
+
box-shadow:none;
|
272 |
+
border:1px solid #ddd;
|
273 |
+
font-weight:bold;
|
274 |
+
}
|
275 |
+
|
276 |
+
.kuClearLeft{
|
277 |
+
clear:left;
|
278 |
+
line-height:0px;
|
279 |
+
}
|
280 |
+
|
281 |
+
|
282 |
+
/* klevu results div */
|
283 |
+
.kuResults{
|
284 |
+
margin-top:10px;
|
285 |
+
}
|
286 |
+
|
287 |
+
/* styles for list view results */
|
288 |
+
.kuListView{
|
289 |
+
margin-top:10px;
|
290 |
+
}
|
291 |
+
|
292 |
+
.kuListView ul{
|
293 |
+
margin:0px;
|
294 |
+
padding:0px;
|
295 |
+
}
|
296 |
+
|
297 |
+
/* In LISTVIEW: list style for each result */
|
298 |
+
.kuListView ul li{
|
299 |
+
display:block;
|
300 |
+
width: 100%;
|
301 |
+
height: auto;
|
302 |
+
padding: 10px;
|
303 |
+
border-bottom: 1px solid #eee;
|
304 |
+
text-align:left;
|
305 |
+
}
|
306 |
+
|
307 |
+
/* In LISTVIEW: for wrapping the image in fixed size div */
|
308 |
+
.kuListView .klevuImgWrap{
|
309 |
+
float:left;
|
310 |
+
overflow:hidden;
|
311 |
+
width:15% !important;
|
312 |
+
height:120px !important;
|
313 |
+
text-align:center;
|
314 |
+
}
|
315 |
+
|
316 |
+
/* In GRIDVIEW: thumbnail of the product */
|
317 |
+
.kuListView img{
|
318 |
+
max-width:100% !important;
|
319 |
+
max-height:120px !important;
|
320 |
+
width:auto;
|
321 |
+
height:auto;
|
322 |
+
border:none;
|
323 |
+
outline:none;
|
324 |
+
}
|
325 |
+
|
326 |
+
/* In LISTVIEW: display product name and description */
|
327 |
+
.kuListView ul li .kuNameDesc{
|
328 |
+
float:left;
|
329 |
+
width:65%;
|
330 |
+
margin-left:5px;
|
331 |
+
}
|
332 |
+
|
333 |
+
.kuListView ul li .kuName{
|
334 |
+
padding:5px;
|
335 |
+
}
|
336 |
+
|
337 |
+
.kuListView ul li .kuDesc{
|
338 |
+
line-height:20px;
|
339 |
+
padding:5px;
|
340 |
+
font-style:normal;
|
341 |
+
}
|
342 |
+
|
343 |
+
/* In LISTVIEW: set product name color and font size */
|
344 |
+
.kuListView ul li .kuName a{
|
345 |
+
font-size:14px;
|
346 |
+
text-decoration:none;
|
347 |
+
color:inherit;
|
348 |
+
font-weight:bold;
|
349 |
+
font-style:normal;
|
350 |
+
}
|
351 |
+
|
352 |
+
.kuListView ul li .kuName a:hover{
|
353 |
+
text-decoration:underline;
|
354 |
+
}
|
355 |
+
|
356 |
+
/* In LISTVIEW: div to display saleprice and original price */
|
357 |
+
.kuListView ul li .kuPrice{
|
358 |
+
float:left;
|
359 |
+
width:15%;
|
360 |
+
margin-top:5px;
|
361 |
+
margin-bottom:5px;
|
362 |
+
padding:5px;
|
363 |
+
text-align:center;
|
364 |
+
}
|
365 |
+
|
366 |
+
/* In LISTVIEW: div to display saleprice */
|
367 |
+
.kuListView ul li .kuSalePrice{
|
368 |
+
font-weight:bold;
|
369 |
+
font-size:14px;
|
370 |
+
margin-bottom:5px;
|
371 |
+
}
|
372 |
+
|
373 |
+
/* In LISTVIEW: div to display original price with line-through style */
|
374 |
+
.kuListView ul li .kuOrigPrice{
|
375 |
+
font-size:13px;
|
376 |
+
text-decoration:line-through;
|
377 |
+
}
|
378 |
+
|
379 |
+
/* In LISTVIEW: set color to highlight search keyowrd in name and description */
|
380 |
+
.kuListView ul li strong{
|
381 |
+
color:#2980B9;
|
382 |
+
}
|
383 |
+
|
384 |
+
/* styles for grid view results */
|
385 |
+
.kuGridView{
|
386 |
+
margin-top:10px;
|
387 |
+
}
|
388 |
+
|
389 |
+
.kuGridView ul{
|
390 |
+
margin:0px;
|
391 |
+
padding:0px;
|
392 |
+
margin-left:0px;
|
393 |
+
}
|
394 |
+
|
395 |
+
/* In GRIDVIEW: list style for each result */
|
396 |
+
.kuGridView ul li{
|
397 |
+
display: inline-block;
|
398 |
+
width: 24%;
|
399 |
+
min-height: 275px;
|
400 |
+
padding: 0;
|
401 |
+
vertical-align: top;
|
402 |
+
border-top: 1px solid #ddd;
|
403 |
+
text-align:center;
|
404 |
+
margin:2px;
|
405 |
+
padding-top:15px;
|
406 |
+
margin-left:0px !important;
|
407 |
+
font-style:normal;
|
408 |
+
}
|
409 |
+
|
410 |
+
.kuGridView ul li:nth-child(1),.kuGridView ul li:nth-child(2),.kuGridView ul li:nth-child(3),.kuGridView ul li:nth-child(4){
|
411 |
+
border-top:none;
|
412 |
+
}
|
413 |
+
|
414 |
+
/* In GRIDVIEW: for wrapping the image in fixed size div */
|
415 |
+
.kuGridView .klevuImgWrap{
|
416 |
+
float:none;
|
417 |
+
overflow:hidden;
|
418 |
+
padding:5px;
|
419 |
+
width:90% !important;
|
420 |
+
height:140px !important;
|
421 |
+
text-align:center;
|
422 |
+
margin:0 auto;
|
423 |
+
}
|
424 |
+
|
425 |
+
/* In GRIDVIEW: thumbnail of the product */
|
426 |
+
.kuGridView img{
|
427 |
+
max-width:100% !important;
|
428 |
+
height:140px !important;
|
429 |
+
width:auto;
|
430 |
+
border:none;
|
431 |
+
outline:none;
|
432 |
+
display:inline-block !important;
|
433 |
+
}
|
434 |
+
|
435 |
+
/* In GRIDVIEW: remove float value for name and description div */
|
436 |
+
.kuGridView .kuNameDesc{
|
437 |
+
float:none;
|
438 |
+
}
|
439 |
+
|
440 |
+
/* In GRIDVIEW: discription is not displayed in grid layout*/
|
441 |
+
.kuGridView .kuDesc{
|
442 |
+
display:none;
|
443 |
+
}
|
444 |
+
|
445 |
+
.kuGridView ul li .kuName{
|
446 |
+
padding:5px;
|
447 |
+
min-height:45px;
|
448 |
+
}
|
449 |
+
|
450 |
+
|
451 |
+
/* CSS for add to cart button */
|
452 |
+
.kuGridView ul li .kuAddtocart{
|
453 |
+
display:block;
|
454 |
+
height:20px;
|
455 |
+
margin-top:20px;
|
456 |
+
}
|
457 |
+
|
458 |
+
.kuGridView ul li input[type="text"]{
|
459 |
+
display:inline-block;
|
460 |
+
width:25%;
|
461 |
+
float:left;
|
462 |
+
height:22px;
|
463 |
+
border:1px solid #ddd;
|
464 |
+
outline:none;
|
465 |
+
text-align:right;
|
466 |
+
}
|
467 |
+
|
468 |
+
.kuGridView ul li a.kuAddtocartBtn{
|
469 |
+
display:inline-block;
|
470 |
+
background: #616161;
|
471 |
+
float:right;
|
472 |
+
color: #fff;
|
473 |
+
width:72%;
|
474 |
+
padding-top:6px;
|
475 |
+
padding-bottom:6px;
|
476 |
+
margin-bottom: 0;
|
477 |
+
text-align: center;
|
478 |
+
vertical-align: middle;
|
479 |
+
cursor: pointer;
|
480 |
+
white-space: nowrap;
|
481 |
+
-webkit-user-select: none;
|
482 |
+
-moz-user-select: none;
|
483 |
+
-ms-user-select: none;
|
484 |
+
-o-user-select: none;
|
485 |
+
text-decoration:none;
|
486 |
+
|
487 |
+
}
|
488 |
+
|
489 |
+
.kuListView ul li .klevu-addtocart{
|
490 |
+
float:right;
|
491 |
+
display:block;
|
492 |
+
width:15%;
|
493 |
+
height:20px;
|
494 |
+
margin-top:20px;
|
495 |
+
text-align:center;
|
496 |
+
}
|
497 |
+
|
498 |
+
|
499 |
+
.kuListView ul li input[type="text"]{
|
500 |
+
width:5%;
|
501 |
+
float:none;
|
502 |
+
height:22px;
|
503 |
+
border:1px solid #ddd;
|
504 |
+
outline:none;
|
505 |
+
text-align:right;
|
506 |
+
}
|
507 |
+
|
508 |
+
.kuListView ul li a.kuAddtocartBtn{
|
509 |
+
background: #616161;
|
510 |
+
float:none;
|
511 |
+
color: #fff;
|
512 |
+
width:15%;
|
513 |
+
padding-top:6px;
|
514 |
+
padding-bottom:6px;
|
515 |
+
padding:6px;
|
516 |
+
margin-bottom: 0;
|
517 |
+
text-align: center;
|
518 |
+
vertical-align: middle;
|
519 |
+
cursor: pointer;
|
520 |
+
white-space: nowrap;
|
521 |
+
-webkit-user-select: none;
|
522 |
+
-moz-user-select: none;
|
523 |
+
-ms-user-select: none;
|
524 |
+
-o-user-select: none;
|
525 |
+
text-decoration:none;
|
526 |
+
|
527 |
+
}
|
528 |
+
|
529 |
+
|
530 |
+
/* In GRIDVIEW: set product name color and font size */
|
531 |
+
.kuGridView ul li .kuName a{
|
532 |
+
font-size:13px;
|
533 |
+
text-decoration:none;
|
534 |
+
color:inherit;
|
535 |
+
font-style:normal;
|
536 |
+
}
|
537 |
+
|
538 |
+
.kuGridView ul li .kuName a:hover{
|
539 |
+
text-decoration:underline;
|
540 |
+
}
|
541 |
+
|
542 |
+
/* In GRIDVIEW: div to display saleprice and original price */
|
543 |
+
.kuGridView ul li .kuPrice{
|
544 |
+
float:none;
|
545 |
+
margin-top:5px;
|
546 |
+
margin-bottom:5px;
|
547 |
+
padding:5px;
|
548 |
+
}
|
549 |
+
|
550 |
+
/* In GRIDVIEW: div to display saleprice */
|
551 |
+
.kuGridView ul li .kuSalePrice{
|
552 |
+
font-weight:bold;
|
553 |
+
font-size:14px;
|
554 |
+
margin-bottom:5px;
|
555 |
+
}
|
556 |
+
|
557 |
+
/* In GRIDVIEW: div to display original price with line-through style */
|
558 |
+
.kuGridView ul li .kuOrigPrice{
|
559 |
+
font-size:13px;
|
560 |
+
text-decoration:line-through;
|
561 |
+
}
|
562 |
+
|
563 |
+
/* In GRIDVIEW: set color to highlight search keyowrd in name and description */
|
564 |
+
.kuGridView ul li strong{
|
565 |
+
color:#2980B9;
|
566 |
+
}
|
567 |
+
|
568 |
+
|
569 |
+
/* pagination links at bottom of results */
|
570 |
+
.kuBottomPagi{
|
571 |
+
padding:5px;
|
572 |
+
background-color:#eee;
|
573 |
+
border:1px solid #ddd;
|
574 |
+
}
|
575 |
+
|
576 |
+
.kuBottomPagi .kuPerPage{
|
577 |
+
margin-left:0px;
|
578 |
+
text-align: left;
|
579 |
+
}
|
580 |
+
|
581 |
+
.kuBottomPagi .kuPagination{
|
582 |
+
width: 50%;
|
583 |
+
float: right;
|
584 |
+
margin-left: 10px;
|
585 |
+
}
|
586 |
+
|
587 |
+
.kuPagination a{
|
588 |
+
font-style:normal;
|
589 |
+
}
|
590 |
+
|
591 |
+
.kuClearBoth{
|
592 |
+
clear:both;
|
593 |
+
}
|
594 |
+
|
595 |
+
/* div to display No records found message */
|
596 |
+
.kuNoRecordFound{
|
597 |
+
text-align:center;
|
598 |
+
margin-top:10%;
|
599 |
+
margin-bottom:10%;
|
600 |
+
}
|
601 |
+
|
602 |
+
/* show variants */
|
603 |
+
.kuVariants{
|
604 |
+
font-size: 9px;
|
605 |
+
text-align: center;
|
606 |
+
margin-top:2px;
|
607 |
+
}
|
608 |
+
|
609 |
+
/* height for loader div */
|
610 |
+
#loader{
|
611 |
+
height:400px;
|
612 |
+
}
|
613 |
+
|
614 |
+
#loader img{
|
615 |
+
margin-top:10%;
|
616 |
+
display: inline-block;
|
617 |
+
width:auto !important;
|
618 |
+
}
|
skin/frontend/base/default/css/klevu/klevu-landing-responsive.css
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.kuContainer{
|
2 |
+
width:100% !important;
|
3 |
+
}
|
4 |
+
|
5 |
+
@media only screen and (max-width: 1024px) {
|
6 |
+
.kuSortby{
|
7 |
+
width:45%;
|
8 |
+
}
|
9 |
+
|
10 |
+
.kuView{
|
11 |
+
width:50%;
|
12 |
+
text-align:right;
|
13 |
+
}
|
14 |
+
|
15 |
+
.kuPerPage{
|
16 |
+
width:45%;
|
17 |
+
text-align:left;
|
18 |
+
margin-left:0px;
|
19 |
+
margin-top:10px;
|
20 |
+
}
|
21 |
+
|
22 |
+
.kuPagination{
|
23 |
+
width:50%;
|
24 |
+
margin-top:10px;
|
25 |
+
}
|
26 |
+
|
27 |
+
.kuGridView ul li{
|
28 |
+
width:31%;
|
29 |
+
}
|
30 |
+
|
31 |
+
.kuListView ul li .kuNameDesc{
|
32 |
+
width:80%;
|
33 |
+
}
|
34 |
+
|
35 |
+
.kuListView ul li .kuPrice{
|
36 |
+
float:none !important;
|
37 |
+
width:100%;
|
38 |
+
}
|
39 |
+
|
40 |
+
.kuListView ul li .kuPrice .kuSalePrice{
|
41 |
+
display:inline !important;
|
42 |
+
}
|
43 |
+
|
44 |
+
.kuListView ul li .kuPrice .kuOrigPrice{
|
45 |
+
display:inline !important;
|
46 |
+
}
|
47 |
+
|
48 |
+
.kuGridView ul li:nth-child(4){
|
49 |
+
border-top:1px solid #ddd;
|
50 |
+
}
|
51 |
+
|
52 |
+
}
|
53 |
+
|
54 |
+
@media only screen and (min-width: 641px) and (max-width: 768px) {
|
55 |
+
.kuResultList{
|
56 |
+
width:74%;
|
57 |
+
}
|
58 |
+
|
59 |
+
.kuGridView ul li{
|
60 |
+
width:31%;
|
61 |
+
}
|
62 |
+
|
63 |
+
.kuGridView ul li:nth-child(4){
|
64 |
+
border-top:1px solid #ddd;
|
65 |
+
}
|
66 |
+
|
67 |
+
}
|
68 |
+
|
69 |
+
@media only screen and (max-width: 640px) {
|
70 |
+
.kuFilters{
|
71 |
+
display:none !important;
|
72 |
+
}
|
73 |
+
|
74 |
+
.kuResultList{
|
75 |
+
float:none;
|
76 |
+
width:100%;
|
77 |
+
margin-left:0px;
|
78 |
+
}
|
79 |
+
|
80 |
+
.kuSortby{
|
81 |
+
width:50%;
|
82 |
+
height:50px;
|
83 |
+
}
|
84 |
+
|
85 |
+
.kuSortHeader{
|
86 |
+
margin:0px;
|
87 |
+
}
|
88 |
+
|
89 |
+
.kuView{
|
90 |
+
width:50%;
|
91 |
+
text-align:right;
|
92 |
+
height:50px;
|
93 |
+
}
|
94 |
+
|
95 |
+
.kuPerPage{
|
96 |
+
width:35%;
|
97 |
+
text-align:left;
|
98 |
+
margin:0 auto;
|
99 |
+
margin-top:0px;
|
100 |
+
}
|
101 |
+
|
102 |
+
.kuPagination{
|
103 |
+
width:65%;
|
104 |
+
margin:0 auto;
|
105 |
+
margin-top:0px;
|
106 |
+
text-align:right;
|
107 |
+
}
|
108 |
+
|
109 |
+
.kuGridView ul li{
|
110 |
+
width:31%;
|
111 |
+
}
|
112 |
+
|
113 |
+
.kuGridView ul li:nth-child(3){
|
114 |
+
border-top:none;
|
115 |
+
}
|
116 |
+
|
117 |
+
.kuGridView ul li:nth-child(4){
|
118 |
+
border-top:1px solid #ddd;
|
119 |
+
}
|
120 |
+
|
121 |
+
.kuBottomPagi .kuPerPage{
|
122 |
+
margin-left:0px;
|
123 |
+
text-align: center;
|
124 |
+
margin-bottom:5px;
|
125 |
+
}
|
126 |
+
|
127 |
+
.kuBottomPagi .kuPagination{
|
128 |
+
width: 100%;
|
129 |
+
float: none;
|
130 |
+
}
|
131 |
+
|
132 |
+
}
|
133 |
+
|
134 |
+
@media only screen and (max-width: 480px) {
|
135 |
+
.kuGridView ul li{
|
136 |
+
width:47%;
|
137 |
+
}
|
138 |
+
|
139 |
+
.kuGridView ul li:nth-child(3),.kuGridView ul li:nth-child(4){
|
140 |
+
border-top:1px solid #ddd;
|
141 |
+
}
|
142 |
+
}
|
skin/frontend/base/default/images/klevu/btn-gridview.png
ADDED
Binary file
|
skin/frontend/base/default/images/klevu/btn-listview.png
ADDED
Binary file
|
skin/frontend/base/default/images/klevu/ku-loader.gif
ADDED
Binary file
|