Version Notes
Bringing Live Indexing up to stable state
Download this release
Release Info
Developer | SearchSpring Development Team |
Extension | SearchSpring_Manager |
Version | 1.1.0 |
Comparing to | |
See all releases |
Version 1.1.0
- app/code/community/SearchSpring/ErrorCodes.php +46 -0
- app/code/community/SearchSpring/Manager/Block/Layer/Filter/SearchSpringCategory.php +37 -0
- app/code/community/SearchSpring/Manager/Block/Layer/Filter/SearchSpringList.php +41 -0
- app/code/community/SearchSpring/Manager/Block/Layer/View.php +186 -0
- app/code/community/SearchSpring/Manager/Builder/OperationBuilder.php +196 -0
- app/code/community/SearchSpring/Manager/Collection.php +60 -0
- app/code/community/SearchSpring/Manager/Entity/IndexingRequestBody.php +91 -0
- app/code/community/SearchSpring/Manager/Entity/OperationsCollection.php +17 -0
- app/code/community/SearchSpring/Manager/Entity/RecordsCollection.php +142 -0
- app/code/community/SearchSpring/Manager/Entity/RequestBody.php +16 -0
- app/code/community/SearchSpring/Manager/Entity/RequestParams.php +81 -0
- app/code/community/SearchSpring/Manager/Entity/SearchCollection.php +138 -0
- app/code/community/SearchSpring/Manager/Entity/SearchRequestBody.php +131 -0
- app/code/community/SearchSpring/Manager/Entity/SearchResult.php +69 -0
- app/code/community/SearchSpring/Manager/Entity/SearchResult/Result.php +37 -0
- app/code/community/SearchSpring/Manager/Factory/ApiFactory.php +70 -0
- app/code/community/SearchSpring/Manager/Factory/GeneratorFactory.php +222 -0
- app/code/community/SearchSpring/Manager/Factory/IndexingRequestBodyFactory.php +38 -0
- app/code/community/SearchSpring/Manager/Factory/PricingFactory.php +53 -0
- app/code/community/SearchSpring/Manager/Factory/SearchRequestBodyFactory.php +22 -0
- app/code/community/SearchSpring/Manager/Generator/ProductGenerator.php +68 -0
- app/code/community/SearchSpring/Manager/Handler/ApiErrorHandler.php +90 -0
- app/code/community/SearchSpring/Manager/Helper/Data.php +117 -0
- app/code/community/SearchSpring/Manager/Iterator.php +21 -0
- app/code/community/SearchSpring/Manager/Model/Catalog/Category/Attribute/EnableSearchSpring/Backend.php +26 -0
- app/code/community/SearchSpring/Manager/Model/Catalog/Category/Attribute/EnableSearchSpring/Source.php +18 -0
- app/code/community/SearchSpring/Manager/Model/Layer.php +65 -0
- app/code/community/SearchSpring/Manager/Model/Layer/Filter/SearchSpring.php +131 -0
- app/code/community/SearchSpring/Manager/Model/Layer/Filter/SearchSpringCategory.php +109 -0
- app/code/community/SearchSpring/Manager/Model/Layer/Filter/SearchSpringCategoryItem.php +29 -0
- app/code/community/SearchSpring/Manager/Model/Layer/Filter/SearchSpringItem.php +126 -0
- app/code/community/SearchSpring/Manager/Model/Observer/CategorySaveObserver.php +202 -0
- app/code/community/SearchSpring/Manager/Model/Observer/LiveIndexer.php +26 -0
- app/code/community/SearchSpring/Manager/Model/Observer/ProductSaveObserver.php +186 -0
- app/code/community/SearchSpring/Manager/Operation/Product.php +121 -0
- app/code/community/SearchSpring/Manager/Operation/Product/SetCategories.php +125 -0
- app/code/community/SearchSpring/Manager/Operation/Product/SetCoreFields.php +169 -0
- app/code/community/SearchSpring/Manager/Operation/Product/SetFields.php +78 -0
- app/code/community/SearchSpring/Manager/Operation/Product/SetId.php +30 -0
- app/code/community/SearchSpring/Manager/Operation/Product/SetImages.php +90 -0
- app/code/community/SearchSpring/Manager/Operation/Product/SetOptions.php +47 -0
- app/code/community/SearchSpring/Manager/Operation/Product/SetPricing.php +79 -0
- app/code/community/SearchSpring/Manager/Operation/Product/SetRatings.php +56 -0
- app/code/community/SearchSpring/Manager/Operation/ProductOperation.php +41 -0
- app/code/community/SearchSpring/Manager/Provider/ProductCollection/FeedProvider.php +99 -0
- app/code/community/SearchSpring/Manager/Provider/ProductCollection/ProductProvider.php +101 -0
- app/code/community/SearchSpring/Manager/Provider/ProductCollectionProvider.php +28 -0
- app/code/community/SearchSpring/Manager/Request/JSON.php +56 -0
- app/code/community/SearchSpring/Manager/Service/SearchSpring/ApiAdapter.php +77 -0
- app/code/community/SearchSpring/Manager/Service/SearchSpring/IndexingApiAdapter.php +64 -0
- app/code/community/SearchSpring/Manager/Service/SearchSpring/SearchApiAdapter.php +72 -0
- app/code/community/SearchSpring/Manager/Strategy/Pricing/BundleStrategy.php +69 -0
- app/code/community/SearchSpring/Manager/Strategy/Pricing/ConfigurableStrategy.php +29 -0
- app/code/community/SearchSpring/Manager/Strategy/Pricing/GroupedStrategy.php +47 -0
- app/code/community/SearchSpring/Manager/Strategy/Pricing/SimpleStrategy.php +29 -0
- app/code/community/SearchSpring/Manager/Strategy/Pricing/Strategy.php +190 -0
- app/code/community/SearchSpring/Manager/Strategy/PricingStrategy.php +49 -0
- app/code/community/SearchSpring/Manager/String/Sanitizer.php +46 -0
- app/code/community/SearchSpring/Manager/Transformer/ProductCollectionToRecordCollectionTransformer.php +91 -0
- app/code/community/SearchSpring/Manager/Validator/ProductValidator.php +132 -0
- app/code/community/SearchSpring/Manager/VarienObject/Data.php +94 -0
- app/code/community/SearchSpring/Manager/Writer/Product/FileWriter.php +145 -0
- app/code/community/SearchSpring/Manager/Writer/Product/Params/FileWriterParams.php +155 -0
- app/code/community/SearchSpring/Manager/Writer/Product/Params/ResponseWriterParams.php +95 -0
- app/code/community/SearchSpring/Manager/Writer/Product/ResponseWriter.php +49 -0
- app/code/community/SearchSpring/Manager/Writer/ProductWriter.php +33 -0
- app/code/community/SearchSpring/Manager/controllers/GenerateController.php +174 -0
- app/code/community/SearchSpring/Manager/etc/adminhtml.xml +26 -0
- app/code/community/SearchSpring/Manager/etc/composer.json +15 -0
- app/code/community/SearchSpring/Manager/etc/config.xml +138 -0
- app/code/community/SearchSpring/Manager/etc/readme.md +55 -0
- app/code/community/SearchSpring/Manager/etc/system.xml +154 -0
- app/design/frontend/base/default/layout/searchspring_manager.xml +41 -0
- app/design/frontend/base/default/template/searchspring_manager/layer/category_filter.phtml +29 -0
- app/design/frontend/base/default/template/searchspring_manager/layer/filter.phtml +20 -0
- app/design/frontend/base/default/template/searchspring_manager/layer/state.phtml +29 -0
- app/design/frontend/base/default/template/searchspring_manager/layer/view.phtml +32 -0
- app/design/frontend/base/default/template/searchspring_manager/product/list.phtml +37 -0
- app/design/frontend/base/default/template/searchspring_manager/product/list/toolbar.phtml +94 -0
- app/etc/modules/SearchSpring_SearchSpringManager.xml +12 -0
- app/locale/en_US/template/email/searchspring_api_error.html +1 -0
- package.xml +2 -0
- skin/frontend/base/default/searchspring/css/styles.css +10 -0
app/code/community/SearchSpring/ErrorCodes.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* ErrorCodes.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_ErrorCodes
|
10 |
+
*
|
11 |
+
* Hold a list of all the error codes that can be returned from the API
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_ErrorCodes
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* If we can not resolve the product type for a product
|
19 |
+
*/
|
20 |
+
const PRODUCT_TYPE_NOT_FOUND = 1;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Could not write to the directory
|
24 |
+
*/
|
25 |
+
const DIR_NOT_WRITABLE = 2;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Could not create feed for unkown reason
|
29 |
+
*/
|
30 |
+
const FEED_WRITE_ERROR = 3;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Filename is not passed into feed generation
|
34 |
+
*/
|
35 |
+
const FILENAME_NOT_SET = 4;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Type parameter not found
|
39 |
+
*/
|
40 |
+
const TYPE_NOT_SET = 5;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Ids parameter not found
|
44 |
+
*/
|
45 |
+
const IDS_NOT_SET = 6;
|
46 |
+
}
|
app/code/community/SearchSpring/Manager/Block/Layer/Filter/SearchSpringCategory.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SearchSpring_Manager_Block_Layer_Filter_SearchSpringCategory extends SearchSpring_Manager_Block_Layer_Filter_SearchSpringList
|
4 |
+
{
|
5 |
+
|
6 |
+
protected $_filterModelName = 'searchspring_manager/layer_filter_searchSpringCategory';
|
7 |
+
protected $_searchSpringFacet;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Return the name of the facet
|
11 |
+
*
|
12 |
+
* @return string
|
13 |
+
*/
|
14 |
+
public function getName() {
|
15 |
+
return $this->__('Category');
|
16 |
+
}
|
17 |
+
|
18 |
+
public function showFilter() {
|
19 |
+
return true;
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Passthrough Parent Categories - from filter model
|
24 |
+
*
|
25 |
+
* @return array
|
26 |
+
*/
|
27 |
+
public function getParents() {
|
28 |
+
if (!$this->hasData('parent_categories')) {
|
29 |
+
$parents = $this->_filter->getParents();
|
30 |
+
if (!is_array($parents))
|
31 |
+
$parents = array();
|
32 |
+
$this->setData('parent_categories', $parents);
|
33 |
+
}
|
34 |
+
return $this->getData('parent_categories');
|
35 |
+
}
|
36 |
+
|
37 |
+
}
|
app/code/community/SearchSpring/Manager/Block/Layer/Filter/SearchSpringList.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SearchSpring_Manager_Block_Layer_Filter_SearchSpringList extends Mage_Catalog_Block_Layer_Filter_Abstract
|
4 |
+
{
|
5 |
+
|
6 |
+
protected $_filterModelName = 'searchspring_manager/layer_filter_searchSpring';
|
7 |
+
protected $_searchSpringFacet;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Set the SearchSpring facet response
|
11 |
+
*/
|
12 |
+
public function setSearchSpringFacet($facet) {
|
13 |
+
$this->_searchSpringFacet = $facet;
|
14 |
+
return $this;
|
15 |
+
}
|
16 |
+
|
17 |
+
protected function _prepareFilter()
|
18 |
+
{
|
19 |
+
parent::_prepareFilter();
|
20 |
+
$this->_filter->setSearchSpringFacet($this->_searchSpringFacet);
|
21 |
+
return $this;
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Return the filter model
|
26 |
+
*
|
27 |
+
* @return Mage_Catalog_Model_Layer_Filter_Attribute
|
28 |
+
*/
|
29 |
+
public function getFilter() {
|
30 |
+
return $this->_filter;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Return whether or not to display the filter
|
35 |
+
*
|
36 |
+
* @return bool
|
37 |
+
*/
|
38 |
+
public function showFilter() {
|
39 |
+
return $this->getItemsCount() > 0;
|
40 |
+
}
|
41 |
+
}
|
app/code/community/SearchSpring/Manager/Block/Layer/View.php
ADDED
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SearchSpring_Manager_Block_Layer_View extends Mage_Catalog_Block_Layer_View {
|
4 |
+
|
5 |
+
protected $_defaultToolbarBlock = 'catalog/product_list_toolbar';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Internal constructor
|
9 |
+
*/
|
10 |
+
protected function _construct()
|
11 |
+
{
|
12 |
+
parent::_construct();
|
13 |
+
if ($this->isSearchSpringEnabled()) {
|
14 |
+
// Register our version of the layer model for the benifit of the product_list block
|
15 |
+
Mage::register('current_layer', $this->getLayer(), true);
|
16 |
+
}
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Apply filters from a request to a collection
|
21 |
+
*
|
22 |
+
* TODO - When we start to have more layer filter
|
23 |
+
* types, we'll want to move this logic into the
|
24 |
+
* apply functions of each filter model.
|
25 |
+
*
|
26 |
+
* @param Zend_Controller_Request_Abstract $request
|
27 |
+
* @param $collection
|
28 |
+
*/
|
29 |
+
protected function _applyFilters(Zend_Controller_Request_Abstract $request, $collection) {
|
30 |
+
$params = $request->getParams();
|
31 |
+
foreach($params as $param => $values) {
|
32 |
+
if(strpos($param, 'filter_') === 0) {
|
33 |
+
|
34 |
+
// convert non-arrays into arrays
|
35 |
+
if(!is_array($values)) {
|
36 |
+
$values = array($values);
|
37 |
+
}
|
38 |
+
|
39 |
+
$field = substr($param, 7);
|
40 |
+
|
41 |
+
foreach($values as $value) {
|
42 |
+
if(strpos($value, 'RANGE:') === 0) {
|
43 |
+
list($low, $high) = explode(' TO ', substr($value, 6));
|
44 |
+
$collection->addFilter($field . '.low', $low);
|
45 |
+
$collection->addFilter($field . '.high', $high);
|
46 |
+
} else {
|
47 |
+
$collection->addFilter($field, $value);
|
48 |
+
}
|
49 |
+
}
|
50 |
+
}
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Prepare child blocks
|
56 |
+
*
|
57 |
+
* @return Mage_Catalog_Block_Layer_View
|
58 |
+
*/
|
59 |
+
protected function _prepareLayout()
|
60 |
+
{
|
61 |
+
if ($this->isSearchSpringEnabled()) {
|
62 |
+
$head = Mage::app()->getLayout()->getBlock('head');
|
63 |
+
$head->addItem('skin_css', 'searchspring/css/styles.css');
|
64 |
+
|
65 |
+
// Load toolbar to apply pagination/sorting to collection
|
66 |
+
$toolbarBlock = $this->getLayout()->createBlock($this->_defaultToolbarBlock, microtime());
|
67 |
+
$collection = $this->getLayer()->getProductCollection();
|
68 |
+
$toolbarBlock->setCollection($collection);
|
69 |
+
|
70 |
+
$this->_applyFilters($this->getRequest(), $collection);
|
71 |
+
|
72 |
+
$stateBlock = $this->getLayout()->createBlock($this->_stateBlockName, 'ss_layer_view_state')
|
73 |
+
->setLayer($this->getLayer());
|
74 |
+
|
75 |
+
$stateBlock->setTemplate('searchspring_manager/layer/state.phtml');
|
76 |
+
|
77 |
+
$this->setChild('layer_state', $stateBlock);
|
78 |
+
|
79 |
+
$filterableAttributes = $this->_getFilterableAttributes();
|
80 |
+
|
81 |
+
foreach ($filterableAttributes as $attribute) {
|
82 |
+
if ($attribute->field == 'category_ids') {
|
83 |
+
$blockType = 'searchspring_manager/layer_filter_searchSpringCategory';
|
84 |
+
$template = 'searchspring_manager/layer/category_filter.phtml';
|
85 |
+
} else {
|
86 |
+
$blockType = 'searchspring_manager/layer_filter_searchSpringList';
|
87 |
+
$template = 'searchspring_manager/layer/filter.phtml';
|
88 |
+
}
|
89 |
+
|
90 |
+
$blocks[$attribute->field] = $this->getLayout()->createBlock($blockType)
|
91 |
+
->setLayer($this->getLayer())
|
92 |
+
->setSearchSpringFacet($attribute)
|
93 |
+
->init()
|
94 |
+
->setTemplate($template);
|
95 |
+
|
96 |
+
$this->setChild($attribute->field . '_filter', $blocks[$attribute->field]);
|
97 |
+
}
|
98 |
+
|
99 |
+
|
100 |
+
foreach($collection->getFilterSummary() as $summaryFilter) {
|
101 |
+
// Skip Category
|
102 |
+
if($summaryFilter->field == 'category_ids') {
|
103 |
+
continue;
|
104 |
+
}
|
105 |
+
|
106 |
+
$filter = $blocks[$summaryFilter->field]->getFilter();
|
107 |
+
$this->getLayer()->getState()->addFilter($this->_createFilterItem($filter, $summaryFilter->filterValue, $summaryFilter->value));
|
108 |
+
}
|
109 |
+
|
110 |
+
return $this;
|
111 |
+
} else {
|
112 |
+
return parent::_prepareLayout();
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
protected function _getEmptyCategoryAttribute() {
|
117 |
+
$attribute = new stdClass();
|
118 |
+
$attribute->field = 'category_ids';
|
119 |
+
$attribute->label = 'category_ids';
|
120 |
+
$attribute->type = 'list';
|
121 |
+
$attribute->collapse = 0;
|
122 |
+
$attribute->facet_active = 1;
|
123 |
+
$attribute->values = array();
|
124 |
+
return $attribute;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Create filter item object
|
129 |
+
*
|
130 |
+
* @param SearchSpring_Manager_Model_Layer_Filter_SearchSpring $filter
|
131 |
+
* @param string $label
|
132 |
+
* @param mixed $value
|
133 |
+
* @param int $count
|
134 |
+
* @return Mage_Catalog_Model_Layer_Filter_Item
|
135 |
+
*/
|
136 |
+
protected function _createFilterItem($filter, $label, $value, $count=0)
|
137 |
+
{
|
138 |
+
$item = Mage::getModel('searchspring_manager/layer_filter_searchSpringItem')
|
139 |
+
->setFilter($filter)
|
140 |
+
->setLabel($label)
|
141 |
+
->setValue($value)
|
142 |
+
->setCount($count);
|
143 |
+
|
144 |
+
return $item;
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Get all layer filters
|
149 |
+
*
|
150 |
+
* @return array
|
151 |
+
*/
|
152 |
+
public function getFilters()
|
153 |
+
{
|
154 |
+
if ($this->isSearchSpringEnabled()) {
|
155 |
+
$filters = array();
|
156 |
+
if ($categoryFilter = $this->_getCategoryFilter()) {
|
157 |
+
$filters[] = $categoryFilter;
|
158 |
+
}
|
159 |
+
|
160 |
+
$filterableAttributes = $this->_getFilterableAttributes();
|
161 |
+
foreach ($filterableAttributes as $attribute) {
|
162 |
+
$filters[] = $this->getChild($attribute->field . '_filter');
|
163 |
+
}
|
164 |
+
|
165 |
+
return $filters;
|
166 |
+
} else {
|
167 |
+
return parent::getFilters();
|
168 |
+
}
|
169 |
+
}
|
170 |
+
|
171 |
+
public function isSearchSpringEnabled()
|
172 |
+
{
|
173 |
+
return $this->getLayer()->isSearchSpringEnabled();
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Get layer object
|
178 |
+
*
|
179 |
+
* @return Mage_Catalog_Model_Layer
|
180 |
+
*/
|
181 |
+
public function getLayer()
|
182 |
+
{
|
183 |
+
return Mage::getSingleton('searchspring_manager/layer');
|
184 |
+
}
|
185 |
+
|
186 |
+
}
|
app/code/community/SearchSpring/Manager/Builder/OperationBuilder.php
ADDED
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* OperationBuilder.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Builder_OperationBuilder
|
10 |
+
*
|
11 |
+
* Builder for product operations
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Builder_OperationBuilder
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Service to sanitize string data
|
19 |
+
*
|
20 |
+
* @var SearchSpring_Manager_String_Sanitizer $sanitizer
|
21 |
+
*/
|
22 |
+
private $sanitizer;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Api records collection
|
26 |
+
*
|
27 |
+
* @var SearchSpring_Manager_Entity_RecordsCollection $records
|
28 |
+
*/
|
29 |
+
private $records;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The operation class name
|
33 |
+
*
|
34 |
+
* @var string $className
|
35 |
+
*/
|
36 |
+
private $className;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Magento product
|
40 |
+
*
|
41 |
+
* @var Mage_Catalog_Model_Product $product
|
42 |
+
*/
|
43 |
+
private $product;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* The class prefix
|
47 |
+
*
|
48 |
+
* Use this to prepend to the class name when the object is built
|
49 |
+
*
|
50 |
+
* @var string $classPrefix
|
51 |
+
*/
|
52 |
+
private $classPrefix = '';
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Operation parameters
|
56 |
+
*
|
57 |
+
* Used for adding additional data to the operation
|
58 |
+
*
|
59 |
+
* @var array $parameters
|
60 |
+
*/
|
61 |
+
private $parameters;
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Constructor
|
65 |
+
*
|
66 |
+
* @param SearchSpring_Manager_String_Sanitizer $sanitizer
|
67 |
+
* @param SearchSpring_Manager_Entity_RecordsCollection $records
|
68 |
+
* @param null $className
|
69 |
+
* @param Mage_Catalog_Model_Product $product
|
70 |
+
* @param string $classPrefix
|
71 |
+
*/
|
72 |
+
public function __construct(
|
73 |
+
SearchSpring_Manager_String_Sanitizer $sanitizer = null,
|
74 |
+
SearchSpring_Manager_Entity_RecordsCollection $records = null,
|
75 |
+
$className = null,
|
76 |
+
Mage_Catalog_Model_Product $product = null,
|
77 |
+
$classPrefix = ''
|
78 |
+
) {
|
79 |
+
$this->sanitizer = $sanitizer;
|
80 |
+
$this->records = $records;
|
81 |
+
$this->className = $className;
|
82 |
+
$this->product = $product;
|
83 |
+
$this->classPrefix = $classPrefix;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Set the string sanitizer
|
88 |
+
*
|
89 |
+
* @param SearchSpring_Manager_String_Sanitizer $sanitizer
|
90 |
+
*
|
91 |
+
* @return $this
|
92 |
+
*/
|
93 |
+
public function setSanitizer(SearchSpring_Manager_String_Sanitizer $sanitizer)
|
94 |
+
{
|
95 |
+
$this->sanitizer = $sanitizer;
|
96 |
+
|
97 |
+
return $this;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Set the records collection
|
102 |
+
*
|
103 |
+
* @param SearchSpring_Manager_Entity_RecordsCollection $records
|
104 |
+
*
|
105 |
+
* @return $this
|
106 |
+
*/
|
107 |
+
public function setRecords(SearchSpring_Manager_Entity_RecordsCollection $records)
|
108 |
+
{
|
109 |
+
$this->records = $records;
|
110 |
+
|
111 |
+
return $this;
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Set the class prefix
|
116 |
+
*
|
117 |
+
* @param $classPrefix
|
118 |
+
*
|
119 |
+
* @return $this
|
120 |
+
*/
|
121 |
+
public function setClassPrefix($classPrefix)
|
122 |
+
{
|
123 |
+
$this->classPrefix = (string)$classPrefix;
|
124 |
+
|
125 |
+
return $this;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Set the class name
|
130 |
+
*
|
131 |
+
* @param string $className
|
132 |
+
*
|
133 |
+
* @return $this
|
134 |
+
*/
|
135 |
+
public function setClassName($className)
|
136 |
+
{
|
137 |
+
$this->className = $className;
|
138 |
+
|
139 |
+
return $this;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Set additional data to operation
|
144 |
+
*
|
145 |
+
* @param array $parameters
|
146 |
+
*
|
147 |
+
* @return $this
|
148 |
+
*/
|
149 |
+
public function setParameters(array $parameters)
|
150 |
+
{
|
151 |
+
$this->parameters = $parameters;
|
152 |
+
|
153 |
+
return $this;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Make a new operation instance
|
158 |
+
*
|
159 |
+
* @param null $className
|
160 |
+
* @param array $parameters
|
161 |
+
* @param bool $useClassPrefix
|
162 |
+
*
|
163 |
+
* @throws InvalidArgumentException If className is not a valid type
|
164 |
+
* @throws UnexpectedValueException If a member variable is not set
|
165 |
+
*
|
166 |
+
* @return SearchSpring_Manager_Operation_Product
|
167 |
+
*/
|
168 |
+
public function build($className = null, array $parameters = array(), $useClassPrefix = true)
|
169 |
+
{
|
170 |
+
if ($className !== null) {
|
171 |
+
$this->className = $className;
|
172 |
+
}
|
173 |
+
|
174 |
+
if (null === $this->sanitizer) {
|
175 |
+
throw new UnexpectedValueException('Sanitizer must not be null');
|
176 |
+
}
|
177 |
+
|
178 |
+
if (null === $this->records) {
|
179 |
+
throw new UnexpectedValueException('Records collection must not be null');
|
180 |
+
}
|
181 |
+
|
182 |
+
if (null === $this->className) {
|
183 |
+
throw new UnexpectedValueException('Class name must not be null');
|
184 |
+
}
|
185 |
+
|
186 |
+
$class = ($useClassPrefix) ? $this->classPrefix . $this->className : $this->className;
|
187 |
+
$operation = new $class($this->sanitizer, $this->records, $parameters);
|
188 |
+
|
189 |
+
$class = 'SearchSpring_Manager_Operation_Product';
|
190 |
+
if (!$operation instanceof $class) {
|
191 |
+
throw new InvalidArgumentException('$class must be an instance of SearchSpring_Manager_Operation_Product');
|
192 |
+
}
|
193 |
+
|
194 |
+
return $operation;
|
195 |
+
}
|
196 |
+
}
|
app/code/community/SearchSpring/Manager/Collection.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File Collection.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Interface SearchSpring_Manager_Collection
|
10 |
+
*
|
11 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
12 |
+
*/
|
13 |
+
interface SearchSpring_Manager_Collection
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* Get value of key from the current index
|
17 |
+
*
|
18 |
+
* @param string $key
|
19 |
+
*
|
20 |
+
* @return mixed
|
21 |
+
*/
|
22 |
+
public function get($key);
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Set data to key at current index
|
26 |
+
*
|
27 |
+
* @param string $key
|
28 |
+
* @param mixed $element
|
29 |
+
*
|
30 |
+
* @return mixed
|
31 |
+
*/
|
32 |
+
public function set($key, $element);
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Add data to key at current index
|
36 |
+
*
|
37 |
+
* Will not replace existing data at key
|
38 |
+
*
|
39 |
+
* @param string $key
|
40 |
+
* @param $element
|
41 |
+
*
|
42 |
+
* @return mixed
|
43 |
+
*/
|
44 |
+
public function add($key, $element);
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Unset key from current index
|
48 |
+
*
|
49 |
+
* @param string $key
|
50 |
+
* @return mixed
|
51 |
+
*/
|
52 |
+
public function remove($key);
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Return an array of data
|
56 |
+
*
|
57 |
+
* @return array
|
58 |
+
*/
|
59 |
+
public function toArray();
|
60 |
+
}
|
app/code/community/SearchSpring/Manager/Entity/IndexingRequestBody.php
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File IndexingRequestBody.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Entity_IndexingRequestBody
|
10 |
+
*
|
11 |
+
* The class models a SearchSpring API request body which needs a feed id and an array of records.
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Entity_IndexingRequestBody extends SearchSpring_Manager_Entity_RequestBody
|
16 |
+
{
|
17 |
+
/**#@+
|
18 |
+
* Request types
|
19 |
+
*/
|
20 |
+
const TYPE_PRODUCT = 'product';
|
21 |
+
const TYPE_CATEGORY = 'category';
|
22 |
+
/**#@-*/
|
23 |
+
|
24 |
+
/**
|
25 |
+
* An array of allowable types
|
26 |
+
*
|
27 |
+
* @var array $allowableTypes
|
28 |
+
*/
|
29 |
+
public static $allowableTypes = array(
|
30 |
+
self::TYPE_PRODUCT,
|
31 |
+
self::TYPE_CATEGORY,
|
32 |
+
);
|
33 |
+
|
34 |
+
/**
|
35 |
+
* The type of request
|
36 |
+
*
|
37 |
+
* @var string $type
|
38 |
+
*/
|
39 |
+
private $type;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* An array of category/product ids
|
43 |
+
*
|
44 |
+
* @var array $ids
|
45 |
+
*/
|
46 |
+
private $ids;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* If we should delete these ids
|
50 |
+
*
|
51 |
+
* @var bool $shouldDelete
|
52 |
+
*/
|
53 |
+
private $shouldDelete;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Constructor
|
57 |
+
*
|
58 |
+
* @param string $type
|
59 |
+
* @param array $ids
|
60 |
+
* @param $shouldDelete
|
61 |
+
*/
|
62 |
+
public function __construct($type, array $ids, $shouldDelete)
|
63 |
+
{
|
64 |
+
$this->type = $type;
|
65 |
+
$this->ids = $ids;
|
66 |
+
$this->shouldDelete = $shouldDelete;
|
67 |
+
|
68 |
+
$this->feedId = Mage::helper('searchspring_manager')->getApiFeedId();
|
69 |
+
if (null === $this->feedId) {
|
70 |
+
throw new UnexpectedValueException('SearchSpring: Feed ID must be set');
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Returns a value that's allowed to be given to json_encode
|
76 |
+
*
|
77 |
+
* @return array
|
78 |
+
*/
|
79 |
+
public function jsonSerialize()
|
80 |
+
{
|
81 |
+
$body = array(
|
82 |
+
'type' => $this->type,
|
83 |
+
'ids' => $this->ids,
|
84 |
+
'delete' => $this->shouldDelete,
|
85 |
+
'feedId' => $this->feedId,
|
86 |
+
'generateUrl' => Mage::getUrl('searchspring/generate/index',array('_secure'=>true))
|
87 |
+
);
|
88 |
+
|
89 |
+
return $body;
|
90 |
+
}
|
91 |
+
}
|
app/code/community/SearchSpring/Manager/Entity/OperationsCollection.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* OperationsCollection.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Entity_OperationsCollection
|
10 |
+
*
|
11 |
+
* Simply extending \ArrayObject in order to provide more functionality down the road if need be
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Entity_OperationsCollection extends ArrayObject
|
16 |
+
{
|
17 |
+
}
|
app/code/community/SearchSpring/Manager/Entity/RecordsCollection.php
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File RecordsCollection.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Entity_RecordsCollection
|
10 |
+
*
|
11 |
+
* Manages a 2d array of field data. The Iterator methods will reference the first dimension of the array. The
|
12 |
+
* Collection methods will use the current index and act on the second dimension of the array.
|
13 |
+
*
|
14 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
15 |
+
*/
|
16 |
+
class SearchSpring_Manager_Entity_RecordsCollection
|
17 |
+
implements SearchSpring_Manager_Collection, SearchSpring_Manager_Iterator
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* The array of data
|
21 |
+
*
|
22 |
+
* @var array $fields
|
23 |
+
*/
|
24 |
+
private $fields = array();
|
25 |
+
|
26 |
+
/**
|
27 |
+
* The current record index
|
28 |
+
*
|
29 |
+
* @var int $index
|
30 |
+
*/
|
31 |
+
private $index = 0;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* {@inheritdoc}
|
35 |
+
*/
|
36 |
+
public function current()
|
37 |
+
{
|
38 |
+
if (!isset($this->fields[$this->key()])) {
|
39 |
+
throw new OutOfBoundsException('Index not found');
|
40 |
+
}
|
41 |
+
|
42 |
+
return $this->fields[$this->key()];
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* {@inheritdoc}
|
47 |
+
*/
|
48 |
+
public function next()
|
49 |
+
{
|
50 |
+
++$this->index;
|
51 |
+
|
52 |
+
return null;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* {@inheritdoc}
|
57 |
+
*/
|
58 |
+
public function key()
|
59 |
+
{
|
60 |
+
return $this->index;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* {@inheritdoc}
|
65 |
+
*/
|
66 |
+
public function valid()
|
67 |
+
{
|
68 |
+
return isset($this->fields[$this->key()]);
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* {@inheritdoc}
|
73 |
+
*/
|
74 |
+
public function rewind()
|
75 |
+
{
|
76 |
+
$this->index = 0;
|
77 |
+
|
78 |
+
return null;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* {@inheritdoc}
|
83 |
+
*/
|
84 |
+
public function end()
|
85 |
+
{
|
86 |
+
end($this->fields);
|
87 |
+
|
88 |
+
return null;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* {@inheritdoc}
|
93 |
+
*/
|
94 |
+
public function get($key)
|
95 |
+
{
|
96 |
+
if (!isset($this->fields[$this->key()][$key])) {
|
97 |
+
throw new OutOfBoundsException('Key not found');
|
98 |
+
}
|
99 |
+
|
100 |
+
return $this->fields[$this->key()][$key];
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* {@inheritdoc}
|
105 |
+
*/
|
106 |
+
public function set($key, $element)
|
107 |
+
{
|
108 |
+
$this->fields[$this->key()][$key] = $element;
|
109 |
+
|
110 |
+
return $this;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* {@inheritdoc}
|
115 |
+
*/
|
116 |
+
public function add($key, $element)
|
117 |
+
{
|
118 |
+
$this->fields[$this->key()][$key][] = $element;
|
119 |
+
|
120 |
+
return $this;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* {@inheritdoc}
|
125 |
+
*/
|
126 |
+
public function remove($key)
|
127 |
+
{
|
128 |
+
if (!isset($this->fields[$this->key()][$key])) {
|
129 |
+
throw new OutOfBoundsException('Key not found');
|
130 |
+
}
|
131 |
+
|
132 |
+
unset($this->fields[$this->key()][$key]);
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* {@inheritdoc}
|
137 |
+
*/
|
138 |
+
public function toArray()
|
139 |
+
{
|
140 |
+
return $this->fields;
|
141 |
+
}
|
142 |
+
}
|
app/code/community/SearchSpring/Manager/Entity/RequestBody.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File IndexingRequestBody.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Entity_RequestBody
|
10 |
+
*
|
11 |
+
* @author James Bathgate <james@b7interactive.com>
|
12 |
+
*/
|
13 |
+
class SearchSpring_Manager_Entity_RequestBody
|
14 |
+
{
|
15 |
+
|
16 |
+
}
|
app/code/community/SearchSpring/Manager/Entity/RequestParams.php
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* RequestParams.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Entity_RequestParams
|
10 |
+
*
|
11 |
+
* Store request parameters
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Entity_RequestParams
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* How many records to limit
|
19 |
+
*
|
20 |
+
* @var int $count
|
21 |
+
*/
|
22 |
+
private $count;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Limit offest
|
26 |
+
*
|
27 |
+
* @var int $offset
|
28 |
+
*/
|
29 |
+
private $offset;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The store id
|
33 |
+
*
|
34 |
+
* @var string $store
|
35 |
+
*/
|
36 |
+
private $store;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Constructor
|
40 |
+
*
|
41 |
+
* @param int $count
|
42 |
+
* @param int $offset
|
43 |
+
* @param string $store
|
44 |
+
*/
|
45 |
+
public function __construct($count, $offset, $store)
|
46 |
+
{
|
47 |
+
$this->count = $count;
|
48 |
+
$this->offset = $offset;
|
49 |
+
$this->store = $store;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Get the offset
|
54 |
+
*
|
55 |
+
* @return int
|
56 |
+
*/
|
57 |
+
public function getOffset()
|
58 |
+
{
|
59 |
+
return $this->offset;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Get the store id
|
64 |
+
*
|
65 |
+
* @return string
|
66 |
+
*/
|
67 |
+
public function getStore()
|
68 |
+
{
|
69 |
+
return $this->store;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Get the limit count
|
74 |
+
*
|
75 |
+
* @return int
|
76 |
+
*/
|
77 |
+
public function getCount()
|
78 |
+
{
|
79 |
+
return $this->count;
|
80 |
+
}
|
81 |
+
}
|
app/code/community/SearchSpring/Manager/Entity/SearchCollection.php
ADDED
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File SearchRequest.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Entity_SearchCollection
|
10 |
+
*
|
11 |
+
* The class models a SearchSpring SearchCollection
|
12 |
+
*
|
13 |
+
* @author James Bathgate <james@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Entity_SearchCollection extends Mage_Catalog_Model_Resource_Collection_Abstract
|
16 |
+
{
|
17 |
+
protected $_api;
|
18 |
+
protected $_requestBody;
|
19 |
+
|
20 |
+
protected $_results;
|
21 |
+
|
22 |
+
protected $_loaded = false;
|
23 |
+
|
24 |
+
const SORT_ORDER_ASC = 'asc';
|
25 |
+
const SORT_ORDER_DESC = 'desc';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @param SearchSpring_Manager_Service_SearchSpring_SearchApiAdapter $api
|
29 |
+
* @param SearchSpring_Manager_Entity_SearchRequestBody $requestBody
|
30 |
+
*/
|
31 |
+
|
32 |
+
public function __construct(
|
33 |
+
SearchSpring_Manager_Service_SearchSpring_SearchApiAdapter $api,
|
34 |
+
SearchSpring_Manager_Entity_SearchRequestBody $requestBody
|
35 |
+
) {
|
36 |
+
$this->_api = $api;
|
37 |
+
$this->_requestBody = $requestBody;
|
38 |
+
}
|
39 |
+
|
40 |
+
/*
|
41 |
+
* $type will be ignored since it's handled by the SMC settings
|
42 |
+
*/
|
43 |
+
public function addFilter($field, $value, $type='and') {
|
44 |
+
$this->_requestBody->addFilter($field, $value);
|
45 |
+
return $this;
|
46 |
+
}
|
47 |
+
|
48 |
+
public function addBackgroundFilter($field, $value) {
|
49 |
+
$this->_requestBody->addBackgroundFilter($field, $value);
|
50 |
+
return $this;
|
51 |
+
}
|
52 |
+
|
53 |
+
public function addFilterOnly($field, $values) {
|
54 |
+
foreach($values as $value) {
|
55 |
+
$this->_requestBody->addFilterOnly($field, $value);
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
public function setCurPage($page) {
|
60 |
+
$this->_requestBody->setPage($page);
|
61 |
+
return $this;
|
62 |
+
}
|
63 |
+
|
64 |
+
public function getCurPage($offset=0) {
|
65 |
+
return $this->_requestBody->getPage()+$offset;
|
66 |
+
}
|
67 |
+
|
68 |
+
public function setPageSize($size) {
|
69 |
+
$this->_requestBody->setResultsPerPage($size);
|
70 |
+
return $this;
|
71 |
+
}
|
72 |
+
|
73 |
+
public function getPageSize() {
|
74 |
+
return $this->_requestBody->getResultsPerPage();
|
75 |
+
}
|
76 |
+
|
77 |
+
public function setOrder($field, $dir = self::SORT_ORDER_ASC) {
|
78 |
+
$this->_requestBody->setSort($field, $dir);
|
79 |
+
return $this;
|
80 |
+
}
|
81 |
+
|
82 |
+
public function load($printQuery = false, $logQuery = false) {
|
83 |
+
if(!$this->_loaded) {
|
84 |
+
$this->_results = new SearchSpring_Manager_Entity_SearchResult(
|
85 |
+
$this->_api->search($this->_requestBody)
|
86 |
+
);
|
87 |
+
|
88 |
+
$this->_loaded = true;
|
89 |
+
}
|
90 |
+
|
91 |
+
return $this;
|
92 |
+
}
|
93 |
+
|
94 |
+
public function count() {
|
95 |
+
return $this->_results->getNumResults();
|
96 |
+
}
|
97 |
+
|
98 |
+
public function getSize() {
|
99 |
+
return $this->_results->getNumResults();
|
100 |
+
}
|
101 |
+
|
102 |
+
public function getLastPageNumber() {
|
103 |
+
return ceil($this->_results->getNumResults() / $this->_results->getPerPage());
|
104 |
+
}
|
105 |
+
|
106 |
+
public function getResults() {
|
107 |
+
if(!$this->_loaded) {
|
108 |
+
$this->load();
|
109 |
+
}
|
110 |
+
|
111 |
+
return $this->_results;
|
112 |
+
}
|
113 |
+
|
114 |
+
public function getMerchandisingContent() {
|
115 |
+
return $this->_results->getMerchandising();
|
116 |
+
}
|
117 |
+
|
118 |
+
public function getSorting() {
|
119 |
+
return $this->_results->getSorting();
|
120 |
+
}
|
121 |
+
|
122 |
+
public function getFilterSummary() {
|
123 |
+
return $this->_results->getFilterSummary();
|
124 |
+
}
|
125 |
+
|
126 |
+
|
127 |
+
/**
|
128 |
+
* SearchSpring automatically includes counts, so we do nothing.
|
129 |
+
*
|
130 |
+
* @param Mage_Eav_Model_Entity_Collection_Abstract $categoryCollection
|
131 |
+
* @return Mage_Catalog_Model_Resource_Product_Collection
|
132 |
+
*/
|
133 |
+
public function addCountToCategories($categoryCollection)
|
134 |
+
{
|
135 |
+
return $this;
|
136 |
+
}
|
137 |
+
|
138 |
+
}
|
app/code/community/SearchSpring/Manager/Entity/SearchRequestBody.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File IndexingRequestBody.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Entity_SearchRequestBody
|
10 |
+
*
|
11 |
+
* The class models a SearchSpring Search API request body
|
12 |
+
*
|
13 |
+
* @author James Bathgate <james@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Entity_SearchRequestBody extends SearchSpring_Manager_Entity_RequestBody
|
16 |
+
{
|
17 |
+
|
18 |
+
protected $_siteId;
|
19 |
+
|
20 |
+
protected $_filters = array();
|
21 |
+
protected $_backgroundFilters = array();
|
22 |
+
|
23 |
+
protected $_filterOnly = array();
|
24 |
+
|
25 |
+
protected $_page = 1;
|
26 |
+
protected $_resultsPerPage = 30;
|
27 |
+
|
28 |
+
protected $_sortField;
|
29 |
+
protected $_sortDir = 'asc';
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Constructor
|
33 |
+
*/
|
34 |
+
public function __construct()
|
35 |
+
{
|
36 |
+
$this->_siteId = Mage::helper('searchspring_manager')->getApiSiteId();
|
37 |
+
|
38 |
+
if (null === $this->_siteId) {
|
39 |
+
throw new UnexpectedValueException('SearchSpring: Site ID must be set');
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
public function addFilter($field, $value, $append = false) {
|
44 |
+
if(!isset($this->_filters[$field])) {
|
45 |
+
$this->_filters[$field] = $value;
|
46 |
+
} else {
|
47 |
+
if(!is_array($this->_filters[$field])) {
|
48 |
+
$this->_filters[$field] = array($this->_filters[$field]);
|
49 |
+
}
|
50 |
+
|
51 |
+
$this->_filters[$field][] = $value;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
public function addBackgroundFilter($field, $value, $append = false) {
|
56 |
+
if(!isset($this->_backgroundFilters[$field])) {
|
57 |
+
$this->_backgroundFilters[$field] = $value;
|
58 |
+
} else {
|
59 |
+
if(!is_array($this->_backgroundFilters[$field])) {
|
60 |
+
$this->_backgroundFilters[$field] = array($this->_backgroundFilters[$field]);
|
61 |
+
}
|
62 |
+
|
63 |
+
$this->_backgroundFilters[$field][] = $value;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
public function addFilterOnly($field, $value) {
|
68 |
+
if(!isset($this->_filterOnly[$field])) {
|
69 |
+
$this->_filterOnly[$field] = $value;
|
70 |
+
} else {
|
71 |
+
if(!is_array($this->_filterOnly[$field])) {
|
72 |
+
$this->_filterOnly[$field] = array($this->_filterOnly[$field]);
|
73 |
+
}
|
74 |
+
|
75 |
+
$this->_filterOnly[$field][] = $value;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
public function setPage($page) {
|
80 |
+
$this->_page = $page;
|
81 |
+
}
|
82 |
+
|
83 |
+
public function getPage() {
|
84 |
+
return $this->_page;
|
85 |
+
}
|
86 |
+
|
87 |
+
public function setResultsPerPage($rpp) {
|
88 |
+
$this->_resultsPerPage = $rpp;
|
89 |
+
}
|
90 |
+
|
91 |
+
public function getResultsPerPage() {
|
92 |
+
return $this->_resultsPerPage;
|
93 |
+
}
|
94 |
+
|
95 |
+
public function setSort($field, $dir) {
|
96 |
+
$this->_sortField = $field;
|
97 |
+
$this->_sortDir = $dir;
|
98 |
+
}
|
99 |
+
|
100 |
+
public function __toString() {
|
101 |
+
$parameters = array(
|
102 |
+
'siteId' => $this->_siteId,
|
103 |
+
'page' => $this->_page,
|
104 |
+
'resultsPerPage' => $this->_resultsPerPage
|
105 |
+
);
|
106 |
+
|
107 |
+
foreach($this->_filters as $field => $value) {
|
108 |
+
$parameters['filter.' . $field] = $value;
|
109 |
+
}
|
110 |
+
|
111 |
+
foreach($this->_backgroundFilters as $field => $value) {
|
112 |
+
$parameters['bgfilter.' . $field] = $value;
|
113 |
+
}
|
114 |
+
|
115 |
+
foreach($this->_filterOnly as $field => $value) {
|
116 |
+
$parameters['filter.' . $field . '.only'] = $value;
|
117 |
+
}
|
118 |
+
|
119 |
+
if(!is_null($this->_sortField)) {
|
120 |
+
$parameters['sort.' . $this->_sortField] = $this->_sortDir;
|
121 |
+
}
|
122 |
+
|
123 |
+
$url = http_build_query($parameters);
|
124 |
+
|
125 |
+
// remove [] from multi-valued filters
|
126 |
+
$url = preg_replace('/\%5B\d+\%5D/', '', $url);
|
127 |
+
|
128 |
+
return $url;
|
129 |
+
}
|
130 |
+
|
131 |
+
}
|
app/code/community/SearchSpring/Manager/Entity/SearchResult.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File SearchResult.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Entity_SearchResult
|
10 |
+
*
|
11 |
+
* The class models a SearchSpring Search API result body
|
12 |
+
*
|
13 |
+
* @author James Bathgate <james@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Entity_SearchResult
|
16 |
+
{
|
17 |
+
|
18 |
+
protected $_results = array();
|
19 |
+
|
20 |
+
protected $_pagination;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Constructor
|
24 |
+
*
|
25 |
+
* @param mixed JSON decoded SearchSpring search result
|
26 |
+
*/
|
27 |
+
public function __construct($results)
|
28 |
+
{
|
29 |
+
// print "<pre>"; var_dump($results);print "</pre>";exit;
|
30 |
+
$this->_pagination = $results->pagination;
|
31 |
+
$this->_results = $results->results;
|
32 |
+
$this->_facets = $results->facets;
|
33 |
+
$this->_merchandising = $results->merchandising;
|
34 |
+
$this->_sorting = $results->sorting;
|
35 |
+
$this->_filterSummary = $results->filterSummary;
|
36 |
+
}
|
37 |
+
|
38 |
+
public function getResults() {
|
39 |
+
return $this->_results;
|
40 |
+
}
|
41 |
+
|
42 |
+
public function getFacets() {
|
43 |
+
return $this->_facets;
|
44 |
+
}
|
45 |
+
|
46 |
+
public function getNumResults() {
|
47 |
+
return $this->_pagination->totalResults;
|
48 |
+
}
|
49 |
+
|
50 |
+
public function getPerPage() {
|
51 |
+
return $this->_pagination->perPage;
|
52 |
+
}
|
53 |
+
|
54 |
+
public function getMerchandisingContent() {
|
55 |
+
if(isset($this->_merchandising->content)) {
|
56 |
+
return $this->_merchandising->content;
|
57 |
+
} else {
|
58 |
+
return new stdClass();
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
public function getSorting() {
|
63 |
+
return $this->_sorting->options;
|
64 |
+
}
|
65 |
+
|
66 |
+
public function getFilterSummary() {
|
67 |
+
return $this->_filterSummary;
|
68 |
+
}
|
69 |
+
}
|
app/code/community/SearchSpring/Manager/Entity/SearchResult/Result.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File Result.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Entity_SearchResult_Result
|
10 |
+
*
|
11 |
+
* The class implements product functions for a SearchSpring Result
|
12 |
+
*
|
13 |
+
* @author James Bathgate <james@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Entity_SearchResult_Result
|
16 |
+
{
|
17 |
+
|
18 |
+
protected $_result;
|
19 |
+
/**
|
20 |
+
* Constructor
|
21 |
+
*
|
22 |
+
* @param stdClass $result
|
23 |
+
*/
|
24 |
+
public function __construct($result)
|
25 |
+
{
|
26 |
+
$this->_result = $result;
|
27 |
+
}
|
28 |
+
|
29 |
+
public function getProductUrl() {
|
30 |
+
return $this->_result->url;
|
31 |
+
}
|
32 |
+
|
33 |
+
public function getData($field) {
|
34 |
+
$data = $this->_result->$field;
|
35 |
+
var_dump($data);
|
36 |
+
}
|
37 |
+
}
|
app/code/community/SearchSpring/Manager/Factory/ApiFactory.php
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* ApiFactory.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Factory_ApiFactory
|
10 |
+
*
|
11 |
+
* Create a SearchSpring api request object
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Factory_ApiFactory
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Make the object
|
19 |
+
*
|
20 |
+
* Pulls in config values from the Magento configuration. Uses the Varien curl adapter.
|
21 |
+
*
|
22 |
+
* @param $type string The type of API to build (index or search)
|
23 |
+
*
|
24 |
+
* @return SearchSpring_Manager_Service_SearchSpring_IndexingApiAdapter
|
25 |
+
*
|
26 |
+
* @throws UnexpectedValueException
|
27 |
+
*/
|
28 |
+
public function make($type)
|
29 |
+
{
|
30 |
+
$baseUrl = Mage::helper('searchspring_manager')->getApiBaseUrl();
|
31 |
+
$siteId = Mage::helper('searchspring_manager')->getApiSiteId();
|
32 |
+
$secretKey = Mage::helper('searchspring_manager')->getApiSecretKey();
|
33 |
+
|
34 |
+
if (null === $baseUrl) {
|
35 |
+
throw new UnexpectedValueException('SearchSpring: Base URL must be set');
|
36 |
+
}
|
37 |
+
|
38 |
+
if (null === $siteId) {
|
39 |
+
throw new UnexpectedValueException('SearchSpring: Site ID must be set');
|
40 |
+
}
|
41 |
+
|
42 |
+
if (null === $secretKey) {
|
43 |
+
throw new UnexpectedValueException('SearchSpring: Secret key must be set');
|
44 |
+
}
|
45 |
+
|
46 |
+
$apiErrorHandler = new SearchSpring_Manager_Handler_ApiErrorHandler();
|
47 |
+
|
48 |
+
if($type == 'index') {
|
49 |
+
$curl = new Varien_Http_Adapter_Curl();
|
50 |
+
$curl->setConfig(array('timeout' => 15, 'userpwd' => $siteId . ':' . $secretKey));
|
51 |
+
|
52 |
+
$api = new SearchSpring_Manager_Service_SearchSpring_IndexingApiAdapter(
|
53 |
+
$apiErrorHandler,
|
54 |
+
$curl,
|
55 |
+
$baseUrl
|
56 |
+
);
|
57 |
+
} else {
|
58 |
+
$curl = new Varien_Http_Adapter_Curl();
|
59 |
+
$curl->setConfig(array('timeout' => 15));
|
60 |
+
|
61 |
+
$api = new SearchSpring_Manager_Service_SearchSpring_SearchApiAdapter(
|
62 |
+
$apiErrorHandler,
|
63 |
+
$curl,
|
64 |
+
$baseUrl
|
65 |
+
);
|
66 |
+
}
|
67 |
+
|
68 |
+
return $api;
|
69 |
+
}
|
70 |
+
}
|
app/code/community/SearchSpring/Manager/Factory/GeneratorFactory.php
ADDED
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* GeneratorFactory.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Factory_GeneratorFactory
|
10 |
+
*
|
11 |
+
* Creates a generator object
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Factory_GeneratorFactory
|
16 |
+
{
|
17 |
+
/**#@+
|
18 |
+
* Generator types
|
19 |
+
*/
|
20 |
+
const TYPE_FEED = 'feed';
|
21 |
+
const TYPE_PRODUCT = 'product';
|
22 |
+
const TYPE_CATEGORY = 'category';
|
23 |
+
/**#@-*/
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Create a generator
|
27 |
+
*
|
28 |
+
* @param string $type Generator type
|
29 |
+
* @param SearchSpring_Manager_Entity_RequestParams $requestParams Request parameters
|
30 |
+
* @param array $params Additional parameters
|
31 |
+
*
|
32 |
+
* @throws OutOfBoundsException If a key is not found
|
33 |
+
* @throws InvalidArgumentException If the type is not found
|
34 |
+
*
|
35 |
+
* @return SearchSpring_Manager_Generator_ProductGenerator
|
36 |
+
*
|
37 |
+
*/
|
38 |
+
public function make($type, SearchSpring_Manager_Entity_RequestParams $requestParams, array $params = array())
|
39 |
+
{
|
40 |
+
$operationsBuilder = new SearchSpring_Manager_Builder_OperationBuilder();
|
41 |
+
$operationsCollection = new SearchSpring_Manager_Entity_OperationsCollection();
|
42 |
+
$productRecords = new SearchSpring_Manager_Entity_RecordsCollection();
|
43 |
+
|
44 |
+
// setup default operations
|
45 |
+
$this->createOperations($operationsBuilder, $operationsCollection, $productRecords);
|
46 |
+
|
47 |
+
$transformer = new SearchSpring_Manager_Transformer_ProductCollectionToRecordCollectionTransformer(
|
48 |
+
$productRecords,
|
49 |
+
$operationsCollection
|
50 |
+
);
|
51 |
+
|
52 |
+
switch($type) {
|
53 |
+
case self::TYPE_FEED:
|
54 |
+
if (!isset($params['filename'])) {
|
55 |
+
throw new OutOfBoundsException('Key "filename" not found in array');
|
56 |
+
}
|
57 |
+
|
58 |
+
$filename = $params['filename'];
|
59 |
+
|
60 |
+
$generator = $this->makeFeedGenerator($transformer, $requestParams, $filename);
|
61 |
+
|
62 |
+
break;
|
63 |
+
case self::TYPE_PRODUCT:
|
64 |
+
if (!isset($params['ids'])) {
|
65 |
+
throw new OutOfBoundsException('Key "ids" not found in array');
|
66 |
+
}
|
67 |
+
|
68 |
+
$ids = $params['ids'];
|
69 |
+
|
70 |
+
$generator = $this->makeProductGenerator($transformer, $ids, $requestParams);
|
71 |
+
|
72 |
+
break;
|
73 |
+
case self::TYPE_CATEGORY:
|
74 |
+
if (!isset($params['ids'])) {
|
75 |
+
throw new OutOfBoundsException('Key "ids" not found in array');
|
76 |
+
}
|
77 |
+
|
78 |
+
$ids = $params['ids'];
|
79 |
+
|
80 |
+
if (!is_array($ids)) {
|
81 |
+
throw new InvalidArgumentException('Ids must be an array');
|
82 |
+
}
|
83 |
+
|
84 |
+
$validator = new SearchSpring_Manager_Validator_ProductValidator();
|
85 |
+
|
86 |
+
// get product ids for each category
|
87 |
+
$productIds = array();
|
88 |
+
foreach ($ids as $id) {
|
89 |
+
/** @var Mage_Catalog_Model_Category $category */
|
90 |
+
$category = Mage::getModel('catalog/category')->load($id);
|
91 |
+
|
92 |
+
// Check for non-existent category
|
93 |
+
if(!is_null($category->getId())) {
|
94 |
+
/** @var Mage_Catalog_Model_Resource_Product_Collection $products */
|
95 |
+
$products = Mage::getModel('catalog/product')
|
96 |
+
->getCollection()
|
97 |
+
->joinField('category_id', 'catalog/category_product', 'category_id', 'product_id = entity_id', null, 'left')
|
98 |
+
->addAttributeToSelect('*')
|
99 |
+
->addAttributeToFilter('category_id', array('in' => $id));
|
100 |
+
foreach($products as $product) {
|
101 |
+
if($validator->isValid($product)) {
|
102 |
+
$productIds[] = $product->getId();
|
103 |
+
}
|
104 |
+
}
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
// remove duplicates
|
109 |
+
$productIds = array_unique($productIds);
|
110 |
+
|
111 |
+
// make a product generator based on product ids
|
112 |
+
$generator = $this->makeProductGenerator($transformer, $productIds, $requestParams);
|
113 |
+
|
114 |
+
break;
|
115 |
+
default:
|
116 |
+
throw new InvalidArgumentException('Type not found.');
|
117 |
+
}
|
118 |
+
|
119 |
+
return $generator;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Create default operations
|
124 |
+
*
|
125 |
+
* @param SearchSpring_Manager_Builder_OperationBuilder $operationsBuilder
|
126 |
+
* @param SearchSpring_Manager_Entity_OperationsCollection $operationsCollection
|
127 |
+
* @param SearchSpring_Manager_Entity_RecordsCollection $productRecords
|
128 |
+
*/
|
129 |
+
private function createOperations(
|
130 |
+
SearchSpring_Manager_Builder_OperationBuilder $operationsBuilder,
|
131 |
+
SearchSpring_Manager_Entity_OperationsCollection $operationsCollection,
|
132 |
+
SearchSpring_Manager_Entity_RecordsCollection $productRecords
|
133 |
+
) {
|
134 |
+
$operationsBuilder->setSanitizer(new SearchSpring_Manager_String_Sanitizer())
|
135 |
+
->setRecords($productRecords)
|
136 |
+
->setClassPrefix(SearchSpring_Manager_Operation_Product::OPERATION_CLASS_PREFIX);
|
137 |
+
|
138 |
+
$operationsCollection->append($operationsBuilder->build('SetFields'));
|
139 |
+
$operationsCollection->append($operationsBuilder->build('SetCoreFields'));
|
140 |
+
$operationsCollection->append($operationsBuilder->build('SetImages'));
|
141 |
+
$operationsCollection->append($operationsBuilder->build('SetOptions'));
|
142 |
+
$operationsCollection->append($operationsBuilder->build('SetCategories'));
|
143 |
+
|
144 |
+
// add pricing factory and if we should display zero priced products as additional data
|
145 |
+
$operationsCollection->append($operationsBuilder->build('SetPricing',
|
146 |
+
array(
|
147 |
+
'pricingFactory' => new SearchSpring_Manager_Factory_PricingFactory(),
|
148 |
+
'displayZeroPrice' => (int)Mage::helper('searchspring_manager')->isZeroPriceIndexingEnabled(),
|
149 |
+
)
|
150 |
+
)
|
151 |
+
);
|
152 |
+
|
153 |
+
$operationsCollection->append($operationsBuilder->build('SetRatings'));
|
154 |
+
|
155 |
+
// dispatch event allowing additional operations to be added before loop starts
|
156 |
+
$operationsBuilder->setClassPrefix(null);
|
157 |
+
Mage::dispatchEvent('searchspring_add_operations', array(
|
158 |
+
'operations' => $operationsCollection,
|
159 |
+
'builder' => $operationsBuilder,
|
160 |
+
)
|
161 |
+
);
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Make a feed generator
|
166 |
+
*
|
167 |
+
* Uses a feed collection provider and file writer
|
168 |
+
*
|
169 |
+
* @param SearchSpring_Manager_Transformer_ProductCollectionToRecordCollectionTransformer $transformer
|
170 |
+
* @param SearchSpring_Manager_Entity_RequestParams $requestParams
|
171 |
+
* @param string $filename
|
172 |
+
*
|
173 |
+
* @return SearchSpring_Manager_Generator_ProductGenerator
|
174 |
+
*/
|
175 |
+
private function makeFeedGenerator(
|
176 |
+
SearchSpring_Manager_Transformer_ProductCollectionToRecordCollectionTransformer $transformer,
|
177 |
+
SearchSpring_Manager_Entity_RequestParams $requestParams,
|
178 |
+
$filename
|
179 |
+
) {
|
180 |
+
$collectionProvider = new SearchSpring_Manager_Provider_ProductCollection_FeedProvider($requestParams);
|
181 |
+
|
182 |
+
$xmlWriter = new XMLWriter();
|
183 |
+
$writerParams = new SearchSpring_Manager_Writer_Product_Params_FileWriterParams(
|
184 |
+
$requestParams,
|
185 |
+
$collectionProvider->getCollectionCount(),
|
186 |
+
$filename
|
187 |
+
);
|
188 |
+
$writer = new SearchSpring_Manager_Writer_Product_FileWriter($xmlWriter, $writerParams);
|
189 |
+
$generator = new SearchSpring_Manager_Generator_ProductGenerator($collectionProvider, $writer, $transformer);
|
190 |
+
|
191 |
+
return $generator;
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Make a product generator
|
196 |
+
*
|
197 |
+
* Uses a product type product collection provider and response writer
|
198 |
+
*
|
199 |
+
* @param SearchSpring_Manager_Transformer_ProductCollectionToRecordCollectionTransformer $transformer
|
200 |
+
* @param array $ids
|
201 |
+
* @param SearchSpring_Manager_Entity_RequestParams $requestParams
|
202 |
+
*
|
203 |
+
* @return SearchSpring_Manager_Generator_ProductGenerator
|
204 |
+
*/
|
205 |
+
private function makeProductGenerator(
|
206 |
+
SearchSpring_Manager_Transformer_ProductCollectionToRecordCollectionTransformer $transformer,
|
207 |
+
array $ids,
|
208 |
+
SearchSpring_Manager_Entity_RequestParams $requestParams
|
209 |
+
) {
|
210 |
+
$collectionProvider = new SearchSpring_Manager_Provider_ProductCollection_ProductProvider($ids, $requestParams);
|
211 |
+
$writerParams = new SearchSpring_Manager_Writer_Product_Params_ResponseWriterParams(
|
212 |
+
$requestParams,
|
213 |
+
$collectionProvider->getCollectionCount()
|
214 |
+
);
|
215 |
+
$writer = new SearchSpring_Manager_Writer_Product_ResponseWriter($writerParams);
|
216 |
+
$generator = new SearchSpring_Manager_Generator_ProductGenerator($collectionProvider, $writer, $transformer);
|
217 |
+
|
218 |
+
return $generator;
|
219 |
+
|
220 |
+
|
221 |
+
}
|
222 |
+
}
|
app/code/community/SearchSpring/Manager/Factory/IndexingRequestBodyFactory.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* IndexingRequestBodyFactory.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Factory_IndexingRequestBodyFactory
|
10 |
+
*
|
11 |
+
* Create a request body
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Factory_IndexingRequestBodyFactory
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Make a request body
|
19 |
+
*
|
20 |
+
* @param $type
|
21 |
+
* @param array $ids
|
22 |
+
* @param bool $shouldDelete
|
23 |
+
*
|
24 |
+
* @throws InvalidArgumentException
|
25 |
+
* @return SearchSpring_Manager_Entity_IndexingRequestBody
|
26 |
+
*
|
27 |
+
*/
|
28 |
+
public function make($type, array $ids, $shouldDelete = false)
|
29 |
+
{
|
30 |
+
if (!in_array($type, SearchSpring_Manager_Entity_IndexingRequestBody::$allowableTypes)) {
|
31 |
+
throw new InvalidArgumentException('Type must be one of allowable types');
|
32 |
+
}
|
33 |
+
|
34 |
+
$requestBody = new SearchSpring_Manager_Entity_IndexingRequestBody($type, $ids, $shouldDelete);
|
35 |
+
|
36 |
+
return $requestBody;
|
37 |
+
}
|
38 |
+
}
|
app/code/community/SearchSpring/Manager/Factory/PricingFactory.php
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File PricingFactory.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Factory_PricingFactory
|
10 |
+
*
|
11 |
+
* Creates a pricing strategy.
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Factory_PricingFactory
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Creates a pricing strategy based on product type
|
19 |
+
*
|
20 |
+
* Throws an exception if it can't properly resolve the type.
|
21 |
+
*
|
22 |
+
* @param Mage_Catalog_Model_Product $product
|
23 |
+
*
|
24 |
+
* @return SearchSpring_Manager_Strategy_Pricing_Strategy
|
25 |
+
* @throws UnexpectedValueException
|
26 |
+
*/
|
27 |
+
static public function make(Mage_Catalog_Model_Product $product)
|
28 |
+
{
|
29 |
+
$productType = $product->getTypeId();
|
30 |
+
|
31 |
+
switch($productType) {
|
32 |
+
case Mage_Catalog_Model_Product_Type::TYPE_SIMPLE:
|
33 |
+
$strategy = new SearchSpring_Manager_Strategy_Pricing_SimpleStrategy($product);
|
34 |
+
|
35 |
+
break;
|
36 |
+
case Mage_Catalog_Model_Product_Type::TYPE_GROUPED:
|
37 |
+
$strategy = new SearchSpring_Manager_Strategy_Pricing_GroupedStrategy($product);
|
38 |
+
|
39 |
+
break;
|
40 |
+
case Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE:
|
41 |
+
$strategy = new SearchSpring_Manager_Strategy_Pricing_ConfigurableStrategy($product);
|
42 |
+
break;
|
43 |
+
case Mage_Catalog_Model_Product_Type::TYPE_BUNDLE:
|
44 |
+
$strategy = new SearchSpring_Manager_Strategy_Pricing_BundleStrategy($product);
|
45 |
+
|
46 |
+
break;
|
47 |
+
default:
|
48 |
+
throw new UnexpectedValueException('Could not resolve product type');
|
49 |
+
}
|
50 |
+
|
51 |
+
return $strategy;
|
52 |
+
}
|
53 |
+
}
|
app/code/community/SearchSpring/Manager/Factory/SearchRequestBodyFactory.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* IndexingRequestBodyFactory.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Factory_SearchRequestBodyFactory
|
10 |
+
*
|
11 |
+
* Create a request body
|
12 |
+
*
|
13 |
+
* @author James Bathgate <james@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Factory_SearchRequestBodyFactory
|
16 |
+
{
|
17 |
+
public function make()
|
18 |
+
{
|
19 |
+
$requestBody = new SearchSpring_Manager_Entity_SearchRequestBody();
|
20 |
+
return $requestBody;
|
21 |
+
}
|
22 |
+
}
|
app/code/community/SearchSpring/Manager/Generator/ProductGenerator.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* ProductGenerator.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Generator_ProductGenerator
|
10 |
+
*
|
11 |
+
* Handles generation of product records
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Generator_ProductGenerator
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Object that handles writing a record collection
|
19 |
+
*
|
20 |
+
* @var SearchSpring_Manager_Writer_ProductWriter $writer
|
21 |
+
*/
|
22 |
+
private $writer;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Transforms product collection to record collection
|
26 |
+
*
|
27 |
+
* @var SearchSpring_Manager_Transformer_ProductCollectionToRecordCollectionTransformer
|
28 |
+
*/
|
29 |
+
private $transformer;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Provides a collection
|
33 |
+
*
|
34 |
+
* @var SearchSpring_Manager_Provider_ProductCollectionProvider
|
35 |
+
*/
|
36 |
+
private $collectionProvider;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Constructor
|
40 |
+
*
|
41 |
+
* @param SearchSpring_Manager_Provider_ProductCollectionProvider $collectionProvider
|
42 |
+
* @param SearchSpring_Manager_Writer_ProductWriter $writer
|
43 |
+
* @param SearchSpring_Manager_Transformer_ProductCollectionToRecordCollectionTransformer $transformer
|
44 |
+
*/
|
45 |
+
public function __construct(
|
46 |
+
SearchSpring_Manager_Provider_ProductCollectionProvider $collectionProvider,
|
47 |
+
SearchSpring_Manager_Writer_ProductWriter $writer,
|
48 |
+
SearchSpring_Manager_Transformer_ProductCollectionToRecordCollectionTransformer $transformer
|
49 |
+
) {
|
50 |
+
$this->collectionProvider = $collectionProvider;
|
51 |
+
$this->writer = $writer;
|
52 |
+
$this->transformer = $transformer;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Gets a product collection, transform to record collection, and then write the records collection
|
57 |
+
*
|
58 |
+
* @return string The response message
|
59 |
+
*/
|
60 |
+
public function generate()
|
61 |
+
{
|
62 |
+
$productCollection = $this->collectionProvider->getCollection();
|
63 |
+
$recordCollection = $this->transformer->transform($productCollection);
|
64 |
+
$resultMessage = $this->writer->write($recordCollection);
|
65 |
+
|
66 |
+
return $resultMessage;
|
67 |
+
}
|
68 |
+
}
|
app/code/community/SearchSpring/Manager/Handler/ApiErrorHandler.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File ApiErrorHandler.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Handler_ApiErrorHandler
|
10 |
+
*
|
11 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
12 |
+
*/
|
13 |
+
class SearchSpring_Manager_Handler_ApiErrorHandler
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* The amount of times we'll try to update before giving up
|
17 |
+
*/
|
18 |
+
const RETRY_LIMIT = 3;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Email to send API failures
|
22 |
+
*/
|
23 |
+
const FAILURE_EMAIL = 'dev-null+alert-email@b7interactive.com';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* The number of times we've tried to update SearchSpring
|
27 |
+
*
|
28 |
+
* @var int
|
29 |
+
*/
|
30 |
+
private $attempts = 0;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Check if we should continue trying based on the response code and number of attempts
|
34 |
+
*
|
35 |
+
* @param string $response
|
36 |
+
*
|
37 |
+
* @return bool
|
38 |
+
*/
|
39 |
+
public function shouldRetry($response)
|
40 |
+
{
|
41 |
+
$responseCode = Zend_Http_Response::extractCode($response);
|
42 |
+
|
43 |
+
if (200 === $responseCode) {
|
44 |
+
return false;
|
45 |
+
}
|
46 |
+
|
47 |
+
++$this->attempts;
|
48 |
+
|
49 |
+
if ($this->attempts < self::RETRY_LIMIT) {
|
50 |
+
return true;
|
51 |
+
}
|
52 |
+
|
53 |
+
$this->notifyUser();
|
54 |
+
$this->email($response);
|
55 |
+
|
56 |
+
return false;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Put a message in the flashbag that there was an issue
|
61 |
+
*/
|
62 |
+
private function notifyUser()
|
63 |
+
{
|
64 |
+
/** @var Mage_Core_Model_Session $session */
|
65 |
+
$session = Mage::getSingleton('core/session');
|
66 |
+
$session->addNotice('There was a problem while trying to update SearchSpring. This issue will be investigated.');
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Send an email that something failed
|
71 |
+
*
|
72 |
+
* @param string $response
|
73 |
+
*
|
74 |
+
* @return bool
|
75 |
+
*/
|
76 |
+
private function email($response)
|
77 |
+
{
|
78 |
+
$templateVars = array('response' => $response);
|
79 |
+
|
80 |
+
/** @var Mage_Core_Model_Email_Template $template */
|
81 |
+
$template = Mage::getModel('core/email_template');
|
82 |
+
$emailTemplate = $template->loadDefault('api_error');
|
83 |
+
$emailTemplate->setData('sender_name', 'System')->setData('sender_email', 'no-reply@b7interactive.com');
|
84 |
+
$emailTemplate->setTemplateType('html')->setTemplateSubject('SearchSpring Magento Live Indexing Error');
|
85 |
+
|
86 |
+
$emailTemplate->send(self::FAILURE_EMAIL, 'SearchSpring', $templateVars);
|
87 |
+
|
88 |
+
return true;
|
89 |
+
}
|
90 |
+
}
|
app/code/community/SearchSpring/Manager/Helper/Data.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File Data.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Helper_Data
|
10 |
+
*
|
11 |
+
* You should need to put anything in this class, but Magento needs to to function.
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Helper_Data extends Mage_Core_Helper_Abstract
|
16 |
+
{
|
17 |
+
|
18 |
+
const XML_PATH_GLOBAL_LIVE_INDEXING_ENABLE_FL = 'ssmanager/ssmanager_general/live_indexing';
|
19 |
+
const XML_PATH_GLOBAL_CATEGORY_ENABLE_FL = 'ssmanager/ssmanager_catalog/enable_categories';
|
20 |
+
|
21 |
+
const XML_PATH_INDEX_ZERO_PRICE = 'ssmanager/ssmanager_general/index_zero_price';
|
22 |
+
|
23 |
+
const XML_PATH_API_FEED_ID = 'ssmanager/ssmanager_api/feed_id';
|
24 |
+
const XML_PATH_API_SITE_ID = 'ssmanager/ssmanager_api/site_id';
|
25 |
+
const XML_PATH_API_BASE_URL = 'ssmanager/ssmanager_api/base_url';
|
26 |
+
const XML_PATH_API_SECRET_KEY = 'ssmanager/ssmanager_api/secret_key';
|
27 |
+
|
28 |
+
const XML_PATH_GENERATE_CACHE_IMAGES = 'ssmanager/ssmanager_images/generate_cache_images';
|
29 |
+
const XML_PATH_IMAGE_WIDTH = 'ssmanager/ssmanager_images/image_width';
|
30 |
+
const XML_PATH_IMAGE_HEIGHT = 'ssmanager/ssmanager_images/image_height';
|
31 |
+
|
32 |
+
const XML_PATH_GENERATE_SWATCH_IMAGES = 'ssmanager/ssmanager_images/generate_swatch_images';
|
33 |
+
const XML_PATH_SWATCH_WIDTH = 'ssmanager/ssmanager_images/swatch_width';
|
34 |
+
const XML_PATH_SWATCH_HEIGHT = 'ssmanager/ssmanager_images/swatch_height';
|
35 |
+
|
36 |
+
public function isLiveIndexingEnabled()
|
37 |
+
{
|
38 |
+
return Mage::getStoreConfigFlag(self::XML_PATH_GLOBAL_LIVE_INDEXING_ENABLE_FL);
|
39 |
+
}
|
40 |
+
|
41 |
+
public function isCategorySearchEnabled()
|
42 |
+
{
|
43 |
+
return Mage::getStoreConfigFlag(self::XML_PATH_GLOBAL_CATEGORY_ENABLE_FL);
|
44 |
+
}
|
45 |
+
|
46 |
+
public function isZeroPriceIndexingEnabled()
|
47 |
+
{
|
48 |
+
return Mage::getStoreConfigFlag(self::XML_PATH_INDEX_ZERO_PRICE);
|
49 |
+
}
|
50 |
+
|
51 |
+
public function getApiFeedId()
|
52 |
+
{
|
53 |
+
return Mage::getStoreConfig(self::XML_PATH_API_FEED_ID);
|
54 |
+
}
|
55 |
+
|
56 |
+
public function getApiSiteId()
|
57 |
+
{
|
58 |
+
return Mage::getStoreConfig(self::XML_PATH_API_SITE_ID);
|
59 |
+
}
|
60 |
+
|
61 |
+
public function getApiBaseUrl()
|
62 |
+
{
|
63 |
+
return Mage::getStoreConfig(self::XML_PATH_API_BASE_URL);
|
64 |
+
}
|
65 |
+
|
66 |
+
public function getApiSecretKey()
|
67 |
+
{
|
68 |
+
return Mage::getStoreConfig(self::XML_PATH_API_SECRET_KEY);
|
69 |
+
}
|
70 |
+
|
71 |
+
public function isCacheImagesEnabled()
|
72 |
+
{
|
73 |
+
return Mage::getStoreConfig(self::XML_PATH_GENERATE_CACHE_IMAGES);
|
74 |
+
}
|
75 |
+
|
76 |
+
public function getImageHeight()
|
77 |
+
{
|
78 |
+
return Mage::getStoreConfig(self::XML_PATH_IMAGE_HEIGHT);
|
79 |
+
}
|
80 |
+
|
81 |
+
public function getImageWidth()
|
82 |
+
{
|
83 |
+
return Mage::getStoreConfig(self::XML_PATH_IMAGE_WIDTH);
|
84 |
+
}
|
85 |
+
|
86 |
+
public function isSwatchImagesEnabled()
|
87 |
+
{
|
88 |
+
return Mage::getStoreConfig(self::XML_PATH_GENERATE_SWATCH_IMAGES);
|
89 |
+
}
|
90 |
+
|
91 |
+
public function getSwatchHeight()
|
92 |
+
{
|
93 |
+
return Mage::getStoreConfig(self::XML_PATH_SWATCH_HEIGHT);
|
94 |
+
}
|
95 |
+
|
96 |
+
public function getSwatchWidth()
|
97 |
+
{
|
98 |
+
return Mage::getStoreConfig(self::XML_PATH_SWATCH_WIDTH);
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Intended for layout action parameter helper calls
|
103 |
+
*
|
104 |
+
* If the current layer category is enabled, return
|
105 |
+
* new template; if not return the blocks existing template
|
106 |
+
*/
|
107 |
+
public function getBlockTemplateIfCategoryEnabled($block, $newTemplate)
|
108 |
+
{
|
109 |
+
$layer = Mage::getSingleton('searchspring_manager/layer');
|
110 |
+
if ($layer->isSearchSpringEnabled()) {
|
111 |
+
return $newTemplate;
|
112 |
+
}
|
113 |
+
return Mage::app()->getLayout()->getBlock($block)->getTemplate();
|
114 |
+
}
|
115 |
+
|
116 |
+
|
117 |
+
}
|
app/code/community/SearchSpring/Manager/Iterator.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File Iterator.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Interface SearchSpring_Manager_Iterator
|
10 |
+
*
|
11 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
12 |
+
*/
|
13 |
+
interface SearchSpring_Manager_Iterator extends Iterator
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* Move the index to the last element
|
17 |
+
*
|
18 |
+
* @return null
|
19 |
+
*/
|
20 |
+
public function end();
|
21 |
+
}
|
app/code/community/SearchSpring/Manager/Model/Catalog/Category/Attribute/EnableSearchSpring/Backend.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SearchSpring_Manager_Model_Catalog_Category_Attribute_EnableSearchSpring_Backend extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract
|
4 |
+
{
|
5 |
+
|
6 |
+
public function afterLoad($object)
|
7 |
+
{
|
8 |
+
parent::afterLoad($object);
|
9 |
+
$attrCode = $this->getAttribute()->getAttributeCode();
|
10 |
+
$rawValue = $object->getData($attrCode);
|
11 |
+
switch ($rawValue) {
|
12 |
+
case SearchSpring_Manager_Model_Catalog_Category_Attribute_EnableSearchSpring_Source::VALUE_ENABLED:
|
13 |
+
$boolValue = true;
|
14 |
+
break;
|
15 |
+
case SearchSpring_Manager_Model_Catalog_Category_Attribute_EnableSearchSpring_Source::VALUE_DISABLED:
|
16 |
+
$boolValue = false;
|
17 |
+
break;
|
18 |
+
default:
|
19 |
+
$boolValue = Mage::helper('searchspring_manager')->isCategorySearchEnabled();
|
20 |
+
break;
|
21 |
+
}
|
22 |
+
$object->setData('is_search_spring_enabled', $boolValue);
|
23 |
+
return $this;
|
24 |
+
}
|
25 |
+
|
26 |
+
}
|
app/code/community/SearchSpring/Manager/Model/Catalog/Category/Attribute/EnableSearchSpring/Source.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class SearchSpring_Manager_Model_Catalog_Category_Attribute_EnableSearchSpring_Source extends Mage_Eav_Model_Entity_Attribute_Source_Abstract {
|
3 |
+
|
4 |
+
const VALUE_CONFIG = 0;
|
5 |
+
const VALUE_DISABLED = 1;
|
6 |
+
const VALUE_ENABLED = 2;
|
7 |
+
|
8 |
+
public function getAllOptions($withEmpty = true)
|
9 |
+
{
|
10 |
+
$options = array(
|
11 |
+
array('label' => 'Use Store SearchSpring Config', 'value' => self::VALUE_CONFIG),
|
12 |
+
array('label' => 'Disabled', 'value' => self::VALUE_DISABLED),
|
13 |
+
array('label' => 'Enabled', 'value' => self::VALUE_ENABLED)
|
14 |
+
);
|
15 |
+
|
16 |
+
return $options;
|
17 |
+
}
|
18 |
+
}
|
app/code/community/SearchSpring/Manager/Model/Layer.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Layer.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Model_Layer
|
10 |
+
*
|
11 |
+
* Overrides existing Layer object
|
12 |
+
*
|
13 |
+
* @author James Bathgate <james@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Model_Layer extends Mage_Catalog_Model_Layer
|
16 |
+
{
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Retrieve current layer search collection
|
20 |
+
*/
|
21 |
+
public function getProductCollection()
|
22 |
+
{
|
23 |
+
if (!$this->isSearchSpringEnabled()) {
|
24 |
+
return parent::getProductCollection();
|
25 |
+
}
|
26 |
+
|
27 |
+
if (isset($this->_productCollections[$this->getCurrentCategory()->getId()])) {
|
28 |
+
$collection = $this->_productCollections[$this->getCurrentCategory()->getId()];
|
29 |
+
} else {
|
30 |
+
$apiFactory = new SearchSpring_Manager_Factory_ApiFactory();
|
31 |
+
$api = $apiFactory->make('search');
|
32 |
+
|
33 |
+
$searchRequestBodyFactory = new SearchSpring_Manager_Factory_SearchRequestBodyFactory();
|
34 |
+
$searchRequestBody = $searchRequestBodyFactory->make();
|
35 |
+
|
36 |
+
$collection = new SearchSpring_Manager_Entity_SearchCollection($api, $searchRequestBody);
|
37 |
+
$collection->addFilter('category_ids', $this->getCurrentCategory()->getId());
|
38 |
+
$collection->addFilterOnly('category_ids', explode(',', $this->getCurrentCategory()->getChildren()));
|
39 |
+
|
40 |
+
$this->_productCollections[$this->getCurrentCategory()->getId()] = $collection;
|
41 |
+
}
|
42 |
+
|
43 |
+
return $collection;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Returns whether SearchSpring is enabled for the current category or not
|
48 |
+
*
|
49 |
+
* @return bool
|
50 |
+
*/
|
51 |
+
public function isSearchSpringEnabled()
|
52 |
+
{
|
53 |
+
return $this->getCurrentCategory()->getIsSearchSpringEnabled();
|
54 |
+
}
|
55 |
+
|
56 |
+
public function getFilterableAttributes()
|
57 |
+
{
|
58 |
+
if($this->isSearchSpringEnabled()) {
|
59 |
+
return $this->getProductCollection()->getResults()->getFacets();
|
60 |
+
} else {
|
61 |
+
return parent::getFilterableAttributes();
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
}
|
app/code/community/SearchSpring/Manager/Model/Layer/Filter/SearchSpring.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SearchSpring_Manager_Model_Layer_Filter_SearchSpring extends Mage_Catalog_Model_Layer_Filter_Abstract
|
4 |
+
{
|
5 |
+
|
6 |
+
protected $_searchSpringFacet;
|
7 |
+
protected $_currentValue;
|
8 |
+
|
9 |
+
protected $_itemModelName = 'searchspring_manager/layer_filter_searchSpringItem';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Apply attribute option to State
|
13 |
+
*
|
14 |
+
* @param Zend_Controller_Request_Abstract $request
|
15 |
+
* @param Varien_Object $filterBlock
|
16 |
+
* @return Mage_Catalog_Model_Layer_Filter_Attribute
|
17 |
+
*/
|
18 |
+
public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
|
19 |
+
{
|
20 |
+
return $this;
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Returns the multiple mode of the SearchSpring Facet
|
25 |
+
*/
|
26 |
+
public function getMultipleMode() {
|
27 |
+
|
28 |
+
return isset($this->_searchSpringFacet->multiple)?$this->_searchSpringFacet->multiple:'single';
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Set searchspring facet data
|
33 |
+
*
|
34 |
+
* @param $facet
|
35 |
+
* @return $this
|
36 |
+
*/
|
37 |
+
public function setSearchSpringFacet($facet) {
|
38 |
+
$this->_searchSpringFacet = $facet;
|
39 |
+
$this->_requestVar = 'filter_' . $facet->field;
|
40 |
+
return $this;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Initialize filter items
|
45 |
+
*
|
46 |
+
* @return Mage_Catalog_Model_Layer_Filter_Abstract
|
47 |
+
*/
|
48 |
+
protected function _initItems()
|
49 |
+
{
|
50 |
+
$data = $this->_getItemsData();
|
51 |
+
$items = array();
|
52 |
+
foreach ($data as $itemData) {
|
53 |
+
$items[] = $this->_createItem(
|
54 |
+
$itemData['label'],
|
55 |
+
$itemData['value'],
|
56 |
+
$itemData['count']
|
57 |
+
);
|
58 |
+
}
|
59 |
+
$this->_items = $items;
|
60 |
+
|
61 |
+
|
62 |
+
return $this;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Create filter item object
|
67 |
+
*
|
68 |
+
* @param string $label
|
69 |
+
* @param mixed $value
|
70 |
+
* @param int $count
|
71 |
+
* @return Mage_Catalog_Model_Layer_Filter_Item
|
72 |
+
*/
|
73 |
+
protected function _createItem($label, $value, $count=0)
|
74 |
+
{
|
75 |
+
$item = Mage::getModel($this->_itemModelName)
|
76 |
+
->setFilter($this)
|
77 |
+
->setLabel($label)
|
78 |
+
->setValue($value)
|
79 |
+
->setCount($count);
|
80 |
+
|
81 |
+
return $item;
|
82 |
+
}
|
83 |
+
|
84 |
+
public function getCurrentValue() {
|
85 |
+
if(!isset($this->_currentValue)) {
|
86 |
+
$this->_currentValue = Mage::app()->getRequest()->getParam($this->getRequestVar());
|
87 |
+
}
|
88 |
+
return $this->_currentValue;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Get data array for building attribute filter items
|
93 |
+
*
|
94 |
+
* @return array
|
95 |
+
*/
|
96 |
+
protected function _getItemsData()
|
97 |
+
{
|
98 |
+
$items = array();
|
99 |
+
|
100 |
+
foreach($this->_searchSpringFacet->values as $value) {
|
101 |
+
$item = array(
|
102 |
+
'label' => $value->label,
|
103 |
+
'count' => $value->count,
|
104 |
+
'type' => $value->type
|
105 |
+
);
|
106 |
+
|
107 |
+
if($value->type == 'value') {
|
108 |
+
$item['value'] = $value->value;
|
109 |
+
} else if($value->type == 'range') {
|
110 |
+
$value = 'RANGE:' . $value->low . ' TO ' . $value->high;
|
111 |
+
/* 'low' => $value->low,
|
112 |
+
'high' => $value->high
|
113 |
+
);*/
|
114 |
+
$item['value'] = $value;
|
115 |
+
}
|
116 |
+
$items[] = $item;
|
117 |
+
}
|
118 |
+
|
119 |
+
return $items;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Return the name of the facet
|
124 |
+
*
|
125 |
+
* @return string
|
126 |
+
*/
|
127 |
+
public function getName() {
|
128 |
+
return $this->_searchSpringFacet->label;
|
129 |
+
}
|
130 |
+
|
131 |
+
}
|
app/code/community/SearchSpring/Manager/Model/Layer/Filter/SearchSpringCategory.php
ADDED
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SearchSpring_Manager_Model_Layer_Filter_SearchSpringCategory extends SearchSpring_Manager_Model_Layer_Filter_SearchSpring
|
4 |
+
{
|
5 |
+
|
6 |
+
protected $_itemModelName = 'searchspring_manager/layer_filter_searchSpringCategoryItem';
|
7 |
+
|
8 |
+
protected $_childCategories = array();
|
9 |
+
|
10 |
+
public function getCurrentValue() {
|
11 |
+
if(!isset($this->_currentValue)) {
|
12 |
+
$this->_currentValue = Mage::app()->getRequest()->getParam($this->getRequestVar());
|
13 |
+
}
|
14 |
+
|
15 |
+
if(is_null($this->_currentValue)) {
|
16 |
+
$this->_currentValue = $this->getLayer()->getCurrentCategory()->getId();
|
17 |
+
}
|
18 |
+
|
19 |
+
return $this->_currentValue;
|
20 |
+
}
|
21 |
+
|
22 |
+
public function getCurrentCategory() {
|
23 |
+
if(!isset($this->_currentCategory)) {
|
24 |
+
$categoryId = $this->getCurrentValue();
|
25 |
+
$this->_currentCategory = Mage::getModel('catalog/category')->load($categoryId);
|
26 |
+
}
|
27 |
+
|
28 |
+
return $this->_currentCategory;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Get data array for building attribute filter items
|
33 |
+
*
|
34 |
+
* @return array
|
35 |
+
*/
|
36 |
+
protected function _getItemsData()
|
37 |
+
{
|
38 |
+
$childCategories = $this->_getChildCategories();
|
39 |
+
|
40 |
+
$items = array();
|
41 |
+
|
42 |
+
foreach($this->_searchSpringFacet->values as $value) {
|
43 |
+
|
44 |
+
if(!isset($this->_childCategories[$value->value])) {
|
45 |
+
continue;
|
46 |
+
}
|
47 |
+
|
48 |
+
$category = $this->_childCategories[$value->value];
|
49 |
+
|
50 |
+
$item = array(
|
51 |
+
'label' => $category->getName(),
|
52 |
+
'count' => $value->count,
|
53 |
+
'type' => $value->type,
|
54 |
+
'value' => $value->value
|
55 |
+
);
|
56 |
+
|
57 |
+
$items[] = $item;
|
58 |
+
}
|
59 |
+
|
60 |
+
return $items;
|
61 |
+
}
|
62 |
+
|
63 |
+
public function getChildCategory($id) {
|
64 |
+
if(empty($this->_childCategories)) {
|
65 |
+
$this->_getChildCategories();
|
66 |
+
}
|
67 |
+
|
68 |
+
return $this->_childCategories[$id];
|
69 |
+
}
|
70 |
+
|
71 |
+
protected function _getChildCategories() {
|
72 |
+
if(empty($this->_childCategories)) {
|
73 |
+
$category = $this->getCurrentCategory();
|
74 |
+
$children = $category->getChildrenCategories();
|
75 |
+
|
76 |
+
foreach ($children as $child) {
|
77 |
+
$this->_childCategories[$child->getId()] = $child;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
return $this->_childCategories;
|
82 |
+
|
83 |
+
}
|
84 |
+
|
85 |
+
public function getParents() {
|
86 |
+
$pathIds = array_reverse(explode(',', $this->getCurrentCategory()->getPathInStore()));
|
87 |
+
$categories = Mage::getResourceModel('catalog/category_collection')
|
88 |
+
->setStore(Mage::app()->getStore())
|
89 |
+
->addAttributeToSelect('name')
|
90 |
+
->addAttributeToSelect('url_key')
|
91 |
+
->addFieldToFilter('entity_id', array('in' => $pathIds))
|
92 |
+
->addFieldToFilter('is_active', 1)
|
93 |
+
->setOrder('level')
|
94 |
+
->load()
|
95 |
+
->getItems();
|
96 |
+
|
97 |
+
return $categories;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Return the name of the facet
|
102 |
+
*
|
103 |
+
* @return string
|
104 |
+
*/
|
105 |
+
public function getName() {
|
106 |
+
return $this->__('Category');
|
107 |
+
}
|
108 |
+
|
109 |
+
}
|
app/code/community/SearchSpring/Manager/Model/Layer/Filter/SearchSpringCategoryItem.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SearchSpring_Manager_Model_Layer_Filter_SearchSpringCategoryItem extends SearchSpring_Manager_Model_Layer_Filter_SearchSpringItem
|
4 |
+
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Get filter item url
|
8 |
+
*
|
9 |
+
* @return string
|
10 |
+
*/
|
11 |
+
public function getUrl()
|
12 |
+
{
|
13 |
+
|
14 |
+
$query = array(
|
15 |
+
Mage::getBlockSingleton('page/html_pager')->getPageVarName() => null // exclude current page from urls
|
16 |
+
);
|
17 |
+
|
18 |
+
$url = Mage::getUrl('',
|
19 |
+
array(
|
20 |
+
'_current' => true,
|
21 |
+
'_direct' => Mage::getModel('core/url_rewrite')->loadByIdPath('category/' . $this->getValue())->getRequestPath(),
|
22 |
+
'_query' => $query
|
23 |
+
)
|
24 |
+
);
|
25 |
+
|
26 |
+
return $url;
|
27 |
+
}
|
28 |
+
|
29 |
+
}
|
app/code/community/SearchSpring/Manager/Model/Layer/Filter/SearchSpringItem.php
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SearchSpring_Manager_Model_Layer_Filter_SearchSpringItem extends Mage_Catalog_Model_Layer_Filter_Item
|
4 |
+
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Get filter item url
|
8 |
+
*
|
9 |
+
* @return string
|
10 |
+
*/
|
11 |
+
public function getUrl()
|
12 |
+
{
|
13 |
+
$value = $this->_getUrlValue();
|
14 |
+
|
15 |
+
$query = array(
|
16 |
+
$this->getFilter()->getRequestVar() => $value,
|
17 |
+
Mage::getBlockSingleton('page/html_pager')->getPageVarName() => null // exclude current page from urls
|
18 |
+
);
|
19 |
+
|
20 |
+
$url = Mage::getUrl('*/*/*', array('_current'=>true, '_use_rewrite'=>true, '_query'=>$query));
|
21 |
+
|
22 |
+
return $url;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Get url for remove item from filter
|
27 |
+
*
|
28 |
+
* @return string
|
29 |
+
*/
|
30 |
+
public function getRemoveUrl()
|
31 |
+
{
|
32 |
+
// Get URL knows if the current value is already selected and will remove it as part of the URL.
|
33 |
+
return $this->getUrl();
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Returns true if the current value item is active
|
38 |
+
*/
|
39 |
+
public function isActive() {
|
40 |
+
$currentValue = $this->getFilter()->getCurrentValue();
|
41 |
+
$itemValue = $this->getValue();
|
42 |
+
|
43 |
+
return $this->_containsValue($currentValue, $itemValue);
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Get the value to set for the URL if the current item is selected.
|
48 |
+
*/
|
49 |
+
protected function _getUrlValue() {
|
50 |
+
$currentValue = $this->getFilter()->getCurrentValue();
|
51 |
+
$itemValue = $this->getValue();
|
52 |
+
|
53 |
+
if($this->_containsValue($currentValue, $itemValue)) {
|
54 |
+
return $this->_removeValue($currentValue, $itemValue);
|
55 |
+
} else {
|
56 |
+
return $this->_addValue($currentValue, $itemValue);
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Return the current value
|
62 |
+
*/
|
63 |
+
public function getValue() {
|
64 |
+
$value = parent::getValue();
|
65 |
+
if(isset($value->rangeLow)) {
|
66 |
+
$value = 'RANGE:' . $value->rangeLow . ' TO ' . $value->rangeHigh;
|
67 |
+
}
|
68 |
+
return $value;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Check if itemValue is contained in the currentValue
|
73 |
+
*
|
74 |
+
* @param $currentValue
|
75 |
+
* @param $itemValue
|
76 |
+
* @return bool
|
77 |
+
*/
|
78 |
+
protected function _containsValue($currentValue, $itemValue) {
|
79 |
+
if(is_null($currentValue)) {
|
80 |
+
return false;
|
81 |
+
} else if(!is_array($currentValue)) {
|
82 |
+
return $currentValue == $itemValue;
|
83 |
+
} else {
|
84 |
+
return in_array($itemValue, $currentValue);
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Remove itemValue from the currentValue
|
90 |
+
*
|
91 |
+
* @param $currentValue
|
92 |
+
* @param $itemValue
|
93 |
+
* @return mixed
|
94 |
+
*/
|
95 |
+
protected function _removeValue($currentValue, $itemValue) {
|
96 |
+
if(!is_array($currentValue)) {
|
97 |
+
return null;
|
98 |
+
} else {
|
99 |
+
unset($currentValue[array_search($itemValue, $currentValue)]);
|
100 |
+
return $currentValue;
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Add itemValue to the currentValue
|
106 |
+
*
|
107 |
+
* @param $currentValue
|
108 |
+
* @param $itemValue
|
109 |
+
* @return mixed
|
110 |
+
*/
|
111 |
+
protected function _addValue($currentValue, $itemValue) {
|
112 |
+
if ($this->getFilter()->getMultipleMode() == 'multiple-intersect' || $this->getFilter()->getMultipleMode() == 'multiple-union') {
|
113 |
+
if (is_null($currentValue)) {
|
114 |
+
$currentValue = $itemValue;
|
115 |
+
} else if (!is_array($currentValue)) {
|
116 |
+
$currentValue = array($currentValue, $itemValue);
|
117 |
+
} else {
|
118 |
+
$currentValue[] = $itemValue;
|
119 |
+
}
|
120 |
+
} else {
|
121 |
+
$currentValue = $itemValue;
|
122 |
+
}
|
123 |
+
return $currentValue;
|
124 |
+
}
|
125 |
+
|
126 |
+
}
|
app/code/community/SearchSpring/Manager/Model/Observer/CategorySaveObserver.php
ADDED
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* CategorySaveObserver.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Model_Observer_CategorySaveObserver
|
10 |
+
*
|
11 |
+
* On a category change, trigger one of these methods
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Model_Observer_CategorySaveObserver extends SearchSpring_Manager_Model_Observer_LiveIndexer
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Performs operations on a Varien_Object
|
19 |
+
*
|
20 |
+
* @var SearchSpring_Manager_VarienObject_Data $varienObjectData
|
21 |
+
*/
|
22 |
+
private $varienObjectData;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Api adapter for connecting to SearchSpring api
|
26 |
+
*
|
27 |
+
* @var SearchSpring_Manager_Service_SearchSpring_IndexingApiAdapter $api
|
28 |
+
*/
|
29 |
+
private $api;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Create a request body
|
33 |
+
*
|
34 |
+
* @var SearchSpring_Manager_Factory_IndexingRequestBodyFactory $requestBodyFactory
|
35 |
+
*/
|
36 |
+
private $requestBodyFactory;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Constructor
|
40 |
+
*/
|
41 |
+
public function __construct()
|
42 |
+
{
|
43 |
+
$apiFactory = new SearchSpring_Manager_Factory_ApiFactory();
|
44 |
+
$this->api = $apiFactory->make('index');
|
45 |
+
$this->requestBodyFactory = new SearchSpring_Manager_Factory_IndexingRequestBodyFactory();
|
46 |
+
$this->varienObjectData = new SearchSpring_Manager_VarienObject_Data();
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* After a category is saved
|
51 |
+
*
|
52 |
+
* We only push out an update to products and sub-products if the category name or status has changed
|
53 |
+
*
|
54 |
+
* @todo implement status change
|
55 |
+
*
|
56 |
+
* @param Varien_Event_Observer $productEvent
|
57 |
+
*
|
58 |
+
* @return bool
|
59 |
+
*/
|
60 |
+
public function afterSaveUpdateProductCategory(Varien_Event_Observer $productEvent)
|
61 |
+
{
|
62 |
+
if (!$this->isEnabled()) {
|
63 |
+
return true;
|
64 |
+
}
|
65 |
+
|
66 |
+
/** @var Mage_Catalog_Model_Category $category */
|
67 |
+
$category = $productEvent->getData('category');
|
68 |
+
|
69 |
+
// if this is a new category return because we already sent the ids
|
70 |
+
if (true === $this->varienObjectData->isNew($category)) {
|
71 |
+
return true;
|
72 |
+
}
|
73 |
+
|
74 |
+
$updates = $this->varienObjectData->findUpdatedData($category);
|
75 |
+
|
76 |
+
// if category name is not changed, this will not affect the product categories
|
77 |
+
if (!isset($updates['name']) && !isset($updates['is_active'])) {
|
78 |
+
return true;
|
79 |
+
}
|
80 |
+
|
81 |
+
$requestBody = $this->requestBodyFactory->make(
|
82 |
+
SearchSpring_Manager_Entity_IndexingRequestBody::TYPE_CATEGORY,
|
83 |
+
$category->getAllChildren(true)
|
84 |
+
);
|
85 |
+
$this->api->pushIds($requestBody);
|
86 |
+
|
87 |
+
return true;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* After category products have changed
|
92 |
+
*
|
93 |
+
* This is triggered when products are checked or unchecked for a category. Only affects products of category.
|
94 |
+
*
|
95 |
+
* @param Varien_Event_Observer $productEvent
|
96 |
+
*
|
97 |
+
* @return bool
|
98 |
+
*/
|
99 |
+
public function afterProductChangeUpdateProductCategory(Varien_Event_Observer $productEvent)
|
100 |
+
{
|
101 |
+
if (!$this->isEnabled()) {
|
102 |
+
return true;
|
103 |
+
}
|
104 |
+
|
105 |
+
$validator = new SearchSpring_Manager_Validator_ProductValidator();
|
106 |
+
|
107 |
+
$productIds = $productEvent->getData('product_ids');
|
108 |
+
foreach($productIds as $k => $productId) {
|
109 |
+
$product = Mage::getModel('catalog/product')->load($productId);
|
110 |
+
if(!$validator->isValid($product)) {
|
111 |
+
unset($productIds[$k]);
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
$requestBody = $this->requestBodyFactory->make(
|
116 |
+
SearchSpring_Manager_Entity_IndexingRequestBody::TYPE_PRODUCT,
|
117 |
+
$productIds
|
118 |
+
);
|
119 |
+
|
120 |
+
$this->api->pushIds($requestBody);
|
121 |
+
|
122 |
+
return true;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* After a category is moved
|
127 |
+
*
|
128 |
+
* Updates products and sub-products. Only update if path is changed. This should be double checked, but path
|
129 |
+
* should not be changed if the category is just reordered.
|
130 |
+
*
|
131 |
+
* @param Varien_Event_Observer $productEvent
|
132 |
+
*
|
133 |
+
* @return bool
|
134 |
+
*/
|
135 |
+
public function afterMoveUpdateProductCategory(Varien_Event_Observer $productEvent)
|
136 |
+
{
|
137 |
+
if (!$this->isEnabled()) {
|
138 |
+
return true;
|
139 |
+
}
|
140 |
+
|
141 |
+
$category = $productEvent->getData('category');
|
142 |
+
$updates = $this->varienObjectData->findUpdatedData($category);
|
143 |
+
|
144 |
+
if (!isset($updates['path'])) {
|
145 |
+
return true;
|
146 |
+
}
|
147 |
+
|
148 |
+
$requestBody = $this->requestBodyFactory->make(
|
149 |
+
SearchSpring_Manager_Entity_IndexingRequestBody::TYPE_CATEGORY,
|
150 |
+
$category->getAllChildren(true)
|
151 |
+
);
|
152 |
+
$this->api->pushIds($requestBody);
|
153 |
+
|
154 |
+
return true;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* After a category is deleted
|
159 |
+
*
|
160 |
+
* Remove the category from products and sub-products.
|
161 |
+
*
|
162 |
+
* @param Varien_Event_Observer $productEvent
|
163 |
+
* @return bool
|
164 |
+
*/
|
165 |
+
public function afterDeleteUpdateProductCategory(Varien_Event_Observer $productEvent)
|
166 |
+
{
|
167 |
+
if (!$this->isEnabled()) {
|
168 |
+
return true;
|
169 |
+
}
|
170 |
+
|
171 |
+
/** @var Mage_Catalog_Model_Category $category */
|
172 |
+
$category = $productEvent->getData('category');
|
173 |
+
$requestBody = $this->requestBodyFactory->make(
|
174 |
+
SearchSpring_Manager_Entity_IndexingRequestBody::TYPE_PRODUCT,
|
175 |
+
$this->getCategoryProductIds($category)
|
176 |
+
);
|
177 |
+
$this->api->pushIds($requestBody);
|
178 |
+
|
179 |
+
return true;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Get product ids for category and subcategories
|
184 |
+
*
|
185 |
+
* @param Mage_Catalog_Model_Category $category
|
186 |
+
*
|
187 |
+
* @return array
|
188 |
+
*/
|
189 |
+
private function getCategoryProductIds(Mage_Catalog_Model_Category $category)
|
190 |
+
{
|
191 |
+
/** @var Mage_Catalog_Model_Resource_Product_Collection $collection */
|
192 |
+
$collection = mage::getModel('catalog/product')->getCollection()
|
193 |
+
->addAttributeToSelect('*')
|
194 |
+
->joinField('category_id', 'catalog/category_product', 'category_id', 'product_id=entity_id', null, 'left')
|
195 |
+
->addAttributeToFilter('category_id', array('in' => $category->getAllChildren(true)));
|
196 |
+
$collection->getSelect()->group('e.entity_id');
|
197 |
+
$productIds = $collection->load()->getAllIds();
|
198 |
+
|
199 |
+
return $productIds;
|
200 |
+
}
|
201 |
+
|
202 |
+
}
|
app/code/community/SearchSpring/Manager/Model/Observer/LiveIndexer.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* LiveIndexer.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Model_Observer_LiveIndexer
|
10 |
+
*
|
11 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
12 |
+
*/
|
13 |
+
abstract class SearchSpring_Manager_Model_Observer_LiveIndexer
|
14 |
+
{
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Checks if live indexing is enabled
|
18 |
+
*
|
19 |
+
* @return bool
|
20 |
+
*/
|
21 |
+
protected function isEnabled()
|
22 |
+
{
|
23 |
+
return Mage::helper('searchspring_manager')->isLiveIndexingEnabled();
|
24 |
+
}
|
25 |
+
|
26 |
+
}
|
app/code/community/SearchSpring/Manager/Model/Observer/ProductSaveObserver.php
ADDED
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File ProductSaveObserver.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Model_Observer_ProductSaveObserver
|
10 |
+
*
|
11 |
+
* Listens for product save events and pushes ids to api
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Model_Observer_ProductSaveObserver extends SearchSpring_Manager_Model_Observer_LiveIndexer
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Create an api adapter for SearchSpring
|
19 |
+
*
|
20 |
+
* @var SearchSpring_Manager_Service_SearchSpring_IndexingApiAdapter $api
|
21 |
+
*/
|
22 |
+
private $api;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Creates a request body
|
26 |
+
*
|
27 |
+
* @var SearchSpring_Manager_Factory_IndexingRequestBodyFactory
|
28 |
+
*/
|
29 |
+
private $requestBodyFactory;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* List of parentIds for the updated product.
|
33 |
+
* @var array
|
34 |
+
*/
|
35 |
+
protected $_productIds = array();
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Constructor
|
39 |
+
*
|
40 |
+
* We need to do some setup in here because there's no way to inject dependencies
|
41 |
+
*/
|
42 |
+
public function __construct()
|
43 |
+
{
|
44 |
+
$apiFactory = new SearchSpring_Manager_Factory_ApiFactory();
|
45 |
+
$this->api = $apiFactory->make('index');
|
46 |
+
$this->requestBodyFactory = new SearchSpring_Manager_Factory_IndexingRequestBodyFactory();
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* After a product is saved, push that product to the SearchSpring API
|
51 |
+
*
|
52 |
+
* @param Varien_Event_Observer $productEvent The product event data
|
53 |
+
*
|
54 |
+
* @return bool
|
55 |
+
*/
|
56 |
+
public function afterSavePushProduct(Varien_Event_Observer $productEvent)
|
57 |
+
{
|
58 |
+
if (!$this->isEnabled()) {
|
59 |
+
return true;
|
60 |
+
}
|
61 |
+
|
62 |
+
$product = $productEvent->getData('product');
|
63 |
+
$this->_productIds = $this->_getProductIds($product);
|
64 |
+
|
65 |
+
$this->_handleProductChange();
|
66 |
+
return true;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Before a product is deleted grab all IDs
|
71 |
+
*
|
72 |
+
* @param Varien_Event_Observer $productEvent The product event data
|
73 |
+
*
|
74 |
+
* @return bool
|
75 |
+
*/
|
76 |
+
public function beforeDeletePushProduct(Varien_Event_Observer $productEvent) {
|
77 |
+
$product = $productEvent->getData('product');
|
78 |
+
$this->_productIds = $this->_getProductIds($product);
|
79 |
+
return true;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* After a product is deleted, push that product delete to the SearchSpring API
|
84 |
+
*
|
85 |
+
* @param Varien_Event_Observer $productEvent The product event data
|
86 |
+
*
|
87 |
+
* @return bool
|
88 |
+
*/
|
89 |
+
public function afterDeletePushProduct(Varien_Event_Observer $productEvent)
|
90 |
+
{
|
91 |
+
if (!$this->isEnabled()) {
|
92 |
+
return true;
|
93 |
+
}
|
94 |
+
|
95 |
+
$this->_handleProductChange();
|
96 |
+
return true;
|
97 |
+
}
|
98 |
+
|
99 |
+
protected function _handleProductChange() {
|
100 |
+
$productIds = $this->_getActions();
|
101 |
+
|
102 |
+
// create the request body with product ids
|
103 |
+
if(!empty($productIds['delete'])) {
|
104 |
+
$requestBody = $this->requestBodyFactory->make(
|
105 |
+
SearchSpring_Manager_Entity_IndexingRequestBody::TYPE_PRODUCT,
|
106 |
+
$productIds['delete'],
|
107 |
+
true
|
108 |
+
);
|
109 |
+
}
|
110 |
+
|
111 |
+
// create the request body with product ids
|
112 |
+
if(!empty($productIds['update'])) {
|
113 |
+
$requestBody = $this->requestBodyFactory->make(
|
114 |
+
SearchSpring_Manager_Entity_IndexingRequestBody::TYPE_PRODUCT,
|
115 |
+
$productIds['update']
|
116 |
+
);
|
117 |
+
}
|
118 |
+
|
119 |
+
// send ids to api
|
120 |
+
$this->api->pushIds($requestBody);
|
121 |
+
|
122 |
+
return true;
|
123 |
+
}
|
124 |
+
|
125 |
+
protected function _getProductIds($product) {
|
126 |
+
$productIds = array();
|
127 |
+
// If the product is a simple product we may need to check its parent(s)
|
128 |
+
if($product->getTypeId() == "simple"){
|
129 |
+
// Check for configurable parent
|
130 |
+
$productIds = Mage::getModel('catalog/product_type_configurable')->getParentIdsByChild($product->getId());
|
131 |
+
|
132 |
+
// If there are no configurable parents check grouped
|
133 |
+
if(empty($productIds)) {
|
134 |
+
$productIds = Mage::getModel('catalog/product_type_grouped')->getParentIdsByChild($product->getId());
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
$productIds[] = $product->getId();
|
139 |
+
|
140 |
+
return $productIds;
|
141 |
+
}
|
142 |
+
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Get list of update/deletes for product and parents.
|
146 |
+
*
|
147 |
+
* @param Mage_Catalog_Model_Product $product The product being updated
|
148 |
+
*
|
149 |
+
* @return array
|
150 |
+
*/
|
151 |
+
protected function _getActions() {
|
152 |
+
$productActions = array();
|
153 |
+
|
154 |
+
$validator = new SearchSpring_Manager_Validator_ProductValidator();
|
155 |
+
|
156 |
+
// Figure out deletes
|
157 |
+
foreach($this->_productIds as $productId) {
|
158 |
+
$product = Mage::getModel('catalog/product')->load($productId);
|
159 |
+
|
160 |
+
$isValid = $validator->isValid(
|
161 |
+
$product
|
162 |
+
);
|
163 |
+
|
164 |
+
if(!$isValid) {
|
165 |
+
$productActions['delete'][] = $productId;
|
166 |
+
} else {
|
167 |
+
$pricingStrategy = SearchSpring_Manager_Factory_PricingFactory::make($product);
|
168 |
+
$pricingStrategy->calculatePrices();
|
169 |
+
|
170 |
+
// Only check should delete if the product is otherwise valid
|
171 |
+
$shouldDelete = $validator->shouldDelete(
|
172 |
+
$product,
|
173 |
+
$pricingStrategy
|
174 |
+
);
|
175 |
+
|
176 |
+
if($shouldDelete) {
|
177 |
+
$productActions['delete'][] = $productId;
|
178 |
+
} else {
|
179 |
+
$productActions['update'][] = $productId;
|
180 |
+
}
|
181 |
+
}
|
182 |
+
}
|
183 |
+
|
184 |
+
return $productActions;
|
185 |
+
}
|
186 |
+
}
|
app/code/community/SearchSpring/Manager/Operation/Product.php
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Product.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Operation_Product
|
10 |
+
*
|
11 |
+
* Abstract class for all product operations
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
abstract class SearchSpring_Manager_Operation_Product implements SearchSpring_Manager_Operation_ProductOperation
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* SearchSpring operation class prefix
|
19 |
+
*/
|
20 |
+
const OPERATION_CLASS_PREFIX = 'SearchSpring_Manager_Operation_Product_';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Service to sanitize string data
|
24 |
+
*
|
25 |
+
* @var SearchSpring_Manager_String_Sanitizer
|
26 |
+
*/
|
27 |
+
private $sanitizer;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Records collection
|
31 |
+
*
|
32 |
+
* @var SearchSpring_Manager_Entity_RecordsCollection $records
|
33 |
+
*/
|
34 |
+
private $records;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* An array of additional data
|
38 |
+
*
|
39 |
+
* @var array $parameters
|
40 |
+
*/
|
41 |
+
private $parameters;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Constructor
|
45 |
+
*
|
46 |
+
* @param SearchSpring_Manager_String_Sanitizer $sanitizer
|
47 |
+
* @param SearchSpring_Manager_Entity_RecordsCollection $records
|
48 |
+
* @param array $parameters
|
49 |
+
*/
|
50 |
+
public function __construct(
|
51 |
+
SearchSpring_Manager_String_Sanitizer $sanitizer,
|
52 |
+
SearchSpring_Manager_Entity_RecordsCollection $records,
|
53 |
+
array $parameters = array()
|
54 |
+
) {
|
55 |
+
$this->sanitizer = $sanitizer;
|
56 |
+
$this->records = $records;
|
57 |
+
$this->parameters = $parameters;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Overridable method to determine if an operation is valid for the product
|
62 |
+
*
|
63 |
+
* Will allow operations to cancel adding a product record. Defaults to true.
|
64 |
+
*
|
65 |
+
* @param Mage_Catalog_Model_Product $product
|
66 |
+
*
|
67 |
+
* @return bool
|
68 |
+
*/
|
69 |
+
public function isValid(Mage_Catalog_Model_Product $product)
|
70 |
+
{
|
71 |
+
return true;
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Get records collection
|
76 |
+
*
|
77 |
+
* @return SearchSpring_Manager_Entity_RecordsCollection
|
78 |
+
*/
|
79 |
+
protected final function getRecords()
|
80 |
+
{
|
81 |
+
return $this->records;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* {@inheritdoc}
|
86 |
+
*/
|
87 |
+
public final function setRecords(SearchSpring_Manager_Entity_RecordsCollection $records)
|
88 |
+
{
|
89 |
+
$this->records = $records;
|
90 |
+
|
91 |
+
return $this;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Get the sanitizer
|
96 |
+
*
|
97 |
+
* @return SearchSpring_Manager_String_Sanitizer
|
98 |
+
*/
|
99 |
+
protected final function getSanitizer()
|
100 |
+
{
|
101 |
+
return $this->sanitizer;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Get a parameter from array
|
106 |
+
*
|
107 |
+
* @param string $key
|
108 |
+
*
|
109 |
+
* @return mixed
|
110 |
+
*
|
111 |
+
* @throws InvalidArgumentException If the key does not exist
|
112 |
+
*/
|
113 |
+
protected final function getParameter($key)
|
114 |
+
{
|
115 |
+
if (!isset($this->parameters[$key])) {
|
116 |
+
throw new InvalidArgumentException('Key does not exist');
|
117 |
+
}
|
118 |
+
|
119 |
+
return $this->parameters[$key];
|
120 |
+
}
|
121 |
+
}
|
app/code/community/SearchSpring/Manager/Operation/Product/SetCategories.php
ADDED
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* SetCategories.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Operation_Product_SetCategories
|
10 |
+
*
|
11 |
+
* Set category data to the feed
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Operation_Product_SetCategories extends SearchSpring_Manager_Operation_Product
|
16 |
+
{
|
17 |
+
/**#@+
|
18 |
+
* Feed Constants
|
19 |
+
*/
|
20 |
+
const FEED_CATEGORY_HIERARCHY = 'category_hierarchy';
|
21 |
+
const FEED_CATEGORY_NAME = 'category_name';
|
22 |
+
const FEED_CATEGORY_IDS = 'category_ids';
|
23 |
+
/**#@-*/
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Category names we should skip
|
27 |
+
*
|
28 |
+
* @var array
|
29 |
+
*/
|
30 |
+
private $skipCategories = array('Root Catalog', 'Default Category', null);
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Sets category data to feed
|
34 |
+
* - category_hierarchy
|
35 |
+
* - category_name
|
36 |
+
*
|
37 |
+
* @param Mage_Catalog_Model_Product $product
|
38 |
+
*
|
39 |
+
* @return $this
|
40 |
+
*/
|
41 |
+
public function perform(Mage_Catalog_Model_Product $product)
|
42 |
+
{
|
43 |
+
$categoryHierarchies = array();
|
44 |
+
$categoryNames = array();
|
45 |
+
$categoryIds = array();
|
46 |
+
|
47 |
+
|
48 |
+
/** @var Mage_Catalog_Model_Category $category */
|
49 |
+
foreach($product->getCategoryIds() as $categoryId) {
|
50 |
+
// load category data
|
51 |
+
$category = Mage::getModel('catalog/category')->load($categoryId);
|
52 |
+
|
53 |
+
if (!$category->getData('is_active')) {
|
54 |
+
continue;
|
55 |
+
}
|
56 |
+
|
57 |
+
$categoryName = $category->getData('name');
|
58 |
+
if (in_array($categoryName, $this->skipCategories)) {
|
59 |
+
continue;
|
60 |
+
}
|
61 |
+
|
62 |
+
$categoryPath = $category->getPathIds();
|
63 |
+
|
64 |
+
$categoryIds = array_merge($categoryIds, $categoryPath);
|
65 |
+
|
66 |
+
$hierarchies = $this->buildCategoryHierarchy($categoryPath);
|
67 |
+
|
68 |
+
foreach ($hierarchies as $value) {
|
69 |
+
$categoryHierarchies[] = $value;
|
70 |
+
}
|
71 |
+
|
72 |
+
$categoryNames[] = $categoryName;
|
73 |
+
}
|
74 |
+
|
75 |
+
$categoryHierarchies = array_unique($categoryHierarchies);
|
76 |
+
|
77 |
+
if (empty($categoryHierarchies)) {
|
78 |
+
$this->getRecords()->set(self::FEED_CATEGORY_HIERARCHY, $categoryHierarchies);
|
79 |
+
}
|
80 |
+
|
81 |
+
// we need to do an additional loop here because array_unique preserves keys
|
82 |
+
// this causes an issue when converting to json as it will create an object if keys aren't sequential
|
83 |
+
foreach ($categoryHierarchies as $hierarchy) {
|
84 |
+
$this->getRecords()->add(self::FEED_CATEGORY_HIERARCHY, $hierarchy);
|
85 |
+
}
|
86 |
+
|
87 |
+
$this->getRecords()->set(self::FEED_CATEGORY_IDS, array_values(array_unique($categoryIds)));
|
88 |
+
|
89 |
+
$this->getRecords()->set(self::FEED_CATEGORY_NAME, $categoryNames);
|
90 |
+
|
91 |
+
return $this;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Build the category hierarchy based on path
|
96 |
+
*
|
97 |
+
* Will return an array with all levels
|
98 |
+
*
|
99 |
+
* Example:
|
100 |
+
* Level 1
|
101 |
+
* Level 1 | Level 2
|
102 |
+
* Level 1 | Level 2 | Level 3
|
103 |
+
*
|
104 |
+
* @param array $categoryPath
|
105 |
+
*
|
106 |
+
* @return array
|
107 |
+
*/
|
108 |
+
private function buildCategoryHierarchy(array $categoryPath)
|
109 |
+
{
|
110 |
+
$hierarchy = array();
|
111 |
+
$currentHierarchy = array();
|
112 |
+
foreach ($categoryPath as $categoryId) {
|
113 |
+
$category = Mage::getModel('catalog/category')->load($categoryId);
|
114 |
+
|
115 |
+
$categoryName = $category->getData('name');
|
116 |
+
if (in_array($categoryName, $this->skipCategories)) {
|
117 |
+
continue;
|
118 |
+
}
|
119 |
+
$currentHierarchy[] = $categoryName;
|
120 |
+
$hierarchy[] = implode('/', $currentHierarchy);
|
121 |
+
}
|
122 |
+
|
123 |
+
return $hierarchy;
|
124 |
+
}
|
125 |
+
}
|
app/code/community/SearchSpring/Manager/Operation/Product/SetCoreFields.php
ADDED
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* SetCoreFields.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Operation_Product_SetCoreFields
|
10 |
+
*
|
11 |
+
* Set SearchSpring core fields to the feed
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Operation_Product_SetCoreFields extends SearchSpring_Manager_Operation_Product
|
16 |
+
{
|
17 |
+
/**#@+
|
18 |
+
* Feed constants
|
19 |
+
*/
|
20 |
+
const FEED_SKU = 'sku';
|
21 |
+
const FEED_PRODUCT_TYPE = 'product_type';
|
22 |
+
const FEED_DESCRIPTION = 'description';
|
23 |
+
const FEED_SHORT_DESCRIPTION = 'short_description';
|
24 |
+
const FEED_QUANTITY = 'quantity';
|
25 |
+
const FEED_IN_STOCK = 'in_stock';
|
26 |
+
const FEED_WEIGHT = 'weight';
|
27 |
+
const FEED_MANUFACTURER = 'manufacturer';
|
28 |
+
const FEED_URL = 'url';
|
29 |
+
const FEED_NAME = 'name';
|
30 |
+
const FEED_CHILD_QUANTITY = 'child_quantity';
|
31 |
+
const FEED_CHILD_SKU = 'child_sku';
|
32 |
+
const FEED_CHILD_NAME = 'child_name';
|
33 |
+
/**#@-*/
|
34 |
+
|
35 |
+
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Add SearchSpring core fields to the feed
|
39 |
+
* - sku
|
40 |
+
* - product_type
|
41 |
+
* - quantity
|
42 |
+
* - in_stock
|
43 |
+
* - weight
|
44 |
+
* - manufacturer
|
45 |
+
* - url
|
46 |
+
* - url
|
47 |
+
* - image_url
|
48 |
+
* - thumbnail_url
|
49 |
+
* - cached_thumbnail_url
|
50 |
+
* - name
|
51 |
+
* - description
|
52 |
+
* - short_description
|
53 |
+
* - child_quantity
|
54 |
+
* - child_name
|
55 |
+
* - child_sku
|
56 |
+
*
|
57 |
+
* @param Mage_Catalog_Model_Product $product
|
58 |
+
*
|
59 |
+
* @return $this
|
60 |
+
*/
|
61 |
+
public function perform(Mage_Catalog_Model_Product $product)
|
62 |
+
{
|
63 |
+
$webBaseUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
|
64 |
+
|
65 |
+
$this->getRecords()->set(self::FEED_SKU, $product->getSku());
|
66 |
+
$this->getRecords()->set(self::FEED_PRODUCT_TYPE, $product->getData('type_id'));
|
67 |
+
$this->getRecords()->set(self::FEED_QUANTITY, number_format($this->getQuantity($product)));
|
68 |
+
$this->getRecords()->set(self::FEED_IN_STOCK, $product->isInStock());
|
69 |
+
$this->getRecords()->set(self::FEED_WEIGHT, number_format((double)$product->getWeight(), 2));
|
70 |
+
$this->getRecords()->set(self::FEED_MANUFACTURER, $product->getAttributeText('manufacturer'));
|
71 |
+
$this->getRecords()->set(self::FEED_URL, $webBaseUrl . $product->getUrlPath());
|
72 |
+
|
73 |
+
$productName = $this->getSanitizer()->removeNewlinesAndStripTags($product->getName());
|
74 |
+
$description = $this->getSanitizer()->sanitizeForRequest($product->getData('description'));
|
75 |
+
$shortDescription = $this->getSanitizer()->sanitizeForRequest($product->getData('short_description'));
|
76 |
+
$this->getRecords()->set(self::FEED_NAME, $productName);
|
77 |
+
$this->getRecords()->set(self::FEED_DESCRIPTION, $description);
|
78 |
+
$this->getRecords()->set(self::FEED_SHORT_DESCRIPTION, $shortDescription);
|
79 |
+
|
80 |
+
$this->setChildQuantity($product);
|
81 |
+
|
82 |
+
return $this;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Helper method to get the quantity from a product
|
87 |
+
*
|
88 |
+
* @param Mage_Catalog_Model_Product $product
|
89 |
+
* @return int
|
90 |
+
*/
|
91 |
+
private function getQuantity(Mage_Catalog_Model_Product $product)
|
92 |
+
{
|
93 |
+
$quantity = $product->getData('stock_item')->getData('qty');
|
94 |
+
|
95 |
+
return (int)$quantity;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* If the product is composite, find the child quantities and set that to the field
|
100 |
+
*/
|
101 |
+
private function setChildQuantity(Mage_Catalog_Model_Product $product)
|
102 |
+
{
|
103 |
+
// default to normal quantity
|
104 |
+
$childQuantity = $this->getRecords()->get(self::FEED_QUANTITY);
|
105 |
+
|
106 |
+
// find the child quantity if it exists
|
107 |
+
switch ($product->getTypeId()) {
|
108 |
+
case Mage_Catalog_Model_Product_Type::TYPE_GROUPED:
|
109 |
+
/** @var Mage_Catalog_Model_Product_Type_Grouped $typeInstance */
|
110 |
+
$typeInstance = $product->getTypeInstance(true);
|
111 |
+
$associated = $typeInstance->getAssociatedProducts($product);
|
112 |
+
$childQuantity = $this->getQuantityForChildren($associated);
|
113 |
+
|
114 |
+
break;
|
115 |
+
case Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE:
|
116 |
+
/** @var Mage_Catalog_Model_Product_Type_Configurable $typeInstance */
|
117 |
+
$typeInstance = $product->getTypeInstance(true);
|
118 |
+
|
119 |
+
/** @var Mage_Catalog_Model_Product_Type_Configurable_Attribute $attribute */
|
120 |
+
foreach ($typeInstance->getConfigurableAttributesAsArray($product) as $attribute) {
|
121 |
+
foreach ($attribute['values'] as $value) {
|
122 |
+
$this->getRecords()->add($attribute['attribute_code'], $value['label']);
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
$children = $typeInstance->getUsedProducts(null, $product);
|
127 |
+
$childQuantity = $this->getQuantityForChildren($children);
|
128 |
+
|
129 |
+
break;
|
130 |
+
case Mage_Catalog_Model_Product_Type::TYPE_BUNDLE:
|
131 |
+
/** @var Mage_Bundle_Model_Product_Type $typeInstance */
|
132 |
+
$typeInstance = $product->getTypeInstance(true);
|
133 |
+
$optionsIds = $typeInstance->getOptionsIds($product);
|
134 |
+
$selections = $typeInstance->getSelectionsCollection($optionsIds, $product);
|
135 |
+
$bundleOptions = $typeInstance->getOptionsByIds($optionsIds, $product);
|
136 |
+
$bundleOptions->appendSelections($selections);
|
137 |
+
|
138 |
+
/** @var Mage_Bundle_Model_Option $bundleOption */
|
139 |
+
foreach ($bundleOptions as $bundleOption) {
|
140 |
+
$childQuantity += $this->getQuantityForChildren($bundleOption->getData('selections'));
|
141 |
+
}
|
142 |
+
|
143 |
+
break;
|
144 |
+
}
|
145 |
+
|
146 |
+
$this->getRecords()->set(self::FEED_CHILD_QUANTITY, $childQuantity);
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Loop over an array of products to set field data and calculate total child quantity
|
151 |
+
*
|
152 |
+
* @param array $products
|
153 |
+
* @return int
|
154 |
+
*/
|
155 |
+
private function getQuantityForChildren(array $products)
|
156 |
+
{
|
157 |
+
$quantity = 0;
|
158 |
+
|
159 |
+
/** @var Mage_Catalog_Model_Product $product */
|
160 |
+
foreach ($products as $product) {
|
161 |
+
$this->getRecords()->add(self::FEED_CHILD_SKU, $product->getSku());
|
162 |
+
$this->getRecords()->add(self::FEED_CHILD_NAME, $product->getName());
|
163 |
+
|
164 |
+
$quantity += $this->getQuantity($product);
|
165 |
+
}
|
166 |
+
|
167 |
+
return $quantity;
|
168 |
+
}
|
169 |
+
}
|
app/code/community/SearchSpring/Manager/Operation/Product/SetFields.php
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* SetFields.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Operation_Product_SetFields
|
10 |
+
*
|
11 |
+
* Set product attributes to the field
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Operation_Product_SetFields extends SearchSpring_Manager_Operation_Product
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Add magento product attributes to the feed
|
19 |
+
*
|
20 |
+
* @param Mage_Catalog_Model_Product $product
|
21 |
+
* @return $this
|
22 |
+
*/
|
23 |
+
public function perform(Mage_Catalog_Model_Product $product)
|
24 |
+
{
|
25 |
+
/** @var Mage_Catalog_Model_Resource_Eav_Attribute $attribute */
|
26 |
+
foreach($product->getAttributes() as $key => $attribute) {
|
27 |
+
$this->getRecords()->set($key, $this->getAttributeValue($product, $attribute));
|
28 |
+
}
|
29 |
+
|
30 |
+
return $this;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* If product is not enabled or visible, set invalid
|
35 |
+
*
|
36 |
+
* @param Mage_Catalog_Model_Product $product
|
37 |
+
*
|
38 |
+
* @return bool
|
39 |
+
*/
|
40 |
+
public function isValid(Mage_Catalog_Model_Product $product)
|
41 |
+
{
|
42 |
+
// product must be enabled
|
43 |
+
if ((int)$product->getData('status') !== Mage_Catalog_Model_Product_Status::STATUS_ENABLED) {
|
44 |
+
return false;
|
45 |
+
}
|
46 |
+
|
47 |
+
// product must be visible in catalog and search
|
48 |
+
if ((int)$product->getData('visibility') !== Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH) {
|
49 |
+
return false;
|
50 |
+
}
|
51 |
+
|
52 |
+
return true;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Get the attribute value from the attribute object
|
57 |
+
*
|
58 |
+
* @param Mage_Catalog_Model_Product $product
|
59 |
+
* @param Mage_Eav_Model_Entity_Attribute $attribute
|
60 |
+
*
|
61 |
+
* @return array|string|null
|
62 |
+
*/
|
63 |
+
private function getAttributeValue(Mage_Catalog_Model_Product $product, Mage_Eav_Model_Entity_Attribute $attribute)
|
64 |
+
{
|
65 |
+
$attributeValue = $attribute->getFrontend()->getValue($product);
|
66 |
+
$returnValue = null;
|
67 |
+
|
68 |
+
if (is_array($attributeValue)) {
|
69 |
+
foreach ($attributeValue as $v) {
|
70 |
+
$returnValue[] = json_encode($v);
|
71 |
+
}
|
72 |
+
} else {
|
73 |
+
$returnValue = $this->getSanitizer()->sanitizeForRequest($attributeValue);
|
74 |
+
}
|
75 |
+
|
76 |
+
return $returnValue;
|
77 |
+
}
|
78 |
+
}
|
app/code/community/SearchSpring/Manager/Operation/Product/SetId.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* SetId.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Operation_Product_SetId
|
10 |
+
*
|
11 |
+
* Set the product id to the feed
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Operation_Product_SetId extends SearchSpring_Manager_Operation_Product
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Set product id to the feed
|
19 |
+
*
|
20 |
+
* @param Mage_Catalog_Model_Product $product
|
21 |
+
*
|
22 |
+
* @return $this
|
23 |
+
*/
|
24 |
+
public function perform(Mage_Catalog_Model_Product $product)
|
25 |
+
{
|
26 |
+
$this->getRecords()->set($product->getIdFieldName(), $product->getId());
|
27 |
+
|
28 |
+
return $this;
|
29 |
+
}
|
30 |
+
}
|
app/code/community/SearchSpring/Manager/Operation/Product/SetImages.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* SetImages.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Operation_Product_SetImages
|
10 |
+
*
|
11 |
+
* Add product images to the feed
|
12 |
+
*
|
13 |
+
* @author James Bathgate <james@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Operation_Product_SetImages extends SearchSpring_Manager_Operation_Product
|
16 |
+
{
|
17 |
+
const DEFAULT_IMAGE_WIDTH = 200;
|
18 |
+
const DEFAULT_IMAGE_HEIGHT = 200;
|
19 |
+
|
20 |
+
const FEED_IMAGE_URL = 'image_url';
|
21 |
+
const FEED_THUMBNAIL_URL = 'thumbnail_url';
|
22 |
+
const FEED_CACHED_THUMBNAIL_URL = 'cached_thumbnail_url';
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Url path for product images
|
26 |
+
*/
|
27 |
+
const PREFIX_MEDIA_PRODUCT = 'catalog/product';
|
28 |
+
|
29 |
+
protected $_mediaBaseUrl;
|
30 |
+
|
31 |
+
protected $_imageHeight;
|
32 |
+
protected $_imageWidth;
|
33 |
+
|
34 |
+
|
35 |
+
public function __construct(
|
36 |
+
SearchSpring_Manager_String_Sanitizer $sanitizer,
|
37 |
+
SearchSpring_Manager_Entity_RecordsCollection $records,
|
38 |
+
array $parameters = array()
|
39 |
+
) {
|
40 |
+
parent::__construct($sanitizer, $records, $parameters);
|
41 |
+
|
42 |
+
if(Mage::helper('searchspring_manager')->isCacheImagesEnabled()) {
|
43 |
+
$this->_imageWidth = Mage::helper('searchspring_manager')->getImageWidth();
|
44 |
+
$this->_imageHeight = Mage::helper('searchspring_manager')->getImageHeight();
|
45 |
+
|
46 |
+
if (empty($this->_imageWidth)) {
|
47 |
+
if (!empty($this->_imageHeight)) {
|
48 |
+
$this->_imageWidth = $this->_imageHeight;
|
49 |
+
} else {
|
50 |
+
$this->_imageWidth = self::DEFAULT_IMAGE_WIDTH;
|
51 |
+
$this->_imageHeight = self::DEFAULT_IMAGE_HEIGHT;
|
52 |
+
}
|
53 |
+
} else if (empty($this->_imageHeight)) {
|
54 |
+
if (!empty($this->_imageWidth)) {
|
55 |
+
$this->_imageHeight = $this->_imageWidth;
|
56 |
+
} else {
|
57 |
+
$this->_imageHeight = self::DEFAULT_IMAGE_HEIGHT;
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Set magento product options to the feed
|
66 |
+
*
|
67 |
+
* @param Mage_Catalog_Model_Product $product
|
68 |
+
*
|
69 |
+
* @return $this
|
70 |
+
*/
|
71 |
+
public function perform(Mage_Catalog_Model_Product $product)
|
72 |
+
{
|
73 |
+
$mediaBaseUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA);
|
74 |
+
|
75 |
+
$this->getRecords()->set(self::FEED_IMAGE_URL, $mediaBaseUrl . self::PREFIX_MEDIA_PRODUCT . $product->getData('image'));
|
76 |
+
$this->getRecords()->set(self::FEED_THUMBNAIL_URL, $mediaBaseUrl . self::PREFIX_MEDIA_PRODUCT . $product->getData('thumbnail'));
|
77 |
+
|
78 |
+
/** @var Mage_Catalog_Helper_Image $imageHelper */
|
79 |
+
$imageHelper = Mage::helper('catalog/image');
|
80 |
+
|
81 |
+
if(Mage::helper('searchspring_manager')->isCacheImagesEnabled()) {
|
82 |
+
$this->getRecords()->set(
|
83 |
+
self::FEED_CACHED_THUMBNAIL_URL,
|
84 |
+
(string) $imageHelper->init($product, 'image')->resize($this->_imageWidth, $this->_imageHeight)
|
85 |
+
);
|
86 |
+
}
|
87 |
+
|
88 |
+
return $this;
|
89 |
+
}
|
90 |
+
}
|
app/code/community/SearchSpring/Manager/Operation/Product/SetOptions.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* SetOptions.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Operation_Product_SetOptions
|
10 |
+
*
|
11 |
+
* Set product options to the feed
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Operation_Product_SetOptions extends SearchSpring_Manager_Operation_Product
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Set magento product options to the feed
|
19 |
+
*
|
20 |
+
* @param Mage_Catalog_Model_Product $product
|
21 |
+
*
|
22 |
+
* @return $this
|
23 |
+
*/
|
24 |
+
public function perform(Mage_Catalog_Model_Product $product)
|
25 |
+
{
|
26 |
+
/** @var Mage_Catalog_Model_Product_Option $option */
|
27 |
+
foreach ($product->getOptions() as $option) {
|
28 |
+
$optionType = $option->getType();
|
29 |
+
|
30 |
+
if ($optionType !== Mage_Catalog_Model_Product_Option::OPTION_TYPE_DROP_DOWN) {
|
31 |
+
continue;
|
32 |
+
}
|
33 |
+
|
34 |
+
$title = strtolower(trim($option->getData('title')));
|
35 |
+
$title = preg_replace('/_+/', '_', preg_replace('/[^a-z0-9_]+/i', '_', $title));
|
36 |
+
$key = 'option_' . $title;
|
37 |
+
|
38 |
+
/** @var Mage_Catalog_Model_Product_Option_Value $optionValue */
|
39 |
+
foreach ($option->getValues() as $optionValue) {
|
40 |
+
$value = $this->getSanitizer()->sanitizeForRequest($optionValue->getData('title'));
|
41 |
+
$this->getRecords()->add($key, $value);
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
return $this;
|
46 |
+
}
|
47 |
+
}
|
app/code/community/SearchSpring/Manager/Operation/Product/SetPricing.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* SetPricing.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Operation_Product_SetPricing
|
10 |
+
*
|
11 |
+
* Set pricing data to the feed
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Operation_Product_SetPricing extends SearchSpring_Manager_Operation_Product
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Set the pricing data
|
19 |
+
*
|
20 |
+
* @param Mage_Catalog_Model_Product $product
|
21 |
+
*
|
22 |
+
* @return $this
|
23 |
+
* @throws UnexpectedValueException If pricing is not the right type
|
24 |
+
*/
|
25 |
+
public function perform(Mage_Catalog_Model_Product $product)
|
26 |
+
{
|
27 |
+
/** @var SearchSpring_Manager_Factory_PricingFactory $pricingFactory */
|
28 |
+
$pricingFactory = $this->getParameter('pricingFactory');
|
29 |
+
|
30 |
+
// this will throw an exception if the product is not the right type
|
31 |
+
// that's OK because if it does, we did something wrong
|
32 |
+
$pricingStrategy = $pricingFactory->make($product);
|
33 |
+
|
34 |
+
$pricingStrategy->calculatePrices();
|
35 |
+
|
36 |
+
// prices should have been calculated earlier to determine if products should be deleted
|
37 |
+
$this->getRecords()->set('price', $pricingStrategy->getSalePrice());
|
38 |
+
$this->getRecords()->set('regular_price', $pricingStrategy->getTierPrice());
|
39 |
+
$this->getRecords()->set('normal_price', $pricingStrategy->getNormalPrice());
|
40 |
+
|
41 |
+
return $this;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* If price is zero, set invalid
|
46 |
+
*
|
47 |
+
* @param Mage_Catalog_Model_Product $product
|
48 |
+
*
|
49 |
+
* @return bool
|
50 |
+
*/
|
51 |
+
public function isValid(Mage_Catalog_Model_Product $product)
|
52 |
+
{
|
53 |
+
/** @var SearchSpring_Manager_Factory_PricingFactory $pricingFactory */
|
54 |
+
$pricingFactory = $this->getParameter('pricingFactory');
|
55 |
+
$displayZeroPrice = $this->getParameter('displayZeroPrice');
|
56 |
+
|
57 |
+
try {
|
58 |
+
$pricingStrategy = $pricingFactory->make($product);
|
59 |
+
} catch (UnexpectedValueException $e) {
|
60 |
+
// product is not a type we're currently handling
|
61 |
+
return false;
|
62 |
+
}
|
63 |
+
|
64 |
+
// we must run this before we can check prices
|
65 |
+
$pricingStrategy->calculatePrices();
|
66 |
+
|
67 |
+
$productHasZeroPrice = (0 == $pricingStrategy->getNormalPrice()
|
68 |
+
&& 0 == $pricingStrategy->getTierPrice()
|
69 |
+
&& 0 == $pricingStrategy->getSalePrice()
|
70 |
+
);
|
71 |
+
|
72 |
+
// if we shouldn't show 0 prices and the product price is 0
|
73 |
+
if ($productHasZeroPrice && !$displayZeroPrice) {
|
74 |
+
return false;
|
75 |
+
}
|
76 |
+
|
77 |
+
return true;
|
78 |
+
}
|
79 |
+
}
|
app/code/community/SearchSpring/Manager/Operation/Product/SetRatings.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* SetRatings.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Operation_Product_SetRatings
|
10 |
+
*
|
11 |
+
* Set rating data to the feed
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Operation_Product_SetRatings extends SearchSpring_Manager_Operation_Product
|
16 |
+
{
|
17 |
+
/**#@+
|
18 |
+
* Feed Constants
|
19 |
+
*/
|
20 |
+
const FEED_RATING_PERCENTAGE = 'rating_percentage';
|
21 |
+
const FEED_RATING_STAR = 'rating_star';
|
22 |
+
const FEED_RATING_COUNT = 'rating_count';
|
23 |
+
/**#@-*/
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Set rating data to the feed
|
27 |
+
* - rating_percentage
|
28 |
+
* - rating_star
|
29 |
+
* - rating_count
|
30 |
+
*
|
31 |
+
* @param Mage_Catalog_Model_Product $product
|
32 |
+
*
|
33 |
+
* @return $this
|
34 |
+
*/
|
35 |
+
public function perform(Mage_Catalog_Model_Product $product)
|
36 |
+
{
|
37 |
+
$votes = Mage::getModel('rating/rating_option_vote')
|
38 |
+
->getResourceCollection()
|
39 |
+
->setEntityPkFilter($product->getId())
|
40 |
+
->load();
|
41 |
+
|
42 |
+
$ratings = array();
|
43 |
+
foreach ($votes as $vote) {
|
44 |
+
$ratings[] = $vote['percent'];
|
45 |
+
}
|
46 |
+
|
47 |
+
$ratingCount = count($votes);
|
48 |
+
|
49 |
+
$ratingPercentage = (0 === $ratingCount) ? 0 : array_sum($ratings) / $ratingCount;
|
50 |
+
$this->getRecords()->set(self::FEED_RATING_PERCENTAGE, $ratingPercentage);
|
51 |
+
$this->getRecords()->set(self::FEED_RATING_STAR, round($ratingPercentage / 20));
|
52 |
+
$this->getRecords()->set(self::FEED_RATING_COUNT, $ratingCount);
|
53 |
+
|
54 |
+
return $this;
|
55 |
+
}
|
56 |
+
}
|
app/code/community/SearchSpring/Manager/Operation/ProductOperation.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Operation.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Interface SearchSpring_Manager_Visitor_Product_Operation
|
10 |
+
*
|
11 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
12 |
+
*/
|
13 |
+
interface SearchSpring_Manager_Operation_ProductOperation
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* Perform an operation
|
17 |
+
*
|
18 |
+
* @param Mage_Catalog_Model_Product $product
|
19 |
+
*
|
20 |
+
* @return self
|
21 |
+
*/
|
22 |
+
public function perform(Mage_Catalog_Model_Product $product);
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Checks validity of operation
|
26 |
+
*
|
27 |
+
* @param Mage_Catalog_Model_Product $product
|
28 |
+
*
|
29 |
+
* @return mixed
|
30 |
+
*/
|
31 |
+
public function isValid(Mage_Catalog_Model_Product $product);
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Set records collection to operation
|
35 |
+
*
|
36 |
+
* @param SearchSpring_Manager_Entity_RecordsCollection $records
|
37 |
+
*
|
38 |
+
* @return mixed
|
39 |
+
*/
|
40 |
+
public function setRecords(SearchSpring_Manager_Entity_RecordsCollection $records);
|
41 |
+
}
|
app/code/community/SearchSpring/Manager/Provider/ProductCollection/FeedProvider.php
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* FeedProvider.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Provider_ProductCollection_FeedProvider
|
10 |
+
*
|
11 |
+
* Provides a ProductCollection for feeds
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Provider_ProductCollection_FeedProvider
|
16 |
+
implements SearchSpring_Manager_Provider_ProductCollectionProvider
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
* A ProductCollection
|
20 |
+
*
|
21 |
+
* @var Mage_Catalog_Model_Resource_Product_Collection $collection
|
22 |
+
*/
|
23 |
+
private $collection;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* The size of the collection
|
27 |
+
*
|
28 |
+
* @var int $collectionCount
|
29 |
+
*/
|
30 |
+
private $collectionCount;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Request parameters
|
34 |
+
*
|
35 |
+
* Used to get the store for filter
|
36 |
+
*
|
37 |
+
* @var SearchSpring_Manager_Entity_RequestParams
|
38 |
+
*/
|
39 |
+
private $requestParams;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Constructor
|
43 |
+
*
|
44 |
+
* @param SearchSpring_Manager_Entity_RequestParams $requestParams
|
45 |
+
*/
|
46 |
+
public function __construct(SearchSpring_Manager_Entity_RequestParams $requestParams)
|
47 |
+
{
|
48 |
+
$this->requestParams = $requestParams;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* {@inheritdoc}
|
53 |
+
*/
|
54 |
+
public function getCollection()
|
55 |
+
{
|
56 |
+
if (null !== $this->collection) {
|
57 |
+
return $this->collection;
|
58 |
+
}
|
59 |
+
|
60 |
+
$showOos = Mage::helper('cataloginventory')->isShowOutOfStock();
|
61 |
+
|
62 |
+
/** @var Mage_Catalog_Model_Resource_Product_Collection $collection */
|
63 |
+
$collection = Mage::getModel('catalog/product')->getCollection();
|
64 |
+
$collection->addStoreFilter(Mage::app()->getStore($this->requestParams->getStore())->getId());
|
65 |
+
$collection->addAttributeToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
|
66 |
+
$collection->addAttributeToFilter('type_id', array('in' => SearchSpring_Manager_Validator_ProductValidator::$allowableTypes));
|
67 |
+
$collection->addAttributeToFilter('visibility', Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
|
68 |
+
|
69 |
+
|
70 |
+
if (!$showOos) {
|
71 |
+
Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($collection);
|
72 |
+
}
|
73 |
+
|
74 |
+
$collection->getSelect()->limit($this->requestParams->getCount(), $this->requestParams->getOffset());
|
75 |
+
$this->collection = $collection;
|
76 |
+
|
77 |
+
return $this->collection;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* {@inheritdoc}
|
82 |
+
*/
|
83 |
+
public function getCollectionCount()
|
84 |
+
{
|
85 |
+
if (null !== $this->collectionCount) {
|
86 |
+
return $this->collectionCount;
|
87 |
+
}
|
88 |
+
|
89 |
+
// if collection isn't set, get it first
|
90 |
+
if (null === $this->collection) {
|
91 |
+
$this->getCollection();
|
92 |
+
}
|
93 |
+
|
94 |
+
// set collection count before limit is applied
|
95 |
+
$this->collectionCount = $this->collection->getSize();
|
96 |
+
|
97 |
+
return $this->collectionCount;
|
98 |
+
}
|
99 |
+
}
|
app/code/community/SearchSpring/Manager/Provider/ProductCollection/ProductProvider.php
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* ProductProvider.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Provider_ProductCollection_ProductProvider
|
10 |
+
*
|
11 |
+
* Provides a ProductCollection for product types
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Provider_ProductCollection_ProductProvider
|
16 |
+
implements SearchSpring_Manager_Provider_ProductCollectionProvider
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
* A ProductCollection
|
20 |
+
*
|
21 |
+
* @var Mage_Catalog_Model_Resource_Product_Collection $collection
|
22 |
+
*/
|
23 |
+
private $collection;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* The size of the collection
|
27 |
+
*
|
28 |
+
* @var int $collectionCount
|
29 |
+
*/
|
30 |
+
private $collectionCount;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* An array of product ids
|
34 |
+
*
|
35 |
+
* @var array $ids
|
36 |
+
*/
|
37 |
+
private $ids;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Request parameters
|
41 |
+
*
|
42 |
+
* Needed to get current count/offset values
|
43 |
+
*
|
44 |
+
* @var SearchSpring_Manager_Entity_RequestParams
|
45 |
+
*/
|
46 |
+
private $requestParams;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Constructor
|
50 |
+
*
|
51 |
+
* @param array $ids
|
52 |
+
* @param SearchSpring_Manager_Entity_RequestParams $requestParams
|
53 |
+
*/
|
54 |
+
public function __construct(array $ids, SearchSpring_Manager_Entity_RequestParams $requestParams = null)
|
55 |
+
{
|
56 |
+
$this->ids = $ids;
|
57 |
+
$this->requestParams = $requestParams;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* {@inheritdoc}
|
62 |
+
*/
|
63 |
+
public function getCollection()
|
64 |
+
{
|
65 |
+
if (null !== $this->collection) {
|
66 |
+
return $this->collection;
|
67 |
+
}
|
68 |
+
|
69 |
+
/** @var Mage_Catalog_Model_Resource_Product_Collection $collection */
|
70 |
+
$collection = Mage::getModel('catalog/product')
|
71 |
+
->getCollection()
|
72 |
+
->addAttributeToFilter('entity_id', array('in' => $this->ids))
|
73 |
+
->addAttributeToFilter('visibility', Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
|
74 |
+
|
75 |
+
if (null !== $this->requestParams) {
|
76 |
+
$collection->getSelect()->limit($this->requestParams->getCount(), $this->requestParams->getOffset());
|
77 |
+
}
|
78 |
+
|
79 |
+
$this->collection = $collection;
|
80 |
+
|
81 |
+
return $this->collection;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* {@inheritdoc}
|
86 |
+
*/
|
87 |
+
public function getCollectionCount()
|
88 |
+
{
|
89 |
+
if (null !== $this->collectionCount) {
|
90 |
+
return $this->collectionCount;
|
91 |
+
}
|
92 |
+
|
93 |
+
if (null === $this->collection) {
|
94 |
+
$this->getCollection();
|
95 |
+
}
|
96 |
+
|
97 |
+
$this->collectionCount = $this->collection->getSize();
|
98 |
+
|
99 |
+
return $this->collectionCount;
|
100 |
+
}
|
101 |
+
}
|
app/code/community/SearchSpring/Manager/Provider/ProductCollectionProvider.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* ProductCollectionProvider.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Interface SearchSpring_Manager_Provider_ProductCollectionProvider
|
10 |
+
*
|
11 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
12 |
+
*/
|
13 |
+
interface SearchSpring_Manager_Provider_ProductCollectionProvider
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* Gets the ProductCollection
|
17 |
+
*
|
18 |
+
* @return Mage_Catalog_Model_Resource_Product_Collection
|
19 |
+
*/
|
20 |
+
public function getCollection();
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Get the collection count
|
24 |
+
*
|
25 |
+
* @return int
|
26 |
+
*/
|
27 |
+
public function getCollectionCount();
|
28 |
+
}
|
app/code/community/SearchSpring/Manager/Request/JSON.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* JSON.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Request_JSON
|
10 |
+
*
|
11 |
+
* Wrapper for Request object that allows you to easily access JSON POST Data.
|
12 |
+
*
|
13 |
+
* @author James Bathgate <james@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Request_JSON
|
16 |
+
{
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Request parameters parsed from JSON
|
20 |
+
*
|
21 |
+
* @var object $request
|
22 |
+
*/
|
23 |
+
private $params;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Constructor
|
27 |
+
*
|
28 |
+
* @param Mage_Core_Controller_Request_Http $request
|
29 |
+
*/
|
30 |
+
public function __construct(Mage_Core_Controller_Request_Http $request) {
|
31 |
+
$rawBody = $request->getRawBody();
|
32 |
+
|
33 |
+
if(!empty($rawBody)) {
|
34 |
+
$this->params = json_decode($rawBody, true);
|
35 |
+
|
36 |
+
if(null === $this->params) {
|
37 |
+
throw new Exception('Invalid JSON in Request');
|
38 |
+
}
|
39 |
+
} else {
|
40 |
+
$this->params = array();
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Returns parameter from JSON request
|
48 |
+
*
|
49 |
+
* @param string $parameter
|
50 |
+
*
|
51 |
+
* @return mixed
|
52 |
+
*/
|
53 |
+
public function getParam($parameter, $default=NULL) {
|
54 |
+
return isset($this->params[$parameter])?$this->params[$parameter]:$default;
|
55 |
+
}
|
56 |
+
}
|
app/code/community/SearchSpring/Manager/Service/SearchSpring/ApiAdapter.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File ApiAdapter.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Service_SearchSpring_ApiAdapter
|
10 |
+
*
|
11 |
+
* Adapter for the SearchSpring API
|
12 |
+
*
|
13 |
+
* @author James Bathgate <james@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Service_SearchSpring_ApiAdapter
|
16 |
+
{
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Format for create the url endpoint
|
20 |
+
*
|
21 |
+
* [baseurl]/[method]
|
22 |
+
*/
|
23 |
+
const URL_FORMAT = '%s/%s';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* The curl adapter
|
27 |
+
*
|
28 |
+
* @var Varien_Http_Adapter_Curl $curl
|
29 |
+
*/
|
30 |
+
protected $curl;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* An API error handler if a request fails
|
34 |
+
*
|
35 |
+
* @var SearchSpring_Manager_Handler_ApiErrorHandler
|
36 |
+
*/
|
37 |
+
protected $errorHandler;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* The base url for the endpoint
|
41 |
+
*
|
42 |
+
* @var string $baseUrl
|
43 |
+
*/
|
44 |
+
protected $baseUrl;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Constructor
|
48 |
+
*
|
49 |
+
* @param SearchSpring_Manager_Handler_ApiErrorHandler $errorHandler
|
50 |
+
* @param Varien_Http_Adapter_Curl $curl
|
51 |
+
* @param string $baseUrl
|
52 |
+
*/
|
53 |
+
public function __construct(
|
54 |
+
SearchSpring_Manager_Handler_ApiErrorHandler $errorHandler,
|
55 |
+
Varien_Http_Adapter_Curl $curl,
|
56 |
+
$baseUrl
|
57 |
+
) {
|
58 |
+
$this->errorHandler = $errorHandler;
|
59 |
+
$this->curl = $curl;
|
60 |
+
$this->baseUrl = $baseUrl;
|
61 |
+
}
|
62 |
+
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Build the url based on expected format
|
66 |
+
*
|
67 |
+
* @param string $method
|
68 |
+
*
|
69 |
+
* @return string
|
70 |
+
*/
|
71 |
+
protected function buildUrl($method)
|
72 |
+
{
|
73 |
+
$url = sprintf(self::URL_FORMAT, $this->baseUrl, $method);
|
74 |
+
|
75 |
+
return $url;
|
76 |
+
}
|
77 |
+
}
|
app/code/community/SearchSpring/Manager/Service/SearchSpring/IndexingApiAdapter.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File IndexingApiAdapter.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Service_SearchSpring_IndexingApiAdapter
|
10 |
+
*
|
11 |
+
* Adapter for the SearchSpring Indexing API
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Service_SearchSpring_IndexingApiAdapter extends SearchSpring_Manager_Service_SearchSpring_ApiAdapter
|
16 |
+
{
|
17 |
+
const API_INDEX = 'api/index/magento/generate';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Push ids to api
|
21 |
+
*
|
22 |
+
* @param SearchSpring_Manager_Entity_IndexingRequestBody $requestBody
|
23 |
+
*/
|
24 |
+
public function pushIds(SearchSpring_Manager_Entity_IndexingRequestBody $requestBody)
|
25 |
+
{
|
26 |
+
$this->call(self::API_INDEX, $requestBody);
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Generic method that accepts any api endpoint path
|
31 |
+
*
|
32 |
+
* @param string $method
|
33 |
+
* @param SearchSpring_Manager_Entity_IndexingRequestBody $requestBody
|
34 |
+
*/
|
35 |
+
public function call($method, SearchSpring_Manager_Entity_IndexingRequestBody $requestBody)
|
36 |
+
{
|
37 |
+
$url = $this->buildUrl($method);
|
38 |
+
$this->request(Zend_Http_Client::POST, $url, json_encode($requestBody->jsonSerialize()));
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Helper method to make an api request
|
43 |
+
*
|
44 |
+
* @param string $httpMethod
|
45 |
+
* @param string $url
|
46 |
+
* @param string $body
|
47 |
+
*
|
48 |
+
* @return int
|
49 |
+
*/
|
50 |
+
private function request($httpMethod, $url, $body)
|
51 |
+
{
|
52 |
+
$this->curl->write($httpMethod, $url, Zend_Http_Client::HTTP_1, array(), $body);
|
53 |
+
$response = $this->curl->read();
|
54 |
+
$responseCode = Zend_Http_Response::extractCode($response);
|
55 |
+
$this->curl->close();
|
56 |
+
|
57 |
+
if ($this->errorHandler->shouldRetry($response)) {
|
58 |
+
$this->request($httpMethod, $url, $body);
|
59 |
+
}
|
60 |
+
|
61 |
+
return $responseCode;
|
62 |
+
}
|
63 |
+
|
64 |
+
}
|
app/code/community/SearchSpring/Manager/Service/SearchSpring/SearchApiAdapter.php
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File SearchApiAdapter.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Service_SearchSpring_IndexingApiAdapter
|
10 |
+
*
|
11 |
+
* Adapter for the SearchSpring Indexing API
|
12 |
+
*
|
13 |
+
* @author James Bathgate <james@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Service_SearchSpring_SearchApiAdapter extends SearchSpring_Manager_Service_SearchSpring_ApiAdapter
|
16 |
+
{
|
17 |
+
|
18 |
+
const API_SEARCH = 'api/search/search.json';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Push ids to api
|
22 |
+
*
|
23 |
+
* @param SearchSpring_Manager_Entity_SearchRequestBody $requestBody
|
24 |
+
*/
|
25 |
+
public function search(SearchSpring_Manager_Entity_SearchRequestBody $requestBody)
|
26 |
+
{
|
27 |
+
$response = $this->call(self::API_SEARCH, $requestBody);
|
28 |
+
|
29 |
+
if(null === ($result = json_decode($response))) {
|
30 |
+
throw new Exception('Unable to parse SearchSpring search response JSON');
|
31 |
+
}
|
32 |
+
|
33 |
+
return $result;
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Generic method that accepts any api endpoint path
|
38 |
+
*
|
39 |
+
* @param string $method
|
40 |
+
* @param SearchSpring_Manager_Entity_SearchRequestBody $requestBody
|
41 |
+
*/
|
42 |
+
public function call($method, SearchSpring_Manager_Entity_SearchRequestBody $requestBody)
|
43 |
+
{
|
44 |
+
$url = $this->buildUrl($method);
|
45 |
+
return $this->request(Zend_Http_Client::GET, $url, (string)$requestBody);
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Helper method to make an api request
|
50 |
+
*
|
51 |
+
* @param string $httpMethod
|
52 |
+
* @param string $url
|
53 |
+
* @param string $body
|
54 |
+
*
|
55 |
+
* @return int
|
56 |
+
*/
|
57 |
+
private function request($httpMethod, $url, $parameters)
|
58 |
+
{
|
59 |
+
$this->curl->write($httpMethod, $url . '?' . $parameters, Zend_Http_Client::HTTP_1, array());
|
60 |
+
$response = $this->curl->read();
|
61 |
+
|
62 |
+
$responseCode = Zend_Http_Response::extractCode($response);
|
63 |
+
$responseBody = Zend_Http_Response::extractBody($response);
|
64 |
+
|
65 |
+
if ($this->errorHandler->shouldRetry($response)) {
|
66 |
+
return $this->request($httpMethod, $url, $parameters);
|
67 |
+
}
|
68 |
+
|
69 |
+
return $responseBody;
|
70 |
+
}
|
71 |
+
|
72 |
+
}
|
app/code/community/SearchSpring/Manager/Strategy/Pricing/BundleStrategy.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File BundleStrategy.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Strategy_Pricing_BundleStrategy
|
10 |
+
*
|
11 |
+
* Calculate prices for bundled products
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Strategy_Pricing_BundleStrategy extends SearchSpring_Manager_Strategy_Pricing_Strategy
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* {@inheritdoc}
|
19 |
+
*/
|
20 |
+
public function calculatePrices()
|
21 |
+
{
|
22 |
+
/** @var Mage_Bundle_Model_Product_Type $typeInstance */
|
23 |
+
$typeInstance = $this->getProduct()->getTypeInstance(true);
|
24 |
+
|
25 |
+
$totalRegularPrice = 0;
|
26 |
+
$totalTierPrice = 0;
|
27 |
+
$totalSalePrice = 0;
|
28 |
+
|
29 |
+
// set up bundle options
|
30 |
+
$optionsIds = $typeInstance->getOptionsIds($this->getProduct());
|
31 |
+
$selections = $typeInstance->getSelectionsCollection($optionsIds, $this->getProduct());
|
32 |
+
$bundleOptions = $typeInstance->getOptionsByIds($optionsIds, $this->getProduct());
|
33 |
+
$bundleOptions->appendSelections($selections);
|
34 |
+
|
35 |
+
/** @var Mage_Bundle_Model_Option $bundleOption */
|
36 |
+
foreach ($bundleOptions as $bundleOption) {
|
37 |
+
// if it's not required, it doesn't count as part of the minimal price
|
38 |
+
if (!$bundleOption->getRequired()) {
|
39 |
+
continue;
|
40 |
+
}
|
41 |
+
|
42 |
+
$regularPrices = array();
|
43 |
+
$tierPrices = array();
|
44 |
+
$salePrices = array();
|
45 |
+
|
46 |
+
/** @var Mage_Catalog_Model_Product $product */
|
47 |
+
foreach ($bundleOption->getData('selections') as $product) {
|
48 |
+
$regularPrice = (double)$product->getPrice();
|
49 |
+
$tierPrice = (double)$this->getLowestTierPrice($product);
|
50 |
+
$salePrice = (double)$product->getFinalPrice();
|
51 |
+
|
52 |
+
$regularPrices[] = $regularPrice;
|
53 |
+
$tierPrices[] = $tierPrice;
|
54 |
+
$salePrices[] = $salePrice;
|
55 |
+
}
|
56 |
+
|
57 |
+
$totalRegularPrice += $this->findMinPrice($regularPrices);
|
58 |
+
$totalTierPrice += $this->findMinPrice($tierPrices);
|
59 |
+
$totalSalePrice += $this->findMinPrice($salePrices);
|
60 |
+
}
|
61 |
+
|
62 |
+
$this->setNormalPrice($totalRegularPrice);
|
63 |
+
$this->setTierPrice($totalTierPrice);
|
64 |
+
$this->setSalePrice($totalSalePrice);
|
65 |
+
|
66 |
+
return $this;
|
67 |
+
}
|
68 |
+
|
69 |
+
}
|
app/code/community/SearchSpring/Manager/Strategy/Pricing/ConfigurableStrategy.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File ConfigurableStrategy.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Strategy_Pricing_ConfigurableStrategy
|
10 |
+
*
|
11 |
+
* Calculate prices for configurable products
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Strategy_Pricing_ConfigurableStrategy extends SearchSpring_Manager_Strategy_Pricing_Strategy
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* {@inheritdoc}
|
19 |
+
*/
|
20 |
+
public function calculatePrices()
|
21 |
+
{
|
22 |
+
$product = $this->getProduct();
|
23 |
+
$this->setNormalPrice($product->getPrice());
|
24 |
+
$this->setTierPrice($this->getLowestTierPrice($product));
|
25 |
+
$this->setSalePrice($product->getFinalPrice());
|
26 |
+
|
27 |
+
return $this;
|
28 |
+
}
|
29 |
+
}
|
app/code/community/SearchSpring/Manager/Strategy/Pricing/GroupedStrategy.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File GroupedStrategy.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Strategy_Pricing_GroupedStrategy
|
10 |
+
*
|
11 |
+
* Calculate prices for grouped products
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Strategy_Pricing_GroupedStrategy extends SearchSpring_Manager_Strategy_Pricing_Strategy
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* {@inheritdoc}
|
19 |
+
*/
|
20 |
+
public function calculatePrices()
|
21 |
+
{
|
22 |
+
/** @var Mage_Catalog_Model_Product_Type_Grouped $typeInstance */
|
23 |
+
$typeInstance = $this->getProduct()->getTypeInstance(true);
|
24 |
+
$associated = $typeInstance->getAssociatedProducts($this->getProduct());
|
25 |
+
|
26 |
+
$regularPrices = array();
|
27 |
+
$tierPrices = array();
|
28 |
+
$salePrices = array();
|
29 |
+
|
30 |
+
/** @var Mage_Catalog_Model_Product $product */
|
31 |
+
foreach($associated as $product) {
|
32 |
+
$regularPrice = (double)$product->getPrice();
|
33 |
+
$tierPrice = (double)$this->getLowestTierPrice($product);
|
34 |
+
$salePrice = (double)$product->getFinalPrice();
|
35 |
+
|
36 |
+
$regularPrices[] = $regularPrice;
|
37 |
+
$tierPrices[] = $tierPrice;
|
38 |
+
$salePrices[] = $salePrice;
|
39 |
+
}
|
40 |
+
|
41 |
+
$this->setNormalPrice($this->findMinPrice($regularPrices));
|
42 |
+
$this->setTierPrice($this->findMinPrice($tierPrices));
|
43 |
+
$this->setSalePrice($this->findMinPrice($salePrices));
|
44 |
+
|
45 |
+
return $this;
|
46 |
+
}
|
47 |
+
}
|
app/code/community/SearchSpring/Manager/Strategy/Pricing/SimpleStrategy.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File SimpleStrategy.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Strategy_Pricing_SimpleStrategy
|
10 |
+
*
|
11 |
+
* Calculate prices for grouped products
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Strategy_Pricing_SimpleStrategy extends SearchSpring_Manager_Strategy_Pricing_Strategy
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* {@inheritdoc}
|
19 |
+
*/
|
20 |
+
public function calculatePrices()
|
21 |
+
{
|
22 |
+
$product = $this->getProduct();
|
23 |
+
$this->setNormalPrice($product->getPrice());
|
24 |
+
$this->setTierPrice($this->getLowestTierPrice($product));
|
25 |
+
$this->setSalePrice($product->getFinalPrice());
|
26 |
+
|
27 |
+
return $this;
|
28 |
+
}
|
29 |
+
}
|
app/code/community/SearchSpring/Manager/Strategy/Pricing/Strategy.php
ADDED
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File Strategy.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Strategy_Pricing_Strategy
|
10 |
+
*
|
11 |
+
* Abstract class for pricing strategies. Holds getters for price data.
|
12 |
+
*
|
13 |
+
* @todo This should probably be a separate class that just holds the data rather than an abstract with subclasses.
|
14 |
+
*
|
15 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
16 |
+
*/
|
17 |
+
abstract class SearchSpring_Manager_Strategy_Pricing_Strategy implements SearchSpring_Manager_Strategy_PricingStrategy
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Magento product
|
21 |
+
*
|
22 |
+
* @var Mage_Catalog_Model_Product $product
|
23 |
+
*/
|
24 |
+
private $product;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* The regular price of the product
|
28 |
+
*
|
29 |
+
* @var double $regularPrice
|
30 |
+
*/
|
31 |
+
private $regularPrice;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* The price of the product including tier prices
|
35 |
+
*
|
36 |
+
* @var double $tierPrice
|
37 |
+
*/
|
38 |
+
private $tierPrice;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The price of the product from getFinalPrice()
|
42 |
+
*
|
43 |
+
* @var double $salePrice
|
44 |
+
*/
|
45 |
+
private $salePrice;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* {@inheritdoc}
|
49 |
+
*/
|
50 |
+
public function __construct(Mage_Catalog_Model_Product $product)
|
51 |
+
{
|
52 |
+
$this->product = $product;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Get the product
|
57 |
+
*
|
58 |
+
* @return Mage_Catalog_Model_Product
|
59 |
+
*/
|
60 |
+
protected function getProduct()
|
61 |
+
{
|
62 |
+
return $this->product;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* {@inheritdoc}
|
67 |
+
*/
|
68 |
+
public function getNormalPrice()
|
69 |
+
{
|
70 |
+
$price = $this->formatPrice($this->regularPrice);
|
71 |
+
|
72 |
+
return $price;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Set the regular price
|
77 |
+
*
|
78 |
+
* @param double $price
|
79 |
+
*/
|
80 |
+
protected function setNormalPrice($price)
|
81 |
+
{
|
82 |
+
$this->regularPrice = $price;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* {@inheritdoc}
|
87 |
+
*/
|
88 |
+
public function getTierPrice()
|
89 |
+
{
|
90 |
+
$minPrice = min($this->regularPrice, $this->tierPrice);
|
91 |
+
$price = $this->formatPrice($minPrice);
|
92 |
+
|
93 |
+
return $price;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Set the tier price
|
98 |
+
*
|
99 |
+
* @param double $price
|
100 |
+
*/
|
101 |
+
protected function setTierPrice($price)
|
102 |
+
{
|
103 |
+
$this->tierPrice = $price;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* {@inheritdoc}
|
108 |
+
*/
|
109 |
+
public function getSalePrice()
|
110 |
+
{
|
111 |
+
$minPrice = min($this->regularPrice, $this->tierPrice, $this->salePrice);
|
112 |
+
$price = $this->formatPrice($minPrice);
|
113 |
+
|
114 |
+
return $price;
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Set the sale price
|
119 |
+
*
|
120 |
+
* @param double $price
|
121 |
+
*/
|
122 |
+
protected function setSalePrice($price)
|
123 |
+
{
|
124 |
+
$this->salePrice = $price;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Find the minimum price in array
|
129 |
+
*
|
130 |
+
* Returns 0 if array if empty
|
131 |
+
*
|
132 |
+
* @param array $prices
|
133 |
+
*
|
134 |
+
* @return int
|
135 |
+
*/
|
136 |
+
protected function findMinPrice(array $prices)
|
137 |
+
{
|
138 |
+
if (empty($prices)) {
|
139 |
+
return 0;
|
140 |
+
}
|
141 |
+
|
142 |
+
return min($prices);
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Find the lowest tier price for product
|
147 |
+
*
|
148 |
+
* @param Mage_Catalog_Model_Product $product
|
149 |
+
*
|
150 |
+
* @return double
|
151 |
+
*/
|
152 |
+
protected function getLowestTierPrice(Mage_Catalog_Model_Product $product)
|
153 |
+
{
|
154 |
+
/** @var array $tierPrices */
|
155 |
+
$tierPrices = $product->getTierPrice();
|
156 |
+
|
157 |
+
if (empty($tierPrices)) {
|
158 |
+
$price = (double)$product->getPrice();
|
159 |
+
|
160 |
+
return $price;
|
161 |
+
}
|
162 |
+
|
163 |
+
$prices = array();
|
164 |
+
foreach ($tierPrices as $tierPrice) {
|
165 |
+
if ($tierPrice == 0) {
|
166 |
+
continue;
|
167 |
+
}
|
168 |
+
|
169 |
+
$prices[] = (double)$tierPrice['price'];
|
170 |
+
}
|
171 |
+
|
172 |
+
$lowestPrice = min($prices);
|
173 |
+
|
174 |
+
return $lowestPrice;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Format number to two decimals
|
179 |
+
*
|
180 |
+
* @param double $price
|
181 |
+
* @return double
|
182 |
+
*/
|
183 |
+
private function formatPrice($price)
|
184 |
+
{
|
185 |
+
$price = (double)$price;
|
186 |
+
$price = (double)number_format($price, 2);
|
187 |
+
|
188 |
+
return $price;
|
189 |
+
}
|
190 |
+
}
|
app/code/community/SearchSpring/Manager/Strategy/PricingStrategy.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File PricingStrategy.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Interface SearchSpring_Manager_Strategy_PricingStrategy
|
10 |
+
*
|
11 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
12 |
+
*/
|
13 |
+
interface SearchSpring_Manager_Strategy_PricingStrategy
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* Constructor
|
17 |
+
*
|
18 |
+
* @param Mage_Catalog_Model_Product $product
|
19 |
+
*/
|
20 |
+
public function __construct(Mage_Catalog_Model_Product $product);
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Calculate lowest prices
|
24 |
+
*
|
25 |
+
* @return self
|
26 |
+
*/
|
27 |
+
public function calculatePrices();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Return the regular price
|
31 |
+
*
|
32 |
+
* @return double
|
33 |
+
*/
|
34 |
+
public function getNormalPrice();
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Return the lowest between regular price and tier price
|
38 |
+
*
|
39 |
+
* @return double
|
40 |
+
*/
|
41 |
+
public function getTierPrice();
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Return the lowest price between all kinds of prices
|
45 |
+
*
|
46 |
+
* @return double
|
47 |
+
*/
|
48 |
+
public function getSalePrice();
|
49 |
+
}
|
app/code/community/SearchSpring/Manager/String/Sanitizer.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Sanitizer.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_String_Sanitizer
|
10 |
+
*
|
11 |
+
* Service to sanitize string data
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_String_Sanitizer
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Helper method to remove unwanted characters
|
19 |
+
*
|
20 |
+
* @param string $value
|
21 |
+
* @return string|null
|
22 |
+
*/
|
23 |
+
public function sanitizeForRequest($value)
|
24 |
+
{
|
25 |
+
$value = preg_replace('/[^(\x20-\x7F)\x0A]*/','', $value);
|
26 |
+
|
27 |
+
return $value;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Strip newline and tab characters
|
32 |
+
*
|
33 |
+
* @param string $value
|
34 |
+
*
|
35 |
+
* @return string|null
|
36 |
+
*/
|
37 |
+
public function removeNewlinesAndStripTags($value)
|
38 |
+
{
|
39 |
+
$value = strip_tags($value);
|
40 |
+
$value = str_replace("\n", "", $value);
|
41 |
+
$value = str_replace("\r", "", $value);
|
42 |
+
$value = str_replace("\t", "", $value);
|
43 |
+
|
44 |
+
return $value;
|
45 |
+
}
|
46 |
+
}
|
app/code/community/SearchSpring/Manager/Transformer/ProductCollectionToRecordCollectionTransformer.php
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* ProductCollectionToRecordCollectionTransformer.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Transformer_ProductCollectionToRecordCollectionTransformer
|
10 |
+
*
|
11 |
+
* Transform a Magento product collection to our records collection. Only performs a 1-way transform
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Transformer_ProductCollectionToRecordCollectionTransformer
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* @var SearchSpring_Manager_Entity_RecordsCollection
|
19 |
+
*/
|
20 |
+
private $recordsCollection;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var SearchSpring_Manager_Entity_OperationsCollection
|
24 |
+
*/
|
25 |
+
private $operationsCollection;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Constructor
|
29 |
+
*
|
30 |
+
* @param SearchSpring_Manager_Entity_RecordsCollection $recordsCollection
|
31 |
+
* @param SearchSpring_Manager_Entity_OperationsCollection $operationsCollection
|
32 |
+
*/
|
33 |
+
public function __construct(
|
34 |
+
SearchSpring_Manager_Entity_RecordsCollection $recordsCollection,
|
35 |
+
SearchSpring_Manager_Entity_OperationsCollection $operationsCollection
|
36 |
+
) {
|
37 |
+
$this->recordsCollection = $recordsCollection;
|
38 |
+
$this->operationsCollection = $operationsCollection;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Transforms product collection to records collection
|
43 |
+
*
|
44 |
+
* @param Mage_Catalog_Model_Resource_Product_Collection $productCollection
|
45 |
+
*
|
46 |
+
* @return SearchSpring_Manager_Entity_RecordsCollection
|
47 |
+
*/
|
48 |
+
public function transform(Mage_Catalog_Model_Resource_Product_Collection $productCollection)
|
49 |
+
{
|
50 |
+
/** @var Mage_Catalog_Model_Product $product */
|
51 |
+
foreach ($productCollection as $product) {
|
52 |
+
// load product data
|
53 |
+
$product->load($product->getId());
|
54 |
+
|
55 |
+
// default to valid
|
56 |
+
$productValid = true;
|
57 |
+
|
58 |
+
/** @var SearchSpring_Manager_Operation_Product $operation */
|
59 |
+
foreach ($this->operationsCollection as $operation) {
|
60 |
+
// check if any operation validation invalidates this product
|
61 |
+
if (false === $operation->isValid($product)) {
|
62 |
+
$productValid = false;
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
// only set id if product is invalid and continue to next product
|
67 |
+
if (false === $productValid) {
|
68 |
+
$operation = new SearchSpring_Manager_Operation_Product_SetId(
|
69 |
+
new SearchSpring_Manager_String_Sanitizer(),
|
70 |
+
$this->recordsCollection
|
71 |
+
);
|
72 |
+
|
73 |
+
$operation->perform($product);
|
74 |
+
|
75 |
+
// increment record
|
76 |
+
$this->recordsCollection->next();
|
77 |
+
|
78 |
+
continue;
|
79 |
+
}
|
80 |
+
|
81 |
+
foreach ($this->operationsCollection as $operation) {
|
82 |
+
$operation->perform($product);
|
83 |
+
}
|
84 |
+
|
85 |
+
// increment record
|
86 |
+
$this->recordsCollection->next();
|
87 |
+
}
|
88 |
+
|
89 |
+
return $this->recordsCollection;
|
90 |
+
}
|
91 |
+
}
|
app/code/community/SearchSpring/Manager/Validator/ProductValidator.php
ADDED
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* File ProductValidator.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Validator_ProductValidator
|
10 |
+
*
|
11 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
12 |
+
*/
|
13 |
+
class SearchSpring_Manager_Validator_ProductValidator implements Zend_Validate_Interface
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* An array of allowable product types for validation
|
17 |
+
*
|
18 |
+
* @var array $allowableTypes
|
19 |
+
*/
|
20 |
+
public static $allowableTypes = array(
|
21 |
+
Mage_Catalog_Model_Product_Type::TYPE_SIMPLE,
|
22 |
+
Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE,
|
23 |
+
Mage_Catalog_Model_Product_Type::TYPE_GROUPED,
|
24 |
+
Mage_Catalog_Model_Product_Type::TYPE_BUNDLE,
|
25 |
+
);
|
26 |
+
|
27 |
+
/**
|
28 |
+
* An array of messages that details why the validator failed
|
29 |
+
*
|
30 |
+
* @var array $messages
|
31 |
+
*/
|
32 |
+
private $messages = array();
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Determines if we should delete this product from the SearchSpring index
|
36 |
+
*
|
37 |
+
* @param Mage_Catalog_Model_Product $product
|
38 |
+
* @param SearchSpring_Manager_Strategy_PricingStrategy $pricing
|
39 |
+
*
|
40 |
+
* @return bool
|
41 |
+
* @throws UnexpectedValueException
|
42 |
+
*/
|
43 |
+
public function shouldDelete(
|
44 |
+
Mage_Catalog_Model_Product $product,
|
45 |
+
SearchSpring_Manager_Strategy_PricingStrategy $pricing
|
46 |
+
) {
|
47 |
+
$status = (int)$product->getStatus();
|
48 |
+
$origStatus = (int)$product->getOrigData('status');
|
49 |
+
$visibility = (int)$product->getData('visibility');
|
50 |
+
$origVisibility = (int)$product->getOrigData('visibility');
|
51 |
+
|
52 |
+
// if product became disabled
|
53 |
+
if (
|
54 |
+
$status === Mage_Catalog_Model_Product_Status::STATUS_DISABLED
|
55 |
+
&& $origStatus === Mage_Catalog_Model_Product_Status::STATUS_ENABLED
|
56 |
+
) {
|
57 |
+
return true;
|
58 |
+
}
|
59 |
+
|
60 |
+
// if product became not visible
|
61 |
+
if (
|
62 |
+
$visibility !== Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH
|
63 |
+
&& $origVisibility === Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH
|
64 |
+
) {
|
65 |
+
return true;
|
66 |
+
}
|
67 |
+
|
68 |
+
// if product is out of stock
|
69 |
+
$displayOos = Mage::helper('cataloginventory')->isShowOutOfStock();
|
70 |
+
if (!$product->isInStock() && !$displayOos) {
|
71 |
+
return true;
|
72 |
+
}
|
73 |
+
|
74 |
+
if (null === $pricing->getNormalPrice() || null === $pricing->getTierPrice() || null === $pricing->getSalePrice()) {
|
75 |
+
throw new UnexpectedValueException('Pricing calculations must be run before we can check if product should be deleted');
|
76 |
+
}
|
77 |
+
|
78 |
+
// if product has a zero price
|
79 |
+
$displayZeroPrice = Mage::helper('searchspring_manager')->isZeroPriceIndexingEnabled();
|
80 |
+
$productHaZeroPrice = 0 == $pricing->getNormalPrice() && 0 == $pricing->getTierPrice() && 0 == $pricing->getSalePrice();
|
81 |
+
if ($productHaZeroPrice && !$displayZeroPrice) {
|
82 |
+
return true;
|
83 |
+
}
|
84 |
+
|
85 |
+
return false;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* {@inheritdoc}
|
90 |
+
*/
|
91 |
+
public function isValid($product)
|
92 |
+
{
|
93 |
+
$this->messages = array();
|
94 |
+
|
95 |
+
/** @var Mage_Catalog_Model_Product $product */
|
96 |
+
if (!$product instanceof Mage_Catalog_Model_Product) {
|
97 |
+
$this->messages[] = 'Validator expected a Mage_Catalog_Model_Product.';
|
98 |
+
|
99 |
+
return false;
|
100 |
+
}
|
101 |
+
|
102 |
+
// product must be enabled
|
103 |
+
if ((int)$product->getData('status') !== Mage_Catalog_Model_Product_Status::STATUS_ENABLED) {
|
104 |
+
$this->messages[] = 'Product is not enabled';
|
105 |
+
}
|
106 |
+
|
107 |
+
// product must be an allowed type
|
108 |
+
if (!in_array($product->getData('type_id'), self::$allowableTypes)) {
|
109 |
+
$this->messages[] = 'Product is not an allowable type.';
|
110 |
+
}
|
111 |
+
|
112 |
+
// product must be visible in catalog and search
|
113 |
+
if ((int)$product->getData('visibility') !== Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH) {
|
114 |
+
$this->messages[] = 'Product must be visible in catalog and search';
|
115 |
+
}
|
116 |
+
|
117 |
+
// if we have errors, return false
|
118 |
+
if (!empty($this->messages)) {
|
119 |
+
return false;
|
120 |
+
}
|
121 |
+
|
122 |
+
return true;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* {@inheritdoc}
|
127 |
+
*/
|
128 |
+
public function getMessages()
|
129 |
+
{
|
130 |
+
return $this->messages;
|
131 |
+
}
|
132 |
+
}
|
app/code/community/SearchSpring/Manager/VarienObject/Data.php
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Data.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_VarienObject_Data
|
10 |
+
*
|
11 |
+
* Performs operations on Varien_Objects
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_VarienObject_Data
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Finds updated data on object
|
19 |
+
*
|
20 |
+
* @param Varien_Object $object
|
21 |
+
*
|
22 |
+
* @return array
|
23 |
+
*/
|
24 |
+
public function findUpdatedData(Varien_Object $object)
|
25 |
+
{
|
26 |
+
$originalData = $object->getOrigData();
|
27 |
+
$data = $object->getData();
|
28 |
+
|
29 |
+
$updated = $this->arrayDiffAssocRecursive($data, $originalData);
|
30 |
+
|
31 |
+
return $updated;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Determines if the object is new
|
36 |
+
*
|
37 |
+
* @param Varien_Object $object
|
38 |
+
*
|
39 |
+
* @return bool
|
40 |
+
*/
|
41 |
+
public function isNew(Varien_Object $object)
|
42 |
+
{
|
43 |
+
$isNew = null === $object->getOrigData();
|
44 |
+
|
45 |
+
return $isNew;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Finds array_diff_assoc recursively
|
50 |
+
*
|
51 |
+
* Will serialize each array field before performing array_diff_assoc(). This will resolve any errors that occur
|
52 |
+
* when running array_diff_assoc() and values that are not strings. It will then unserialize each field in the
|
53 |
+
* difference array returned from array_diff_assoc().
|
54 |
+
*
|
55 |
+
* @param array $changed
|
56 |
+
* @param array $original
|
57 |
+
* @return array
|
58 |
+
*/
|
59 |
+
private function arrayDiffAssocRecursive(array $changed, array $original)
|
60 |
+
{
|
61 |
+
$changed = $this->arrayValuesToString($changed);
|
62 |
+
$original = $this->arrayValuesToString($original);
|
63 |
+
|
64 |
+
$difference = array_map(
|
65 |
+
'unserialize',
|
66 |
+
array_diff_assoc(
|
67 |
+
array_map('serialize', $changed),
|
68 |
+
array_map('serialize', $original)
|
69 |
+
)
|
70 |
+
);
|
71 |
+
|
72 |
+
return $difference;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Casts scalar array values to strings
|
77 |
+
*
|
78 |
+
* @param array $array
|
79 |
+
*
|
80 |
+
* @return array
|
81 |
+
*/
|
82 |
+
private function arrayValuesToString(array $array)
|
83 |
+
{
|
84 |
+
foreach ($array as $key => $value) {
|
85 |
+
if (!is_scalar($value)) {
|
86 |
+
continue;
|
87 |
+
}
|
88 |
+
|
89 |
+
$array[$key] = (string) $value;
|
90 |
+
}
|
91 |
+
|
92 |
+
return $array;
|
93 |
+
}
|
94 |
+
}
|
app/code/community/SearchSpring/Manager/Writer/Product/FileWriter.php
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* ProductWriterXml.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Writer_Product_FileWriter
|
10 |
+
*
|
11 |
+
* Responsible for writing product data to xml
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Writer_Product_FileWriter implements SearchSpring_Manager_Writer_ProductWriter
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Format for continue response
|
19 |
+
*/
|
20 |
+
const MESSAGE_FORMAT_CONTINUE = '%s|%d';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* XmlWriter object
|
24 |
+
*
|
25 |
+
* @var XMLWriter $xmlWriter
|
26 |
+
*/
|
27 |
+
private $xmlWriter;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Holds values the writer needs
|
31 |
+
*
|
32 |
+
* @var SearchSpring_Manager_Writer_Product_FileWriter $writerParams
|
33 |
+
*/
|
34 |
+
private $writerParams;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Constructor
|
38 |
+
*
|
39 |
+
* @param XMLWriter $xmlWriter
|
40 |
+
* @param SearchSpring_Manager_Writer_Product_Params_FileWriterParams $writerParams
|
41 |
+
*/
|
42 |
+
public function __construct(
|
43 |
+
XMLWriter $xmlWriter,
|
44 |
+
SearchSpring_Manager_Writer_Product_Params_FileWriterParams $writerParams
|
45 |
+
) {
|
46 |
+
$this->xmlWriter = $xmlWriter;
|
47 |
+
$this->writerParams = $writerParams;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Transform ProductRecords to xml and write to file
|
52 |
+
*
|
53 |
+
* @param SearchSpring_Manager_Entity_RecordsCollection $records
|
54 |
+
*
|
55 |
+
* @return null
|
56 |
+
* @throws UnexpectedValueException
|
57 |
+
*/
|
58 |
+
public function write(SearchSpring_Manager_Entity_RecordsCollection $records)
|
59 |
+
{
|
60 |
+
$this->startWriting();
|
61 |
+
|
62 |
+
foreach ($records as $record) {
|
63 |
+
if (!is_array($record)) {
|
64 |
+
throw new UnexpectedValueException('Record in unknown format');
|
65 |
+
}
|
66 |
+
$this->xmlWriter->startElement('Product');
|
67 |
+
|
68 |
+
foreach ($record as $key => $value) {
|
69 |
+
if (!is_array($value)) {
|
70 |
+
$this->xmlWriter->writeElement($key, $value);
|
71 |
+
|
72 |
+
continue;
|
73 |
+
}
|
74 |
+
|
75 |
+
// if it's an array, we want to add all elements to the same node with the same key
|
76 |
+
foreach ($value as $v) {
|
77 |
+
$this->xmlWriter->writeElement($key, $v);
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
$this->xmlWriter->endElement();
|
82 |
+
}
|
83 |
+
|
84 |
+
$this->endWriting();
|
85 |
+
|
86 |
+
// get the response string
|
87 |
+
$response = $this->getResponse();
|
88 |
+
|
89 |
+
return $response;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Set up stream and setup document if it's the first write
|
94 |
+
*/
|
95 |
+
private function startWriting()
|
96 |
+
{
|
97 |
+
$this->xmlWriter->openMemory();
|
98 |
+
|
99 |
+
if (!$this->writerParams->isFirst()) {
|
100 |
+
return;
|
101 |
+
}
|
102 |
+
|
103 |
+
if (is_file($this->writerParams->getTempFilename())) {
|
104 |
+
unlink($this->writerParams->getTempFilename());
|
105 |
+
}
|
106 |
+
|
107 |
+
$this->xmlWriter->startDocument('1.0', 'UTF-8');
|
108 |
+
$this->xmlWriter->startElement('Products');
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Write to file from memory and cleanup document if it's the last write
|
113 |
+
*/
|
114 |
+
private function endWriting()
|
115 |
+
{
|
116 |
+
if ($this->writerParams->isLast()) {
|
117 |
+
$this->xmlWriter->writeRaw('</Products>');
|
118 |
+
}
|
119 |
+
|
120 |
+
file_put_contents($this->writerParams->getTempFilename(), $this->xmlWriter->flush(), FILE_APPEND);
|
121 |
+
|
122 |
+
if ($this->writerParams->isLast()) {
|
123 |
+
rename($this->writerParams->getTempFilename(), $this->writerParams->getFilename());
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Get the response string
|
129 |
+
*
|
130 |
+
* @return string
|
131 |
+
*/
|
132 |
+
private function getResponse()
|
133 |
+
{
|
134 |
+
$response = self::REGEN_COMPLETE;
|
135 |
+
if (!$this->writerParams->isLast()) {
|
136 |
+
$response = sprintf(
|
137 |
+
self::MESSAGE_FORMAT_CONTINUE,
|
138 |
+
self::REGEN_CONTINUE,
|
139 |
+
$this->writerParams->getRequestParams()->getCount() + $this->writerParams->getRequestParams()->getOffset()
|
140 |
+
);
|
141 |
+
}
|
142 |
+
|
143 |
+
return $response;
|
144 |
+
}
|
145 |
+
}
|
app/code/community/SearchSpring/Manager/Writer/Product/Params/FileWriterParams.php
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WriterParams.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Writer_Product_Params_FileWriterParams
|
10 |
+
*
|
11 |
+
* A parameter object that holds values needed for writing files
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Writer_Product_Params_FileWriterParams
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Filename pattern
|
19 |
+
*/
|
20 |
+
const FILENAME_FINAL_PATTERN = 'searchspring_%s.xml';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Temporary filename pattern
|
24 |
+
*/
|
25 |
+
const FILENAME_TEMP_PATTERN = 'searchspring_%s.%s.tmp.xml';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Total number of products in Magento
|
29 |
+
*
|
30 |
+
* @var int $totalProducts
|
31 |
+
*/
|
32 |
+
private $totalProducts;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* The unique filename to avoid collisions during generation
|
36 |
+
*
|
37 |
+
* @var string $uniqueFilename
|
38 |
+
*/
|
39 |
+
private $uniqueFilename;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Whether or not we're writing for the first time
|
43 |
+
*
|
44 |
+
* @var bool $isFirst
|
45 |
+
*/
|
46 |
+
private $isFirst;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Whether or not we're writing the last set of records
|
50 |
+
*
|
51 |
+
* @var bool $isLast
|
52 |
+
*/
|
53 |
+
private $isLast;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* The temporary filename
|
57 |
+
*
|
58 |
+
* @var string $tempFilename
|
59 |
+
*/
|
60 |
+
private $tempFilename;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* The filename
|
64 |
+
*
|
65 |
+
* @var string $filename
|
66 |
+
*/
|
67 |
+
private $filename;
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @var SearchSpring_Manager_Entity_RequestParams
|
71 |
+
*/
|
72 |
+
private $requestParams;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Constructor
|
76 |
+
*
|
77 |
+
* @param SearchSpring_Manager_Entity_RequestParams $requestParams
|
78 |
+
* @param int $totalProducts
|
79 |
+
* @param string $uniqueFilename
|
80 |
+
*/
|
81 |
+
public function __construct(SearchSpring_Manager_Entity_RequestParams $requestParams, $totalProducts, $uniqueFilename)
|
82 |
+
{
|
83 |
+
$this->requestParams = $requestParams;
|
84 |
+
$this->totalProducts = $totalProducts;
|
85 |
+
$this->uniqueFilename = $uniqueFilename;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Get the request parameters object
|
90 |
+
*
|
91 |
+
* @return SearchSpring_Manager_Entity_RequestParams
|
92 |
+
*/
|
93 |
+
public function getRequestParams()
|
94 |
+
{
|
95 |
+
return $this->requestParams;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Calculates if this is the first write
|
100 |
+
*
|
101 |
+
* @return bool
|
102 |
+
*/
|
103 |
+
public function isFirst()
|
104 |
+
{
|
105 |
+
if (null === $this->isFirst) {
|
106 |
+
$this->isFirst = (0 === $this->requestParams->getOffset());
|
107 |
+
}
|
108 |
+
|
109 |
+
return $this->isFirst;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Calculates if this is the last write
|
114 |
+
*
|
115 |
+
* @return bool
|
116 |
+
*/
|
117 |
+
public function isLast()
|
118 |
+
{
|
119 |
+
if (null === $this->isLast) {
|
120 |
+
$this->isLast = ($this->totalProducts <= ($this->requestParams->getCount() + $this->requestParams->getOffset()));
|
121 |
+
}
|
122 |
+
|
123 |
+
return $this->isLast;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Get temporary filename
|
128 |
+
*
|
129 |
+
* @return string
|
130 |
+
*/
|
131 |
+
public function getTempFilename()
|
132 |
+
{
|
133 |
+
if (null === $this->tempFilename) {
|
134 |
+
$this->tempFilename = Mage::getBaseDir()
|
135 |
+
. DS
|
136 |
+
. sprintf(self::FILENAME_TEMP_PATTERN, $this->requestParams->getStore(), $this->uniqueFilename);
|
137 |
+
}
|
138 |
+
|
139 |
+
return $this->tempFilename;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Get filename
|
144 |
+
*
|
145 |
+
* @return string
|
146 |
+
*/
|
147 |
+
public function getFilename()
|
148 |
+
{
|
149 |
+
if (null === $this->filename) {
|
150 |
+
$this->filename = Mage::getBaseDir() . DS . sprintf(self::FILENAME_FINAL_PATTERN, $this->requestParams->getStore());
|
151 |
+
}
|
152 |
+
|
153 |
+
return $this->filename;
|
154 |
+
}
|
155 |
+
}
|
app/code/community/SearchSpring/Manager/Writer/Product/Params/ResponseWriterParams.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WriterParams.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Writer_Provider_WriterParams
|
10 |
+
*
|
11 |
+
* Store parameters for response writer
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Writer_Product_Params_ResponseWriterParams
|
16 |
+
{
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Total number of products in Magento
|
20 |
+
*
|
21 |
+
* @var int $totalProducts
|
22 |
+
*/
|
23 |
+
private $totalProducts;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Whether or not we're writing for the first time
|
27 |
+
*
|
28 |
+
* @var bool $isFirst
|
29 |
+
*/
|
30 |
+
private $isFirst;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Whether or not we're writing the last set of records
|
34 |
+
*
|
35 |
+
* @var bool $isLast
|
36 |
+
*/
|
37 |
+
private $isLast;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var SearchSpring_Manager_Entity_RequestParams
|
41 |
+
*/
|
42 |
+
private $requestParams;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Constructor
|
46 |
+
*
|
47 |
+
* @param SearchSpring_Manager_Entity_RequestParams $requestParams
|
48 |
+
* @param int $totalProducts
|
49 |
+
*/
|
50 |
+
public function __construct(SearchSpring_Manager_Entity_RequestParams $requestParams, $totalProducts)
|
51 |
+
{
|
52 |
+
$this->requestParams = $requestParams;
|
53 |
+
$this->totalProducts = $totalProducts;
|
54 |
+
}
|
55 |
+
|
56 |
+
public function getRequestParams()
|
57 |
+
{
|
58 |
+
return $this->requestParams;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Calculates if this is the first write
|
63 |
+
*
|
64 |
+
* @return bool
|
65 |
+
*/
|
66 |
+
public function isFirst()
|
67 |
+
{
|
68 |
+
if (null === $this->isFirst) {
|
69 |
+
$this->isFirst = (0 === $this->requestParams->getOffset());
|
70 |
+
}
|
71 |
+
|
72 |
+
return $this->isFirst;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Calculates if this is the last write
|
77 |
+
*
|
78 |
+
* @return bool
|
79 |
+
*/
|
80 |
+
public function isLast()
|
81 |
+
{
|
82 |
+
$totalCount = $this->requestParams->getCount() + $this->requestParams->getOffset();
|
83 |
+
|
84 |
+
// if we defaulted to 0, we're only doing one iteration
|
85 |
+
if (0 === $totalCount) {
|
86 |
+
return true;
|
87 |
+
}
|
88 |
+
|
89 |
+
if (null === $this->isLast) {
|
90 |
+
$this->isLast = ($this->totalProducts <= $totalCount);
|
91 |
+
}
|
92 |
+
|
93 |
+
return $this->isLast;
|
94 |
+
}
|
95 |
+
}
|
app/code/community/SearchSpring/Manager/Writer/Product/ResponseWriter.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* ResponseWriter.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_Writer_Product_ResponseWriter
|
10 |
+
*
|
11 |
+
* Write a collection as a response
|
12 |
+
*
|
13 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
14 |
+
*/
|
15 |
+
class SearchSpring_Manager_Writer_Product_ResponseWriter implements SearchSpring_Manager_Writer_ProductWriter
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Parameters for writing responses
|
19 |
+
*
|
20 |
+
* @var SearchSpring_Manager_Writer_Product_Params_ResponseWriterParams
|
21 |
+
*/
|
22 |
+
private $params;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Constructor
|
26 |
+
*
|
27 |
+
* @param SearchSpring_Manager_Writer_Product_Params_ResponseWriterParams $params
|
28 |
+
*/
|
29 |
+
public function __construct(SearchSpring_Manager_Writer_Product_Params_ResponseWriterParams $params)
|
30 |
+
{
|
31 |
+
$this->params = $params;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Write a response and return that as the message
|
36 |
+
*
|
37 |
+
* @param SearchSpring_Manager_Entity_RecordsCollection $recordsCollection
|
38 |
+
* @return array
|
39 |
+
*/
|
40 |
+
public function write(SearchSpring_Manager_Entity_RecordsCollection $recordsCollection)
|
41 |
+
{
|
42 |
+
$response = array('status' => self::REGEN_COMPLETE, 'products' => $recordsCollection->toArray());
|
43 |
+
if (!$this->params->isLast()) {
|
44 |
+
$response['status'] = self::REGEN_CONTINUE;
|
45 |
+
}
|
46 |
+
|
47 |
+
return $response;
|
48 |
+
}
|
49 |
+
}
|
app/code/community/SearchSpring/Manager/Writer/ProductWriter.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* ProductWriter.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Interface SearchSpring_Manager_Writer_ProductWriter
|
10 |
+
*
|
11 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
12 |
+
*/
|
13 |
+
interface SearchSpring_Manager_Writer_ProductWriter
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* Continue response
|
17 |
+
*/
|
18 |
+
const REGEN_CONTINUE = 'continue';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Complete response
|
22 |
+
*/
|
23 |
+
const REGEN_COMPLETE = 'complete';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Write a collection
|
27 |
+
*
|
28 |
+
* @param SearchSpring_Manager_Entity_RecordsCollection $recordsCollection
|
29 |
+
*
|
30 |
+
* @return string The response message
|
31 |
+
*/
|
32 |
+
public function write(SearchSpring_Manager_Entity_RecordsCollection $recordsCollection);
|
33 |
+
}
|
app/code/community/SearchSpring/Manager/controllers/GenerateController.php
ADDED
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* GenerateController.php
|
4 |
+
*
|
5 |
+
* @copyright B7 Interactive, LLC. All Rights Reserved.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class SearchSpring_Manager_GenerateController
|
10 |
+
*
|
11 |
+
* @author Nate Brunette <nate@b7interactive.com>
|
12 |
+
*/
|
13 |
+
class SearchSpring_Manager_GenerateController extends Mage_Core_Controller_Front_Action
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* Default starting point if no parameter is set
|
17 |
+
*/
|
18 |
+
const OFFSET_DEFAULT = 0;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Default product limit if no parameter is set
|
22 |
+
*/
|
23 |
+
const COUNT_DEFAULT = 100;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Default store if no parameter is set
|
27 |
+
*/
|
28 |
+
const STORE_DEFAULT = 'default';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Default action for updating based on product/category id
|
32 |
+
*
|
33 |
+
* Parameters:
|
34 |
+
* type (required): The type of id passed in. Can be 'product' or 'category'
|
35 |
+
* ids (required): An array of ids
|
36 |
+
*/
|
37 |
+
public function indexAction()
|
38 |
+
{
|
39 |
+
$request = new SearchSpring_Manager_Request_JSON($this->getRequest());
|
40 |
+
|
41 |
+
$type = $request->getParam('type');
|
42 |
+
$ids = $request->getParam('ids');
|
43 |
+
|
44 |
+
if (null === $type) {
|
45 |
+
$this->setJsonResponse(
|
46 |
+
array(
|
47 |
+
'status' => 'error',
|
48 |
+
'errorCode' => SearchSpring_ErrorCodes::TYPE_NOT_SET,
|
49 |
+
'message' => 'Type must be specified'
|
50 |
+
),
|
51 |
+
400
|
52 |
+
);
|
53 |
+
|
54 |
+
return;
|
55 |
+
}
|
56 |
+
|
57 |
+
if (null === $ids) {
|
58 |
+
$this->setJsonResponse(
|
59 |
+
array(
|
60 |
+
'status' => 'error',
|
61 |
+
'errorCode' => SearchSpring_ErrorCodes::IDS_NOT_SET,
|
62 |
+
'message' => 'Ids must be specified'
|
63 |
+
),
|
64 |
+
400
|
65 |
+
);
|
66 |
+
|
67 |
+
return;
|
68 |
+
}
|
69 |
+
|
70 |
+
$requestParams = new SearchSpring_Manager_Entity_RequestParams(
|
71 |
+
(int)$request->getParam('size', null),
|
72 |
+
(int)$request->getParam('start', null),
|
73 |
+
$request->getParam('store', self::STORE_DEFAULT)
|
74 |
+
);
|
75 |
+
|
76 |
+
$params = array('ids' => $ids);
|
77 |
+
|
78 |
+
$generatorFactory = new SearchSpring_Manager_Factory_GeneratorFactory();
|
79 |
+
$generator = $generatorFactory->make($type, $requestParams, $params);
|
80 |
+
$message = $generator->generate();
|
81 |
+
|
82 |
+
$this->setJsonResponse($message);
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Generate an xml feed of all products
|
88 |
+
*
|
89 |
+
* Parameters:
|
90 |
+
* filename (required): A unique filename when creating temporary files.
|
91 |
+
* start (optional): The starting point for fetching products. Defaults to 0.
|
92 |
+
* count (optional): The number of products to fetch. Defaults to 100.
|
93 |
+
* store (optional): The store name as a string. Defaults to 'default'
|
94 |
+
*/
|
95 |
+
public function feedAction()
|
96 |
+
{
|
97 |
+
// check file is writable first
|
98 |
+
if (!is_writable(Mage::getBaseDir())) {
|
99 |
+
$this->setJsonResponse(
|
100 |
+
array(
|
101 |
+
'status' => 'error',
|
102 |
+
'errorCode' => SearchSpring_ErrorCodes::DIR_NOT_WRITABLE,
|
103 |
+
'message' => 'Magento base directory is not writable'
|
104 |
+
),
|
105 |
+
500
|
106 |
+
);
|
107 |
+
|
108 |
+
return;
|
109 |
+
}
|
110 |
+
|
111 |
+
$uniqueFilename = $this->getRequest()->getParam('filename');
|
112 |
+
|
113 |
+
if (null === $uniqueFilename) {
|
114 |
+
$this->setJsonResponse(
|
115 |
+
array(
|
116 |
+
'status' => 'error',
|
117 |
+
'errorCode' => SearchSpring_ErrorCodes::FILENAME_NOT_SET,
|
118 |
+
'message' => 'Unique filename must be passed in'
|
119 |
+
),
|
120 |
+
400
|
121 |
+
);
|
122 |
+
|
123 |
+
return;
|
124 |
+
}
|
125 |
+
|
126 |
+
$requestParams = new SearchSpring_Manager_Entity_RequestParams(
|
127 |
+
(int)$this->getRequest()->getParam('count', self::COUNT_DEFAULT),
|
128 |
+
(int)$this->getRequest()->getParam('start', self::OFFSET_DEFAULT),
|
129 |
+
$this->getRequest()->getParam('store', self::STORE_DEFAULT)
|
130 |
+
);
|
131 |
+
|
132 |
+
$params = array('filename' => $uniqueFilename);
|
133 |
+
|
134 |
+
$generatorFactory = new SearchSpring_Manager_Factory_GeneratorFactory();
|
135 |
+
$generator = $generatorFactory->make(
|
136 |
+
SearchSpring_Manager_Factory_GeneratorFactory::TYPE_FEED,
|
137 |
+
$requestParams,
|
138 |
+
$params
|
139 |
+
);
|
140 |
+
$message = $generator->generate();
|
141 |
+
|
142 |
+
$this->setTextResponse($message);
|
143 |
+
|
144 |
+
return;
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Set appropriate response variables for a json response
|
149 |
+
*
|
150 |
+
* @param array $message The message that should be sent back
|
151 |
+
* @param int $responseCode The Http response code
|
152 |
+
*/
|
153 |
+
private function setJsonResponse(array $message, $responseCode = 200)
|
154 |
+
{
|
155 |
+
$this->getResponse()->setHeader('Content-type', 'application/json');
|
156 |
+
$this->getResponse()->setHttpResponseCode($responseCode);
|
157 |
+
|
158 |
+
$responseBody = json_encode($message);
|
159 |
+
$this->getResponse()->setBody($responseBody);
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Set a text based response
|
164 |
+
*
|
165 |
+
* @param string $message
|
166 |
+
* @param int $responseCode
|
167 |
+
*/
|
168 |
+
private function setTextResponse($message, $responseCode = 200)
|
169 |
+
{
|
170 |
+
$this->getResponse()->setHeader('Content-type', 'text/plain');
|
171 |
+
$this->getResponse()->setHttpResponseCode($responseCode);
|
172 |
+
$this->getResponse()->setBody($message);
|
173 |
+
}
|
174 |
+
}
|
app/code/community/SearchSpring/Manager/etc/adminhtml.xml
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<acl>
|
4 |
+
<resources>
|
5 |
+
<all>
|
6 |
+
<title>Allow Everything</title>
|
7 |
+
</all>
|
8 |
+
<admin>
|
9 |
+
<children>
|
10 |
+
<system>
|
11 |
+
<children>
|
12 |
+
<config>
|
13 |
+
<children>
|
14 |
+
<ssmanager translate="title">
|
15 |
+
<title>An Example Section</title>
|
16 |
+
<sort_order>100</sort_order>
|
17 |
+
</ssmanager>
|
18 |
+
</children>
|
19 |
+
</config>
|
20 |
+
</children>
|
21 |
+
</system>
|
22 |
+
</children>
|
23 |
+
</admin>
|
24 |
+
</resources>
|
25 |
+
</acl>
|
26 |
+
</config>
|
app/code/community/SearchSpring/Manager/etc/composer.json
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "SearchSpring/Manager",
|
3 |
+
"license": "OSL-3.0",
|
4 |
+
"type": "magento-module",
|
5 |
+
"description": "Add your description here",
|
6 |
+
"require": {
|
7 |
+
"magento-hackathon/magento-composer-installer": "*"
|
8 |
+
},
|
9 |
+
"authors": [
|
10 |
+
{
|
11 |
+
"name": "Nate Brunette",
|
12 |
+
"email": "nate@b7interactive.com"
|
13 |
+
}
|
14 |
+
]
|
15 |
+
}
|
app/code/community/SearchSpring/Manager/etc/config.xml
ADDED
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<SearchSpring_Manager>
|
5 |
+
<version>1.1.0</version>
|
6 |
+
</SearchSpring_Manager>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<models>
|
10 |
+
<searchspring_manager>
|
11 |
+
<class>SearchSpring_Manager_Model</class>
|
12 |
+
</searchspring_manager>
|
13 |
+
</models>
|
14 |
+
<blocks>
|
15 |
+
<searchspring_manager>
|
16 |
+
<class>SearchSpring_Manager_Block</class>
|
17 |
+
</searchspring_manager>
|
18 |
+
<!-- Add back in for Category Page Management -->
|
19 |
+
<!-- <catalog> -->
|
20 |
+
<!-- <rewrite> -->
|
21 |
+
<!-- <layer_view>SearchSpring_Manager_Block_Layer_View</layer_view> -->
|
22 |
+
<!-- </rewrite> -->
|
23 |
+
<!-- </catalog> -->
|
24 |
+
</blocks>
|
25 |
+
<helpers>
|
26 |
+
<searchspring_manager>
|
27 |
+
<class>SearchSpring_Manager_Helper</class>
|
28 |
+
</searchspring_manager>
|
29 |
+
</helpers>
|
30 |
+
<events>
|
31 |
+
<catalog_product_save_after>
|
32 |
+
<observers>
|
33 |
+
<searchspring_manager_after_save_push_product>
|
34 |
+
<class>searchspring_manager/observer_productSaveObserver</class>
|
35 |
+
<method>afterSavePushProduct</method>
|
36 |
+
</searchspring_manager_after_save_push_product>
|
37 |
+
</observers>
|
38 |
+
</catalog_product_save_after>
|
39 |
+
<catalog_product_delete_before>
|
40 |
+
<observers>
|
41 |
+
<searchspring_manager_before_delete_push_product>
|
42 |
+
<class>searchspring_manager/observer_productSaveObserver</class>
|
43 |
+
<method>beforeDeletePushProduct</method>
|
44 |
+
</searchspring_manager_before_delete_push_product>
|
45 |
+
</observers>
|
46 |
+
</catalog_product_delete_before>
|
47 |
+
<catalog_product_delete_after_done>
|
48 |
+
<observers>
|
49 |
+
<searchspring_manager_after_delete_push_product>
|
50 |
+
<class>searchspring_manager/observer_productSaveObserver</class>
|
51 |
+
<method>afterDeletePushProduct</method>
|
52 |
+
</searchspring_manager_after_delete_push_product>
|
53 |
+
</observers>
|
54 |
+
</catalog_product_delete_after_done>
|
55 |
+
<catalog_category_save_after>
|
56 |
+
<observers>
|
57 |
+
<searchspring_manager_after_save_update_product_category>
|
58 |
+
<class>searchspring_manager/observer_categorySaveObserver</class>
|
59 |
+
<method>afterSaveUpdateProductCategory</method>
|
60 |
+
</searchspring_manager_after_save_update_product_category>
|
61 |
+
</observers>
|
62 |
+
</catalog_category_save_after>
|
63 |
+
<category_move>
|
64 |
+
<observers>
|
65 |
+
<searchspring_manager_after_move_update_product_category>
|
66 |
+
<class>searchspring_manager/observer_categorySaveObserver</class>
|
67 |
+
<method>afterMoveUpdateProductCategory</method>
|
68 |
+
</searchspring_manager_after_move_update_product_category>
|
69 |
+
</observers>
|
70 |
+
</category_move>
|
71 |
+
<catalog_category_change_products>
|
72 |
+
<observers>
|
73 |
+
<searchspring_manager_after_product_change_update_product_category>
|
74 |
+
<class>searchspring_manager/observer_categorySaveObserver</class>
|
75 |
+
<method>afterProductChangeUpdateProductCategory</method>
|
76 |
+
</searchspring_manager_after_product_change_update_product_category>
|
77 |
+
</observers>
|
78 |
+
</catalog_category_change_products>
|
79 |
+
<catalog_controller_category_delete>
|
80 |
+
<observers>
|
81 |
+
<searchspring_manager_after_delete_update_product_category>
|
82 |
+
<class>searchspring_manager/observer_categorySaveObserver</class>
|
83 |
+
<method>afterDeleteUpdateProductCategory</method>
|
84 |
+
</searchspring_manager_after_delete_update_product_category>
|
85 |
+
</observers>
|
86 |
+
</catalog_controller_category_delete>
|
87 |
+
</events>
|
88 |
+
<template>
|
89 |
+
<email>
|
90 |
+
<api_error module="searchspring_manager">
|
91 |
+
<label>API Error Template</label>
|
92 |
+
<file>searchspring_api_error.html</file>
|
93 |
+
<type>html</type>
|
94 |
+
</api_error>
|
95 |
+
</email>
|
96 |
+
</template>
|
97 |
+
<resources>
|
98 |
+
<searchspring_manager>
|
99 |
+
<setup>
|
100 |
+
<module>SearchSpring_Manager</module>
|
101 |
+
<class>Mage_Catalog_Model_Resource_Setup</class>
|
102 |
+
</setup>
|
103 |
+
<connection>
|
104 |
+
<use>core_setup</use>
|
105 |
+
</connection>
|
106 |
+
</searchspring_manager>
|
107 |
+
</resources>
|
108 |
+
</global>
|
109 |
+
<frontend>
|
110 |
+
<routers>
|
111 |
+
<searchspring>
|
112 |
+
<use>standard</use>
|
113 |
+
<args>
|
114 |
+
<module>SearchSpring_Manager</module>
|
115 |
+
<frontName>searchspring</frontName>
|
116 |
+
</args>
|
117 |
+
</searchspring>
|
118 |
+
</routers>
|
119 |
+
<!-- Add back in for Category Page Management -->
|
120 |
+
<!-- <layout> -->
|
121 |
+
<!-- <updates> -->
|
122 |
+
<!-- <searchspring_manager module="SearchSpring_Manager"> -->
|
123 |
+
<!-- <file>searchspring_manager.xml</file> -->
|
124 |
+
<!-- </searchspring_manager> -->
|
125 |
+
<!-- </updates> -->
|
126 |
+
<!-- </layout> -->
|
127 |
+
</frontend>
|
128 |
+
<default>
|
129 |
+
<ssmanager>
|
130 |
+
<ssmanager_general>
|
131 |
+
<live_indexing>0</live_indexing>
|
132 |
+
</ssmanager_general>
|
133 |
+
<ssmanager_catalog>
|
134 |
+
<enable_categories>0</enable_categories>
|
135 |
+
</ssmanager_catalog>
|
136 |
+
</ssmanager>
|
137 |
+
</default>
|
138 |
+
</config>
|
app/code/community/SearchSpring/Manager/etc/readme.md
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
SearchSpring SearchSpringManager Extension
|
2 |
+
=====================
|
3 |
+
Add your description here
|
4 |
+
Facts
|
5 |
+
-----
|
6 |
+
- version: 0.4.0
|
7 |
+
- extension key: SearchSpring_SearchSpringManager
|
8 |
+
- [extension on Magento Connect](http://www.magentocommerce.com/magento-connect/searchspring)-searchspringmanager-1234.html)
|
9 |
+
- Magento Connect 1.0 extension key: magento-community/SearchSpring_SearchSpringManager
|
10 |
+
- Magento Connect 2.0 extension key: http://connect20.magentocommerce.com/community/SearchSpring_SearchSpringManager
|
11 |
+
- [extension on GitHub](https://github.com/searchspring/SearchSpring_SearchSpringManager
|
12 |
+
- [direct download link](http://connect.magentocommerce.com/community/get/SearchSpring_SearchSpringManager-1.0.0.tgz)
|
13 |
+
|
14 |
+
Description
|
15 |
+
-----------
|
16 |
+
This paragraph describes what the extension does.
|
17 |
+
|
18 |
+
Requirements
|
19 |
+
------------
|
20 |
+
- PHP >= 5.2.0
|
21 |
+
- Mage_Core
|
22 |
+
- ...
|
23 |
+
|
24 |
+
Compatibility
|
25 |
+
-------------
|
26 |
+
- Magento >= 1.7
|
27 |
+
|
28 |
+
Installation Instructions
|
29 |
+
-------------------------
|
30 |
+
1. Install the extension via Magento Connect with the key shown above or copy all the files into your document root.
|
31 |
+
2. Clear the cache, logout from the admin panel and then login again.
|
32 |
+
3. Configure and activate the extension under System - Configuration - Company - Example Extension.
|
33 |
+
4. ...
|
34 |
+
|
35 |
+
Uninstallation
|
36 |
+
--------------
|
37 |
+
1. Remove all extension files from your Magento installation
|
38 |
+
2. ...
|
39 |
+
|
40 |
+
Support
|
41 |
+
-------
|
42 |
+
If you have any issues with this extension, open an issue on [GitHub](https://github.com/searchspring/SearchSpring_SearchSpringManager/issues).
|
43 |
+
|
44 |
+
Contribution
|
45 |
+
------------
|
46 |
+
Any contribution is highly appreciated. The best way to contribute code is to open a [pull request on GitHub](https://help.github.com/articles/using-pull-requests).
|
47 |
+
|
48 |
+
Developers
|
49 |
+
---------
|
50 |
+
Nate Brunette
|
51 |
+
James Bathgate
|
52 |
+
|
53 |
+
Copyright
|
54 |
+
---------
|
55 |
+
(c) 2014 SearchSpring
|
app/code/community/SearchSpring/Manager/etc/system.xml
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<tabs>
|
4 |
+
<searchspring translate="label" module="searchspring_manager">
|
5 |
+
<label>SearchSpring</label>
|
6 |
+
<sort_order>500</sort_order>
|
7 |
+
</searchspring>
|
8 |
+
</tabs>
|
9 |
+
<sections>
|
10 |
+
<ssmanager translate="label">
|
11 |
+
<label>Manager Settings</label>
|
12 |
+
<tab>searchspring</tab>
|
13 |
+
<frontend_type>text</frontend_type>
|
14 |
+
<sort_order>100</sort_order>
|
15 |
+
<show_in_default>1</show_in_default>
|
16 |
+
<show_in_website>1</show_in_website>
|
17 |
+
<show_in_store>1</show_in_store>
|
18 |
+
<groups>
|
19 |
+
<ssmanager_general translate="label" module="searchspring_manager">
|
20 |
+
<label>Indexing Configuration</label>
|
21 |
+
<frontend_type>text</frontend_type>
|
22 |
+
<sort_order>100</sort_order>
|
23 |
+
<show_in_default>1</show_in_default>
|
24 |
+
<show_in_website>1</show_in_website>
|
25 |
+
<show_in_store>1</show_in_store>
|
26 |
+
<fields>
|
27 |
+
<live_indexing translate="label">
|
28 |
+
<label>Live Indexing</label>
|
29 |
+
<comment>If live indexing is enabled, on product/category saves, SearchSpring will get an update of changes. Only enable this if Magento cache is updated on save.</comment>
|
30 |
+
<frontend_type>select</frontend_type>
|
31 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
32 |
+
<sort_order>5</sort_order>
|
33 |
+
<show_in_default>1</show_in_default>
|
34 |
+
<show_in_website>1</show_in_website>
|
35 |
+
<show_in_store>1</show_in_store>
|
36 |
+
</live_indexing>
|
37 |
+
<index_zero_price translate="label">
|
38 |
+
<label>Display products with 0 price</label>
|
39 |
+
<frontend_type>select</frontend_type>
|
40 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
41 |
+
<sort_order>10</sort_order>
|
42 |
+
<show_in_default>1</show_in_default>
|
43 |
+
<show_in_website>1</show_in_website>
|
44 |
+
<show_in_store>1</show_in_store>
|
45 |
+
</index_zero_price>
|
46 |
+
</fields>
|
47 |
+
</ssmanager_general>
|
48 |
+
<ssmanager_images translate="label" module="searchspring_manager">
|
49 |
+
<label>Image Settings</label>
|
50 |
+
<frontend_type>text</frontend_type>
|
51 |
+
<sort_order>100</sort_order>
|
52 |
+
<show_in_default>1</show_in_default>
|
53 |
+
<show_in_website>1</show_in_website>
|
54 |
+
<show_in_store>1</show_in_store>
|
55 |
+
<fields>
|
56 |
+
<generate_cache_images translate="label">
|
57 |
+
<label>Generate Cache Images</label>
|
58 |
+
<comment>If you use cache images and clear your image cache you will need to re-index SearchSpring to re-populate your product images.</comment>
|
59 |
+
<frontend_type>select</frontend_type>
|
60 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
61 |
+
<sort_order>10</sort_order>
|
62 |
+
<show_in_default>1</show_in_default>
|
63 |
+
<show_in_website>1</show_in_website>
|
64 |
+
<show_in_store>1</show_in_store>
|
65 |
+
</generate_cache_images>
|
66 |
+
<image_width translate="label">
|
67 |
+
<label>Image Width</label>
|
68 |
+
<comment>Image width in pixels for generated cache images (Default: 200)</comment>
|
69 |
+
<frontend_type>text</frontend_type>
|
70 |
+
<sort_order>20</sort_order>
|
71 |
+
<show_in_default>1</show_in_default>
|
72 |
+
<show_in_website>1</show_in_website>
|
73 |
+
<show_in_store>1</show_in_store>
|
74 |
+
</image_width>
|
75 |
+
<image_height translate="label">
|
76 |
+
<label>Image Height</label>
|
77 |
+
<comment>Image height in pixels for generated cache images (Default: 200)</comment>
|
78 |
+
<frontend_type>text</frontend_type>
|
79 |
+
<sort_order>30</sort_order>
|
80 |
+
<show_in_default>1</show_in_default>
|
81 |
+
<show_in_website>1</show_in_website>
|
82 |
+
<show_in_store>1</show_in_store>
|
83 |
+
</image_height>
|
84 |
+
</fields>
|
85 |
+
</ssmanager_images>
|
86 |
+
<ssmanager_catalog translate="label" module="searchspring_manager">
|
87 |
+
<label>Catalog Configuration</label>
|
88 |
+
<frontend_type>text</frontend_type>
|
89 |
+
<sort_order>200</sort_order>
|
90 |
+
<show_in_default>1</show_in_default>
|
91 |
+
<show_in_website>1</show_in_website>
|
92 |
+
<show_in_store>1</show_in_store>
|
93 |
+
<fields>
|
94 |
+
<enable_categories translate="label">
|
95 |
+
<label>Category Display</label>
|
96 |
+
<comment>If category display is enabled SearchSpring will power your category pages.</comment>
|
97 |
+
<frontend_type>select</frontend_type>
|
98 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
99 |
+
<sort_order>10</sort_order>
|
100 |
+
<!-- Turn these back on for Category Page Management -->
|
101 |
+
<show_in_default>0</show_in_default>
|
102 |
+
<show_in_website>0</show_in_website>
|
103 |
+
<show_in_store>0</show_in_store>
|
104 |
+
</enable_categories>
|
105 |
+
</fields>
|
106 |
+
</ssmanager_catalog>
|
107 |
+
<ssmanager_api translate="label" module="searchspring_manager">
|
108 |
+
<label>SearchSpring Connection Settings</label>
|
109 |
+
<frontend_type>select</frontend_type>
|
110 |
+
<sort_order>300</sort_order>
|
111 |
+
<show_in_default>1</show_in_default>
|
112 |
+
<show_in_website>1</show_in_website>
|
113 |
+
<show_in_store>1</show_in_store>
|
114 |
+
<fields>
|
115 |
+
<base_url translate="label">
|
116 |
+
<label>Base URL</label>
|
117 |
+
<comment>https://example.com</comment>
|
118 |
+
<frontend_type>text</frontend_type>
|
119 |
+
<sort_order>15</sort_order>
|
120 |
+
<show_in_default>1</show_in_default>
|
121 |
+
<show_in_website>1</show_in_website>
|
122 |
+
<show_in_store>1</show_in_store>
|
123 |
+
</base_url>
|
124 |
+
<site_id translate="label">
|
125 |
+
<label>Site ID</label>
|
126 |
+
<comment>You can find this in the upper right corner of the SearchSpring Management Console</comment>
|
127 |
+
<frontend_type>text</frontend_type>
|
128 |
+
<sort_order>20</sort_order>
|
129 |
+
<show_in_default>1</show_in_default>
|
130 |
+
<show_in_website>1</show_in_website>
|
131 |
+
<show_in_store>1</show_in_store>
|
132 |
+
</site_id>
|
133 |
+
<feed_id translate="label">
|
134 |
+
<label>Feed ID</label>
|
135 |
+
<frontend_type>text</frontend_type>
|
136 |
+
<sort_order>30</sort_order>
|
137 |
+
<show_in_default>1</show_in_default>
|
138 |
+
<show_in_website>1</show_in_website>
|
139 |
+
<show_in_store>1</show_in_store>
|
140 |
+
</feed_id>
|
141 |
+
<secret_key translate="label">
|
142 |
+
<label>Secret Key</label>
|
143 |
+
<frontend_type>text</frontend_type>
|
144 |
+
<sort_order>40</sort_order>
|
145 |
+
<show_in_default>1</show_in_default>
|
146 |
+
<show_in_website>1</show_in_website>
|
147 |
+
<show_in_store>1</show_in_store>
|
148 |
+
</secret_key>
|
149 |
+
</fields>
|
150 |
+
</ssmanager_api>
|
151 |
+
</groups>
|
152 |
+
</ssmanager>
|
153 |
+
</sections>
|
154 |
+
</config>
|
app/design/frontend/base/default/layout/searchspring_manager.xml
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout>
|
3 |
+
|
4 |
+
<catalog_category_layered>
|
5 |
+
<update handle="_searchspring_layered_navigation_override" />
|
6 |
+
</catalog_category_layered>
|
7 |
+
|
8 |
+
<_searchspring_layered_navigation_override>
|
9 |
+
|
10 |
+
<!-- Custom Templates -->
|
11 |
+
|
12 |
+
<reference name="catalog.leftnav">
|
13 |
+
<action method="setTemplate">
|
14 |
+
<template helper="searchspring_manager/getBlockTemplateIfCategoryEnabled">
|
15 |
+
<blockName>catalog.leftnav</blockName>
|
16 |
+
<newTemplate>searchspring_manager/layer/view.phtml</newTemplate>
|
17 |
+
</template>
|
18 |
+
</action>
|
19 |
+
</reference>
|
20 |
+
|
21 |
+
<reference name="product_list">
|
22 |
+
<action method="setTemplate">
|
23 |
+
<template helper="searchspring_manager/getBlockTemplateIfCategoryEnabled">
|
24 |
+
<blockName>product_list</blockName>
|
25 |
+
<newTemplate>searchspring_manager/product/list.phtml</newTemplate>
|
26 |
+
</template>
|
27 |
+
</action>
|
28 |
+
</reference>
|
29 |
+
|
30 |
+
<reference name="product_list_toolbar">
|
31 |
+
<action method="setTemplate">
|
32 |
+
<template helper="searchspring_manager/getBlockTemplateIfCategoryEnabled">
|
33 |
+
<blockName>product_list_toolbar</blockName>
|
34 |
+
<newTemplate>searchspring_manager/product/list/toolbar.phtml</newTemplate>
|
35 |
+
</template>
|
36 |
+
</action>
|
37 |
+
</reference>
|
38 |
+
|
39 |
+
</_searchspring_layered_navigation_override>
|
40 |
+
|
41 |
+
</layout>
|
app/design/frontend/base/default/template/searchspring_manager/layer/category_filter.phtml
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Template for category filter items block
|
4 |
+
*
|
5 |
+
* @see SearchSpring_Manager_Block_Layer_Filter_SearchSpringCategory
|
6 |
+
*/
|
7 |
+
?>
|
8 |
+
|
9 |
+
<ol>
|
10 |
+
<?php //TODO: Maybe we should make these some sort of category parent object instead of using raw category objects -James ?>
|
11 |
+
<?php $_parents = $this->getParents() ?>
|
12 |
+
<?php foreach($_parents as $_id => $_parent): ?>
|
13 |
+
<li class="ss-category_breadcrumb <?php echo ($_id == $this->getCurrentValue()) ? "ss-current_category":"" ?>">
|
14 |
+
<a href="<?php echo $this->urlEscape($_parent->getUrl()) ?>">
|
15 |
+
<?php echo ($_id == $this->getCurrentValue()) ? "":"«" ?> <?php echo $_parent->getName() ?>
|
16 |
+
</a>
|
17 |
+
</li>
|
18 |
+
<?php endforeach; ?>
|
19 |
+
<?php foreach ($this->getItems() as $_item): ?>
|
20 |
+
<li <?php echo $_item->isActive()?'active':'' ?>">
|
21 |
+
<a href="<?php echo $this->urlEscape($_item->getUrl()) ?>">
|
22 |
+
<?php echo $_item->getLabel() ?>
|
23 |
+
<?php if ($this->shouldDisplayProductCount()): ?>
|
24 |
+
<span class="count">(<?php echo $_item->getCount() ?>)</span>
|
25 |
+
<?php endif; ?>
|
26 |
+
</a>
|
27 |
+
</li>
|
28 |
+
<?php endforeach ?>
|
29 |
+
</ol>
|
app/design/frontend/base/default/template/searchspring_manager/layer/filter.phtml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Template for filter items block
|
4 |
+
*
|
5 |
+
* @see SearchSpring_Manager_Block_Layer_Filter_SearchSpringList
|
6 |
+
*/
|
7 |
+
?>
|
8 |
+
|
9 |
+
<ol>
|
10 |
+
<?php foreach ($this->getItems() as $_item): ?>
|
11 |
+
<li <?php echo $_item->isActive()?'class="active"':'' ?>>
|
12 |
+
<a rel="nofollow" href="<?php echo $this->urlEscape($_item->getUrl()) ?>">
|
13 |
+
<?php echo $_item->getLabel() ?>
|
14 |
+
<?php if ($this->shouldDisplayProductCount()): ?>
|
15 |
+
<span class="count">(<?php echo $_item->getCount() ?>)</span>
|
16 |
+
<?php endif; ?>
|
17 |
+
</a>
|
18 |
+
</li>
|
19 |
+
<?php endforeach ?>
|
20 |
+
</ol>
|
app/design/frontend/base/default/template/searchspring_manager/layer/state.phtml
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Category layered navigation state
|
4 |
+
*
|
5 |
+
* @see Mage_Catalog_Block_Layer_State
|
6 |
+
*/
|
7 |
+
?>
|
8 |
+
<?php $_filters = $this->getActiveFilters() ?>
|
9 |
+
<?php if(!empty($_filters)): ?>
|
10 |
+
<div class="currently">
|
11 |
+
<p class="block-subtitle"><?php echo $this->__('Currently Shopping by:') ?></p>
|
12 |
+
<ol>
|
13 |
+
<?php foreach ($_filters as $_filter): ?>
|
14 |
+
<li>
|
15 |
+
<span class="label"><?php echo $this->__($_filter->getName()) ?>:</span> <span class="value"><?php echo $this->stripTags($_filter->getLabel()) ?></span>
|
16 |
+
<?php
|
17 |
+
$clearLinkUrl = $_filter->getClearLinkUrl();
|
18 |
+
if ($clearLinkUrl):
|
19 |
+
?>
|
20 |
+
<a class="btn-previous" href="<?php echo $_filter->getRemoveUrl() ?>" title="<?php echo $this->__('Previous') ?>"><?php echo $this->__('Previous') ?></a>
|
21 |
+
<a class="btn-remove" title="<?php echo $this->escapeHtml($_filter->getFilter()->getClearLinkText()) ?>" href="<?php echo $clearLinkUrl ?>"><?php echo $this->escapeHtml($_filter->getFilter()->getClearLinkText()) ?></a>
|
22 |
+
<?php else: ?>
|
23 |
+
<a class="btn-remove" href="<?php echo $_filter->getRemoveUrl() ?>" title="<?php echo $this->__('Remove This Item') ?>"><?php echo $this->__('Remove This Item') ?></a>
|
24 |
+
<?php endif; ?>
|
25 |
+
</li>
|
26 |
+
<?php endforeach; ?>
|
27 |
+
</ol>
|
28 |
+
</div>
|
29 |
+
<?php endif; ?>
|
app/design/frontend/base/default/template/searchspring_manager/layer/view.phtml
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Category layered navigation
|
4 |
+
*
|
5 |
+
* @see Mage_Catalog_Block_Layer_View
|
6 |
+
*/
|
7 |
+
?>
|
8 |
+
<?php if($this->canShowBlock()): ?>
|
9 |
+
<div class="block block-layered-nav">
|
10 |
+
<div class="block-title">
|
11 |
+
<strong><span><?php echo $this->__('Shop By') ?></span></strong>
|
12 |
+
</div>
|
13 |
+
<div class="block-content">
|
14 |
+
<?php echo $this->getStateHtml() ?>
|
15 |
+
<?php if ($this->getLayer()->getState()->getFilters()): ?>
|
16 |
+
<div class="actions"><a href="<?php echo $this->getClearUrl() ?>"><?php echo $this->__('Clear All') ?></a></div>
|
17 |
+
<?php endif; ?>
|
18 |
+
<?php if($this->canShowOptions()): ?>
|
19 |
+
<dl id="narrow-by-list">
|
20 |
+
<?php $_filters = $this->getFilters() ?>
|
21 |
+
<?php foreach ($_filters as $_filter): ?>
|
22 |
+
<?php if($_filter->showFilter()): ?>
|
23 |
+
<dt><?php echo $this->__($_filter->getName()) ?></dt>
|
24 |
+
<dd><?php echo $_filter->getHtml() ?></dd>
|
25 |
+
<?php endif; ?>
|
26 |
+
<?php endforeach; ?>
|
27 |
+
</dl>
|
28 |
+
<script type="text/javascript">decorateDataList('narrow-by-list')</script>
|
29 |
+
<?php endif; ?>
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
<?php endif; ?>
|
app/design/frontend/base/default/template/searchspring_manager/product/list.phtml
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$_productCollection=$this->getLoadedProductCollection();
|
3 |
+
$_results = $_productCollection->getResults();
|
4 |
+
$_merchandisingContent = $_results->getMerchandisingContent();
|
5 |
+
?>
|
6 |
+
<?php if(!$_productCollection->count()): ?>
|
7 |
+
<p class="note-msg"><?php echo $this->__('There are no products matching the selection.') ?></p>
|
8 |
+
<?php else: ?>
|
9 |
+
<div class="category-products">
|
10 |
+
<?php echo $this->getToolbarHtml() ?>
|
11 |
+
|
12 |
+
<div class="merchandising" id="searchspring-merch_header"><?php echo isset($_merchandisingContent->header)?$_merchandisingContent->header:'' ?></div>
|
13 |
+
<div class="merchandising" id="searchspring-merch_banner"><?php echo isset($_merchandisingContent->banner)?$_merchandisingContent->banner:'' ?></div>
|
14 |
+
|
15 |
+
<?php // List mode ?>
|
16 |
+
<?php if($this->getMode()!='grid'): ?>
|
17 |
+
<ol class="products-list" id="products-list">
|
18 |
+
<?php echo $_results->getResults(); ?>
|
19 |
+
</ol>
|
20 |
+
<script type="text/javascript">decorateList('products-list', 'none-recursive')</script>
|
21 |
+
|
22 |
+
<?php else: ?>
|
23 |
+
|
24 |
+
<?php // Grid Mode ?>
|
25 |
+
<ul class="products-grid">
|
26 |
+
<?php echo $_results->getResults(); ?>
|
27 |
+
</ul>
|
28 |
+
<script type="text/javascript">decorateGeneric($$('ul.products-grid'), ['odd','even','first','last'])</script>
|
29 |
+
<?php endif; ?>
|
30 |
+
|
31 |
+
<div class="merchandising" id="searchspring-merch_footer"><?php echo isset($_merchandisingContent->footer)?$_merchandisingContent->footer:'' ?></div>
|
32 |
+
|
33 |
+
<div class="toolbar-bottom">
|
34 |
+
<?php echo $this->getToolbarHtml() ?>
|
35 |
+
</div>
|
36 |
+
</div>
|
37 |
+
<?php endif; ?>
|
app/design/frontend/base/default/template/searchspring_manager/product/list/toolbar.phtml
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Academic Free License (AFL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE_AFL.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/afl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category design
|
22 |
+
* @package rwd_default
|
23 |
+
* @copyright Copyright (c) 2014 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
25 |
+
*/
|
26 |
+
?>
|
27 |
+
<?php
|
28 |
+
/**
|
29 |
+
* Product list toolbar
|
30 |
+
*
|
31 |
+
* @see Mage_Catalog_Block_Product_List_Toolbar
|
32 |
+
*/
|
33 |
+
?>
|
34 |
+
|
35 |
+
<?php if($this->getCollection()->getSize()): ?>
|
36 |
+
<div class="toolbar">
|
37 |
+
<?php if( $this->isExpanded() ): ?>
|
38 |
+
<div class="sorter">
|
39 |
+
<?php if( $this->isEnabledViewSwitcher() ): ?>
|
40 |
+
<p class="view-mode">
|
41 |
+
<?php $_modes = $this->getModes(); ?>
|
42 |
+
<?php if($_modes && count($_modes)>1): ?>
|
43 |
+
<label><?php echo $this->__('View as') ?></label>
|
44 |
+
<?php foreach ($this->getModes() as $_code=>$_label): ?>
|
45 |
+
<?php if($this->isModeActive($_code)): ?>
|
46 |
+
<strong title="<?php echo $_label ?>" class="<?php echo strtolower($_code); ?>"><?php echo $_label ?></strong>
|
47 |
+
<?php else: ?>
|
48 |
+
<a href="<?php echo $this->getModeUrl($_code) ?>" title="<?php echo $_label ?>" class="<?php echo strtolower($_code); ?>"><?php echo $_label ?></a>
|
49 |
+
<?php endif; ?>
|
50 |
+
<?php endforeach; ?>
|
51 |
+
<?php endif; ?>
|
52 |
+
</p>
|
53 |
+
<?php endif; ?>
|
54 |
+
<div class="sort-by">
|
55 |
+
<label><?php echo $this->__('Sort By') ?></label>
|
56 |
+
<select onchange="setLocation(this.value)" title="<?php echo $this->__('Sort By') ?>">
|
57 |
+
<?php foreach($this->getCollection()->getSorting() as $_sort): ?>
|
58 |
+
<option value="<?php echo $this->getOrderUrl($_sort->field, $_sort->direction) ?>"<?php if(isset($_sort->active) && $_sort->active): ?> selected="selected"<?php endif; ?>>
|
59 |
+
<?php echo $this->__($_sort->label) ?>
|
60 |
+
</option>
|
61 |
+
<?php endforeach; ?>
|
62 |
+
</select>
|
63 |
+
</div>
|
64 |
+
</div>
|
65 |
+
<?php endif; ?>
|
66 |
+
<div class="pager">
|
67 |
+
<div class="count-container">
|
68 |
+
<?php if($this->getLastPageNum()>1): ?>
|
69 |
+
<p class="amount amount--has-pages">
|
70 |
+
<?php echo $this->__('%s-%s of %s', $this->getFirstNum(), $this->getLastNum(), $this->getTotalNum()) ?>
|
71 |
+
</p>
|
72 |
+
<?php else: ?>
|
73 |
+
<p class="amount amount--no-pages">
|
74 |
+
<strong><?php echo $this->__('%s Item(s)', $this->getTotalNum()) ?></strong>
|
75 |
+
</p>
|
76 |
+
<?php endif; ?>
|
77 |
+
|
78 |
+
<div class="limiter">
|
79 |
+
<label><?php echo $this->__('Show') ?></label>
|
80 |
+
<select onchange="setLocation(this.value)" title="<?php echo $this->__('Results per page'); ?>">
|
81 |
+
<?php foreach ($this->getAvailableLimit() as $_key=>$_limit): ?>
|
82 |
+
<option value="<?php echo $this->getLimitUrl($_key) ?>"<?php if($this->isLimitCurrent($_key)): ?> selected="selected"<?php endif ?>>
|
83 |
+
<?php echo $_limit ?>
|
84 |
+
</option>
|
85 |
+
<?php endforeach; ?>
|
86 |
+
</select>
|
87 |
+
</div>
|
88 |
+
</div>
|
89 |
+
|
90 |
+
<?php echo $this->getPagerHtml() ?>
|
91 |
+
|
92 |
+
</div>
|
93 |
+
</div>
|
94 |
+
<?php endif ?>
|
app/etc/modules/SearchSpring_SearchSpringManager.xml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<SearchSpring_Manager>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
<depends>
|
8 |
+
<Mage_Catalog/>
|
9 |
+
</depends>
|
10 |
+
</SearchSpring_Manager>
|
11 |
+
</modules>
|
12 |
+
</config>
|
app/locale/en_US/template/email/searchspring_api_error.html
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
{{var response}}
|
package.xml
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package><name>SearchSpring_Manager</name><version>1.1.0</version><stability>stable</stability><license>SearchSpring Terms of Service</license><channel>community</channel><extends></extends><summary>Connects your Magento store to SearchSpring's subscription-based site search and category navigation services.</summary><description>SearchSpring improves the default Magento site search. Providing merchants with flexible, learning technology that enhances site search functionality, optimizes product results in real-time, allows for custom navigation, automates product SEO and provides fully configurable merchandising. Shoppers will find your products quickly and easily, generating repeat visits and increased sales!</description><notes>Bringing Live Indexing up to stable state</notes><authors><author><name>SearchSpring Development Team</name><user>searchspring</user><email>info@searchspring.com</email></author></authors><date>2014-09-30</date><time>11:46:04</time><compatible></compatible><dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies><contents><target name="mage"><dir name="app"><dir name="code"><dir name="community"><dir name="SearchSpring"><file name="ErrorCodes.php" hash="0cd381b82de093b811a2b6b38b5977f0"/><dir name="Manager"><file name="Collection.php" hash="0ebd621892bccd5d59ed3edcafada89b"/><file name="Iterator.php" hash="6f68effbe5452c1a6abd97cbf4b528ee"/><dir name="Block"><dir name="Layer"><file name="View.php" hash="ae69c24e04b03048cc2cd9b7cc436603"/><dir name="Filter"><file name="SearchSpringCategory.php" hash="39fc479e15275db637c227e596d040f5"/><file name="SearchSpringList.php" hash="743bb9cb690c9df3d74e9de2c206d020"/></dir></dir></dir><dir name="Builder"><file name="OperationBuilder.php" hash="d85ad0a561091d34b3b98efd95646962"/></dir><dir name="controllers"><file name="GenerateController.php" hash="895d4dc9abc957bd6fbe177df313b0e9"/></dir><dir name="Entity"><file name="IndexingRequestBody.php" hash="673c2bbc190f59c43204f7c155baa912"/><file name="OperationsCollection.php" hash="be19c06bb1be447bd57601e67ac87557"/><file name="RecordsCollection.php" hash="845b1967928f9a2d7fd33cecdfd517a2"/><file name="RequestBody.php" hash="4b6d7fd23f57527e9d53dd938d69a88d"/><file name="RequestParams.php" hash="f4778075264cd441c87e8de220fdd2a9"/><file name="SearchCollection.php" hash="e64543d4315c16d7a0717da8ec081e09"/><file name="SearchRequestBody.php" hash="bdfd9a2244ce1f9a7db8daca6e613176"/><file name="SearchResult.php" hash="863a720b8a837bd7e56e8a7fa781a1a1"/><dir name="SearchResult"><file name="Result.php" hash="ea4e36fe95e4c412af8d525a4628db5d"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="879a64f061de25cbd1292f4ead6c5b15"/><file name="composer.json" hash="6a36df77eee995788585f7a8a535fa27"/><file name="config.xml" hash="dd8330fdccb265d7f17b6f5c8340d2b2"/><file name="readme.md" hash="30d24e1aae89696090dcf22203802ad2"/><file name="system.xml" hash="89909040b5ecbf08dc4eaee9ff702411"/></dir><dir name="Factory"><file name="ApiFactory.php" hash="3532daf1450984a876c952f33ae76c82"/><file name="GeneratorFactory.php" hash="0920740294f9e8502519e2a4adb75ffc"/><file name="IndexingRequestBodyFactory.php" hash="10e0717f6d938a06a9cfc68f6ac1ceaf"/><file name="PricingFactory.php" hash="bbba11efb7a2fd6ebf8c47d896c365a2"/><file name="SearchRequestBodyFactory.php" hash="4eb409f25d480ca11b08f206f7f4facc"/></dir><dir name="Generator"><file name="ProductGenerator.php" hash="9459fddaba8a85cd300b1063c3f3e76e"/></dir><dir name="Handler"><file name="ApiErrorHandler.php" hash="bcce8cf5cd9f8b2f2107f004338728fd"/></dir><dir name="Helper"><file name="Data.php" hash="3a1cecacc1b62dc0285c8bb49cc426ba"/></dir><dir name="Model"><file name="Layer.php" hash="54afafde0cff2fcf2de2240bbb6cdb20"/><dir name="Catalog"><dir name="Category"><dir name="Attribute"><dir name="EnableSearchSpring"><file name="Backend.php" hash="12d9799f273951ca22717df93088e6bb"/><file name="Source.php" hash="03fad199c925e07fffd5e42f63cbb1bb"/></dir></dir></dir></dir><dir name="Layer"><dir name="Filter"><file name="SearchSpring.php" hash="128a0a569e7d7a4e19b74bc947a4c01a"/><file name="SearchSpringCategory.php" hash="6654bdad88ca43917dbe072b6dfb21f8"/><file name="SearchSpringCategoryItem.php" hash="2dc143031706d2c6a7f4481ef7434bf4"/><file name="SearchSpringItem.php" hash="459fae0c48c411a58ae885d56124b1f3"/></dir></dir><dir name="Observer"><file name="CategorySaveObserver.php" hash="9df9bb087d1718d699e46f9bb47fcdde"/><file name="LiveIndexer.php" hash="f1a68b949648a16cde42df0eb92cc806"/><file name="ProductSaveObserver.php" hash="5739f9536f160e51b111b43bb06c035a"/></dir></dir><dir name="Operation"><file name="Product.php" hash="d1b3114f1463205340604be47ce9e001"/><file name="ProductOperation.php" hash="5e6d97d2aab321d2204b0cc2a774ff9b"/><dir name="Product"><file name="SetCategories.php" hash="9d064f046551e1e12870013aad0ffcaa"/><file name="SetCoreFields.php" hash="7776df7b6c63f3e18c079944a63558d8"/><file name="SetFields.php" hash="a9eaaac10e7ca9ae1719b09c0cacf6a6"/><file name="SetId.php" hash="792f08d85b399d57afca103e9d0eabd1"/><file name="SetImages.php" hash="964cd029a1a7bbffb21039bffb5ee68f"/><file name="SetOptions.php" hash="3db65aee252c0eb6a5c65eac1b641bfb"/><file name="SetPricing.php" hash="a2bb94df706c1c62c5b1cbe26d8afdf6"/><file name="SetRatings.php" hash="d04ad0e2f5e1820b4b8b94880a83aef7"/></dir></dir><dir name="Provider"><file name="ProductCollectionProvider.php" hash="e639e1667ed0f2bc59f2272ad36d3107"/><dir name="ProductCollection"><file name="FeedProvider.php" hash="79f2700320c0f48342f63075bb82ff95"/><file name="ProductProvider.php" hash="bdb5b820343e060bb7cf2bea807a7607"/></dir></dir><dir name="Request"><file name="JSON.php" hash="d88633c88c49d97abf5e92c7c71fe904"/></dir><dir name="Service"><dir name="SearchSpring"><file name="ApiAdapter.php" hash="819f9d17cf64603b360c66ad1e12ddf0"/><file name="IndexingApiAdapter.php" hash="a5d324c30d82d335f745ec601b5db243"/><file name="SearchApiAdapter.php" hash="4de843465c9eea8646402bcbd289aef9"/></dir></dir><dir name="Strategy"><file name="PricingStrategy.php" hash="ee021066a76db7fc2710e329daed1a4b"/><dir name="Pricing"><file name="BundleStrategy.php" hash="df2aee59e4a6ff19acf13bbc5f9ad5b9"/><file name="ConfigurableStrategy.php" hash="403e8298c4799ba2b7701255db86a941"/><file name="GroupedStrategy.php" hash="383c482098f502d6cde5dd9ed5cf9e13"/><file name="SimpleStrategy.php" hash="a1b9e7bae38c2def28a7b0a9e6fd456e"/><file name="Strategy.php" hash="78ffa36dd4f52d725178e3cbe716bc24"/></dir></dir><dir name="String"><file name="Sanitizer.php" hash="e89fa5f86714621ea554aea9aa3f796c"/></dir><dir name="Transformer"><file name="ProductCollectionToRecordCollectionTransformer.php" hash="92b10f9ffc3999193d2733ec0dabf276"/></dir><dir name="Validator"><file name="ProductValidator.php" hash="6af19c3c4b696a5e28d8d61aa73cabf4"/></dir><dir name="VarienObject"><file name="Data.php" hash="44f184dabbf0db1958d1f922af92f6a8"/></dir><dir name="Writer"><file name="ProductWriter.php" hash="c7b218d215e68b5e3076ef654a41b141"/><dir name="Product"><file name="FileWriter.php" hash="b296be56f236635afc20e817e6277c80"/><file name="ResponseWriter.php" hash="c1af0cc22a9e823ec07175e2d8e34c9f"/><dir name="Params"><file name="FileWriterParams.php" hash="56cd0166b08f8df5750ad5c98484603a"/><file name="ResponseWriterParams.php" hash="bf66753a5952a78c0049f69ccaa6e74d"/></dir></dir></dir></dir></dir></dir></dir><dir name="design"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="searchspring_manager.xml" hash="32227434f5770ddfd93de42d7feeff71"/></dir><dir name="template"><dir name="searchspring_manager"><dir name="layer"><file name="category_filter.phtml" hash="a9dd8c95a1d63b514cc8e9c5939168c5"/><file name="filter.phtml" hash="79888aac8f72d3597f2980d471237d64"/><file name="state.phtml" hash="168546af0f48a42c31c5a5d66b1de1c3"/><file name="view.phtml" hash="509776f71bc643839ade8d7e025764cb"/></dir><dir name="product"><file name="list.phtml" hash="9849b76e4fefac8ce181b428b5c6a148"/><dir name="list"><file name="toolbar.phtml" hash="aa2235708f7e861c63ba3e3e33ec041f"/></dir></dir></dir></dir></dir></dir></dir></dir><dir name="etc"><dir name="modules"><file name="SearchSpring_SearchSpringManager.xml" hash="613ec81afc8d858f60dee96d91719c09"/></dir></dir><dir name="locale"><dir name="en_US"><dir name="template"><dir name="email"><file name="searchspring_api_error.html" hash="20bc8d923f96ca22dd2fe8cd876c49fe"/></dir></dir></dir></dir></dir><dir name="skin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="searchspring"><dir name="css"><file name="styles.css" hash="95f1ec4a442f0e2239f9a2db9e6e517c"/></dir></dir></dir></dir></dir></dir></target></contents></package>
|
skin/frontend/base/default/searchspring/css/styles.css
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/** Add Styling Override Here **/
|
2 |
+
|
3 |
+
.block-layered-nav dl dd ol > li.active > a {
|
4 |
+
font-weight: bold;
|
5 |
+
}
|
6 |
+
|
7 |
+
.ss-category_breadcrumb.ss-current_category {
|
8 |
+
font-weight: bold;
|
9 |
+
color: #2288bb;
|
10 |
+
}
|