FactFinder - Version 3.0.1

Version Notes

- initial Release

Download this release

Release Info

Developer Magento Core Team
Extension FactFinder
Version 3.0.1
Comparing to
See all releases


Version 3.0.1

Files changed (73) hide show
  1. app/code/community/Flagbit/FactFinder/Block/Adminhtml/Cockpit.php +33 -0
  2. app/code/community/Flagbit/FactFinder/Block/Filter/Slider.php +36 -0
  3. app/code/community/Flagbit/FactFinder/Block/Layer.php +122 -0
  4. app/code/community/Flagbit/FactFinder/Block/Layer/Abstract.php +30 -0
  5. app/code/community/Flagbit/FactFinder/Block/XmlConnect/Catalog/Product/List.php +124 -0
  6. app/code/community/Flagbit/FactFinder/Block/XmlConnect/Catalog/Search.php +123 -0
  7. app/code/community/Flagbit/FactFinder/Block/XmlConnect/Catalog/Search/Suggest.php +56 -0
  8. app/code/community/Flagbit/FactFinder/Helper/Data.php +36 -0
  9. app/code/community/Flagbit/FactFinder/Helper/Debug.php +97 -0
  10. app/code/community/Flagbit/FactFinder/Helper/Search.php +147 -0
  11. app/code/community/Flagbit/FactFinder/Model/Adapter.php +513 -0
  12. app/code/community/Flagbit/FactFinder/Model/Export/Price.php +91 -0
  13. app/code/community/Flagbit/FactFinder/Model/Export/Product.php +437 -0
  14. app/code/community/Flagbit/FactFinder/Model/Export/Stock.php +91 -0
  15. app/code/community/Flagbit/FactFinder/Model/Layer.php +48 -0
  16. app/code/community/Flagbit/FactFinder/Model/Layer/Filter/Attribute.php +114 -0
  17. app/code/community/Flagbit/FactFinder/Model/Layer/Filter/Item.php +20 -0
  18. app/code/community/Flagbit/FactFinder/Model/Mysql4/Product/Attribute/Collection.php +144 -0
  19. app/code/community/Flagbit/FactFinder/Model/Mysql4/Search/Collection.php +126 -0
  20. app/code/community/Flagbit/FactFinder/Model/Mysql4/Search/Engine.php +53 -0
  21. app/code/community/Flagbit/FactFinder/Model/System/Config/Backend/Enabled.php +74 -0
  22. app/code/community/Flagbit/FactFinder/Model/System/Config/Source/Authtype.php +45 -0
  23. app/code/community/Flagbit/FactFinder/Model/System/Config/Source/Identifier.php +41 -0
  24. app/code/community/Flagbit/FactFinder/controllers/Adminhtml/Factfinder/CockpitController.php +53 -0
  25. app/code/community/Flagbit/FactFinder/controllers/ExportController.php +84 -0
  26. app/code/community/Flagbit/FactFinder/etc/adminhtml.xml +49 -0
  27. app/code/community/Flagbit/FactFinder/etc/config.xml +199 -0
  28. app/code/community/Flagbit/FactFinder/etc/system.xml +194 -0
  29. app/design/adminhtml/default/default/layout/factfinder.xml +28 -0
  30. app/design/adminhtml/default/default/template/factfinder/cockpit.phtml +22 -0
  31. app/design/frontend/base/default/layout/factfinder.xml +38 -0
  32. app/design/frontend/base/default/template/factfinder/filter/slider.phtml +46 -0
  33. app/design/frontend/base/default/template/factfinder/form.mini.phtml +38 -0
  34. app/design/frontend/base/default/template/factfinder/logo.phtml +22 -0
  35. app/etc/modules/Flagbit_FactFinder.xml +9 -0
  36. js/factfinder/jXHR.js +84 -0
  37. js/factfinder/suggest.js +181 -0
  38. lib/FACTFinder/Abstract/Adapter.php +107 -0
  39. lib/FACTFinder/Abstract/Configuration.php +158 -0
  40. lib/FACTFinder/Abstract/DataProvider.php +85 -0
  41. lib/FACTFinder/Abstract/ScicAdapter.php +146 -0
  42. lib/FACTFinder/Abstract/SearchAdapter.php +235 -0
  43. lib/FACTFinder/Abstract/SuggestAdapter.php +33 -0
  44. lib/FACTFinder/Abstract/TagCloudAdapter.php +30 -0
  45. lib/FACTFinder/Asn.php +29 -0
  46. lib/FACTFinder/AsnFilterItem.php +65 -0
  47. lib/FACTFinder/AsnGroup.php +127 -0
  48. lib/FACTFinder/AsnSliderFilter.php +124 -0
  49. lib/FACTFinder/BreadCrumbItem.php +68 -0
  50. lib/FACTFinder/Campaign.php +137 -0
  51. lib/FACTFinder/CampaignIterator.php +114 -0
  52. lib/FACTFinder/Configuration.php +347 -0
  53. lib/FACTFinder/EncodingHandler.php +170 -0
  54. lib/FACTFinder/Http/DataProvider.php +240 -0
  55. lib/FACTFinder/Http/ScicAdapter.php +28 -0
  56. lib/FACTFinder/Http/SuggestAdapter.php +34 -0
  57. lib/FACTFinder/Item.php +48 -0
  58. lib/FACTFinder/Loader.php +131 -0
  59. lib/FACTFinder/Paging.php +169 -0
  60. lib/FACTFinder/Parameters.php +106 -0
  61. lib/FACTFinder/ParametersParser.php +349 -0
  62. lib/FACTFinder/ProductsPerPageOptions.php +78 -0
  63. lib/FACTFinder/Record.php +168 -0
  64. lib/FACTFinder/Result.php +33 -0
  65. lib/FACTFinder/SuggestQuery.php +58 -0
  66. lib/FACTFinder/TagQuery.php +41 -0
  67. lib/FACTFinder/Util.php +48 -0
  68. lib/FACTFinder/Xml64/SearchAdapter.php +114 -0
  69. lib/FACTFinder/Xml65/SearchAdapter.php +491 -0
  70. lib/FACTFinder/Xml65/SuggestAdapter.php +58 -0
  71. lib/FACTFinder/Xml65/TagCloudAdapter.php +60 -0
  72. lib/FACTFinderCustom/Configuration.php +250 -0
  73. package.xml +18 -0
app/code/community/Flagbit/FactFinder/Block/Adminhtml/Cockpit.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Black class
12
+ *
13
+ * This Block class provides the FACT-Finder Business User Cockpit Authentication URL
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Cockpit.php 601 2010-12-21 14:07:41Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Block_Adminhtml_Cockpit extends Mage_Adminhtml_Block_Template {
22
+
23
+ /**
24
+ * get FACT-Finder Business User Cockpit Authentication URL
25
+ *
26
+ * @return string
27
+ */
28
+ public function getAuthenticationUrl()
29
+ {
30
+ return Mage::getSingleton('factfinder/adapter')->getAuthenticationUrl();
31
+ }
32
+
33
+ }
app/code/community/Flagbit/FactFinder/Block/Filter/Slider.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Block class
12
+ *
13
+ * Add Slider Javascript to HTML Head
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Slider.php 612 2011-01-28 16:16:04Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Block_Filter_Slider extends Mage_Core_Block_Abstract {
22
+
23
+ /**
24
+ * get Slider Javascript
25
+ *
26
+ * @return string
27
+ */
28
+ protected function _toHtml()
29
+ {
30
+ if(Mage::helper('factfinder/search')->getIsEnabled()){
31
+ return '<script type="text/javascript" language="javascript" src="http://static.express.fact-finder.com/onetouchslider-1.0/de.factfinder.asn.slider.OneTouchSlider.nocache.js"></script>'."\n".
32
+ '<script type="text/javascript" language="javascript"> oneTouchSliderOnLoad = function(){ document.fire("ffslider:init");}</script>'."\n";
33
+
34
+ }
35
+ }
36
+ }
app/code/community/Flagbit/FactFinder/Block/Layer.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Block class
12
+ *
13
+ * This class is used to disable Magento´s default Price and Category Filter Output
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Layer.php 623 2011-02-16 08:22:10Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Block_Layer extends Flagbit_FactFinder_Block_Layer_Abstract
22
+ {
23
+
24
+ /**
25
+ * Prepare child blocks
26
+ *
27
+ * @return Mage_Catalog_Block_Layer_View
28
+ */
29
+ protected function _prepareLayout()
30
+ {
31
+ if(!Mage::helper('factfinder/search')->getIsEnabled()){
32
+ return parent::_prepareLayout();
33
+ }
34
+
35
+ // set default sort Order
36
+ if(Mage::getSingleton('catalog/session')->getSortOrder()){
37
+ Mage::getSingleton('catalog/session')->setSortOrder('relevance');
38
+ }
39
+
40
+ // handle redirects
41
+ $redirect = Mage::getSingleton('factfinder/adapter')->getRedirect();
42
+ if($redirect){
43
+ Mage::app()->getResponse()->setRedirect($redirect);
44
+ }
45
+
46
+ $stateBlock = $this->getLayout()->createBlock('catalog/layer_state')
47
+ ->setLayer($this->getLayer());
48
+
49
+ $this->setChild('layer_state', $stateBlock);
50
+
51
+ $filterableAttributes = $this->_getFilterableAttributes();
52
+ foreach ($filterableAttributes as $attribute) {
53
+ $filterBlockName = $this->_getAttributeFilterBlockName();
54
+
55
+ $filterBlock = $this->getLayout()->createBlock($filterBlockName)
56
+ ->setLayer($this->getLayer())
57
+ ->setAttributeModel($attribute)
58
+ ->init();
59
+
60
+ switch($attribute->getType()){
61
+
62
+ case 'slider':
63
+ if(!($this->getLayout()->getBlock('ffslider') instanceof Flagbit_FactFinder_Block_Filter_Slider)){
64
+ $this->getLayout()->getBlock('head')->setChild('ffslider', $this->getLayout()->createBlock('factfinder/filter_slider'));
65
+ }
66
+ $filterBlock->setTemplate('factfinder/filter/slider.phtml');
67
+ $filterBlock->setData((current($attribute->getItems())));
68
+ $filterBlock->setUnit($attribute->getUnit());
69
+ break;
70
+ }
71
+
72
+ $this->setChild($attribute->getAttributeCode().'_filter', $filterBlock);
73
+ }
74
+
75
+ $this->getLayer()->apply();
76
+ return Mage_Core_Block_Template::_prepareLayout();
77
+ }
78
+
79
+ /**
80
+ * Get category filter block
81
+ *
82
+ * @return Mage_Catalog_Block_Layer_Filter_Category
83
+ */
84
+ protected function _getCategoryFilter()
85
+ {
86
+ if(!Mage::helper('factfinder/search')->getIsEnabled()){
87
+ return parent::_getCategoryFilter();
88
+ }
89
+ return false;
90
+ }
91
+
92
+ /**
93
+ * Retrieve Price Filter block
94
+ *
95
+ * @return Mage_Catalog_Block_Layer_Filter_Price
96
+ */
97
+ protected function _getPriceFilter()
98
+ {
99
+ if(!Mage::helper('factfinder/search')->getIsEnabled()){
100
+ return parent::_getPriceFilter();
101
+ }
102
+ return false;
103
+ }
104
+
105
+ /**
106
+ * Check availability display layer block
107
+ *
108
+ * @return bool
109
+ */
110
+ public function canShowBlock()
111
+ {
112
+ if(!Mage::helper('factfinder/search')->getIsEnabled()){
113
+ return parent::canShowBlock();
114
+ }
115
+
116
+ if ($this->getLayer()->getFilterableAttributes()->count()
117
+ && $this->getLayer()->getProductCollection()->getSize()) {
118
+ return true;
119
+ }
120
+ return false;
121
+ }
122
+ }
app/code/community/Flagbit/FactFinder/Block/Layer/Abstract.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Block class
12
+ *
13
+ * dynamicaly extends the core class whether Enterprise Search is enabled or not
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Abstract.php 618 2011-02-08 11:14:50Z weller $
20
+ */
21
+
22
+ if(Mage::helper('factfinder')->isModuleActive('Enterprise_Search')){
23
+ class Flagbit_FactFinder_Block_Layer_Abstract extends Enterprise_Search_Block_Catalogsearch_Layer {}
24
+ }else{
25
+ class Flagbit_FactFinder_Block_Layer_Abstract extends Mage_CatalogSearch_Block_Layer {}
26
+ }
27
+
28
+
29
+
30
+
app/code/community/Flagbit/FactFinder/Block/XmlConnect/Catalog/Product/List.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Block class
12
+ *
13
+ * This class is used to disable Magento´s default apply Filter
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: List.php 618 2011-02-08 11:14:50Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Block_XmlConnect_Catalog_Product_List extends Mage_XmlConnect_Block_Catalog_Product_List {
22
+
23
+ /**
24
+ * Retrieve product collection with all prepared data and limitations
25
+ *
26
+ * @return Mage_Eav_Model_Entity_Collection_Abstract
27
+ */
28
+ protected function _getProductCollection()
29
+ {
30
+ if(!Mage::helper('factfinder/search')->getIsEnabled()){
31
+ return parent::_getProductCollection();
32
+ }
33
+
34
+ if (is_null($this->_productCollection)) {
35
+ switch($this->getRequest()->getActionName()){
36
+
37
+ case 'search':
38
+ $this->__getSearchProductCollection();
39
+ break;
40
+
41
+ default:
42
+ parent::_getProductCollection();
43
+ break;
44
+ }
45
+ }
46
+ return $this->_productCollection;
47
+ }
48
+
49
+
50
+ /**
51
+ * Retrieve product collection with all prepared data and limitations
52
+ *
53
+ * @return Mage_Eav_Model_Entity_Collection_Abstract
54
+ */
55
+ protected function __getSearchProductCollection()
56
+ {
57
+ if (is_null($this->_productCollection)) {
58
+ $filters = array();
59
+ $request = $this->getRequest();
60
+ $requestParams = $request->getParams();
61
+ $layer = $this->getLayer();
62
+ if (!$layer) {
63
+ return null;
64
+ }
65
+ $category = $this->getCategory();
66
+ if ($category && is_object($category) && $category->getId()) {
67
+ $layer->setCurrentCategory($category);
68
+ }
69
+
70
+ if (!$this->getNeedBlockApplyingFilters()) {
71
+ $attributes = $layer->getFilterableAttributes();
72
+ /**
73
+ * Apply filters
74
+ */
75
+ foreach ($attributes as $attributeItem) {
76
+
77
+ $attributeCode = $attributeItem->getAttributeCode();
78
+ $filterModel = $this->helper('xmlconnect')->getFilterByKey($attributeCode);
79
+
80
+ $filterModel->setLayer($layer)
81
+ ->setAttributeModel($attributeItem);
82
+
83
+ $filterParam = parent::REQUEST_FILTER_PARAM_REFIX . $attributeCode;
84
+ $filters[] = $filterModel;
85
+ }
86
+ $this->_collectedFilters = $filters;
87
+ }
88
+
89
+ /**
90
+ * Products
91
+ */
92
+ $layer = $this->getLayer();
93
+ $collection = $layer->getProductCollection();
94
+
95
+ /**
96
+ * Add rating and review summary, image attribute, apply sort params
97
+ */
98
+ $this->_prepareCollection($collection);
99
+
100
+ /**
101
+ * Apply offset and count
102
+ */
103
+ $offset = (int)$request->getParam('offset', 0);
104
+ $count = (int)$request->getParam('count', 0);
105
+ $count = $count <= 0 ? 1 : $count;
106
+ if($offset + $count < $collection->getSize()){
107
+ $this->setHasProductItems(1);
108
+ }
109
+ $collection->getSelect()->limit($count, $offset);
110
+
111
+ $collection->setFlag('require_stock_items', true);
112
+
113
+ $this->_productCollection = $collection;
114
+ }
115
+
116
+ return $this->_productCollection;
117
+ }
118
+
119
+
120
+ }
121
+
122
+
123
+
124
+
app/code/community/Flagbit/FactFinder/Block/XmlConnect/Catalog/Search.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Block class
12
+ *
13
+ * This class is used provide FAC-Finder filters
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Search.php 618 2011-02-08 11:14:50Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Block_XmlConnect_Catalog_Search extends Mage_XmlConnect_Block_Catalog_Search {
22
+
23
+
24
+ /**
25
+ * Search results xml renderer
26
+ * XML also contains filters that can be apply (accorfingly already applyed filters and search query)
27
+ * and sort fields
28
+ *
29
+ * @return string
30
+ */
31
+ protected function _toHtml()
32
+ {
33
+ if(!Mage::helper('factfinder/search')->getIsEnabled()){
34
+ return parent::_toHtml();
35
+ }
36
+
37
+ $searchXmlObject = new Mage_XmlConnect_Model_Simplexml_Element('<search></search>');
38
+ $filtersXmlObject = new Mage_XmlConnect_Model_Simplexml_Element('<filters></filters>');
39
+
40
+ $helper = Mage::helper('catalogsearch');
41
+ if (method_exists($helper, 'getEngine')) {
42
+ $engine = Mage::helper('catalogsearch')->getEngine();
43
+ $isLayeredNavigationAllowed = ($engine instanceof Varien_Object) ? $engine->isLeyeredNavigationAllowed() : true;
44
+ }
45
+ else {
46
+ $isLayeredNavigationAllowed = true;
47
+ }
48
+
49
+ $request = $this->getRequest();
50
+ $requestParams = $request->getParams();
51
+ $hasMoreProductItems = 0;
52
+
53
+ /**
54
+ * Products
55
+ */
56
+ $productListBlock = $this->getChild('product_list');
57
+ $productListBlock->setNeedBlockApplyingFilters(false);
58
+ if ($productListBlock) {
59
+ $layer = Mage::getSingleton('catalogsearch/layer');
60
+ $productsXmlObj = $productListBlock->setLayer($layer)
61
+ ->setNeedBlockApplyingFilters(!$isLayeredNavigationAllowed)
62
+ ->getProductsXmlObject();
63
+ $searchXmlObject->appendChild($productsXmlObj);
64
+ $hasMoreProductItems = (int)$productListBlock->getHasProductItems();
65
+ }
66
+
67
+ $searchXmlObject->addAttribute('has_more_items', $hasMoreProductItems);
68
+
69
+ /**
70
+ * Filters
71
+ */
72
+ $showFiltersAndOrders = true;
73
+ $reguest = $this->getRequest();
74
+ foreach ($reguest->getParams() as $key => $value) {
75
+ if (0 === strpos($key, parent::REQUEST_SORT_ORDER_PARAM_REFIX) ||
76
+ 0 === strpos($key, parent::REQUEST_FILTER_PARAM_REFIX)) {
77
+ $showFiltersAndOrders = false;
78
+ break;
79
+ }
80
+ }
81
+ if ($isLayeredNavigationAllowed && $productListBlock && $showFiltersAndOrders) {
82
+ $filters = $productListBlock->getCollectedFilters();
83
+
84
+ /**
85
+ * Render filters xml
86
+ */
87
+ foreach ($filters as $filter) {
88
+ if (!count($filter->getAttributeModel()->getItems())) {
89
+ continue;
90
+ }
91
+
92
+ $item = $filtersXmlObject->addChild('item');
93
+ $item->addChild('name', $searchXmlObject->xmlentities($filter->getName()));
94
+ $item->addChild('code', $filter->getRequestVar());
95
+ $values = $item->addChild('values');
96
+
97
+ foreach ($filter->getAttributeModel()->getItems() as $valueArray) {
98
+ $valueItem = new Varien_Object($valueArray);
99
+ $count = (int)$valueItem->getCount();
100
+ if (!$count) {
101
+ continue;
102
+ }
103
+ $value = $values->addChild('value');
104
+ $value->addChild('id', base64_encode($valueItem->getValue()));
105
+ $value->addChild('label', $searchXmlObject->xmlentities(strip_tags($valueItem->getLabel())));
106
+ $value->addChild('count', $count);
107
+ }
108
+ }
109
+ $searchXmlObject->appendChild($filtersXmlObject);
110
+ }
111
+
112
+ /**
113
+ * Sort fields
114
+ */
115
+ if ($showFiltersAndOrders) {
116
+ $searchXmlObject->appendChild($this->getProductSortFeildsXmlObject());
117
+ }
118
+
119
+ return $searchXmlObject->asNiceXml();
120
+ }
121
+
122
+
123
+ }
app/code/community/Flagbit/FactFinder/Block/XmlConnect/Catalog/Search/Suggest.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Block class
12
+ *
13
+ * This class enables FAC-Finder sugguest
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Suggest.php 618 2011-02-08 11:14:50Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Block_XmlConnect_Catalog_Search_Suggest extends Mage_XmlConnect_Block_Catalog_Search_Suggest
22
+ {
23
+ const SUGGEST_ITEM_SEPARATOR = '::sep::';
24
+
25
+ /**
26
+ * Search suggestions xml renderer
27
+ *
28
+ * @return string
29
+ */
30
+ protected function _toHtml()
31
+ {
32
+ $suggestXmlObj = new Mage_XmlConnect_Model_Simplexml_Element('<suggestions></suggestions>');
33
+ if (!$this->getRequest()->getParam('q', false)) {
34
+ return $suggestXmlObj->asNiceXml();
35
+ }
36
+
37
+ $suggestData = Mage::getSingleton('factfinder/adapter')->getSuggestResult($this->getRequest()->getParam('q'));
38
+
39
+ if (!($count = count($suggestData))) {
40
+ return $suggestXmlObj->asNiceXml();
41
+ }
42
+
43
+ $items = '';
44
+ foreach ($suggestData as $index => $item) {
45
+ $items .= $suggestXmlObj->xmlentities(strip_tags($item['query']))
46
+ . self::SUGGEST_ITEM_SEPARATOR
47
+ . (int)$item['hitCount']
48
+ . self::SUGGEST_ITEM_SEPARATOR;
49
+ }
50
+
51
+ $suggestXmlObj = new Mage_XmlConnect_Model_Simplexml_Element('<suggestions>' . $items . '</suggestions>');
52
+
53
+ return $suggestXmlObj->asNiceXml();
54
+ }
55
+
56
+ }
app/code/community/Flagbit/FactFinder/Helper/Data.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Helper class
12
+ *
13
+ * This helper class provides Translation Methods throw Magento Helper Abstract
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Data.php 617 2011-02-08 10:25:54Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Helper_Data extends Mage_Core_Helper_Abstract {
22
+
23
+ /**
24
+ * returns Module Status by Module Code
25
+ *
26
+ * @param string $code Module Code
27
+ * @return boolean
28
+ */
29
+ public function isModuleActive($code)
30
+ {
31
+ $module = Mage::getConfig()->getNode("modules/$code");
32
+ $model = Mage::getConfig()->getNode("global/models/$code");
33
+ return $module && $module->is('active') || $model;
34
+ }
35
+
36
+ }
app/code/community/Flagbit/FactFinder/Helper/Debug.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Helper class
12
+ *
13
+ * This helper class provides some Methods which allows us
14
+ * to debug Modul specific configurations Problems.
15
+ *
16
+ * @category Mage
17
+ * @package Flagbit_FactFinder
18
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
19
+ * @author Joerg Weller <weller@flagbit.de>
20
+ * @version $Id: Debug.php 629 2011-02-18 14:55:16Z weller $
21
+ */
22
+ class Flagbit_FactFinder_Helper_Debug extends Mage_Core_Helper_Abstract {
23
+
24
+ const MODULE_CONFIG_FILE = 'config.xml';
25
+ const LOG_FILE_NAME = 'factfinder.log';
26
+
27
+ /**
28
+ * XML Config Path to Product Identifier Setting
29
+ *
30
+ * @var string
31
+ */
32
+ const XML_CONFIG_PATH_DEBUG_MODE = 'factfinder/config/debug';
33
+
34
+ /**
35
+ * Debug Log to file var/log/factfinder.log
36
+ *
37
+ * @param $message
38
+ * @param $level
39
+ * @param $file
40
+ * @param $forceLog
41
+ */
42
+ public function log($message)
43
+ {
44
+ if(Mage::getStoreConfig(self::XML_CONFIG_PATH_DEBUG_MODE)) {
45
+ return Mage::log($message, null, self::LOG_FILE_NAME, true);
46
+ }
47
+ return $this;
48
+ }
49
+
50
+ /**
51
+ * get Class Rewrite Conflicts for the current Modul
52
+ *
53
+ * return array
54
+ */
55
+ public function getRewriteConflicts()
56
+ {
57
+ $rewriteConflicts = array();
58
+ $xml = simplexml_load_file(Mage::getConfig()->getModuleDir('etc', $this->_getModuleName()).DS.self::MODULE_CONFIG_FILE);
59
+ if ($xml instanceof SimpleXMLElement) {
60
+ $rewriteNodes = $xml->xpath('//rewrite');
61
+
62
+ foreach ($rewriteNodes as $n) {
63
+ $nParent = $n->xpath('..');
64
+ $module = (string) $nParent[0]->getName();
65
+ $nParent2 = $nParent[0]->xpath('..');
66
+ $component = (string) $nParent2[0]->getName();
67
+ $pathNodes = $n->children();
68
+
69
+ foreach ($pathNodes as $pathNode) {
70
+
71
+ $path = (string) $pathNode->getName();
72
+ $completePath = $module.'/'.$path;
73
+
74
+ $rewriteClassName = (string) $pathNode;
75
+
76
+ $instance = Mage::getConfig()->getGroupedClassName(
77
+ substr($component, 0, -1),
78
+ $completePath
79
+ );
80
+ if($instance != $rewriteClassName){
81
+
82
+ try{
83
+ $reflector = new $instance();
84
+ if($reflector instanceof $rewriteClassName){
85
+ continue;
86
+ }
87
+ }catch (Exception $e){}
88
+
89
+ $rewriteConflicts[$rewriteClassName] = $instance;
90
+ }
91
+ }
92
+ }
93
+ }
94
+ return $rewriteConflicts;
95
+ }
96
+
97
+ }
app/code/community/Flagbit/FactFinder/Helper/Search.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Helper class
12
+ *
13
+ * This helper class provides some Methods which allows us
14
+ * to get default und current Values from Toolbar block.
15
+ *
16
+ * @category Mage
17
+ * @package Flagbit_FactFinder
18
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
19
+ * @author Joerg Weller <weller@flagbit.de>
20
+ * @version $Id: Search.php 629 2011-02-18 14:55:16Z weller $
21
+ */
22
+ class Flagbit_FactFinder_Helper_Search extends Mage_Core_Helper_Abstract {
23
+
24
+ /**
25
+ * XML Config Path to Product Identifier Setting
26
+ *
27
+ * @var string
28
+ */
29
+ const XML_CONFIG_PATH_PRODUCT_IDENTIFIER = 'factfinder/config/identifier';
30
+
31
+ /**
32
+ * if FACT-Finder enabled?
33
+ *
34
+ * @return boolean
35
+ */
36
+ public function getIsEnabled($searchPageCheck = true)
37
+ {
38
+ return (
39
+ Mage::getStoreConfig('factfinder/search/enabled')
40
+ && !Mage::getStoreConfig('advanced/modules_disable_output/Flagbit_FactFinder')
41
+ && ($searchPageCheck == false || $this->getIsOnSearchPage())
42
+ ) ? true : false;
43
+ }
44
+
45
+ /**
46
+ * get Module Status depending on Module
47
+ *
48
+ * @return boolean
49
+ */
50
+ public function getIsOnSearchPage()
51
+ {
52
+ return Mage::app()->getRequest()->getModuleName() == 'catalogsearch' || Mage::app()->getRequest()->getModuleName() == 'xmlconnect';
53
+ }
54
+
55
+
56
+ /**
57
+ * get Toolbar Block
58
+ *
59
+ * @return Mage_Catalog_Block_Product_List_Toolbar
60
+ */
61
+ protected function _getToolbarBlock()
62
+ {
63
+ $mainBlock = Mage::app()->getLayout()->getBlock('search.result');
64
+ if($mainBlock instanceof Mage_CatalogSearch_Block_Result){
65
+ $toolbarBlock = $mainBlock->getListBlock()->getToolbarBlock();
66
+ }else{
67
+ $toolbarBlock = Mage::app()->getLayout()->createBlock('catalog/product_list_toolbar');
68
+ }
69
+
70
+ return $toolbarBlock;
71
+ }
72
+
73
+ /**
74
+ * get Entity ID Field Name by Configuration or via Entity
75
+ *
76
+ * @return string
77
+ */
78
+ public function getIdFieldName()
79
+ {
80
+ $idFieldName = Mage::getStoreConfig(self::XML_CONFIG_PATH_PRODUCT_IDENTIFIER);
81
+ if(!$idFieldName){
82
+ $idFieldName = $this->getEntity()->getIdFieldName();
83
+ }
84
+ return $idFieldName;
85
+ }
86
+
87
+ /**
88
+ * get FACT-Finder Suggest URL
89
+ *
90
+ * @return string
91
+ */
92
+ public function getSuggestUrl()
93
+ {
94
+ return Mage::getSingleton('factfinder/adapter')->getSuggestUrl();
95
+ }
96
+
97
+
98
+ /**
99
+ * get current Order
100
+ *
101
+ * @return string
102
+ */
103
+ public function getCurrentOrder()
104
+ {
105
+ return $this->_getToolbarBlock()->getCurrentOrder();
106
+ }
107
+
108
+ /**
109
+ * get current Order Direction
110
+ *
111
+ * @return string
112
+ */
113
+ public function getCurrentDirection()
114
+ {
115
+ return $this->_getToolbarBlock()->getCurrentDirection();
116
+ }
117
+
118
+ /**
119
+ * get Page Limit
120
+ *
121
+ * @return int
122
+ */
123
+ public function getPageLimit()
124
+ {
125
+ return $this->_getToolbarBlock()->getLimit();
126
+ }
127
+
128
+ /**
129
+ * get current Page Number
130
+ *
131
+ * @return int
132
+ */
133
+ public function getCurrentPage()
134
+ {
135
+ return $this->_getToolbarBlock()->getCurrentPage();
136
+ }
137
+
138
+ /**
139
+ * Retrieve query model object
140
+ *
141
+ * @return Mage_CatalogSearch_Model_Query
142
+ */
143
+ public function getQuery()
144
+ {
145
+ return Mage::helper('catalogsearch')->getQuery();
146
+ }
147
+ }
app/code/community/Flagbit/FactFinder/Model/Adapter.php ADDED
@@ -0,0 +1,513 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ require_once BP.DS.'lib'.DS.'FACTFinder'.DS.'Loader.php';
11
+
12
+ /**
13
+ * Model class
14
+ *
15
+ * Adapter between FACT-Finder API Framework and Magento
16
+ *
17
+ * @category Mage
18
+ * @package Flagbit_FactFinder
19
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
20
+ * @author Joerg Weller <weller@flagbit.de>
21
+ * @version $Id: Adapter.php 635 2011-02-23 17:16:14Z weller $
22
+ */
23
+ class Flagbit_FactFinder_Model_Adapter
24
+ {
25
+
26
+ /**
27
+ * FACT-Finder Searchadapter
28
+ * @var FACTFinder_Abstract_SearchAdapter
29
+ */
30
+ protected $_searchAdapter = null;
31
+
32
+ /**
33
+ * FACT-Finder Suggestadapter
34
+ * @var FACTFinder_Abstract_SuggestAdapter
35
+ */
36
+ protected $_suggestAdapter = null;
37
+
38
+ /**
39
+ * FACT-Finder Config
40
+ * @var FACTFinder_Abstract_Configuration
41
+ */
42
+ protected $_config = null;
43
+
44
+ /**
45
+ * FACT-Finder Parameter Parser
46
+ * @var FACTFinder_ParametersParser
47
+ */
48
+ protected $_paramsParser = null;
49
+
50
+ /**
51
+ * FACT-Finder Data Provider
52
+ * @var FACTFinder_Abstract_DataProvider
53
+ */
54
+ protected $_dataProvider = null;
55
+
56
+ /**
57
+ * FACT-Finder After Search Navigation
58
+ * @var array
59
+ */
60
+ protected $_afterSearchNavigation = null;
61
+
62
+ /**
63
+ * FACT-Finder Searchadapter
64
+ * @var array
65
+ */
66
+ protected $_searchResultProductIds = null;
67
+
68
+ /**
69
+ * get FactFinder SearchAdapter
70
+ *
71
+ * @return FACTFinder_Abstract_SearchAdapter
72
+ */
73
+ protected function _getSearchAdapter($collectParams = true)
74
+ {
75
+ if ($this->_searchAdapter == null) {
76
+ $config = $this->_getConfiguration();
77
+ $encodingHandler = FF::getSingleton('encodingHandler', $config);
78
+ $dataProvider = $this->_getDataProvider();
79
+ $this->_searchAdapter = FF::getSingleton(
80
+ 'xml65/searchAdapter',
81
+ $dataProvider,
82
+ $this->_getParamsParser(),
83
+ $encodingHandler
84
+ );
85
+
86
+ if($collectParams == true){
87
+ $this->_collectParams();
88
+ }
89
+ }
90
+
91
+ return $this->_searchAdapter;
92
+ }
93
+
94
+ protected function _collectParams()
95
+ {
96
+ // search Helper
97
+ $helper = Mage::helper('factfinder/search');
98
+ $_request = Mage::app()->getRequest();
99
+
100
+ switch($_request->getModuleName()){
101
+
102
+ case "xmlconnect":
103
+ $this->_setParam('idsOnly', 'true')
104
+ ->_setParam('productsPerPage', $_request->getParam('count'))
105
+ ->_setParam('query', $helper->getQuery()->getQueryText())
106
+ ->_setParam('page', ($_request->getParam('offset') / $_request->getParam('count')) + 1);
107
+
108
+ // add Sorting Param
109
+ $params = Mage::app()->getRequest()->getParams();
110
+ foreach($params as $key => $value){
111
+ if(substr($key, 0, 6) == 'order_'){
112
+ $key = substr($key, 6);
113
+ if(!in_array($key, array('position', 'relevance'))){
114
+ $this->_setParam('sort'.$key, $value);
115
+ }
116
+ }
117
+ }
118
+
119
+ // add Filter Params
120
+ $params = Mage::app()->getRequest()->getParams();
121
+ foreach($params as $key => $value){
122
+ $value = base64_decode($value);
123
+ if(strpos($value, '|')){
124
+ $param = explode('|', $value);
125
+ if($key == 'category'){
126
+ $categories = array_merge(array_slice(explode('/', $param[0]), 1), array($param[1]));
127
+ $filterkey = '';
128
+ foreach($categories as $category){
129
+ $this->_setParam('filtercategoryROOT'.$filterkey, $category);
130
+ $filterkey .= '/'.$category;
131
+ }
132
+ }else{
133
+ $this->_setParam('filter'.$param[0], $param[1]);
134
+ }
135
+ }
136
+ }
137
+
138
+ break;
139
+
140
+ case "catalogsearch":
141
+ default:
142
+ // add Default Params
143
+ $this->_setParam('idsOnly', 'true')
144
+ ->_setParam('productsPerPage', $helper->getPageLimit())
145
+ ->_setParam('query', $helper->getQuery()->getQueryText())
146
+ ->_setParam('page', $helper->getCurrentPage());
147
+
148
+ // add Sorting Param
149
+ if($helper->getCurrentOrder()
150
+ && $helper->getCurrentDirection()
151
+ && $helper->getCurrentOrder() != 'position'
152
+ && $helper->getCurrentOrder() != 'relevance'){
153
+ $this->_setParam('sort'.$helper->getCurrentOrder(), $helper->getCurrentDirection());
154
+ }
155
+
156
+ // add Filter Params
157
+ $params = Mage::app()->getRequest()->getParams();
158
+ foreach($params as $key => $value){
159
+ if(strpos($value, '|')){
160
+ $param = explode('|', $value);
161
+ switch($param[1]){
162
+
163
+ case 'slider':
164
+ $subparam = explode(':', $param[2]);
165
+ $this->_setParam($subparam[0], $subparam[1]);
166
+ $subparam = explode(':', $param[3]);
167
+ $this->_setParam($subparam[0], $subparam[1]);
168
+ break;
169
+
170
+ default:
171
+ if($key == 'category'){
172
+ $categories = array_merge(array_slice(explode('/', $param[0]), 1), array($param[1]));
173
+ $filterkey = '';
174
+ foreach($categories as $category){
175
+ $this->_setParam('filtercategoryROOT'.$filterkey, $category);
176
+ $filterkey .= '/'.$category;
177
+ }
178
+ }else{
179
+ $this->_setParam('filter'.$param[0], $param[1]);
180
+ }
181
+ break;
182
+ }
183
+ }
184
+ }
185
+ break;
186
+
187
+ }
188
+ }
189
+
190
+ /**
191
+ * execute search
192
+ */
193
+ public function checkStatus($configarray = null)
194
+ {
195
+ $status = false;
196
+ try {
197
+ $this->_getConfiguration($configarray);
198
+ $this->_setParam('query', 'FACT-Finder Version');
199
+ $this->_setParam('productsPerPage', '1');
200
+
201
+ $status = $this->_getSearchAdapter(false)->getStatus() == 'resultsFound';
202
+ } catch (Exception $e) {
203
+ $status = false;
204
+ }
205
+ return $status;
206
+ }
207
+
208
+ /**
209
+ * get Redirect URL if there is set one
210
+ *
211
+ * @return string
212
+ */
213
+ public function getRedirect()
214
+ {
215
+ $url = null;
216
+ $campaigns = $this->_getSearchAdapter()->getCampaigns();
217
+ if (!empty($campaigns) && $campaigns->hasRedirect()) {
218
+ $url = $campaigns->getRedirectUrl();
219
+ }
220
+ return $url;
221
+ }
222
+
223
+ /**
224
+ * get Search Suggest URL
225
+ *
226
+ * @return string
227
+ */
228
+ public function getSuggestUrl()
229
+ {
230
+ $dataprovider = $this->_getDataProvider();
231
+ $dataprovider->setType('Suggest.ff');
232
+ $dataprovider->setParams(array());
233
+
234
+ return $dataprovider->getNonAuthenticationUrl();
235
+ }
236
+
237
+ /**
238
+ * get Suggest Adapter
239
+ *
240
+ * @return FACTFinder_Abstract_SuggestAdapter
241
+ */
242
+ protected function _getSuggestAdapter()
243
+ {
244
+ if ($this->_suggestAdapter == null) {
245
+ $config = $this->_getConfiguration();
246
+ $encodingHandler = FF::getSingleton('encodingHandler', $config);
247
+ $params = $this->_getParamsParser()->getServerRequestParams();
248
+ $dataProvider = $this->_getDataProvider();
249
+ $this->_suggestAdapter = FF::getSingleton('http/suggestAdapter', $dataProvider, $this->_getParamsParser(), $encodingHandler);
250
+ }
251
+ return $this->_suggestAdapter;
252
+ }
253
+
254
+ /**
255
+ *
256
+ *
257
+ * @param unknown_type $query
258
+ */
259
+ public function getSuggestResult($query)
260
+ {
261
+ $this->_setParam('query', $query);
262
+ $this->_setParam('format', 'json');
263
+
264
+ return Zend_Json_Decoder::decode($this->_getSuggestAdapter()->getSuggestions());
265
+ }
266
+
267
+
268
+ /**
269
+ * get Search Result Count
270
+ *
271
+ * @return int
272
+ */
273
+ public function getSearchResultCount()
274
+ {
275
+ return $this->_getSearchAdapter()->getResult()->getFoundRecordsCount();
276
+ }
277
+
278
+ /**
279
+ * get After Search Navigation as Array
280
+ * this simulates Magento Filter Attributes with Options
281
+ *
282
+ * @return array
283
+ */
284
+ public function getAfterSearchNavigation()
285
+ {
286
+ if($this->_afterSearchNavigation == null){
287
+ $this->_afterSearchNavigation = array();
288
+ $result = $this->_getSearchAdapter()->getAsn();
289
+
290
+ if ($result instanceof FACTFinder_Asn
291
+ && count($result)){
292
+
293
+ foreach ($result as $row) {
294
+ $this->_afterSearchNavigation[] = array(
295
+ 'attribute_code' => $row->getName(),
296
+ 'name' => $row->getName(),
297
+ 'unit' => $row->getUnit(),
298
+ 'items' => $this->_getAttributeOptions($row->getArrayCopy()),
299
+ 'count' => $row->count(),
300
+ 'type' => $this->_getFilterType($row->getArrayCopy()),
301
+ 'store_label' => $row->getName()
302
+ );
303
+ }
304
+ }
305
+ }
306
+
307
+ return $this->_afterSearchNavigation;
308
+ }
309
+
310
+ /**
311
+ * get Filter Type by FACT-Finder FilterItem
312
+ *
313
+ * @param array $options
314
+ * @return string
315
+ */
316
+ protected function _getFilterType($options)
317
+ {
318
+ $defaultType = 'item';
319
+ foreach($options as $option){
320
+ if(!$option->getType()){
321
+ continue;
322
+ }
323
+ $defaultType = $option->getType();
324
+ break;
325
+ }
326
+ return $defaultType;
327
+ }
328
+
329
+ /**
330
+ * get Attribute Options Array from FactFinder FilterGroupItems
331
+ *
332
+ * @param FACTFinder_AsnFilterItem $options
333
+ * @return array
334
+ */
335
+ protected function _getAttributeOptions($options)
336
+ {
337
+ $attributeOption = array();
338
+ foreach($options as $option){
339
+
340
+ switch ($option->getType()){
341
+
342
+ case "slider":
343
+ $attributeOption[] = array(
344
+ 'type' => $option->getType(),
345
+ 'label' => 'slider',
346
+ 'value' => $this->_getAttributeOptionValue($option),
347
+ 'absolute_min' => $option->getAbsoluteMin(),
348
+ 'absolute_max' => $option->getAbsoluteMax(),
349
+ 'selected_min' => $option->getSelectedMin(),
350
+ 'selected_max' => $option->getSelectedMax(),
351
+ 'count' => true,
352
+ 'selected' => false //$option->isSelected()
353
+ );
354
+ break;
355
+
356
+ default:
357
+ if (!Mage::helper('core/string')->strlen($option->getValue())) {
358
+ continue;
359
+ }
360
+ $attributeOption[] = array(
361
+ 'type' => 'attribute',
362
+ 'label' => $option->getValue(),
363
+ 'value' => $this->_getAttributeOptionValue($option),
364
+ 'count' => $option->getMatchCount(),
365
+ 'selected' => $option->isSelected()
366
+ );
367
+
368
+ break;
369
+
370
+ }
371
+ }
372
+ return $attributeOption;
373
+ }
374
+
375
+ /**
376
+ *
377
+ *
378
+ * @param string $option
379
+ */
380
+ protected function _getAttributeOptionValue($option)
381
+ {
382
+ $selectOptions = $this->_getSearchAdapter()->getSearchParams()->getFilters();
383
+ $value = null;
384
+ switch ($option->getType()) {
385
+
386
+ case "slider";
387
+ $value = $option->getField().'|'.$option->getType().'|'.str_replace(array('&', '='), array('|', ':'), $option->getValue()).'[VALUE]';
388
+ break;
389
+
390
+ default:
391
+ $value = $option->getField();
392
+ if($option->isSelected()){
393
+
394
+ // handle multiselectable Attributes
395
+ if(!empty($selectOptions[$option->getField()]) ){
396
+ if(strpos($option->getField(), 'categoryROOT') === false){
397
+ $values = explode('~~~', $selectOptions[$option->getField()]);
398
+ unset($values[array_search($option->getValue(), $values)]);
399
+ $value .= '|'.implode('~~~', $values);
400
+
401
+ }else{
402
+ $values = explode('/',str_replace('|'.$selectOptions[$option->getField()], '', $value));
403
+ $valueCount = count($values);
404
+ $value = '';
405
+ if($valueCount > 1){
406
+ for($i=0 ; $valueCount > $i ; $i++){
407
+ $value .= ($i != 0 ? ($i == $valueCount-1 ? '|' : '/') : '').$values[$i];
408
+ }
409
+ }
410
+ }
411
+ }
412
+ }else{
413
+ $value .= '|'.$option->getValue();
414
+ // handle multiselectable Attributes
415
+ if(!empty($selectOptions[$option->getField()])){
416
+ $value .= '~~~'.$selectOptions[$option->getField()];
417
+ }
418
+ }
419
+ break;
420
+ }
421
+ return $value;
422
+ }
423
+
424
+
425
+ /**
426
+ * get Search Result Product Ids
427
+ *
428
+ * @return array Products Ids
429
+ */
430
+ public function getSearchResultProductIds()
431
+ {
432
+ if($this->_searchResultProductIds == null){
433
+ $result = $this->_getSearchAdapter()->getResult();
434
+ $this->_searchResultProductIds = array();
435
+ if($result instanceof FACTFinder_Result){
436
+ foreach ($result AS $record){
437
+ $this->_searchResultProductIds[] = $record->getId();
438
+ }
439
+ $this->_searchResultProductIds = array_unique($this->_searchResultProductIds);
440
+ }
441
+ }
442
+
443
+ return $this->_searchResultProductIds;
444
+ }
445
+
446
+ /**
447
+ * set single parameter, which will be looped through to the FACT-Finder request
448
+ *
449
+ * @param string name
450
+ * @param string value
451
+ */
452
+ protected function _setParam($name, $value)
453
+ {
454
+ Mage::helper('factfinder/debug')->log('set Param:'.$name.' => '.$value);
455
+ $this->_getDataProvider()->setParam($name, $value);
456
+ return $this;
457
+ }
458
+
459
+ /**
460
+ * get FactFinder DataProvider
461
+ *
462
+ * @return FACTFinder_Abstract_DataProvider
463
+ */
464
+ protected function _getDataProvider()
465
+ {
466
+ if ($this->_dataProvider == null) {
467
+ $config = $this->_getConfiguration();
468
+ $params = $this->_getParamsParser()->getServerRequestParams();
469
+ $this->_dataProvider = FF::getInstance('http/dataProvider', $params, $config);
470
+ }
471
+ return $this->_dataProvider;
472
+ }
473
+
474
+ /**
475
+ * get Autentivation URL
476
+ *
477
+ * @return string
478
+ */
479
+ public function getAuthenticationUrl()
480
+ {
481
+ $dataprovider = $this->_getDataProvider();
482
+ $dataprovider->setType('Management.ff');
483
+ return $dataprovider->getAuthenticationUrl();
484
+ }
485
+
486
+ /**
487
+ * get FactFinder Params Parser
488
+ *
489
+ * @return FACTFinder_ParametersParser
490
+ */
491
+ protected function _getParamsParser()
492
+ {
493
+ if ($this->_paramsParser == null) {
494
+ $config = $this->_getConfiguration();
495
+ $encodingHandler = FF::getSingleton('encodingHandler', $config);
496
+ $this->_paramsParser = FF::getInstance('parametersParser', $config, $encodingHandler);
497
+ }
498
+ return $this->_paramsParser;
499
+ }
500
+
501
+ /**
502
+ * get FactFinder Configuration
503
+ *
504
+ * @return FACTFinder_Abstract_Configuration config
505
+ */
506
+ protected function _getConfiguration($configarray = null)
507
+ {
508
+ if ($this->_config == null) {
509
+ $this->_config = FF::getSingleton('configuration', $configarray);
510
+ }
511
+ return $this->_config;
512
+ }
513
+ }
app/code/community/Flagbit/FactFinder/Model/Export/Price.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Model class
12
+ *
13
+ * This helper class provides the Price export
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Price.php 601 2010-12-21 14:07:41Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Model_Export_Price extends Mage_Core_Model_Mysql4_Abstract {
22
+
23
+ /**
24
+ * defines Export Columns
25
+ * @var array
26
+ */
27
+ protected $_exportColumns = array('entity_id', 'customer_group_id', 'final_price', 'min_price');
28
+
29
+ /**
30
+ * Resource initialization
31
+ */
32
+ protected function _construct(){
33
+ $this->_setResource('core');
34
+ }
35
+
36
+ /**
37
+ * add CSV Row
38
+ *
39
+ * @param array $data
40
+ */
41
+ protected function _addCsvRow($data)
42
+ {
43
+ foreach($data as &$item){
44
+ $item = str_replace(array("\r", "\n", "\""), ' ', addcslashes(strip_tags($item), '"'));
45
+ }
46
+
47
+ echo '"'.implode('";"', $data).'"'."\n";
48
+ }
49
+
50
+ /**
51
+ * export Product Prices
52
+ * direct Output as CSV
53
+ *
54
+ * @param int $storeId Store View Id
55
+ */
56
+ public function doExport($storeId = null)
57
+ {
58
+ $this->_addCsvRow($this->_exportColumns);
59
+ for($i=1; $prices = $this->_getPrices($storeId, $i); $i++){
60
+ foreach($prices as $price){
61
+ $this->_addCsvRow($price);
62
+ }
63
+ }
64
+ }
65
+
66
+ /**
67
+ * get Prices from Price Index Table
68
+ *
69
+ * @param int $storeId Store ID
70
+ * @param int $part
71
+ * @param int $limit
72
+ * @return array
73
+ */
74
+ protected function _getPrices($storeId, $part = 1, $limit = 100){
75
+
76
+ $store = Mage::app()->getStore($storeId);
77
+ $select = $this->_getWriteAdapter()->select()
78
+ ->from(
79
+ array('e' => $this->getTable('catalog/product_index_price')),
80
+ $this->_exportColumns);
81
+
82
+ if($storeId !== null){
83
+ $select->where('e.website_id = ?', $store->getWebsiteId());
84
+ }
85
+
86
+ $select->limitPage($part, $limit)
87
+ ->order('e.entity_id');
88
+
89
+ return $this->_getWriteAdapter()->fetchAll($select);
90
+ }
91
+ }
app/code/community/Flagbit/FactFinder/Model/Export/Product.php ADDED
@@ -0,0 +1,437 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Model class
12
+ *
13
+ * This helper class provides the Product export
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Product.php 627 2011-02-18 11:48:09Z rudolf_batt $
20
+ */
21
+ class Flagbit_FactFinder_Model_Export_Product extends Mage_CatalogSearch_Model_Mysql4_Fulltext {
22
+
23
+ /**
24
+ * Option ID to Value Mapping Array
25
+ * @var mixed
26
+ */
27
+ protected $_optionIdToValue = null;
28
+
29
+ /**
30
+ * Products to Category Path Mapping
31
+ *
32
+ * @var mixed
33
+ */
34
+ protected $_productsToCategoryPath = null;
35
+
36
+ /**
37
+ * Category Names by ID
38
+ * @var mixed
39
+ */
40
+ protected $_categoryNames = null;
41
+
42
+ /**
43
+ * add CSV Row
44
+ *
45
+ * @param array $data
46
+ */
47
+ protected function _addCsvRow($data)
48
+ {
49
+ foreach($data as &$item){
50
+ $item = str_replace(array("\r", "\n", "\""), array(' ', ' ', "''"), strip_tags($item));
51
+ }
52
+
53
+ echo '"'.implode('";"', $data).'"'."\n";
54
+ }
55
+
56
+ /**
57
+ * get Option Text by Option ID
58
+ *
59
+ * @param int $optionId Option ID
60
+ * @param int $storeId Store ID
61
+ * @return string
62
+ */
63
+ protected function _getAttributeOptionText($optionId, $storeId)
64
+ {
65
+ $value = '';
66
+ if(intval($optionId)){
67
+ if($this->_optionIdToValue === null){
68
+ /*@var $optionCollection Mage_Eav_Model_Mysql4_Entity_Attribute_Option_Collection */
69
+ $optionCollection = Mage::getResourceModel('eav/entity_attribute_option_collection');
70
+ $optionCollection->setStoreFilter($storeId);
71
+ $this->_optionIdToValue = array();
72
+ foreach($optionCollection as $option){
73
+ $this->_optionIdToValue[$option->getId()] = $option->getValue();
74
+ }
75
+ }
76
+ $value = isset($this->_optionIdToValue[$optionId]) ? $this->_optionIdToValue[$optionId] : '';
77
+ }
78
+ return $value;
79
+ }
80
+
81
+ /**
82
+ * export Product Data with Attributes
83
+ * direct Output as CSV
84
+ *
85
+ * @param int $storeId Store View Id
86
+ */
87
+ public function doExport($storeId = null)
88
+ {
89
+ $idFieldName = Mage::helper('factfinder/search')->getIdFieldName();
90
+ $header = array('id', 'parent_id', 'sku', 'category', 'filterable_attributes', 'searchable_attributes');
91
+ foreach($this->_getSearchableAttributes(null, 'system') as $attribute){
92
+ if(in_array($attribute->getAttributeCode(), array('sku', 'status', 'visibility'))){
93
+ continue;
94
+ }
95
+ $header[] = $attribute->getAttributeCode();
96
+ }
97
+
98
+ $this->_addCsvRow($header);
99
+
100
+ // preparesearchable attributes
101
+ $staticFields = array();
102
+ foreach ($this->_getSearchableAttributes('static', 'system') as $attribute) {
103
+ $staticFields[] = $attribute->getAttributeCode();
104
+ }
105
+ $dynamicFields = array(
106
+ 'int' => array_keys($this->_getSearchableAttributes('int')),
107
+ 'varchar' => array_keys($this->_getSearchableAttributes('varchar')),
108
+ 'text' => array_keys($this->_getSearchableAttributes('text')),
109
+ 'decimal' => array_keys($this->_getSearchableAttributes('decimal')),
110
+ 'datetime' => array_keys($this->_getSearchableAttributes('datetime')),
111
+ );
112
+
113
+ // status and visibility filter
114
+ $visibility = $this->_getSearchableAttribute('visibility');
115
+ $status = $this->_getSearchableAttribute('status');
116
+ $visibilityVals = Mage::getSingleton('catalog/product_visibility')->getVisibleInSearchIds();
117
+ $statusVals = Mage::getSingleton('catalog/product_status')->getVisibleStatusIds();
118
+
119
+ $lastProductId = 0;
120
+ while (true) {
121
+ $products = $this->_getSearchableProducts($storeId, $staticFields, null, $lastProductId);
122
+ if (!$products) {
123
+ break;
124
+ }
125
+
126
+ $productAttributes = array();
127
+ $productRelations = array();
128
+ foreach ($products as $productData) {
129
+ $lastProductId = $productData['entity_id'];
130
+ $productAttributes[$productData['entity_id']] = $productData['entity_id'];
131
+ $productChilds = $this->_getProductChildIds($productData['entity_id'], $productData['type_id']);
132
+ $productRelations[$productData['entity_id']] = $productChilds;
133
+ if ($productChilds) {
134
+ foreach ($productChilds as $productChild) {
135
+ $productAttributes[$productChild['entity_id']] = $productChild;
136
+ }
137
+ }
138
+ }
139
+
140
+ $productIndexes = array();
141
+ $productAttributes = $this->_getProductAttributes($storeId, $productAttributes, $dynamicFields);
142
+ foreach ($products as $productData) {
143
+ if (!isset($productAttributes[$productData['entity_id']])) {
144
+ continue;
145
+ }
146
+ $protductAttr = $productAttributes[$productData['entity_id']];
147
+
148
+ if (!isset($protductAttr[$visibility->getId()]) || !in_array($protductAttr[$visibility->getId()], $visibilityVals)) {
149
+ continue;
150
+ }
151
+ if (!isset($protductAttr[$status->getId()]) || !in_array($protductAttr[$status->getId()], $statusVals)) {
152
+ continue;
153
+ }
154
+
155
+ $productIndex = array(
156
+ $productData['entity_id'],
157
+ $productData[$idFieldName],
158
+ $productData['sku'],
159
+ $this->_getCategoryPath($productData['entity_id'], $storeId),
160
+ $this->_formatFilterableAttributes($this->_getSearchableAttributes(null, 'filterable'), $protductAttr, $storeId),
161
+ $this->_formatSearchableAttributes($this->_getSearchableAttributes(null, 'searchable'), $protductAttr, $storeId)
162
+ );
163
+
164
+ $this->_getAttributesRowArray($productIndex, $protductAttr, $storeId);
165
+
166
+ $this->_addCsvRow($productIndex);
167
+
168
+ if ($productChilds = $productRelations[$productData['entity_id']]) {
169
+ foreach ($productChilds as $productChild) {
170
+ if (isset($productAttributes[$productChild['entity_id']])) {
171
+
172
+ $subProductIndex = array(
173
+ $productChild['entity_id'],
174
+ $productData[$idFieldName],
175
+ $productChild['sku'],
176
+ $this->_getCategoryPath($productData['entity_id'], $storeId),
177
+ $this->_formatFilterableAttributes($this->_getSearchableAttributes(null, 'filterable'), $productAttributes[$productChild['entity_id']], $storeId),
178
+ $this->_formatSearchableAttributes($this->_getSearchableAttributes(null, 'searchable'), $productAttributes[$productChild['entity_id']], $storeId)
179
+ );
180
+ $this->_getAttributesRowArray($subProductIndex, $productAttributes[$productChild['entity_id']], $storeId);
181
+
182
+ $this->_addCsvRow($subProductIndex);
183
+ }
184
+ }
185
+ }
186
+ }
187
+ }
188
+ }
189
+
190
+ protected function _formatSearchableAttributes($attributes, $values, $storeId=null)
191
+ {
192
+ $returnArray = array();
193
+ foreach($attributes as $attribute){
194
+ $value = isset($values[$attribute->getId()]) ? $values[$attribute->getId()] : null;
195
+ if(!$value || in_array($attribute->getAttributeCode(), array('sku', 'status', 'visibility', 'price'))){
196
+ continue;
197
+ }
198
+ $attributeValue = $this->_getAttributeValue($attribute->getId(), $value, $storeId);
199
+ if (strval($attributeValue) != "") {
200
+ $returnArray[] = $attributeValue;
201
+ }
202
+ }
203
+ return implode(',', $returnArray);
204
+ }
205
+
206
+ protected function _formatFilterableAttributes($attributes, $values, $storeId=null)
207
+ {
208
+ $returnArray = array();
209
+ foreach($attributes as $attribute){
210
+ $value = isset($values[$attribute->getId()]) ? $values[$attribute->getId()] : null;
211
+ if(!$value || in_array($attribute->getAttributeCode(), array('sku', 'status', 'visibility', 'price'))){
212
+ continue;
213
+ }
214
+ $attributeValue = $this->_getAttributeValue($attribute->getId(), $value, $storeId);
215
+ if (strval($attributeValue) != "") {
216
+ $returnArray[] = $attribute->getAttributeCode().'='.$attributeValue;
217
+ }
218
+ }
219
+ return implode('|', $returnArray);
220
+ }
221
+
222
+ /**
223
+ * Retrieve Searchable attributes
224
+ *
225
+ * @param string $backendType
226
+ * @param string $type possible Types: system, sortable, filterable, searchable
227
+ * @return array
228
+ */
229
+ protected function _getSearchableAttributes($backendType = null, $type = null)
230
+ {
231
+ if (is_null($this->_searchableAttributes)) {
232
+ $this->_searchableAttributes = array();
233
+ $entityType = $this->getEavConfig()->getEntityType('catalog_product');
234
+ $entity = $entityType->getEntity();
235
+
236
+ $whereCond = array(
237
+ $this->_getWriteAdapter()->quoteInto('additional_table.is_searchable=? or additional_table.is_filterable=?', 1),
238
+ $this->_getWriteAdapter()->quoteInto('main_table.attribute_code IN(?)', array('status', 'visibility'))
239
+ );
240
+
241
+ $select = $this->_getWriteAdapter()->select()
242
+ ->from(array('main_table' => $this->getTable('eav/attribute')))
243
+ ->join(
244
+ array('additional_table' => $this->getTable('catalog/eav_attribute')),
245
+ 'additional_table.attribute_id = main_table.attribute_id'
246
+ )
247
+ ->where('main_table.entity_type_id=?', $entityType->getEntityTypeId())
248
+ ->where(join(' OR ', $whereCond));
249
+
250
+ $attributesData = $this->_getWriteAdapter()->fetchAll($select);
251
+ $this->getEavConfig()->importAttributesData($entityType, $attributesData);
252
+ foreach ($attributesData as $attributeData) {
253
+ $attributeCode = $attributeData['attribute_code'];
254
+ $attribute = $this->getEavConfig()->getAttribute($entityType, $attributeCode);
255
+ $attribute->setEntity($entity);
256
+ $this->_searchableAttributes[$attribute->getId()] = $attribute;
257
+ }
258
+ unset($attributesData);
259
+ }
260
+
261
+ if(!is_null($type) || !is_null($backendType)){
262
+ $attributes = array();
263
+ foreach ($this->_searchableAttributes as $attribute) {
264
+
265
+ if(!is_null($backendType)
266
+ && $attribute->getBackendType() != $backendType){
267
+ continue;
268
+ }
269
+
270
+ switch($type){
271
+
272
+ case "system":
273
+ if($attribute->getIsUserDefined()
274
+ && !$attribute->getUsedForSortBy()){
275
+ continue 2;
276
+ }
277
+ break;
278
+
279
+ case "sortable":
280
+ if(!$attribute->getUsedForSortBy()){
281
+ continue 2;
282
+ }
283
+ break;
284
+
285
+ case "filterable":
286
+ if(!$attribute->getIsFilterableInSearch()){
287
+ continue 2;
288
+ }
289
+ break;
290
+
291
+ case "searchable":
292
+ if(!$attribute->getIsUserDefined()
293
+ || !$attribute->getIsSearchable()){
294
+ continue 2;
295
+ }
296
+ break;
297
+ }
298
+
299
+ $attributes[$attribute->getId()] = $attribute;
300
+ }
301
+ return $attributes;
302
+ }
303
+ return $this->_searchableAttributes;
304
+ }
305
+
306
+ /**
307
+ * Get Category Path by Product ID
308
+ *
309
+ * @param int $productId
310
+ * @param int $storeId
311
+ * @return string
312
+ */
313
+ protected function _getCategoryPath($productId, $storeId = null)
314
+ {
315
+
316
+ if($this->_categoryNames === null){
317
+ $categoryCollection = Mage::getResourceModel('catalog/category_attribute_collection');
318
+ $categoryCollection->getSelect()->where("attribute_code IN('name', 'is_active')");
319
+
320
+ foreach($categoryCollection as $categoryModel){
321
+ ${$categoryModel->getAttributeCode().'Model'} = $categoryModel;
322
+ }
323
+
324
+ $select = $this->_getReadAdapter()->select()
325
+ ->from(
326
+ array('main' => $nameModel->getBackendTable()),
327
+ array('entity_id', 'value')
328
+ )
329
+ ->join(
330
+ array('e' => $is_activeModel->getBackendTable()),
331
+ 'main.entity_id=e.entity_id AND (e.store_id = 0 OR e.store_id = '.$storeId.') AND e.attribute_id='.$is_activeModel->getAttributeId(),
332
+ null
333
+ )
334
+ ->where('main.attribute_id=?', $nameModel->getAttributeId())
335
+ ->where('e.value=?', '1')
336
+ ->where('main.store_id = 0 OR main.store_id = ?', $storeId);
337
+
338
+ $this->_categoryNames = $this->_getReadAdapter()->fetchPairs($select);
339
+ }
340
+
341
+ if($this->_productsToCategoryPath === null){
342
+ $select = $this->_getReadAdapter()->select()
343
+ ->from(
344
+ array('main' => $this->getTable('catalog/category_product_index')),
345
+ array('product_id')
346
+ )
347
+ ->join(
348
+ array('e' => $this->getTable('catalog/category')),
349
+ 'main.category_id=e.entity_id',
350
+ null
351
+ )
352
+ ->columns(array('e.path' => new Zend_Db_Expr('GROUP_CONCAT(e.path)')))
353
+ ->where('main.visibility IN(3,4)') //TODO look for Constants
354
+ ->where('main.store_id = ?', $storeId)
355
+ ->group('main.product_id');
356
+
357
+ $this->_productsToCategoryPath = $this->_getReadAdapter()->fetchPairs($select);
358
+ }
359
+
360
+ $value = '';
361
+ if(isset($this->_productsToCategoryPath[$productId])){
362
+ $paths = explode(',', $this->_productsToCategoryPath[$productId]);
363
+ foreach($paths as $path){
364
+ $categoryIds = explode('/', $path);
365
+ $categoryIdsCount = count($categoryIds);
366
+ $categoryPath = '';
367
+ for($i=2;$i < $categoryIdsCount;$i++){
368
+ if(!isset($this->_categoryNames[$categoryIds[$i]])){
369
+ continue 2;
370
+ }
371
+ $categoryPath .= urlencode($this->_categoryNames[$categoryIds[$i]]).'/';
372
+ }
373
+ if($categoryIdsCount > 2){
374
+ $value .= rtrim($categoryPath,'/').'|';
375
+ }
376
+ }
377
+ $value = trim($value, '|');
378
+ }
379
+
380
+ return $value;
381
+ }
382
+
383
+ /**
384
+ * Return all product children ids
385
+ *
386
+ * @param int $productId Product Entity Id
387
+ * @param string $typeId Super Product Link Type
388
+ * @return array
389
+ */
390
+ protected function _getProductChildIds($productId, $typeId)
391
+ {
392
+ $typeInstance = $this->_getProductTypeInstance($typeId);
393
+ $relation = $typeInstance->isComposite()
394
+ ? $typeInstance->getRelationInfo()
395
+ : false;
396
+
397
+ if ($relation && $relation->getTable() && $relation->getParentFieldName() && $relation->getChildFieldName()) {
398
+ $select = $this->_getReadAdapter()->select()
399
+ ->from(
400
+ array('main' => $this->getTable($relation->getTable())),
401
+ array($relation->getChildFieldName()))
402
+
403
+ ->join(
404
+ array('e' => $this->getTable('catalog/product')),
405
+ 'main.'.$relation->getChildFieldName().'=e.entity_id',
406
+ array('entity_id', 'type_id', 'sku')
407
+ )
408
+
409
+ ->where("{$relation->getParentFieldName()}=?", $productId);
410
+ if (!is_null($relation->getWhere())) {
411
+ $select->where($relation->getWhere());
412
+ }
413
+ return $this->_getReadAdapter()->fetchAll($select);
414
+ }
415
+
416
+ return null;
417
+ }
418
+
419
+ /**
420
+ * get Attribute Row Array
421
+ *
422
+ * @param array $dataArray Export row Array
423
+ * @param array $attributes Attributes Array
424
+ * @param int $storeId Store ID
425
+ */
426
+ protected function _getAttributesRowArray(&$dataArray, $values, $storeId=null)
427
+ {
428
+ foreach($this->_getSearchableAttributes(null, 'system') as $attribute){
429
+
430
+ if(in_array($attribute->getAttributeCode(), array('sku', 'status', 'visibility'))){
431
+ continue;
432
+ }
433
+ $value = isset($values[$attribute->getId()]) ? $values[$attribute->getId()] : null;
434
+ $dataArray[$attribute->getAttributeCode()] = $this->_getAttributeValue($attribute->getId(), $value, $storeId);
435
+ }
436
+ }
437
+ }
app/code/community/Flagbit/FactFinder/Model/Export/Stock.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Model class
12
+ *
13
+ * This helper class provides the Stock export
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Stock.php 610 2011-01-19 14:13:34Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Model_Export_Stock extends Mage_Core_Model_Mysql4_Abstract {
22
+
23
+ /**
24
+ * defines Export Columns
25
+ * @var array
26
+ */
27
+ protected $_exportColumns = array('product_id', 'qty', 'stock_status');
28
+
29
+ /**
30
+ * Resource initialization
31
+ */
32
+ protected function _construct(){
33
+ $this->_setResource('core');
34
+ }
35
+
36
+ /**
37
+ * add CSV Row
38
+ *
39
+ * @param array $data
40
+ */
41
+ protected function _addCsvRow($data)
42
+ {
43
+ foreach($data as &$item){
44
+ $item = str_replace(array("\r", "\n", "\""), ' ', addcslashes(strip_tags($item), '"'));
45
+ }
46
+
47
+ echo '"'.implode('";"', $data).'"'."\n";
48
+ }
49
+
50
+ /**
51
+ * export Stock Data
52
+ * direct Output as CSV
53
+ *
54
+ * @param int $storeId Store Id
55
+ */
56
+ public function doExport($storeId = null)
57
+ {
58
+ $this->_addCsvRow($this->_exportColumns);
59
+ for($i=1; $stocks = $this->_getStockData($storeId, $i); $i++){
60
+ foreach($stocks as $stock){
61
+ $this->_addCsvRow($stock);
62
+ }
63
+ }
64
+ }
65
+
66
+ /**
67
+ * get Stocks from Stock Index Table
68
+ *
69
+ * @param int $storeId Store ID
70
+ * @param int $part
71
+ * @param int $limit
72
+ * @return array
73
+ */
74
+ protected function _getStockData($storeId, $part = 1, $limit = 100){
75
+
76
+ $store = Mage::app()->getStore($storeId);
77
+ $select = $this->_getWriteAdapter()->select()
78
+ ->from(
79
+ array('e' => $this->getTable('cataloginventory/stock_status')),
80
+ $this->_exportColumns);
81
+
82
+ if($storeId !== null){
83
+ $select->where('e.website_id = ?', $store->getWebsiteId());
84
+ }
85
+
86
+ $select->limitPage($part, $limit)
87
+ ->order('e.product_id');
88
+
89
+ return $this->_getWriteAdapter()->fetchAll($select);
90
+ }
91
+ }
app/code/community/Flagbit/FactFinder/Model/Layer.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Flagbit_FactFinder_Model_Layer extends Mage_CatalogSearch_Model_Layer
4
+ {
5
+ const XML_PATH_DISPLAY_LAYER_COUNT = 'catalog/search/use_layered_navigation_count';
6
+
7
+ protected $_searchCollection = null;
8
+
9
+ /**
10
+ * Get current layer product collection
11
+ *
12
+ * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
13
+ */
14
+ public function getProductCollection()
15
+ {
16
+ if(!Mage::helper('factfinder/search')->getIsEnabled()){
17
+ return parent::getProductCollection();
18
+ }
19
+
20
+ if(is_null($this->_searchCollection)){
21
+ $this->_searchCollection = Mage::getResourceModel('factfinder/search_collection');
22
+ $this->prepareProductCollection($this->_searchCollection);
23
+
24
+ Mage::helper('factfinder/debug')->log('Search SQL Query: '.$this->_searchCollection->getSelect()->__toString());
25
+ }
26
+ return $this->_searchCollection;
27
+ }
28
+
29
+ /**
30
+ * Get collection of all filterable attributes for layer products set
31
+ *
32
+ * @return Flagbit_FactFinder_Model_Mysql4_Product_Attribute_Collection
33
+ */
34
+ public function getFilterableAttributes()
35
+ {
36
+
37
+ if(!Mage::helper('factfinder/search')->getIsEnabled()){
38
+ return parent::getFilterableAttributes();
39
+ }
40
+
41
+ /* @var $collection Flagbit_FactFinder_Model_Mysql4_Product_Attribute_Collection */
42
+ $collection = Mage::getResourceModel('factfinder/product_attribute_collection')
43
+ ->setItemObjectClass('catalog/resource_eav_attribute')
44
+ ->setStoreId(Mage::app()->getStore()->getId());
45
+
46
+ return $collection;
47
+ }
48
+ }
app/code/community/Flagbit/FactFinder/Model/Layer/Filter/Attribute.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Model class
12
+ *
13
+ * This helper class provides the Price export
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Attribute.php 633 2011-02-23 16:13:29Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Model_Layer_Filter_Attribute extends Mage_CatalogSearch_Model_Layer_Filter_Attribute {
22
+
23
+ /**
24
+ * Array of Magento Layer Filter Items
25
+ * @var mixed
26
+ */
27
+ protected $_filterItems = null;
28
+
29
+ /**
30
+ * Array of Selected Layer Filters
31
+ * @var mixed
32
+ */
33
+ protected $_selectedFilterItems = array();
34
+
35
+ /**
36
+ * Apply attribute option filter to product collection
37
+ *
38
+ * @param Zend_Controller_Request_Abstract $request
39
+ * @param Varien_Object $filterBlock
40
+ * @return Mage_Catalog_Model_Layer_Filter_Attribute
41
+ */
42
+ public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
43
+ {
44
+ if(!Mage::helper('factfinder/search')->getIsEnabled()){
45
+ return parent::apply($request, $filterBlock);
46
+ }
47
+
48
+ $this->_getItemsData();
49
+ $_attributeCode = $filterBlock->getAttributeModel()->getAttributeCode();
50
+ if (isset($this->_selectedFilterItems[$_attributeCode])
51
+ && is_array($this->_selectedFilterItems[$_attributeCode])) {
52
+
53
+ foreach($this->_selectedFilterItems[$_attributeCode] as $option){
54
+ $this->getLayer()->getState()->addFilter($this->_createItem($option['label'], $option['value']));
55
+ }
56
+ }
57
+ return $this;
58
+ }
59
+
60
+
61
+ /**
62
+ * Create filter item object
63
+ *
64
+ * @param string $label
65
+ * @param mixed $value
66
+ * @param int $count
67
+ * @return Mage_Catalog_Model_Layer_Filter_Item
68
+ */
69
+ protected function _createItem($label, $value, $count=0)
70
+ {
71
+ return Mage::getModel('factfinder/layer_filter_item')
72
+ ->setFilter($this)
73
+ ->setLabel($label)
74
+ ->setValue($value)
75
+ ->setCount($count);
76
+ }
77
+
78
+
79
+ /**
80
+ * Get data array for building attribute filter items
81
+ *
82
+ * @return array
83
+ */
84
+ protected function _getItemsData()
85
+ {
86
+ if(!Mage::helper('factfinder/search')->getIsEnabled()){
87
+ return parent::_getItemsData();
88
+ }
89
+
90
+ if($this->_filterItems === null){
91
+ $attribute = $this->getAttributeModel();
92
+ $this->_requestVar = $attribute->getAttributeCode();
93
+
94
+ $key = $this->getLayer()->getStateKey().'_'.$this->_requestVar;
95
+ $data = $this->getLayer()->getAggregator()->getCacheData($key);
96
+
97
+ $options = $attribute->getItems();
98
+ $optionsCount = $attribute->getCount();
99
+ $this->_filterItems = array();
100
+ if(is_array($options)){
101
+ foreach ($options as $option) {
102
+
103
+ if($option['selected'] == true){
104
+ $this->_selectedFilterItems[$attribute->getAttributeCode()][] = $option;
105
+ continue;
106
+ }
107
+ $this->_filterItems[] = $option;
108
+ }
109
+ }
110
+ }
111
+ return $this->_filterItems;
112
+ }
113
+
114
+ }
app/code/community/Flagbit/FactFinder/Model/Layer/Filter/Item.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Flagbit_Factfinder_Model_Layer_Filter_Item extends Mage_Catalog_Model_Layer_Filter_Item {
3
+
4
+
5
+ /**
6
+ * Get url for remove item from filter
7
+ *
8
+ * @return string
9
+ */
10
+ public function getRemoveUrl()
11
+ {
12
+ $query = array($this->getFilter()->getRequestVar()=>$this->getValue());
13
+ $params['_current'] = true;
14
+ $params['_use_rewrite'] = true;
15
+ $params['_query'] = $query;
16
+ $params['_escape'] = true;
17
+ return Mage::getUrl('*/*/*', $params);
18
+ }
19
+
20
+ }
app/code/community/Flagbit/FactFinder/Model/Mysql4/Product/Attribute/Collection.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Model class
12
+ *
13
+ * Filter Attribute Collection
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Collection.php 610 2011-01-19 14:13:34Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Model_Mysql4_Product_Attribute_Collection extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Attribute_Collection {
22
+
23
+ protected $_result = null;
24
+ protected $_attributeLabels = null;
25
+ protected $_storeId = null;
26
+
27
+ /**
28
+ * Get collection size
29
+ *
30
+ * @return int
31
+ */
32
+ public function getSize()
33
+ {
34
+ return count($this->_getAdapter()->getAfterSearchNavigation());
35
+ }
36
+
37
+ /**
38
+ * get Adapter
39
+ *
40
+ * @return Flagbit_FactFinder_Model_Adapter
41
+ */
42
+ protected function _getAdapter()
43
+ {
44
+ return Mage::getSingleton('factfinder/adapter');
45
+ }
46
+
47
+ /**
48
+ * Load entities records into items
49
+ *
50
+ * @return Mage_Eav_Model_Entity_Collection_Abstract
51
+ */
52
+ public function load($printQuery = false, $logQuery = false)
53
+ {
54
+ if ($this->isLoaded()) {
55
+ return $this;
56
+ }
57
+
58
+ $result = $this->_getAdapter()->getAfterSearchNavigation();
59
+
60
+ if (count($result)) {
61
+ $this->resetData();
62
+
63
+ foreach ($result as $row) {
64
+ $item = $this->getNewEmptyItem();
65
+ if ($this->getIdFieldName()) {
66
+ $item->setIdFieldName($this->getIdFieldName());
67
+ }
68
+ $row['store_label'] = $this->_getStoreLabelsByAttributeCode($row['name']);
69
+ $item->addData($row);
70
+ $this->addItem($item);
71
+ }
72
+
73
+ $this->_setIsLoaded();
74
+ $this->_afterLoad();
75
+ }
76
+ return $this;
77
+ }
78
+
79
+
80
+ /**
81
+ * Add search query filter
82
+ *
83
+ * @param Mage_CatalogSearch_Model_Query $query
84
+ * @return Mage_CatalogSearch_Model_Mysql4_Search_Collection
85
+ */
86
+ public function addSearchFilter($query)
87
+ {
88
+ return $this;
89
+ }
90
+
91
+ /**
92
+ * Retrieve store labels by given attribute code
93
+ *
94
+ * @param string $attributeCode
95
+ * @return array
96
+ */
97
+ protected function _getStoreLabelsByAttributeCode($attributeCode)
98
+ {
99
+ if($this->_attributeLabels === null){
100
+ $entityType = Mage::getSingleton('eav/config')->getEntityType('catalog_product');
101
+
102
+ $values = array();
103
+
104
+ $select = $this->getConnection()->select()
105
+ ->from(array('main_table' => $this->getTable('eav/attribute')), array('attribute_code'))
106
+ ->joinLeft(
107
+ array('additional_table' => $this->getTable('eav/attribute_label')),
108
+ 'additional_table.attribute_id = main_table.attribute_id',
109
+ null
110
+ )
111
+ ->columns(array('value' => new Zend_Db_Expr('IF(additional_table.value IS NULL, main_table.frontend_label, additional_table.value)')))
112
+ ->where('main_table.entity_type_id = ?', $entityType->getEntityTypeId())
113
+ ->where('additional_table.store_id IS NULL OR additional_table.store_id=?', $this->_storeId);
114
+
115
+ $this->_attributeLabels = $this->getConnection()->fetchPairs($select);
116
+ }
117
+ return isset($this->_attributeLabels[$attributeCode]) ? $this->_attributeLabels[$attributeCode] : $attributeCode;
118
+ }
119
+
120
+ /**
121
+ * set Store ID
122
+ *
123
+ * @param int $storeId
124
+ * @return Flagbit_FactFinder_Model_Mysql4_Product_Attribute_Collection
125
+ */
126
+ public function setStoreId($storeId)
127
+ {
128
+ $this->_storeId = $storeId;
129
+ return $this;
130
+ }
131
+
132
+ /**
133
+ * Set Order field
134
+ *
135
+ * @param string $attribute
136
+ * @param string $dir
137
+ * @return Mage_CatalogSearch_Model_Mysql4_Fulltext_Collection
138
+ */
139
+ public function setOrder($attribute, $dir='desc')
140
+ {
141
+ return $this;
142
+ }
143
+
144
+ }
app/code/community/Flagbit/FactFinder/Model/Mysql4/Search/Collection.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Model class
12
+ *
13
+ * Search Collection with FACT-Finder Search Results
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Collection.php 627 2011-02-18 11:48:09Z rudolf_batt $
20
+ */
21
+ class Flagbit_FactFinder_Model_Mysql4_Search_Collection
22
+ extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
23
+ {
24
+ /**
25
+ * Get collection size
26
+ *
27
+ * @return int
28
+ */
29
+ public function getSize()
30
+ {
31
+ return $this->_getAdapter()->getSearchResultCount();
32
+ }
33
+
34
+ /**
35
+ * get Factfinder Search Adapter
36
+ *
37
+ * @return Flagbit_FactFinder_Model_Adapter
38
+ */
39
+ protected function _getAdapter()
40
+ {
41
+ return Mage::getSingleton('factfinder/adapter');
42
+ }
43
+
44
+ /**
45
+ * Load entities records into items
46
+ *
47
+ * @return Mage_Eav_Model_Entity_Collection_Abstract
48
+ */
49
+ public function _loadEntities($printQuery = false, $logQuery = false)
50
+ {
51
+
52
+ // get product Ids from Fact-Finder
53
+ $productIds = $this->_getAdapter()->getSearchResultProductIds();
54
+ $idFieldName = Mage::helper('factfinder/search')->getIdFieldName();
55
+
56
+ if (!empty($productIds)) {
57
+
58
+ // add Filter to Query
59
+ $this->addFieldToFilter(
60
+ $idFieldName,
61
+ array('in'=>$productIds)
62
+ );
63
+
64
+ $this->_pageSize = null;
65
+ $entity = $this->getEntity();
66
+
67
+ $this->printLogQuery($printQuery, $logQuery);
68
+
69
+ try {
70
+ $rows = $this->_fetchAll($this->getSelect());
71
+ } catch (Exception $e) {
72
+ Mage::printException($e, $this->getSelect());
73
+ $this->printLogQuery(true, true, $this->getSelect());
74
+ throw $e;
75
+ }
76
+
77
+ $items = array();
78
+ foreach ($rows as $v) {
79
+ $items[$v[$idFieldName]] = $v;
80
+ }
81
+
82
+ foreach ($productIds as $productId){
83
+
84
+ if(empty($items[$productId])){
85
+ continue;
86
+ }
87
+ $v = $items[$productId];
88
+ $object = $this->getNewEmptyItem()
89
+ ->setData($v);
90
+
91
+ $this->addItem($object);
92
+ if (isset($this->_itemsById[$object->getId()])) {
93
+ $this->_itemsById[$object->getId()][] = $object;
94
+ }
95
+ else {
96
+ $this->_itemsById[$object->getId()] = array($object);
97
+ }
98
+ }
99
+
100
+ }
101
+ return $this;
102
+ }
103
+
104
+ /**
105
+ * Add search query filter
106
+ *
107
+ * @param Mage_CatalogSearch_Model_Query $query
108
+ * @return Mage_CatalogSearch_Model_Mysql4_Search_Collection
109
+ */
110
+ public function addSearchFilter($query)
111
+ {
112
+ return $this;
113
+ }
114
+
115
+ /**
116
+ * Set Order field
117
+ *
118
+ * @param string $attribute
119
+ * @param string $dir
120
+ * @return Mage_CatalogSearch_Model_Mysql4_Fulltext_Collection
121
+ */
122
+ public function setOrder($attribute, $dir='desc')
123
+ {
124
+ return $this;
125
+ }
126
+ }
app/code/community/Flagbit/FactFinder/Model/Mysql4/Search/Engine.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Model class
12
+ *
13
+ * FACT-Finder Search Engine Model
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Engine.php 612 2011-01-28 16:16:04Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Model_Mysql4_Search_Engine extends Mage_CatalogSearch_Model_Mysql4_Fulltext_Engine
22
+ {
23
+
24
+ /**
25
+ * Retrieve fulltext search result data collection
26
+ *
27
+ * @return Mage_CatalogSearch_Model_Mysql4_Fulltext_Collection
28
+ */
29
+ public function getResultCollection()
30
+ {
31
+ return Mage::getResourceModel('factfinder/search_collection');
32
+ }
33
+
34
+ /**
35
+ * Define if Layered Navigation is allowed
36
+ *
37
+ * @return bool
38
+ */
39
+ public function isLeyeredNavigationAllowed()
40
+ {
41
+ return true;
42
+ }
43
+
44
+ /**
45
+ * Define if engine is avaliable
46
+ *
47
+ * @return bool
48
+ */
49
+ public function test()
50
+ {
51
+ return Mage::helper('factfinder/search')->getIsEnabled();
52
+ }
53
+ }
app/code/community/Flagbit/FactFinder/Model/System/Config/Backend/Enabled.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Model class
12
+ *
13
+ * Status Enabled Config Field Backend
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Enabled.php 624 2011-02-16 08:47:13Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Model_System_Config_Backend_Enabled extends Mage_Core_Model_Config_Data {
22
+
23
+ /**
24
+ * validate new data. it will print error message if not
25
+ *
26
+ * @return Flagbit_FactFinder_Model_System_Config_Backend_Enabled
27
+ */
28
+ protected function _beforeSave()
29
+ {
30
+ if($this->getValue()){
31
+
32
+ $data = new Varien_Object($this->getFieldsetData());
33
+ $errors = array();
34
+
35
+ if (stripos($data->getAddress(), 'http://') === 0 || strpos($data->getAddress(), '/') !== false) {
36
+ $errors[] = Mage::helper('factfinder')->__('servername should only contain the IP address or the domain - no "http://" or any slashes!');
37
+ }
38
+
39
+ if ($data->getPort() == '') {
40
+ $port = 80;
41
+ } else if (!is_numeric($data->getPort())) {
42
+ $errors[] = Mage::helper('factfinder')->__('the value for "port" must be numeric!');
43
+ } else if(intval($data->getPort()) < 80) { //is there any http port lower 80?
44
+ $errors[] = Mage::helper('factfinder')->__('the value for "port" must be a number greater or equals 80!');
45
+ }
46
+
47
+ if ($data->getAuthPassword() != '' && $data->getAuthUser() == '') {
48
+ $errors[] = Mage::helper('factfinder')->__('there must be a username, if a password should be used');
49
+ }
50
+
51
+ $conflicts = Mage::helper('factfinder/debug')->getRewriteConflicts();
52
+ if(count($conflicts)){
53
+ foreach($conflicts as $moduleClass => $externalClass){
54
+ $errors[] = Mage::helper('factfinder')->__('There is a Class Rewrite Conflict: "%s" already overwritten by "%s"', $moduleClass, $externalClass);
55
+ }
56
+ }
57
+
58
+ if (count($errors) == 0) {
59
+ $adapter = Mage::getSingleton('factfinder/adapter');
60
+ if(!$adapter->checkStatus($this->getFieldsetData())){
61
+ $errors[] = Mage::helper('factfinder')->__('WARNING: was not able to connect to FACT-Finder.');
62
+ }
63
+ }
64
+
65
+ if (count($errors) > 0) {
66
+
67
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('factfinder')->__('FACT-Finder cannot be activated:').' <br/>'. implode('<br/>', $errors));
68
+ $this->setValue('0');
69
+ }
70
+ }
71
+
72
+ return $this;
73
+ }
74
+ }
app/code/community/Flagbit/FactFinder/Model/System/Config/Source/Authtype.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Model class
12
+ *
13
+ * provides Authtype Options
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Authtype.php 601 2010-12-21 14:07:41Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Model_System_Config_Source_Authtype
22
+ {
23
+ /**
24
+ * get Authtypes as Option Array
25
+ *
26
+ * @return array
27
+ */
28
+ public function toOptionArray()
29
+ {
30
+ return array(
31
+ array(
32
+ 'value' => 'http',
33
+ 'label' => Mage::helper('factfinder')->__('http')
34
+ ),
35
+ array(
36
+ 'value' => 'simple',
37
+ 'label' => Mage::helper('factfinder')->__('simple')
38
+ ),
39
+ array(
40
+ 'value' => 'advanced',
41
+ 'label' => Mage::helper('factfinder')->__('advanced')
42
+ )
43
+ );
44
+ }
45
+ }
app/code/community/Flagbit/FactFinder/Model/System/Config/Source/Identifier.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Model class
12
+ *
13
+ * provides Identifier Options
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: Identifier.php 625 2011-02-16 08:49:13Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Model_System_Config_Source_Identifier
22
+ {
23
+ /**
24
+ * get Authtypes as Option Array
25
+ *
26
+ * @return array
27
+ */
28
+ public function toOptionArray()
29
+ {
30
+ return array(
31
+ array(
32
+ 'value' => 'entity_id',
33
+ 'label' => Mage::helper('factfinder')->__('Product ID (default)')
34
+ ),
35
+ array(
36
+ 'value' => 'sku',
37
+ 'label' => Mage::helper('factfinder')->__('Product SKU')
38
+ )
39
+ );
40
+ }
41
+ }
app/code/community/Flagbit/FactFinder/controllers/Adminhtml/Factfinder/CockpitController.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Black class
12
+ *
13
+ * This Block class provides the FACT-Finder Business User Cockpit Authentication URL
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: CockpitController.php 601 2010-12-21 14:07:41Z weller $
20
+ */
21
+ class Flagbit_FactFinder_Adminhtml_Factfinder_CockpitController extends Mage_Adminhtml_Controller_Action
22
+ {
23
+
24
+ /**
25
+ * Load layout, set active menu and breadcrumbs
26
+ *
27
+ * @return Mage_Widget_Adminhtml_Widget_InstanceController
28
+ */
29
+ protected function _initAction()
30
+ {
31
+ $this->loadLayout()
32
+ ->_setActiveMenu('catalog/factfinder_cockpit')
33
+ ->_addBreadcrumb(Mage::helper('factfinder')->__('Catalog'),
34
+ Mage::helper('factfinder')->__('Catalog'))
35
+ ->_addBreadcrumb(Mage::helper('factfinder')->__('FACT-Finder Business User Cockpit'),
36
+ Mage::helper('factfinder')->__('FACT-Finder Business User Cockpit'));
37
+ return $this;
38
+ }
39
+
40
+ /**
41
+ * FACT-Finder Business User Cockpit Action
42
+ */
43
+ public function indexAction()
44
+ {
45
+ $this->_title($this->__('factfinder'))->_title($this->__('FACT-Finder Business User Cockpit'));
46
+
47
+ $this->_initAction()
48
+ ->renderLayout();
49
+ }
50
+
51
+
52
+
53
+ }
app/code/community/Flagbit/FactFinder/controllers/ExportController.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Controller class
12
+ *
13
+ * This class the Export Controller
14
+ * It provides a Products, Prices and Stocks Export
15
+ *
16
+ * @category Mage
17
+ * @package Flagbit_FactFinder
18
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
19
+ * @author Joerg Weller <weller@flagbit.de>
20
+ * @version $Id: ExportController.php 623 2011-02-16 08:22:10Z weller $
21
+ */
22
+ class Flagbit_FactFinder_ExportController extends Mage_Core_Controller_Front_Action {
23
+
24
+ const XML_AUTH_PASSWORD_PATH = 'factfinder/search/auth_password';
25
+
26
+ /**
27
+ * handle Export Authentification
28
+ *
29
+ * @return Mage_Core_Controller_Varien_Action
30
+ */
31
+ public function preDispatch()
32
+ {
33
+ $password = md5(Mage::getStoreConfig(self::XML_AUTH_PASSWORD_PATH));
34
+
35
+ if($password != $this->getRequest()->getParam('key')){
36
+ $this->setFlag('', self::FLAG_NO_DISPATCH, true);
37
+ }
38
+
39
+ return parent::preDispatch();
40
+ }
41
+
42
+ /**
43
+ * get current Store ID
44
+ *
45
+ * @return int
46
+ */
47
+ protected function _getStoreId()
48
+ {
49
+ return Mage::app()->getStore()->getId();
50
+ }
51
+
52
+ /**
53
+ * Initialize Product Export
54
+ */
55
+ public function productAction()
56
+ {
57
+ $exportModel = Mage::getModel('factfinder/export_product');
58
+ $exportModel->doExport(
59
+ $this->_getStoreId()
60
+ );
61
+ }
62
+
63
+ /**
64
+ * Initialize Price Export
65
+ */
66
+ public function priceAction()
67
+ {
68
+ $exportModel = Mage::getModel('factfinder/export_price');
69
+ $exportModel->doExport(
70
+ $this->_getStoreId()
71
+ );
72
+ }
73
+
74
+ /**
75
+ * Initialize Stock Export
76
+ */
77
+ public function stockAction()
78
+ {
79
+ $exportModel = Mage::getModel('factfinder/export_stock');
80
+ $exportModel->doExport(
81
+ $this->_getStoreId()
82
+ );
83
+ }
84
+ }
app/code/community/Flagbit/FactFinder/etc/adminhtml.xml ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Flagbit_FactFinder
5
+ *
6
+ * @category Mage
7
+ * @package Flagbit_FactFinder
8
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
9
+ */
10
+
11
+ /**
12
+ * Module Config
13
+ *
14
+ * @category Mage
15
+ * @package Flagbit_FactFinder
16
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
17
+ * @author Joerg Weller <weller@flagbit.de>
18
+ * @version $Id: adminhtml.xml 601 2010-12-21 14:07:41Z weller $
19
+ */
20
+ -->
21
+ <config>
22
+ <acl>
23
+ <resources>
24
+ <admin>
25
+ <children>
26
+ <catalog>
27
+ <children>
28
+ <factfinder_cockpit translate="title" module="factfinder">
29
+ <title>FACT-Finder Business User Cockpit</title>
30
+ <sort_order>35</sort_order>
31
+ </factfinder_cockpit>
32
+ </children>
33
+ </catalog>
34
+ </children>
35
+ </admin>
36
+ </resources>
37
+ </acl>
38
+ <menu>
39
+ <catalog>
40
+ <children>
41
+ <factfinder_cockpit translate="title" module="factfinder">
42
+ <title>FACT-Finder Business User Cockpit</title>
43
+ <sort_order>35</sort_order>
44
+ <action>adminhtml/factfinder_cockpit</action>
45
+ </factfinder_cockpit>
46
+ </children>
47
+ </catalog>
48
+ </menu>
49
+ </config>
app/code/community/Flagbit/FactFinder/etc/config.xml ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Flagbit_FactFinder
5
+ *
6
+ * @category Mage
7
+ * @package Flagbit_FactFinder
8
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
9
+ */
10
+
11
+ /**
12
+ * Module Config
13
+ *
14
+ * @category Mage
15
+ * @package Flagbit_FactFinder
16
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
17
+ * @author Joerg Weller <weller@flagbit.de>
18
+ * @version $Id: config.xml 635 2011-02-23 17:16:14Z weller $
19
+ */
20
+ -->
21
+ <config>
22
+ <modules>
23
+ <Flagbit_FactFinder>
24
+ <active>true</active>
25
+ <version>3.0.1</version>
26
+ </Flagbit_FactFinder>
27
+ </modules>
28
+ <global>
29
+ <helpers>
30
+ <factfinder>
31
+ <class>Flagbit_FactFinder_Helper</class>
32
+ </factfinder>
33
+ </helpers>
34
+ <blocks>
35
+ <factfinder>
36
+ <class>Flagbit_FactFinder_Block</class>
37
+ </factfinder>
38
+ <catalogsearch>
39
+ <rewrite>
40
+ <layer>Flagbit_FactFinder_Block_Layer</layer>
41
+ </rewrite>
42
+ </catalogsearch>
43
+ <enterprise_search>
44
+ <rewrite>
45
+ <catalogsearch_layer>Flagbit_FactFinder_Block_Layer</catalogsearch_layer>
46
+ </rewrite>
47
+ </enterprise_search>
48
+ <xmlconnect>
49
+ <rewrite>
50
+ <catalog_search>Flagbit_FactFinder_Block_XmlConnect_Catalog_Search</catalog_search>
51
+ <catalog_search_suggest>Flagbit_FactFinder_Block_XmlConnect_Catalog_Search_Suggest</catalog_search_suggest>
52
+ <catalog_product_list>Flagbit_FactFinder_Block_XmlConnect_Catalog_Product_List</catalog_product_list>
53
+ </rewrite>
54
+ </xmlconnect>
55
+ </blocks>
56
+ <models>
57
+ <factfinder>
58
+ <class>Flagbit_FactFinder_Model</class>
59
+ <resourceModel>factfinder_mysql4</resourceModel>
60
+ </factfinder>
61
+ <factfinder_mysql4>
62
+ <class>Flagbit_FactFinder_Model_Mysql4</class>
63
+ </factfinder_mysql4>
64
+ <catalogsearch>
65
+ <rewrite>
66
+ <layer>Flagbit_FactFinder_Model_Layer</layer>
67
+ <layer_filter_attribute>Flagbit_FactFinder_Model_Layer_Filter_Attribute</layer_filter_attribute>
68
+ </rewrite>
69
+ </catalogsearch>
70
+ </models>
71
+ </global>
72
+ <frontend>
73
+ <layout>
74
+ <updates>
75
+ <factfinder>
76
+ <file>factfinder.xml</file>
77
+ </factfinder>
78
+ </updates>
79
+ </layout>
80
+ <routers>
81
+ <factfinder>
82
+ <use>standard</use>
83
+ <args>
84
+ <module>Flagbit_FactFinder</module>
85
+ <frontName>factfinder</frontName>
86
+ </args>
87
+ </factfinder>
88
+ </routers>
89
+ </frontend>
90
+ <adminhtml>
91
+ <acl>
92
+ <resources>
93
+ <admin>
94
+ <children>
95
+ <system>
96
+ <children>
97
+ <config>
98
+ <children>
99
+ <factfinder>
100
+ <title>FACT-Finder</title>
101
+ </factfinder>
102
+ </children>
103
+ </config>
104
+ </children>
105
+ </system>
106
+ </children>
107
+ </admin>
108
+ </resources>
109
+ </acl>
110
+ <translate>
111
+ <modules>
112
+ <Flagbit_FactFinder>
113
+ <files>
114
+ <default>Flagbit_FactFinder.csv</default>
115
+ </files>
116
+ </Flagbit_FactFinder>
117
+ </modules>
118
+ </translate>
119
+ <layout>
120
+ <updates>
121
+ <factfinder>
122
+ <file>factfinder.xml</file>
123
+ </factfinder>
124
+ </updates>
125
+ </layout>
126
+ </adminhtml>
127
+ <admin>
128
+ <routers>
129
+ <adminhtml>
130
+ <args>
131
+ <modules>
132
+ <factfinder before="Mage_Adminhtml">Flagbit_FactFinder_Adminhtml</factfinder>
133
+ </modules>
134
+ </args>
135
+ </adminhtml>
136
+ </routers>
137
+ </admin>
138
+ <default>
139
+ <catalog>
140
+ <search>
141
+ <engine>factfinder/search_engine</engine>
142
+ </search>
143
+ </catalog>
144
+ <factfinder>
145
+ <version>2.3.9</version>
146
+ <revision>$Rev: 25896 $</revision>
147
+ <debug>true</debug>
148
+
149
+ <!-- search settings: WARNING: dont change settings here, please use the Magento backoffice ...
150
+ if you still have to change something here, dont forget to clear the configuration cache -->
151
+ <search>
152
+ <address>magento.fact-finder.de</address>
153
+ <port>8080</port>
154
+ <protokoll>http</protokoll> <!-- possible values: http, https -->
155
+
156
+ <auth_user>client</auth_user>
157
+ <auth_password>magento</auth_password>
158
+ <auth_type>advanced</auth_type> <!-- possible values: http (for FF <= 6.4); simple | advanced (for FF >= 6.5)-->
159
+ <auth_advancedPrefix>FACT-FINDER</auth_advancedPrefix>
160
+ <auth_advancedPostfix>FACT-FINDER</auth_advancedPostfix>
161
+
162
+ <context>MagentoSearch65</context>
163
+ <channel></channel>
164
+ <language></language>
165
+ </search>
166
+ <config>
167
+ <identifier>entity_id</identifier>
168
+ </config>
169
+
170
+ <!-- parameter settings -->
171
+ <params>
172
+ <!-- parameter settings for the server -->
173
+ <server>
174
+ <mapping from="q" to="query" />
175
+ <mapping from="p" to="page" />
176
+ </server>
177
+
178
+ <!-- parameter settings for the client -->
179
+ <client>
180
+ <ignore name="xml" />
181
+ <ignore name="format" />
182
+ <ignore name="x" />
183
+ <ignore name="y" />
184
+ <ignore name="channel" />
185
+ <ignore name="productsPerPage" />
186
+ <mapping from="query" to="q" />
187
+ <mapping from="page" to="p" />
188
+ </client>
189
+ </params>
190
+
191
+ <!-- encoding settings -->
192
+ <encoding>
193
+ <pageContent>UTF-8</pageContent>
194
+ <serverURI>UTF-8</serverURI>
195
+ <pageURI>UTF-8</pageURI>
196
+ </encoding>
197
+ </factfinder>
198
+ </default>
199
+ </config>
app/code/community/Flagbit/FactFinder/etc/system.xml ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Flagbit_FactFinder
5
+ *
6
+ * @category Mage
7
+ * @package Flagbit_FactFinder
8
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
9
+ */
10
+
11
+ /**
12
+ * System Config
13
+ *
14
+ * @category Mage
15
+ * @package Flagbit_FactFinder
16
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
17
+ * @author Joerg Weller <weller@flagbit.de>
18
+ * @version $Id: system.xml 629 2011-02-18 14:55:16Z weller $
19
+ */
20
+ -->
21
+ <config>
22
+ <sections>
23
+ <factfinder translate="label" module="factfinder">
24
+ <label>FACT-Finder</label>
25
+ <tab>catalog</tab>
26
+ <sort_order>420</sort_order>
27
+ <frontend_type>text</frontend_type>
28
+ <show_in_default>1</show_in_default>
29
+ <show_in_website>1</show_in_website>
30
+ <show_in_store>1</show_in_store>
31
+ <groups>
32
+ <!--
33
+ <status>
34
+ <label>FACT-Finder Status</label>
35
+ <frontend_type>text</frontend_type>
36
+ <frontend_model>paypal/adminhtml_system_config_fieldset_global</frontend_model>
37
+ <sort_order>10</sort_order>
38
+ <show_in_default>1</show_in_default>
39
+ <show_in_website>1</show_in_website>
40
+ <show_in_store>1</show_in_store>
41
+ <fields>
42
+ <enabled translate="label comment">
43
+ <label>Use FACT-Finder Search</label>
44
+ <comment>Test FACT-Finder for 30 days at no charge, either using your own product data in our demo system</comment>
45
+ <demo_url><![CDATA[https://merchant.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=merchant/demo_express_checkout]]></demo_url>
46
+ <more_url><![CDATA[http://www.fact-finder.com/Contact.html]]></more_url>
47
+ <config_path>factfinder/search/enabled</config_path>
48
+ <frontend_type>checkbox</frontend_type>
49
+ <sort_order>10</sort_order>
50
+ <show_in_default>1</show_in_default>
51
+ <show_in_website>1</show_in_website>
52
+ </enabled>
53
+ </fields>
54
+ </status>
55
+ -->
56
+ <search translate="label">
57
+ <label>FACT-Finder Accessdata</label>
58
+ <frontend_type>text</frontend_type>
59
+ <sort_order>10</sort_order>
60
+ <show_in_default>1</show_in_default>
61
+ <show_in_website>1</show_in_website>
62
+ <show_in_store>1</show_in_store>
63
+ <fields>
64
+ <enabled translate="label">
65
+ <label>Enabled</label>
66
+ <frontend_type>select</frontend_type>
67
+ <source_model>adminhtml/system_config_source_yesno</source_model>
68
+ <backend_model>factfinder/system_config_backend_enabled</backend_model>
69
+ <show_in_default>1</show_in_default>
70
+ <show_in_website>1</show_in_website>
71
+ <show_in_store>1</show_in_store>
72
+ </enabled>
73
+ <address translate="label">
74
+ <label>Server URL</label>
75
+ <frontend_type>text</frontend_type>
76
+ <sort_order>20</sort_order>
77
+ <show_in_default>1</show_in_default>
78
+ <show_in_website>1</show_in_website>
79
+ <show_in_store>1</show_in_store>
80
+ </address>
81
+ <port translate="label">
82
+ <label>Server Port</label>
83
+ <frontend_type>text</frontend_type>
84
+ <sort_order>30</sort_order>
85
+ <show_in_default>1</show_in_default>
86
+ <show_in_website>1</show_in_website>
87
+ <show_in_store>1</show_in_store>
88
+ </port>
89
+ <context translate="label">
90
+ <label>Context Name</label>
91
+ <comment>Name of the FACT-Finder Application</comment>
92
+ <frontend_type>text</frontend_type>
93
+ <sort_order>40</sort_order>
94
+ <show_in_default>1</show_in_default>
95
+ <show_in_website>1</show_in_website>
96
+ <show_in_store>1</show_in_store>
97
+ </context>
98
+ <auth_user translate="label">
99
+ <label>User Name</label>
100
+ <comment>Username for Authentication</comment>
101
+ <frontend_type>text</frontend_type>
102
+ <sort_order>50</sort_order>
103
+ <show_in_default>1</show_in_default>
104
+ <show_in_website>1</show_in_website>
105
+ <show_in_store>1</show_in_store>
106
+ </auth_user>
107
+ <auth_password translate="label">
108
+ <label>Password</label>
109
+ <frontend_type>password</frontend_type>
110
+ <sort_order>60</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
+ </auth_password>
115
+ <channel translate="label">
116
+ <label>Channel</label>
117
+ <comment>FACT-Finder can provide multiple search indices, each represented by a "channel".
118
+ Leave empty to use default channel.</comment>
119
+ <frontend_type>text</frontend_type>
120
+ <sort_order>70</sort_order>
121
+ <show_in_default>1</show_in_default>
122
+ <show_in_website>1</show_in_website>
123
+ <show_in_store>1</show_in_store>
124
+ </channel>
125
+ <language translate="label">
126
+ <label>Language</label>
127
+ <comment>Some text snippets come directly from FACT-Finder. Set the language code here.
128
+ Leave empty to use the language of the users browser.</comment>
129
+ <frontend_type>text</frontend_type>
130
+ <sort_order>80</sort_order>
131
+ <show_in_default>1</show_in_default>
132
+ <show_in_website>1</show_in_website>
133
+ <show_in_store>1</show_in_store>
134
+ </language>
135
+ <auth_type translate="label">
136
+ <label>Authentication Type</label>
137
+ <frontend_type>select</frontend_type>
138
+ <source_model>factfinder/system_config_source_authtype</source_model>
139
+ <sort_order>90</sort_order>
140
+ <show_in_default>1</show_in_default>
141
+ <show_in_website>1</show_in_website>
142
+ <show_in_store>1</show_in_store>
143
+ </auth_type>
144
+ <auth_advancedPrefix>
145
+ <label>Advanced Authentication Prefix</label>
146
+ <frontend_type>text</frontend_type>
147
+ <comment>The advanced authentication post- and prefix are only used if the authentication
148
+ type is "advanced".</comment>
149
+ <sort_order>100</sort_order>
150
+ <show_in_default>1</show_in_default>
151
+ <show_in_website>1</show_in_website>
152
+ <show_in_store>1</show_in_store>
153
+ </auth_advancedPrefix>
154
+ <auth_advancedPostfix>
155
+ <label>Advanced Authentication Postfix</label>
156
+ <frontend_type>text</frontend_type>
157
+ <sort_order>110</sort_order>
158
+ <show_in_default>1</show_in_default>
159
+ <show_in_website>1</show_in_website>
160
+ <show_in_store>1</show_in_store>
161
+ </auth_advancedPostfix>
162
+ </fields>
163
+ </search>
164
+ <config translate="label">
165
+ <label>FACT-Finder Configdata</label>
166
+ <frontend_type>text</frontend_type>
167
+ <sort_order>20</sort_order>
168
+ <show_in_default>1</show_in_default>
169
+ <show_in_website>1</show_in_website>
170
+ <show_in_store>1</show_in_store>
171
+ <fields>
172
+ <identifier translate="label">
173
+ <label>Product Identifier</label>
174
+ <frontend_type>select</frontend_type>
175
+ <source_model>factfinder/system_config_source_identifier</source_model>
176
+ <show_in_default>1</show_in_default>
177
+ <show_in_website>1</show_in_website>
178
+ <show_in_store>1</show_in_store>
179
+ </identifier>
180
+ <debug translate="label">
181
+ <label>Debug Log</label>
182
+ <frontend_type>select</frontend_type>
183
+ <source_model>adminhtml/system_config_source_yesno</source_model>
184
+ <backend_model>factfinder/system_config_backend_enabled</backend_model>
185
+ <show_in_default>1</show_in_default>
186
+ <show_in_website>1</show_in_website>
187
+ <show_in_store>1</show_in_store>
188
+ </debug>
189
+ </fields>
190
+ </config>
191
+ </groups>
192
+ </factfinder>
193
+ </sections>
194
+ </config>
app/design/adminhtml/default/default/layout/factfinder.xml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Flagbit_FactFinder
5
+ *
6
+ * @category Mage
7
+ * @package Flagbit_FactFinder
8
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
9
+ */
10
+
11
+ /**
12
+ * Module Layout Config
13
+ *
14
+ * @category Mage
15
+ * @package Flagbit_FactFinder
16
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
17
+ * @author Joerg Weller <weller@flagbit.de>
18
+ * @version $Id: factfinder.xml 601 2010-12-21 14:07:41Z weller $
19
+ */
20
+ -->
21
+
22
+ <layout>
23
+ <adminhtml_factfinder_cockpit_index>
24
+ <reference name="content">
25
+ <block type="factfinder/adminhtml_cockpit" name="factfinder_cockpit" template="factfinder/cockpit.phtml"/>
26
+ </reference>
27
+ </adminhtml_factfinder_cockpit_index>
28
+ </layout>
app/design/adminhtml/default/default/template/factfinder/cockpit.phtml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Template
12
+ *
13
+ * Business User Cockpit Template
14
+ *
15
+ * @category Mage
16
+ * @package Flagbit_FactFinder
17
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
18
+ * @author Joerg Weller <weller@flagbit.de>
19
+ * @version $Id: cockpit.phtml 601 2010-12-21 14:07:41Z weller $
20
+ */
21
+ ?>
22
+ <iframe src="<?php echo $this->getAuthenticationUrl();?>" id="factfinder_cockpit_frame" style="width:100%; height:600px;" name="factfinder_cockpit_frame" scrolling="auto"></iframe>
app/design/frontend/base/default/layout/factfinder.xml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Flagbit_FactFinder
5
+ *
6
+ * @category Mage
7
+ * @package Flagbit_FactFinder
8
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
9
+ */
10
+
11
+ /**
12
+ * Module Layout Config
13
+ *
14
+ * @category Mage
15
+ * @package Flagbit_FactFinder
16
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
17
+ * @author Joerg Weller <weller@flagbit.de>
18
+ * @version $Id: factfinder.xml 617 2011-02-08 10:25:54Z weller $
19
+ */
20
+ -->
21
+ <layout version="0.1.0">
22
+ <default>
23
+ <reference name="head">
24
+ <action method="addJs"><script>factfinder/jXHR.js</script></action>
25
+ <action method="addJs"><script>factfinder/suggest.js</script></action>
26
+ </reference>
27
+ <reference name="top.search">
28
+ <action method="setTemplate"><template>factfinder/form.mini.phtml</template></action>
29
+ </reference>
30
+ </default>
31
+
32
+ <catalogsearch_result_index>
33
+ <reference name="content">
34
+ <block type="core/template" name="factfinder.logo" template="factfinder/logo.phtml"/>
35
+ </reference>
36
+ </catalogsearch_result_index>
37
+
38
+ </layout>
app/design/frontend/base/default/template/factfinder/filter/slider.phtml ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Slider HTML Template
12
+ *
13
+ * @category Mage
14
+ * @package Flagbit_FactFinder
15
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
16
+ * @author Joerg Weller <weller@flagbit.de>
17
+ * @version $Id: slider.phtml 614 2011-02-01 16:08:47Z weller $
18
+ */
19
+ ?>
20
+ <ol>
21
+ <?php foreach ($this->getItems() as $_item): ?>
22
+ <li>
23
+ <div id="<?php echo base64_encode($this->getValue());?>" style="width: 170px;padding:10px 0px;"></div>
24
+ <script type="text/javascript" language="javascript">
25
+ //<![CDATA[
26
+
27
+ Event.observe(document, 'ffslider:init', function(event){
28
+ oneTouchSlider.addSlider({
29
+ hostElementId:'<?php echo base64_encode($this->getValue());?>',
30
+ leftBorder: <?php echo $this->getAbsoluteMin();?>,
31
+ rightBorder: <?php echo $this->getAbsoluteMax();?>,
32
+ currentLeft: <?php echo $this->getSelectedMin();?>,
33
+ currentRight: <?php echo $this->getSelectedMax();?>,
34
+ unit:"<?php echo $this->getUnit();?>",
35
+ callback:function(left, right){
36
+ var url = unescape('<?php echo $_item->getUrl() ?>');
37
+ window.location.href= url.replace('[VALUE]',left + '+-+' + right);
38
+ }
39
+ });
40
+ }
41
+ );
42
+ //]]>
43
+ </script>
44
+ </li>
45
+ <?php endforeach ?>
46
+ </ol>
app/design/frontend/base/default/template/factfinder/form.mini.phtml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Template to replace Javascript Suguest
12
+ *
13
+ * @category Mage
14
+ * @package Flagbit_FactFinder
15
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
16
+ * @author Joerg Weller <weller@flagbit.de>
17
+ * @version $Id: form.mini.phtml 619 2011-02-10 08:03:17Z weller $
18
+ */
19
+ ?>
20
+ <form id="search_mini_form" action="<?php echo $this->helper('catalogsearch')->getResultUrl() ?>" method="get">
21
+ <div class="form-search">
22
+ <label for="search"><?php echo $this->__('Search:') ?></label>
23
+ <input id="search" type="text" name="<?php echo $this->helper('catalogsearch')->getQueryParamName() ?>" value="<?php echo $this->helper('catalogsearch')->getEscapedQueryText() ?>" class="input-text" />
24
+ <button type="submit" title="<?php echo $this->__('Search') ?>" class="button"><span><span><?php echo $this->__('Search') ?></span></span></button>
25
+ <div id="search_autocomplete" class="search-autocomplete"></div>
26
+ <script type="text/javascript">
27
+ //<![CDATA[
28
+ <?php if(Mage::helper('factfinder/search')->getIsEnabled(false)):?>
29
+ var searchForm = new FactFinderSuggest('search_mini_form', 'search', '<?php echo $this->__('Search entire store here...') ?>');
30
+ searchForm.initAutocomplete('<?php echo $this->helper('factfinder/search')->getSuggestUrl() ?>', 'search_autocomplete');
31
+ <?php else:?>
32
+ var searchForm = new Varien.searchForm('search_mini_form', 'search', '<?php echo $this->__('Search entire store here...') ?>');
33
+ searchForm.initAutocomplete('<?php echo $this->helper('catalogsearch')->getSuggestUrl() ?>', 'search_autocomplete');
34
+ <?php endif;?>
35
+ //]]>
36
+ </script>
37
+ </div>
38
+ </form>
app/design/frontend/base/default/template/factfinder/logo.phtml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Flagbit_FactFinder
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ */
9
+
10
+ /**
11
+ * Add FACT-Finder Logo to Search Result
12
+ *
13
+ * @category Mage
14
+ * @package Flagbit_FactFinder
15
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
16
+ * @author Joerg Weller <weller@flagbit.de>
17
+ * @version $Id: logo.phtml 615 2011-02-02 15:43:11Z rudolf_batt $
18
+ */
19
+ ?>
20
+ <?php if(Mage::helper('factfinder/search')->getIsEnabled()):?>
21
+ <div style="text-align:center;margin: 10px auto;"><a href="http://www.fact-finder.de"><img src="http://www.fact-finder.de/files/fact_finder_conversion.jpg" border="0" alt="on-site search & navigation – conversion engine FACT-Finder" target="_blank" width="116" height="35"></a></div>
22
+ <?php endif;?>
app/etc/modules/Flagbit_FactFinder.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Flagbit_FactFinder>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </Flagbit_FactFinder>
8
+ </modules>
9
+ </config>
js/factfinder/jXHR.js ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // jXHR.js (JSON-P XHR)
2
+ // v0.1 (c) Kyle Simpson
3
+ // MIT License
4
+
5
+ (function(global){
6
+ var SETTIMEOUT = global.setTimeout, // for better compression
7
+ doc = global.document,
8
+ callback_counter = 0;
9
+
10
+ global.jXHR = function() {
11
+ var script_url,
12
+ script_loaded,
13
+ jsonp_callback,
14
+ scriptElem,
15
+ publicAPI = null;
16
+
17
+ function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } }
18
+
19
+ function reset() {
20
+ script_loaded = false;
21
+ script_url = "";
22
+ removeScript();
23
+ scriptElem = null;
24
+ fireReadyStateChange(0);
25
+ }
26
+
27
+ function ThrowError(msg) {
28
+ try { publicAPI.onerror.call(publicAPI,msg,script_url); } catch (err) { throw new Error(msg); }
29
+ }
30
+
31
+ function handleScriptLoad() {
32
+ if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; }
33
+ this.onload = this.onreadystatechange = null; // prevent memory leak
34
+ script_loaded = true;
35
+ if (publicAPI.readyState !== 4) ThrowError("Script failed to load ["+script_url+"].");
36
+ removeScript();
37
+ }
38
+
39
+ function fireReadyStateChange(rs,args) {
40
+ args = args || [];
41
+ publicAPI.readyState = rs;
42
+ if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args);
43
+ }
44
+
45
+ publicAPI = {
46
+ onerror:null,
47
+ onreadystatechange:null,
48
+ readyState:0,
49
+ open:function(method,url){
50
+ reset();
51
+ internal_callback = "cb"+(callback_counter++);
52
+ (function(icb){
53
+ global.jXHR[icb] = function() {
54
+ try { fireReadyStateChange.call(publicAPI,4,arguments); }
55
+ catch(err) {
56
+ publicAPI.readyState = -1;
57
+ ThrowError("Script failed to run ["+script_url+"].");
58
+ }
59
+ global.jXHR[icb] = null;
60
+ };
61
+ })(internal_callback);
62
+ script_url = url.replace(/=\?/,"=jXHR."+internal_callback);
63
+ fireReadyStateChange(1);
64
+ },
65
+ send:function(){
66
+ SETTIMEOUT(function(){
67
+ scriptElem = doc.createElement("script");
68
+ scriptElem.setAttribute("type","text/javascript");
69
+ scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);};
70
+ scriptElem.setAttribute("src",script_url);
71
+ doc.getElementsByTagName("head")[0].appendChild(scriptElem);
72
+ },0);
73
+ fireReadyStateChange(2);
74
+ },
75
+ setRequestHeader:function(){}, // noop
76
+ getResponseHeader:function(){return "";}, // basically noop
77
+ getAllResponseHeaders:function(){return [];} // ditto
78
+ };
79
+
80
+ reset();
81
+
82
+ return publicAPI;
83
+ };
84
+ })(window);
js/factfinder/suggest.js ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var FactFinderAjax = {
2
+ getTransport: function() {
3
+ return new jXHR();
4
+ },
5
+
6
+ activeRequestCount: 0
7
+ };
8
+
9
+ FactFinderAjax.Response = Class.create(Ajax.Response, {
10
+
11
+ initialize: function(request){
12
+ this.request = request;
13
+ var transport = this.transport = request.transport,
14
+ readyState = this.readyState = transport.readyState;
15
+
16
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
17
+ this.status = this.getStatus();
18
+ this.statusText = this.getStatusText();
19
+ this.responseText = String.interpret(transport.responseText);
20
+ this.headerJSON = this._getHeaderJSON();
21
+ }
22
+
23
+ if(readyState == 4) {
24
+ var xml = transport.responseXML;
25
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
26
+ this.responseJSON = this._getResponseJSON();
27
+ }
28
+ }
29
+ });
30
+
31
+ FactFinderAjax.Request = Class.create(Ajax.Request, {
32
+ _complete: false,
33
+
34
+ initialize: function(url, options) {
35
+ this.options = {
36
+ method: 'get',
37
+ asynchronous: true,
38
+ contentType: 'application/x-www-form-urlencoded',
39
+ encoding: 'UTF-8',
40
+ parameters: '',
41
+ evalJSON: true,
42
+ evalJS: true
43
+ };
44
+ Object.extend(this.options, options || { });
45
+
46
+ this.options.method = this.options.method.toLowerCase();
47
+
48
+ if (Object.isString(this.options.parameters))
49
+ this.options.parameters = this.options.parameters.toQueryParams();
50
+ else if (Object.isHash(this.options.parameters))
51
+ this.options.parameters = this.options.parameters.toObject();
52
+
53
+ this.transport = FactFinderAjax.getTransport();
54
+ this.request(url);
55
+ },
56
+
57
+ request: function(url) {
58
+ this.url = url;
59
+ this.method = this.options.method;
60
+ var params = Object.clone(this.options.parameters);
61
+
62
+ if (!['get', 'post'].include(this.method)) {
63
+ // simulate other verbs over post
64
+ params['_method'] = this.method;
65
+ this.method = 'post';
66
+ }
67
+
68
+ this.parameters = params;
69
+
70
+ if (params = Object.toQueryString(params)) {
71
+ // when GET, append parameters to URL
72
+ if (this.method == 'get')
73
+ this.url += (this.url.include('?') ? '&' : '?') + params + '&jquery_callback=?';
74
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
75
+ params += '&_=';
76
+ }
77
+
78
+ try {
79
+
80
+ var response = new FactFinderAjax.Response(this);
81
+ if (this.options.onCreate) this.options.onCreate(response);
82
+ Ajax.Responders.dispatch('onCreate', this, response);
83
+
84
+ this.transport.open(this.method.toUpperCase(), this.url,
85
+ this.options.asynchronous);
86
+
87
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
88
+
89
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
90
+ this.setRequestHeaders();
91
+
92
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
93
+ this.transport.send(this.body);
94
+
95
+ /* Force Firefox to handle ready state 4 for synchronous requests */
96
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
97
+ this.onStateChange();
98
+
99
+ }
100
+ catch (e) {
101
+ this.dispatchException(e);
102
+ }
103
+ },
104
+
105
+ isSameOrigin: function() {
106
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
107
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
108
+ protocol: location.protocol,
109
+ domain: document.domain,
110
+ port: location.port ? ':' + location.port : ''
111
+ }));
112
+ }
113
+ });
114
+
115
+ var FactFinderAutocompleter = Class.create(Ajax.Autocompleter, {
116
+ caller: null,
117
+ rq: null,
118
+ getUpdatedChoices: function() {
119
+ this.startIndicator();
120
+
121
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
122
+ encodeURIComponent(this.getToken());
123
+
124
+ this.options.parameters = this.options.callback ?
125
+ this.options.callback(this.element, entry) : entry;
126
+
127
+ if(this.options.defaultParams)
128
+ this.options.parameters += '&' + this.options.defaultParams;
129
+
130
+ this.rq = new FactFinderAjax.Request(this.url, this.options);
131
+ this.rq.transport.onreadystatechange = this.caller._loadData.bind(this.caller);
132
+ }
133
+ })
134
+
135
+ var FactFinderSuggest = Class.create(Varien.searchForm, {
136
+ request: null,
137
+
138
+ initAutocomplete : function(url, destinationElement){
139
+ this.request = new FactFinderAutocompleter(
140
+ this.field,
141
+ destinationElement,
142
+ url,
143
+ {
144
+ parameters: 'format=JSONP',
145
+ paramName: 'query',
146
+ method: 'get',
147
+ minChars: 2,
148
+ updateElement: this._selectAutocompleteItem.bind(this),
149
+ onShow : function(element, update) {
150
+ if(!update.style.position || update.style.position=='absolute') {
151
+ update.style.position = 'absolute';
152
+ Position.clone(element, update, {
153
+ setHeight: false,
154
+ offsetTop: element.offsetHeight
155
+ });
156
+ }
157
+ Effect.Appear(update,{duration:0});
158
+ }
159
+ }
160
+ );
161
+ this.request.caller = this;
162
+ },
163
+
164
+ _loadData: function(data) {
165
+ var content = '<ul>';
166
+ content += '<li style="display: none" class="selected"></li>';
167
+ data.each(function(item) {
168
+ content += '<li title="'+item.query+'"><span class="amount">' + item.hitCount + '</span>' + item.query + '</li>';
169
+ });
170
+ content += '</ul>';
171
+
172
+ this.request.updateChoices(content);
173
+ },
174
+
175
+ _selectAutocompleteItem : function(element){
176
+ if(element.title){
177
+ this.field.value = element.title;
178
+ }
179
+ this.form.submit();
180
+ }
181
+ });
lib/FACTFinder/Abstract/Adapter.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * contains the FACTFinder_Abstract_Adapter class only
4
+ */
5
+
6
+ /**
7
+ * handles the issue to create useable object from the data delivered by the dataprovider.
8
+ * this class can also be seen as a factory, but it is rather an adapter, because it converst the responded objects into
9
+ * the useable, unique objects
10
+ *
11
+ * @author Rudolf Batt <rb@omikron.net>
12
+ * @version $Id: Adapter.php 614 2011-02-01 16:08:47Z weller $
13
+ * @package FACTFinder\Abstract
14
+ */
15
+ abstract class FACTFinder_Abstract_Adapter
16
+ {
17
+ private $paramsParser;
18
+ private $dataProvider;
19
+ private $encodingHandler;
20
+
21
+ final public function __construct(FACTFinder_Abstract_DataProvider $dataProvider, FACTFinder_ParametersParser $paramsParser,
22
+ FACTFinder_EncodingHandler $encodingHandler)
23
+ {
24
+ $this->setDataProvider($dataProvider);
25
+ $this->setParamsParser($paramsParser);
26
+ $this->setEncodingHandler($encodingHandler);
27
+ $this->init();
28
+ }
29
+
30
+ /**
31
+ * can be overwritten to do initialising issues, that would normaly done by the constructor. it will be called at
32
+ * the end of the constructor
33
+ *
34
+ * @return void
35
+ */
36
+ protected function init(){}
37
+
38
+ /**
39
+ * returns the data from the dataprovider. decorates the dataprovider::getData method so a inheriting class does not
40
+ * have to use the dataprovider
41
+ */
42
+ protected function getData()
43
+ {
44
+ return $this->getDataProvider()->getData();
45
+ }
46
+
47
+ /**
48
+ * set data provider
49
+ *
50
+ * @param FACTFinder_Abstract_DataProvider
51
+ * @return void
52
+ **/
53
+ public function setDataProvider(FACTFinder_Abstract_DataProvider $dataProvider)
54
+ {
55
+ $this->dataProvider = $dataProvider;
56
+ }
57
+
58
+ /**
59
+ * get data provider
60
+ *
61
+ * @return FACTFinder_Abstract_DataProvider
62
+ **/
63
+ protected function getDataProvider()
64
+ {
65
+ return $this->dataProvider;
66
+ }
67
+
68
+ /**
69
+ * set parameter parser
70
+ *
71
+ * @param FACTFinder_ParametersParser
72
+ **/
73
+ public function setParamsParser(FACTFinder_ParametersParser $paramsParser)
74
+ {
75
+ $this->paramsParser = $paramsParser;
76
+ }
77
+
78
+ /**
79
+ * returns the used factfinder params object.
80
+ *
81
+ * @return FACTFinder_ParametersParser
82
+ **/
83
+ protected function getParamsParser()
84
+ {
85
+ return $this->paramsParser;
86
+ }
87
+
88
+ /**
89
+ * set encoding handler
90
+ *
91
+ * @param FACTFinder_EncodingHandler
92
+ **/
93
+ public function setEncodingHandler(FACTFinder_EncodingHandler $encodingHandler)
94
+ {
95
+ $this->encodingHandler = $encodingHandler;
96
+ }
97
+
98
+ /**
99
+ * returns the used encoding handler
100
+ *
101
+ * @return FACTFinder_EncodingHandler
102
+ **/
103
+ protected function getEncodingHandler()
104
+ {
105
+ return $this->encodingHandler;
106
+ }
107
+ }
lib/FACTFinder/Abstract/Configuration.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * interface to access the needed configuration values
5
+ *
6
+ * @category FACTFinderLib
7
+ * @package FACTFinder\Abstract
8
+ */
9
+ interface FACTFinder_Abstract_Configuration
10
+ {
11
+ /**
12
+ * @return string
13
+ */
14
+ function getVersion();
15
+
16
+ /**
17
+ * @return boolean
18
+ */
19
+ function isDebugEnabled();
20
+
21
+ /**
22
+ * @param string name
23
+ * @return string value
24
+ */
25
+ function getCustomValue($name);
26
+
27
+ /**
28
+ * @return string
29
+ */
30
+ function getRequestProtokoll();
31
+
32
+ /**
33
+ * @return string
34
+ */
35
+ function getServerAddress();
36
+
37
+ /**
38
+ * @return int
39
+ */
40
+ function getServerPort();
41
+
42
+ /**
43
+ * @return string
44
+ */
45
+ function getContext();
46
+
47
+ /**
48
+ * @return string
49
+ */
50
+ function getChannel();
51
+
52
+ /**
53
+ * @return string
54
+ */
55
+ function getLanguage();
56
+
57
+ /**
58
+ * @return string
59
+ */
60
+ function getAuthUser();
61
+
62
+ /**
63
+ * @return string
64
+ */
65
+ function getAuthPasswort();
66
+
67
+ /**
68
+ * @return boolean
69
+ */
70
+ function isHttpAuthenticationType();
71
+
72
+ /**
73
+ * @return boolean
74
+ */
75
+ function isSimpleAuthenticationType();
76
+
77
+ /**
78
+ * @return boolean
79
+ */
80
+ function isAdvancedAuthenticationType();
81
+
82
+ /**
83
+ * @return string
84
+ */
85
+ function getAdvancedAuthPrefix();
86
+
87
+ /**
88
+ * @return string
89
+ */
90
+ function getAdvancedAuthPostfix();
91
+
92
+ /**
93
+ * get mapping rules to map params for the page
94
+ *
95
+ * @return array
96
+ */
97
+ function getPageMappings();
98
+
99
+ /**
100
+ * get mapping rules to map params for the server
101
+ *
102
+ * @return array
103
+ */
104
+ function getServerMappings();
105
+
106
+ /**
107
+ * returns an array of parameter names as array keys with the boolean value true. this are the ignored page
108
+ * parameters from the configuration
109
+ *
110
+ * @return array with string as key and boolean true as value for each of them
111
+ */
112
+ function getIgnoredPageParams();
113
+
114
+ /**
115
+ * returns an array of parameter names as array keys with the boolean value true. this are the ignored server
116
+ * parameters from the configuration
117
+ *
118
+ * @return array with string as key and boolean true as value for each of them
119
+ */
120
+ function getIgnoredServerParams();
121
+
122
+ /**
123
+ * returns an array of the required parameters for the page. The array-keys are the parameter names and the array
124
+ * values are the default values of each parameter
125
+ *
126
+ * @return array string to string map (param-name as array-key; default value as array-value)
127
+ */
128
+ function getRequiredPageParams();
129
+
130
+ /**
131
+ * returns an array of the required parameters for the server. The array-keys are the parameter names and the array
132
+ * values are the default values of each parameter
133
+ *
134
+ * @return array string to string map (param-name as array-key; default value as array-value)
135
+ */
136
+ function getRequiredServerParams();
137
+
138
+ /**
139
+ * get encoding of the page content
140
+ *
141
+ * @return string
142
+ */
143
+ function getPageContentEncoding();
144
+
145
+ /**
146
+ * get encoding of the page url
147
+ *
148
+ * @return string
149
+ */
150
+ function getPageUrlEncoding();
151
+
152
+ /**
153
+ * get encoding of the server url
154
+ *
155
+ * @return string
156
+ */
157
+ function getServerUrlEncoding();
158
+ }
lib/FACTFinder/Abstract/DataProvider.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * abstract data provider
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: DataProvider.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Abstract
9
+ */
10
+ abstract class FACTFinder_Abstract_DataProvider
11
+ {
12
+ private $params = array();
13
+ private $config = array();
14
+ private $type;
15
+
16
+ public function __construct(array $params = null, FACTFinder_Abstract_Configuration $config = null)
17
+ {
18
+ if ($params != null) $this->setParams($params);
19
+ if ($config != null) $this->setConfig($config);
20
+ }
21
+
22
+ /**
23
+ * set type to identify which data should be loaded. that could be a request path or any source identifier
24
+ *
25
+ * @param mixed target
26
+ */
27
+ public function setType($type)
28
+ {
29
+ $this->type = $type;
30
+ }
31
+
32
+ /**
33
+ * return the data for the current config and params; the return type depends on the implementation
34
+ *
35
+ * @return mixed data
36
+ */
37
+ abstract public function getData();
38
+
39
+ /**
40
+ * sets factfinder params object
41
+ *
42
+ * @param array params
43
+ * @return void
44
+ **/
45
+ public function setParams(array $params)
46
+ {
47
+ $this->params = $params;
48
+ }
49
+
50
+ /**
51
+ * set single param
52
+ *
53
+ * @param string name
54
+ * @param string value
55
+ * @return void
56
+ */
57
+ public function setParam($name, $value)
58
+ {
59
+ $this->params[$name] = $value;
60
+ }
61
+
62
+ /**
63
+ * @param FACTFinder_Abstract_IConfiguration config
64
+ */
65
+ public function setConfig(FACTFinder_Abstract_Configuration $config)
66
+ {
67
+ $this->config = $config;
68
+ }
69
+
70
+ /**
71
+ * @return array
72
+ **/
73
+ protected function getParams()
74
+ {
75
+ return $this->params;
76
+ }
77
+
78
+ /**
79
+ * @return FACTFinder_Abstract_IConfiguration
80
+ **/
81
+ protected function getConfig()
82
+ {
83
+ return $this->config;
84
+ }
85
+ }
lib/FACTFinder/Abstract/ScicAdapter.php ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * abstract adapter for the shopping cart information collector tracking
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: ScicAdapter.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Abstract
9
+ */
10
+ abstract class FACTFinder_Abstract_ScicAdapter extends FACTFinder_Abstract_Adapter
11
+ {
12
+ /**
13
+ * let the data provider save the tracking params
14
+ *
15
+ * @return boolean $success
16
+ */
17
+ abstract protected function applyTracking();
18
+
19
+ /**
20
+ * if all needed parameters are available at the request like described in the documentation, just use this method to
21
+ * fetch the needed parameters and track them
22
+ * insure to set a session id if there is no parameter "sid". if this argument is not set or empty and the parameter
23
+ * "sid" is not available, it will try to use session_id() to fetch one.
24
+ *
25
+ * @param string $sid session id
26
+ * @return boolean $success
27
+ */
28
+ public function doTrackingFromRequest($sid = null)
29
+ {
30
+ $params = $this->getParamsParser()->getServerRequestParams();
31
+ if (!empty($sid)) {
32
+ $params['sid'] = $sid;
33
+ } else if (empty($params['sid'])) {
34
+ $params['sid'] = session_id();
35
+ }
36
+ $this->getDataProvider()->setParams($params);
37
+ return $this->applyTracking();
38
+ }
39
+
40
+ /**
41
+ * track a detail click on a product
42
+ *
43
+ * @param string $id id of product
44
+ * @param string $sid session id (if empty, then try to set using the function session_id() )
45
+ * @param string $query query which led to the product
46
+ * @param int $pos position of product in the search result
47
+ * @param int $origPos original position of product in the search result. this data is delivered by FACT-Finder (optional - is set equals to $position by default)
48
+ * @param int $page page number where the product was clicked (optional - is 1 by default)
49
+ * @param double $simi similiarity of the product (optional - is 100.00 by default)
50
+ * @param string $title title of product (optional - is empty by default)
51
+ * @param int $pageSize size of the page where the product was found (optional - is 12 by default)
52
+ * @param int $origPageSize original size of the page before the user could have changed it (optional - is set equals to $page by default)
53
+ * @return boolean $success
54
+ */
55
+ public function trackClick($id, $sid = null, $query, $pos, $origPos = -1, $page = 1, $simi = 100.0, $title = '',
56
+ $pageSize = 12, $origPageSize = -1)
57
+ {
58
+ if (empty($sid)) $sid = session_id();
59
+ if ($origPos == -1) $origPos = $pos;
60
+ if ($origPageSize == -1) $origPageSize = $pageSize;
61
+
62
+ $this->getDataProvider()->setParams(
63
+ array(
64
+ 'query' => $query,
65
+ 'id' => $id,
66
+ 'pos' => $pos,
67
+ 'origPos' => $origPos,
68
+ 'page' => $page,
69
+ 'simi' => $simi,
70
+ 'sid' => $sid,
71
+ 'title' => $title,
72
+ 'event' => 'click',
73
+ 'pageSize' => $pageSize,
74
+ 'origPageSize' => $origPageSize
75
+ )
76
+ );
77
+ return $this->applyTracking();
78
+ }
79
+
80
+ /**
81
+ * track a product which was added to the cart
82
+ *
83
+ * @param string $id id of product
84
+ * @param string $sid session id (if empty, then try to set using the function session_id() )
85
+ * @param int $count number of items purchased for each product (optional - default 1)
86
+ * @param double $price this is the single unit price (optional)
87
+ * @return boolean $success
88
+ */
89
+ public function trackCart($id, $sid = null, $count = 1, $price = null)
90
+ {
91
+ if (empty($sid)) $sid = session_id();
92
+ $params = array(
93
+ 'id' => $id,
94
+ 'sid' => $sid,
95
+ 'count' => $count,
96
+ 'event' => 'cart'
97
+ );
98
+ if (!empty($price)) $params['price'] = $price;
99
+ $this->getDataProvider()->setParams($params);
100
+ return $this->applyTracking();
101
+ }
102
+
103
+ /**
104
+ * track a product which was purchased
105
+ *
106
+ * @param string $id id of product
107
+ * @param string $sid session id (if empty, then try to set using the function session_id() )
108
+ * @param int $count number of items purchased for each product (optional - default 1)
109
+ * @param double $price this is the single unit price (optional)
110
+ * @return boolean $success
111
+ */
112
+ public function trackCheckout($id, $sid = null, $count = 1, $price = null)
113
+ {
114
+ if (empty($sid)) $sid = session_id();
115
+ $params = array(
116
+ 'id' => $id,
117
+ 'sid' => $sid,
118
+ 'count' => $count,
119
+ 'event' => 'checkout'
120
+ );
121
+ if (!empty($price)) $params['price'] = $price;
122
+ $this->getDataProvider()->setParams($params);
123
+ return $this->applyTracking();
124
+ }
125
+
126
+ /**
127
+ * track a click on a recommended product
128
+ *
129
+ * @param string $id id of product
130
+ * @param string $sid session id (if empty, then try to set using the function session_id() )
131
+ * @param int $mainId ID of the product for which the clicked-upon item was recommended
132
+ * @return boolean $success
133
+ */
134
+ public function trackRecommendationClick($id, $sid = null, $mainId)
135
+ {
136
+ if (empty($sid)) $sid = session_id();
137
+ $params = array(
138
+ 'id' => $id,
139
+ 'sid' => $sid,
140
+ 'mainId' => $mainId,
141
+ 'event' => 'recommendationClick'
142
+ );
143
+ $this->getDataProvider()->setParams($params);
144
+ return $this->applyTracking();
145
+ }
146
+ }
lib/FACTFinder/Abstract/SearchAdapter.php ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * adapter for the factfinder search
4
+ *
5
+ * @author Rudolf Batt <rb@omikron.net>
6
+ * @version $Id: SearchAdapter.php 614 2011-02-01 16:08:47Z weller $
7
+ * @package FACTFinder\Abstract
8
+ */
9
+ abstract class FACTFinder_Abstract_SearchAdapter extends FACTFinder_Abstract_Adapter
10
+ {
11
+ private $searchParams;
12
+ private $result;
13
+ private $asn;
14
+ private $sorting;
15
+ private $paging;
16
+ private $productsPerPageOptions;
17
+ private $breadCrumbTrail;
18
+ private $campaigns;
19
+ private $singleWordSearch;
20
+
21
+ const NO_RESULT = 'noResult';
22
+ const RESULTS_FOUND = 'resultsFound';
23
+ const NOTHING_FOUND = 'nothingFound';
24
+
25
+ /**
26
+ * returns the search status of the article number search, which is one of this class constants:
27
+ * NO_RESULT it was not an article number search
28
+ * NOTHING_FOUND is article number search, but nothing found
29
+ * RESULTS_FOUND found article by article number
30
+ * returns null, if no article number search was done
31
+ *
32
+ * @return string status
33
+ **/
34
+ abstract public function getArticleNumberSearchStatus();
35
+
36
+ /**
37
+ * returns true if the query matches the article number search regex, else false. also returns false, when there
38
+ * was any error
39
+ *
40
+ * @return boolean isArticleNumberSearch
41
+ **/
42
+ abstract public function isArticleNumberSearch();
43
+
44
+ /**
45
+ * returns true when search timed out. even if true, nevertheless result records may exist
46
+ *
47
+ * @return boolean
48
+ **/
49
+ abstract public function isSearchTimedOut();
50
+
51
+ /**
52
+ * returns the search status of the search, which is one of this class constants:
53
+ * NO_RESULT: there seems to be any error. no search done
54
+ * NOTHING_FOUND: search done, but nothing found; maybe campaigns are available
55
+ * RESULTS_FOUND: results found
56
+ * returns null, if no article number search was done
57
+ *
58
+ * @return string status
59
+ **/
60
+ abstract public function getStatus();
61
+
62
+ /**
63
+ * creates the result object
64
+ *
65
+ * @return FACTFinder_Result
66
+ **/
67
+ abstract protected function createResult();
68
+
69
+ /**
70
+ * creates the asn object
71
+ *
72
+ * @return FACTFinder_Asn
73
+ **/
74
+ abstract protected function createAsn();
75
+
76
+ /**
77
+ * creates the sorting object
78
+ *
79
+ * @return array of FACTFinder_Item objects
80
+ **/
81
+ abstract protected function createSorting();
82
+
83
+ /**
84
+ * creates the paging object
85
+ *
86
+ * @return FACTFinder_Paging object
87
+ **/
88
+ abstract protected function createPaging();
89
+
90
+ /**
91
+ * creates the paging object
92
+ *
93
+ * @return FACTFinder_ProductsPerPageOptions object
94
+ **/
95
+ abstract protected function createProductsPerPageOptions();
96
+
97
+ /**
98
+ * create breadcrumbtrail
99
+ *
100
+ * @return array of FACTFinder_BreadCrumbItem objects
101
+ */
102
+ abstract protected function createBreadCrumbTrail();
103
+
104
+ /**
105
+ * create campaigns
106
+ *
107
+ * @return FACTFinder_CampaignIterator
108
+ */
109
+ abstract protected function createCampaigns();
110
+
111
+ /**
112
+ * create sindle word search
113
+ *
114
+ * @return array of FACTFinder_SuggestQuery objects
115
+ */
116
+ abstract protected function createSingleWordSearch();
117
+
118
+ /**
119
+ * returns the search params object
120
+ *
121
+ * @return FACTFinder_Parameters result
122
+ **/
123
+ abstract protected function createSearchParams();
124
+
125
+ /**
126
+ * returns the search params object
127
+ *
128
+ * @return FACTFinder_Parameters result
129
+ **/
130
+ public function getSearchParams() {
131
+ if ($this->searchParams == null) {
132
+ $this->searchParams = $this->createSearchParams();
133
+ }
134
+ return $this->searchParams;
135
+ }
136
+
137
+ /**
138
+ * returns the result object
139
+ *
140
+ * @return FACTFinder_Result result
141
+ **/
142
+ public function getResult() {
143
+ if ($this->result == null) {
144
+ $this->result = $this->createResult();
145
+ }
146
+ return $this->result;
147
+ }
148
+
149
+ /**
150
+ * returns the asn object
151
+ *
152
+ * @return FACTFinder_Asn
153
+ **/
154
+ public function getAsn() {
155
+ if ($this->asn == null) {
156
+ $this->asn = $this->createAsn();
157
+ }
158
+ return $this->asn;
159
+ }
160
+
161
+ /**
162
+ * returns the sorting
163
+ *
164
+ * @return array of FACTFinder_SortItem objects
165
+ **/
166
+ public function getSorting() {
167
+ if ($this->sorting == null) {
168
+ $this->sorting = $this->createSorting();
169
+ }
170
+ return $this->sorting;
171
+ }
172
+
173
+ /**
174
+ * returns the paging
175
+ *
176
+ * @return FACTFinder_Paging object
177
+ **/
178
+ public function getPaging() {
179
+ if ($this->paging == null) {
180
+ $this->paging = $this->createPaging();
181
+ }
182
+ return $this->paging;
183
+ }
184
+
185
+ /**
186
+ * return products-per-page-options
187
+ *
188
+ * @return FACTFinder_ProductsPerPageOptions object
189
+ */
190
+ public function getProductsPerPageOptions() {
191
+ if ($this->productsPerPageOptions == null) {
192
+ $this->productsPerPageOptions = $this->createProductsPerPageOptions();
193
+ }
194
+ return $this->productsPerPageOptions;
195
+ }
196
+
197
+ /**
198
+ * returns the breadcrumbtrail
199
+ *
200
+ * @return array of FACTFinder_BreadCrumbItem objects
201
+ */
202
+ public function getBreadCrumbTrail() {
203
+ if ($this->breadCrumbTrail == null) {
204
+ $this->breadCrumbTrail = $this->createBreadCrumbTrail();
205
+ }
206
+ return $this->breadCrumbTrail;
207
+ }
208
+
209
+ /**
210
+ * returns the campaigns
211
+ *
212
+ * @return FACTFinder_CampaignIterator
213
+ */
214
+ public function getCampaigns() {
215
+ if ($this->campaigns == null) {
216
+ $this->campaigns = $this->createCampaigns();
217
+ }
218
+ return $this->campaigns;
219
+ }
220
+
221
+ /**
222
+ * if the result was not good and there are more than one queries used for it, this method will return an array of
223
+ * FACTFinder_AsnFilter objects, for each word a single item. by clicking at a singleWordSearch item, the result
224
+ * should get better
225
+ * please notice, that this feature has to be actived in the FACT-Finder search environment
226
+ *
227
+ * @return array of FACTFinder_SuggestQuery objects
228
+ */
229
+ public function getSingleWordSearch() {
230
+ if ($this->singleWordSearch == null) {
231
+ $this->singleWordSearch = $this->createSingleWordSearch();
232
+ }
233
+ return $this->singleWordSearch;
234
+ }
235
+ }
lib/FACTFinder/Abstract/SuggestAdapter.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * adapter for factfinder's suggest
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: SuggestAdapter.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Abstract
9
+ */
10
+ abstract class FACTFinder_Abstract_SuggestAdapter extends FACTFinder_Abstract_Adapter
11
+ {
12
+ private $suggestions;
13
+
14
+ /**
15
+ * get suggestions created by createSuggesions()
16
+ *
17
+ * @return mixed
18
+ */
19
+ public function getSuggestions()
20
+ {
21
+ if ($this->suggestions == null) {
22
+ $this->suggestions = $this->createSuggestions();
23
+ }
24
+ return $this->suggestions;
25
+ }
26
+
27
+ /**
28
+ * create and return suggestions. dependend to the implementation this can be any type
29
+ *
30
+ * @return mixed
31
+ */
32
+ abstract protected function createSuggestions();
33
+ }
lib/FACTFinder/Abstract/TagCloudAdapter.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * adapter for the factfinder tagcloud data
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: TagCloudAdapter.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Abstract
9
+ */
10
+ abstract class FACTFinder_Abstract_TagCloudAdapter extends FACTFinder_Abstract_Adapter
11
+ {
12
+ private $tagCloud;
13
+
14
+ /**
15
+ * get tag cloud
16
+ *
17
+ * @return array $tagCloud list of FACTFinder_Tag objects
18
+ */
19
+ public function getTagCloud() {
20
+ if ($this->tagCloud == null) {
21
+ $this->tagCloud = $this->createTagCloud();
22
+ }
23
+ return $this->tagCloud;
24
+ }
25
+
26
+ /**
27
+ * @return array $tagCloud list of FACTFinder_Tag objects
28
+ */
29
+ abstract protected function createTagCloud();
30
+ }
lib/FACTFinder/Asn.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * represents a group in the ASN which contains several filters
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: Asn.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Common
9
+ */
10
+ class FACTFinder_Asn extends ArrayIterator
11
+ {
12
+ /**
13
+ * decorates the FACTFinder_AsnGroup::hasPreviewImages() method for each group in the asn. so if one group has
14
+ * preview images, this method returns true
15
+ *
16
+ * @return boolean
17
+ */
18
+ public function hasPreviewImages()
19
+ {
20
+ $hasPreviewImages = false;
21
+ foreach ($this AS $group) {
22
+ if ($group->hasPreviewImages()) {
23
+ $hasPreviewImages = true;
24
+ break;
25
+ }
26
+ }
27
+ return $hasPreviewImages;
28
+ }
29
+ }
lib/FACTFinder/AsnFilterItem.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * represents an filterable item from the after search navigation
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: AsnFilterItem.php 25893 2010-06-29 08:19:43Z rb $
8
+ * @package FACTFinder\Common
9
+ */
10
+ class FACTFinder_AsnFilterItem extends FACTFinder_Item
11
+ {
12
+ private $matchCount;
13
+ private $clusterLevel;
14
+ private $previewImage = null;
15
+ private $field;
16
+
17
+ public function __construct($value, $url, $isSelected = false, $matchCount = 0, $clusterLevel = 0, $previewImage = null, $field = ''){
18
+ parent::__construct($value, $url, $isSelected);
19
+ $this->matchCount = intval($matchCount);
20
+ $this->clusterLevel = intval($clusterLevel);
21
+ $this->previewImage = strval($previewImage);
22
+ $this->field = strval($field);
23
+ }
24
+
25
+ public function getType() {
26
+ return 'item';
27
+ }
28
+
29
+ /**
30
+ * @return String
31
+ */
32
+ public function getField() {
33
+ return $this->field;
34
+ }
35
+
36
+ /**
37
+ * @return int
38
+ */
39
+ public function getMatchCount() {
40
+ return $this->matchCount;
41
+ }
42
+
43
+ /**
44
+ * @return int
45
+ */
46
+ public function getClusterLevel() {
47
+ return $this->clusterLevel;
48
+ }
49
+
50
+ /**
51
+ * return url of a preview image or null if there is no set
52
+ *
53
+ * @return string image url or null if none exists
54
+ */
55
+ public function getPreviewImage() {
56
+ return $this->previewImage;
57
+ }
58
+
59
+ /**
60
+ * @return boolean
61
+ */
62
+ public function hasPreviewImage() {
63
+ return !empty($this->previewImage);
64
+ }
65
+ }
lib/FACTFinder/AsnGroup.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * represents a group in the ASN which contains several filters
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: AsnGroup.php 614 2011-02-01 16:08:47Z weller $
8
+ * @category Collection
9
+ * @package FACTFinder\Common
10
+ */
11
+ class FACTFinder_AsnGroup extends ArrayIterator
12
+ {
13
+ private $name;
14
+ private $detailedLinkCount;
15
+ private $unit;
16
+ private $hasPreviewImages = false;
17
+ private $hasSelectedItems = false;
18
+ private $isSliderStyle = false;
19
+
20
+ /**
21
+ * constructor
22
+ *
23
+ * @param array asn filters to add to this group (default: empty array)
24
+ * @param string name of the group (default: empty string)
25
+ * @param int number of detail links to show (default: 0)
26
+ * @param string untit character of the group (default: empty string)
27
+ * @param string style; possible values: DEFAULT|SLIDER|COLOR (default: DEFAULT)
28
+ */
29
+ public function __construct(array $asnFilters = array(), $name = '', $detailedLinkCount = 0, $unit = '', $style = 'DEFAULT') {
30
+ $this->name = strval($name);
31
+ $this->detailedLinkCount = intval($detailedLinkCount);
32
+ $this->unit = strval($unit);
33
+ $this->style = $style;
34
+
35
+ parent::__construct();
36
+ $this->addFilters($asnFilters);
37
+ }
38
+
39
+ /**
40
+ * return true if group filtering should be done in slider style
41
+ *
42
+ * @return boolean
43
+ */
44
+ public function isSliderStyle() {
45
+ return $this->style == 'SLIDER';
46
+ }
47
+
48
+ /**
49
+ * @return boolean
50
+ */
51
+ public function isColorStyle() {
52
+ return $this->style == 'COLOR';
53
+ }
54
+
55
+ /**
56
+ * @return boolean
57
+ */
58
+ public function isDefaultStyle() {
59
+ return !$this->isSliderStyle() && !$this->isColorStyle();
60
+ }
61
+
62
+ /**
63
+ * return boolean true if one or more items has a preview image
64
+ */
65
+ public function hasPreviewImages()
66
+ {
67
+ return $this->hasPreviewImages;
68
+ }
69
+
70
+ /**
71
+ * return boolean true if one or more items are selected
72
+ */
73
+ public function hasSelectedItems()
74
+ {
75
+ return $this->hasSelectedItems;
76
+ }
77
+
78
+ /**
79
+ * add every filter from the given array to this group
80
+ *
81
+ * @param array of filter objects
82
+ * @return void
83
+ */
84
+ public function addFilters(array $filters)
85
+ {
86
+ foreach($filters AS $filter) {
87
+ $this->addFilter($filter);
88
+ }
89
+ }
90
+
91
+ /**
92
+ * @param filter object
93
+ * @return void
94
+ */
95
+ public function addFilter($filter)
96
+ {
97
+ if ($filter instanceof FACTFinder_AsnFilterItem) {
98
+ if ($filter->hasPreviewImage()) {
99
+ $this->hasPreviewImages = true;
100
+ } else if ($filter->isSelected()) {
101
+ $this->hasSelectedItems = true;
102
+ }
103
+ }
104
+ parent::append($filter);
105
+ }
106
+
107
+ /**
108
+ * @return string name
109
+ */
110
+ public function getName() {
111
+ return $this->name;
112
+ }
113
+
114
+ /**
115
+ * @return string unit
116
+ */
117
+ public function getUnit() {
118
+ return $this->unit;
119
+ }
120
+
121
+ /**
122
+ * @return int
123
+ */
124
+ public function getDetailedLinkCount() {
125
+ return $this->detailedLinkCount;
126
+ }
127
+ }
lib/FACTFinder/AsnSliderFilter.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * represents an asn filter slider item
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: AsnSliderFilter.php 25893 2010-06-29 08:19:43Z rb $
8
+ * @package FACTFinder\Common
9
+ */
10
+ class FACTFinder_AsnSliderFilter
11
+ {
12
+ private $absoluteMin;
13
+ private $absoluteMax;
14
+ private $selectedMin;
15
+ private $selectedMax;
16
+ private $baseUrl;
17
+ private $field;
18
+
19
+ /**
20
+ * @param string base url - it should be possible to simply append the selected min and max value
21
+ * @param float absolute min (default: 0.0)
22
+ * @param float absolute max (default: 0.0)
23
+ * @param float selected min (default: 0.0)
24
+ * @param float selected max (default: 0.0)
25
+ */
26
+ public function __construct($baseUrl, $absoluteMin = 0, $absoluteMax = 0, $selectedMin = 0, $selectedMax = 0, $field = '') {
27
+ $this->baseUrl = $baseUrl;
28
+ $this->setAbsoluteRange($absoluteMin, $absoluteMax);
29
+ $this->setSelectedRange($selectedMin, $selectedMax);
30
+ $this->field = strval($field);
31
+ }
32
+
33
+ public function getType() {
34
+ return 'slider';
35
+ }
36
+
37
+ /**
38
+ * @param float absolute min
39
+ * @param float absolute max
40
+ */
41
+ private function setAbsoluteRange($min, $max) {
42
+ $this->absoluteMin = floatval($min);
43
+ $this->absoluteMax = floatval($max);
44
+ }
45
+
46
+ /**
47
+ * @param float selected min
48
+ * @param float selected max
49
+ */
50
+ public function setSelectedRange($min, $max) {
51
+ $this->selectedMin = floatval($min);
52
+ $this->selectedMax = floatval($max);
53
+ }
54
+
55
+ /**
56
+ * return float
57
+ */
58
+ public function getAbsoluteMin() {
59
+ return $this->absoluteMin;
60
+ }
61
+
62
+ /**
63
+ * return float
64
+ */
65
+ public function getAbsoluteMax() {
66
+ return $this->absoluteMax;
67
+ }
68
+
69
+ /**
70
+ * return float
71
+ */
72
+ public function getSelectedMin() {
73
+ return $this->selectedMin;
74
+ }
75
+
76
+ /**
77
+ * return float
78
+ */
79
+ public function getSelectedMax() {
80
+ return $this->selectedMax;
81
+ }
82
+
83
+ /**
84
+ * @return string url for the current selected range
85
+ */
86
+ public function getUrl() {
87
+ return $this->baseUrl . $this->selectedMin . ' - ' . $this->selectedMax;
88
+ }
89
+
90
+ /**
91
+ * @return string base url
92
+ */
93
+ public function getBaseUrl() {
94
+ return $this->baseUrl;
95
+ }
96
+
97
+ /**
98
+ * returns true if the selected range is not the same as the absolute range
99
+ *
100
+ * @return boolean true if selected
101
+ */
102
+ public function isSelected() {
103
+ return $this->selectedMin != $this->absoluteMin || $this->selectedMax != $this->absoluteMax;
104
+ }
105
+
106
+ /**
107
+ * returns the associated field name to this filter
108
+ *
109
+ * @return string field-name
110
+ */
111
+ public function getField() {
112
+ return $this->field;
113
+ }
114
+
115
+ /**
116
+ * returns the absolute values as parameters and the select parameter-key, so the selected values must be
117
+ * appended to set the selection.
118
+ *
119
+ * @return string parameters for this filter
120
+ */
121
+ public function getValue() {
122
+ return 'filter'.$this->getField().'Absolute='.$this->getAbsoluteMin().' - '.$this->getAbsoluteMax().'&filter'.$this->getField().'=';
123
+ }
124
+ }
lib/FACTFinder/BreadCrumbItem.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * breadcrumb for the breadcrumb navigation
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: BreadCrumbItem.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Common
9
+ */
10
+ class FACTFinder_BreadCrumbItem extends FACTFinder_Item
11
+ {
12
+ const SEARCH_TYPE = 'search';
13
+ const FILTER_TYPE = 'filter';
14
+
15
+ private $type;
16
+ private $fieldName;
17
+ private $fieldUnit;
18
+
19
+ /**
20
+ * @param string value
21
+ * @param string url
22
+ * @param boolean true if this breadcrumb represents the current state of the result
23
+ * @param string type should be "search" or "filter", otherwise the "is..." methods will not work (default: 'filter')
24
+ * @param string filtername
25
+ * @param string filter value
26
+ */
27
+ public function __construct($value, $url, $isSelected = false, $type = 'filter', $fieldName = '', $fieldUnit = '')
28
+ {
29
+ parent::__construct($value, $url, $isSelected);
30
+ $this->type = strval($type);
31
+ if ($this->isFilter()) {
32
+ $this->fieldName = strval($fieldName);
33
+ $this->fieldUnit = strval($fieldUnit);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * @return boolean
39
+ */
40
+ public function isFilter()
41
+ {
42
+ return $this->type == self::FILTER_TYPE;
43
+ }
44
+
45
+ /**
46
+ * @return boolean
47
+ */
48
+ public function isSearch()
49
+ {
50
+ return $this->type == self::SEARCH_TYPE;
51
+ }
52
+
53
+ /**
54
+ * @return string
55
+ */
56
+ public function getFieldName()
57
+ {
58
+ return $this->fieldName;
59
+ }
60
+
61
+ /**
62
+ * @return string
63
+ */
64
+ public function getFieldUnit()
65
+ {
66
+ return $this->fieldUnit;
67
+ }
68
+ }
lib/FACTFinder/Campaign.php ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * represents a factfinder campaign
4
+ *
5
+ * @author Rudolf Batt <rb@omikron.net>
6
+ * @version $Id: Campaign.php 614 2011-02-01 16:08:47Z weller $
7
+ * @package FACTFinder\Common
8
+ */
9
+ class FACTFinder_Campaign
10
+ {
11
+ private $name;
12
+ private $category;
13
+
14
+ private $redirectUrl = null;
15
+ private $pushedProducts = array();
16
+ private $feedback = array();
17
+
18
+ /**
19
+ * @param string name
20
+ * @param string category
21
+ * @param string redirectUrl (default: empty string)
22
+ * @param array pushedProducts; array of records
23
+ * @param array feedback; array of strings
24
+ */
25
+ public function __construct($name = '', $category = '', $redirectUrl = '', array $pushedProducts = array(), $feedback = array()) {
26
+ $this->name = trim($name);
27
+ $this->category = trim($category);
28
+ $this->redirectUrl = trim($redirectUrl);
29
+ $this->addPushedProducts($pushedProducts);
30
+ $this->addFeedback($feedback);
31
+ }
32
+
33
+ /**
34
+ * @return string name
35
+ */
36
+ public function getName() {
37
+ return $this->name;
38
+ }
39
+
40
+ /**
41
+ * @return string url
42
+ */
43
+ public function getCategory(){
44
+ return $this->category;
45
+ }
46
+
47
+ /**
48
+ * true if a redirect link was set
49
+ *
50
+ * @return boolean
51
+ */
52
+ public function hasRedirect()
53
+ {
54
+ return !empty($this->redirectUrl);
55
+ }
56
+
57
+ /**
58
+ * @return string url
59
+ */
60
+ public function getRedirectUrl(){
61
+ return $this->redirectUrl;
62
+ }
63
+
64
+ /**
65
+ * add products to this campaigns
66
+ *
67
+ * @param array of FACTFinder_Record objects
68
+ * @return void
69
+ */
70
+ public function addPushedProducts(array $pushedProducts) {
71
+ foreach ($pushedProducts AS $product) {
72
+ $this->pushedProducts[] = $product;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * true if pushed products exist
78
+ *
79
+ * @return boolean
80
+ */
81
+ public function hasPushedProducts() {
82
+ return sizeof($this->pushedProducts) > 0;
83
+ }
84
+
85
+ /**
86
+ * @return array of records
87
+ */
88
+ public function getPushedProducts() {
89
+ return $this->pushedProducts;
90
+ }
91
+
92
+ /**
93
+ * set the feedback strings. if a feedback with the same key (number) exist, it will be overwritten
94
+ *
95
+ * @param array of string
96
+ * @return void
97
+ */
98
+ public function addFeedback(array $feedback) {
99
+ foreach($feedback AS $nr => $text) {
100
+ $this->feedback[$nr] = trim($text);
101
+ }
102
+ }
103
+
104
+ /**
105
+ * returns true if feedback exists. if no number is given as argument, this methods checks, whether there is any
106
+ * feedback text available. if a number is given, then this method only returns true, if there is a feedback text
107
+ * for this number
108
+ *
109
+ * @param int number of feedback (default: null)
110
+ * @return boolean
111
+ */
112
+ public function hasFeedback($nr = null) {
113
+ if (is_int($nr)) {
114
+ $hasFeedback = isset($this->feedback[$nr]) && $this->feedback[$nr] != '';
115
+ } else {
116
+ $hasFeedback = sizeof($this->feedback) > 0 && implode('', $this->feedback) != '';
117
+ }
118
+ return $hasFeedback;
119
+ }
120
+
121
+ /**
122
+ * when number is given, only the wished feedback text will be returned or an empty string, if this text does not exist.
123
+ * if no number is set, the complete feedback array will be returned
124
+ *
125
+ * @param int $nr
126
+ * @return array|string
127
+ */
128
+ public function getFeedback($nr = null) {
129
+ if ($nr === null) {
130
+ return $this->feedback;
131
+ } else if (isset($this->feedback[$nr])) {
132
+ return $this->feedback[$nr];
133
+ } else {
134
+ return '';
135
+ }
136
+ }
137
+ }
lib/FACTFinder/CampaignIterator.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * represents the whole collection of campaigns. decorates some campaign functions to execute on every campaign
4
+ *
5
+ * @author Rudolf Batt <rb@omikron.net>
6
+ * @version $Id: CampaignIterator.php 614 2011-02-01 16:08:47Z weller $
7
+ * @package FACTFinder\Common
8
+ */
9
+ class FACTFinder_CampaignIterator extends ArrayIterator
10
+ {
11
+ /**
12
+ * true if a redirect link exists at one of all campaigns
13
+ *
14
+ * @see FACTFinder_Campaign::hasRedirect()
15
+ * @return boolean
16
+ */
17
+ public function hasRedirect()
18
+ {
19
+ $hasRedirect = false;
20
+ foreach ($this AS $campaign) {
21
+ if ($campaign->hasRedirect()) {
22
+ $hasRedirect = true;
23
+ break;
24
+ }
25
+ }
26
+ return $hasRedirect;
27
+ }
28
+
29
+ /**
30
+ * return the first redirect of all campaigns or null if non exists
31
+ *
32
+ * @see FACTFinder_Campaign::getRedirectUrl()
33
+ * @return string url
34
+ */
35
+ public function getRedirectUrl(){
36
+ $redirectUrl = null;
37
+ foreach ($this AS $campaign) {
38
+ if ($campaign->hasRedirect()) {
39
+ $redirectUrl = $campaign->getRedirectUrl();
40
+ break;
41
+ }
42
+ }
43
+ return $redirectUrl;
44
+ }
45
+
46
+ /**
47
+ * true if pushed products exist in of all campaigns
48
+ *
49
+ * @see FACTFinder_Campaign::hasPushedProducts()
50
+ * @return boolean
51
+ */
52
+ public function hasPushedProducts() {
53
+ $hasPushedProducts = false;
54
+ foreach ($this AS $campaign) {
55
+ if ($campaign->hasPushedProducts()) {
56
+ $hasPushedProducts = true;
57
+ break;
58
+ }
59
+ }
60
+ return $hasPushedProducts;
61
+ }
62
+
63
+ /**
64
+ * decorates FACTFinder_Campaign::getPushedProducts() for all campaigns
65
+ *
66
+ * @see FACTFinder_Campaign::getPushedProducts()
67
+ * @return array of records
68
+ */
69
+ public function getPushedProducts() {
70
+ $pushedProducts = array();
71
+ foreach ($this AS $campaign) {
72
+ if ($campaign->hasPushedProducts()) {
73
+ $pushedProducts = array_merge($pushedProducts, $campaign->getPushedProducts());
74
+ }
75
+ }
76
+ return $pushedProducts;
77
+ }
78
+
79
+ /**
80
+ * decorates FACTFinder_Campaign::hasFeedback() for each campaign. return true, if one of all campaigns has feedback
81
+ * text snippets
82
+ *
83
+ * @see FACTFinder_Campaign::hasFeedback()
84
+ * @return boolean
85
+ */
86
+ public function hasFeedback($nr = null) {
87
+ $hasFeedback = false;
88
+ foreach ($this AS $campaign) {
89
+ if ($campaign->hasFeedback($nr)) {
90
+ $hasFeedback = true;
91
+ break;
92
+ }
93
+ }
94
+ return $hasFeedback;
95
+ }
96
+
97
+ /**
98
+ * decorates FACTFinder_Campaign::getFeedback() for each campaign. returnes a string of each feedback from all
99
+ * campaigns, glued together with PHP_EOL
100
+ *
101
+ * @see FACTFinder_Campaign::getFeedback()
102
+ * @param int $nr of feedback text
103
+ * @return string
104
+ */
105
+ public function getFeedback($nr) {
106
+ $feedback = '';
107
+ foreach ($this AS $campaign) {
108
+ if ($campaign->hasFeedback()) {
109
+ $feedback .= $campaign->getFeedback($nr).PHP_EOL;
110
+ }
111
+ }
112
+ return $feedback;
113
+ }
114
+ }
lib/FACTFinder/Configuration.php ADDED
@@ -0,0 +1,347 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * this class implements the FACTFinder configuration interface and uses the Zend_Config class. so it's like a decorator
5
+ * for the Zend_Config
6
+ *
7
+ * @package FACTFinder\Common
8
+ */
9
+ class FACTFinder_Configuration implements FACTFinder_Abstract_Configuration
10
+ {
11
+ const HTTP_AUTH = 'http';
12
+ const SIMPLE_AUTH = 'simple';
13
+ const ADVANCED_AUTH = 'advanced';
14
+
15
+ private $zendConfig;
16
+ private $authType;
17
+ private $pageMappings;
18
+ private $serverMappings;
19
+ private $pageIgnores;
20
+ private $serverIgnores;
21
+ private $requiredPageParams;
22
+ private $requiredServerParams;
23
+
24
+ public function __construct(Zend_Config $config)
25
+ {
26
+ $this->zendConfig = $config;
27
+ }
28
+
29
+ /**
30
+ * @return string
31
+ */
32
+ public function getVersion() {
33
+ return $this->zendConfig->version;
34
+ }
35
+
36
+ /**
37
+ * @return boolean
38
+ */
39
+ public function isDebugEnabled() {
40
+ return $this->zendConfig->debug == 'true';
41
+ }
42
+
43
+ /**
44
+ * @param string name
45
+ * @return string value
46
+ */
47
+ public function getCustomValue($name) {
48
+ return $this->zendConfig->$name;
49
+ }
50
+
51
+ /**
52
+ * @return string
53
+ */
54
+ public function getRequestProtokoll() {
55
+ return $this->zendConfig->search->protokoll;
56
+ }
57
+
58
+ /**
59
+ * @return string
60
+ */
61
+ public function getServerAddress() {
62
+ return $this->zendConfig->search->address;
63
+ }
64
+
65
+ /**
66
+ * @return int
67
+ */
68
+ public function getServerPort() {
69
+ return $this->zendConfig->search->port;
70
+ }
71
+
72
+ /**
73
+ * @return string
74
+ */
75
+ public function getContext() {
76
+ return $this->zendConfig->search->context;
77
+ }
78
+
79
+ /**
80
+ * @return string
81
+ */
82
+ public function getChannel() {
83
+ return $this->zendConfig->search->channel;
84
+ }
85
+
86
+ /**
87
+ * @return string
88
+ */
89
+ public function getLanguage() {
90
+ return $this->zendConfig->search->language;
91
+ }
92
+
93
+ /**
94
+ * @return string
95
+ */
96
+ public function getAuthUser() {
97
+ return $this->zendConfig->search->auth->user;
98
+ }
99
+
100
+ /**
101
+ * @return string
102
+ */
103
+ public function getAuthPasswort() {
104
+ return $this->zendConfig->search->auth->password;
105
+ }
106
+
107
+ /**
108
+ * @return boolean
109
+ */
110
+ public function isHttpAuthenticationType() {
111
+ return $this->getAuthType() == self::HTTP_AUTH;
112
+ }
113
+
114
+ /**
115
+ * @return boolean
116
+ */
117
+ public function isSimpleAuthenticationType() {
118
+ return $this->getAuthType() == self::SIMPLE_AUTH;
119
+ }
120
+
121
+ /**
122
+ * @return boolean
123
+ */
124
+ public function isAdvancedAuthenticationType() {
125
+ return $this->getAuthType() == self::ADVANCED_AUTH;
126
+ }
127
+
128
+ private function getAuthType() {
129
+ if ($this->authType == null) {
130
+ $this->authType = $this->zendConfig->search->auth->type;
131
+ if ( $this->authType != self::HTTP_AUTH
132
+ && $this->authType != self::SIMPLE_AUTH
133
+ && $this->authType != self::ADVANCED_AUTH ) {
134
+ $this->authType = self::HTTP_AUTH;
135
+ }
136
+ }
137
+ return $this->authType;
138
+ }
139
+
140
+ /**
141
+ * @return string
142
+ */
143
+ public function getAdvancedAuthPrefix() {
144
+ return $this->zendConfig->search->auth->advancedPrefix;
145
+ }
146
+
147
+ /**
148
+ * @return string
149
+ */
150
+ public function getAdvancedAuthPostfix(){
151
+ return $this->zendConfig->search->auth->advancedPostfix;
152
+ }
153
+
154
+ /**
155
+ * {@inheritdoc}
156
+ *
157
+ * @return array
158
+ */
159
+ public function getPageMappings() {
160
+ if ($this->pageMappings == null) {
161
+ $this->pageMappings = array();
162
+ if ($this->zendConfig->params->client->mapping != null) {
163
+
164
+ // get mapping config as iterable variable
165
+ if ($this->zendConfig->params->client->mapping->from == null) {
166
+ $mapping = $this->zendConfig->params->client->mapping;
167
+ } else {
168
+ $mapping = array($this->zendConfig->params->client->mapping);
169
+ }
170
+
171
+ //load mappings
172
+ foreach($mapping AS $rule) {
173
+ $this->pageMappings[$rule->from] = $rule->to;
174
+ }
175
+ }
176
+ }
177
+ return $this->pageMappings;
178
+ }
179
+
180
+ /**
181
+ * {@inheritdoc}
182
+ *
183
+ * @return array
184
+ */
185
+ public function getServerMappings() {
186
+ if ($this->serverMappings == null) {
187
+ $this->serverMappings = array();
188
+ if ($this->zendConfig->params->server->mapping != null) {
189
+
190
+ // get mapping config as iterable variable
191
+ if ($this->zendConfig->params->server->mapping->from == null) {
192
+ $mapping = $this->zendConfig->params->server->mapping;
193
+ } else {
194
+ $mapping = array($this->zendConfig->params->server->mapping);
195
+ }
196
+
197
+ //load mappings
198
+ foreach($mapping AS $rule) {
199
+ $this->serverMappings[$rule->from] = $rule->to;
200
+ }
201
+ }
202
+ }
203
+ return $this->serverMappings;
204
+ }
205
+
206
+ /**
207
+ * {@inheritdoc}
208
+ *
209
+ * @return array with string as key and boolean true as value for each of them
210
+ */
211
+ public function getIgnoredPageParams() {
212
+ if ($this->pageIgnores == null) {
213
+ $this->pageIgnores = array();
214
+ if (isset($this->zendConfig->params->client->ignore)) {
215
+
216
+ // get ignore rules as iterable variable
217
+ if($this->zendConfig->params->client->ignore->name == null) {
218
+ $ignoreRules = $this->zendConfig->params->client->ignore ;
219
+ } else {
220
+ $ignoreRules = array($this->zendConfig->params->client->ignore );
221
+ }
222
+
223
+ // load ignore rules
224
+ foreach($ignoreRules AS $i) {
225
+ $this->pageIgnores[$i->name] = true;
226
+ }
227
+ }
228
+
229
+ $pageMappings = $this->getPageMappings();
230
+ foreach ($pageMappings AS $from => $to) {
231
+ $this->pageIgnores[$from] = true;
232
+ }
233
+ }
234
+ return $this->pageIgnores;
235
+ }
236
+
237
+ /**
238
+ * {@inheritdoc}
239
+ *
240
+ * @return array with string as key and boolean true as value for each of them
241
+ */
242
+ public function getIgnoredServerParams() {
243
+ if ($this->serverIgnores == null) {
244
+ $this->serverIgnores = array();
245
+ if (isset($this->zendConfig->params->server->ignore)) {
246
+
247
+ // get ignore rules as iterable variable
248
+ if($this->zendConfig->params->server->ignore->name == null) {
249
+ $ignoreRules = $this->zendConfig->params->server->ignore ;
250
+ } else {
251
+ $ignoreRules = array($this->zendConfig->params->server->ignore );
252
+ }
253
+
254
+ // load ignore rules
255
+ foreach($ignoreRules AS $i) {
256
+ $this->serverIgnores[$i->name] = true;
257
+ }
258
+ }
259
+
260
+ $serverMappings = $this->getServerMappings();
261
+ foreach ($serverMappings AS $from => $to) {
262
+ $this->serverIgnores[$from] = true;
263
+ }
264
+ }
265
+ return $this->serverIgnores;
266
+ }
267
+
268
+ /**
269
+ * {@inheritdoc}
270
+ *
271
+ * @return array string to string map (param-name as array-key; default value as array-value)
272
+ */
273
+ public function getRequiredPageParams(){
274
+ if ($this->requiredPageParams == null) {
275
+ $this->requiredPageParams = array();
276
+ if ($this->zendConfig->params->client->required != null) {
277
+
278
+ // get required params config as iterable variable
279
+ if ($this->zendConfig->params->client->required->name == null) {
280
+ $requiredParams = $this->zendConfig->params->client->required;
281
+ } else {
282
+ $requiredParams = array($this->zendConfig->params->client->required);
283
+ }
284
+
285
+ //load mappings
286
+ foreach($requiredParams AS $param) {
287
+ $this->requiredPageParams[$param->name] = $param->default;
288
+ }
289
+ }
290
+ }
291
+ return $this->requiredPageParams;
292
+ }
293
+
294
+ /**
295
+ * {@inheritdoc}
296
+ *
297
+ * @return array string to string map (param-name as array-key; default value as array-value)
298
+ */
299
+ function getRequiredServerParams(){
300
+ if ($this->requiredServerParams == null) {
301
+ $this->requiredServerParams = array();
302
+ if ($this->zendConfig->params->server->required != null) {
303
+
304
+ // get required params config as iterable variable
305
+ if ($this->zendConfig->params->server->required->name == null) {
306
+ $requiredParams = $this->zendConfig->params->server->required;
307
+ } else {
308
+ $requiredParams = array($this->zendConfig->params->server->required);
309
+ }
310
+
311
+ //load mappings
312
+ foreach($requiredParams AS $param) {
313
+ $this->requiredServerParams[$param->name] = $param->default;
314
+ }
315
+ }
316
+ }
317
+ return $this->requiredServerParams;
318
+ }
319
+
320
+
321
+ /**
322
+ * {@inheritdoc}
323
+ *
324
+ * @return string
325
+ */
326
+ function getPageContentEncoding() {
327
+ return $this->zendConfig->encoding->pageContent;
328
+ }
329
+
330
+ /**
331
+ * {@inheritdoc}
332
+ *
333
+ * @return string
334
+ */
335
+ function getPageUrlEncoding() {
336
+ return $this->zendConfig->encoding->pageURI;
337
+ }
338
+
339
+ /**
340
+ * {@inheritdoc}
341
+ *
342
+ * @return string
343
+ */
344
+ function getServerUrlEncoding() {
345
+ return $this->zendConfig->encoding->serverURI;
346
+ }
347
+ }
lib/FACTFinder/EncodingHandler.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * this class handles the different issues of encoding between the values of page-url, server-url, result and pagecontent
5
+ *
6
+ * @package FACTFinder\Common
7
+ */
8
+ class FACTFinder_EncodingHandler
9
+ {
10
+ private $convertMethod;
11
+
12
+ private $pageContentEncoding;
13
+ private $pageUrlEncoding;
14
+ private $serverUrlEncoding;
15
+
16
+ public function __construct(FACTFinder_Abstract_Configuration $config)
17
+ {
18
+ $this->pageContentEncoding = $config->getPageContentEncoding();
19
+ $this->pageUrlEncoding = $config->getPageUrlEncoding();
20
+ $this->serverUrlEncoding = $config->getServerUrlEncoding();
21
+
22
+ if (function_exists('iconv')) {
23
+ $this->convertMethod = 'iConvert';
24
+ } else {
25
+ $this->convertMethod = 'utf8Convert';
26
+ }
27
+ }
28
+
29
+ private function iConvert($inCharset, $outCharset, $string)
30
+ {
31
+ return ($inCharset == $outCharset || empty($inCharset) || empty($outCharset)) ? $string : iconv($inCharset, $outCharset, $string);
32
+ }
33
+
34
+ private function utf8Convert($inCharset, $outCharset, $string)
35
+ {
36
+ if (strtolower($inCharset) != strtolower($outCharset) && !empty($inCharset) && !empty($outCharset)) {
37
+ if (strtolower($inCharset) == 'utf-8') {
38
+ $string = utf8_decode($string);
39
+ } else if (strtolower($outCharset) == 'utf-8') {
40
+ $string = utf8_encode($string);
41
+ } else {
42
+ throw new Exception("can not handle $inCharset to $outCharset conversion!");
43
+ }
44
+ }
45
+ return $string;
46
+ }
47
+
48
+ /**
49
+ * converts the url data, to display correctly at the page
50
+ *
51
+ * @param string|array data
52
+ * @return string|array converted data
53
+ */
54
+ public function encodeUrlForPage($data)
55
+ {
56
+ // notice: urldecode is not needed, because php decodes the url automatically
57
+ if ($this->pageUrlEncoding != $this->pageContentEncoding) {
58
+ if (is_array($data)) {
59
+ $returnData = array();
60
+ foreach ($data AS $key => $value) {
61
+ $key = $this->{$this->convertMethod}($this->pageUrlEncoding, $this->pageContentEncoding, $key);
62
+ $returnData[$key] = $this->{$this->convertMethod}($this->pageUrlEncoding, $this->pageContentEncoding, $value);
63
+ }
64
+ } else if (is_string($data)) {
65
+ $returnData = $this->{$this->convertMethod}($this->pageUrlEncoding, $this->pageContentEncoding, $data);
66
+ }
67
+ } else {
68
+ $returnData = $data;
69
+ }
70
+ return $returnData;
71
+ }
72
+
73
+ /**
74
+ * converts the url data from the server result for the page url
75
+ *
76
+ * @param string|array data
77
+ * @return string|array converted data
78
+ */
79
+ public function encodeServerUrlForPageUrl($data)
80
+ {
81
+ // notice: urldecode is not needed, because the parameters parser is already doing that
82
+ if ($this->serverUrlEncoding != $this->pageUrlEncoding) {
83
+ if (is_array($data)) {
84
+ $returnData = array();
85
+ foreach ($data AS $key => $value) {
86
+ $key = $this->{$this->convertMethod}($this->serverUrlEncoding, $this->pageUrlEncoding, $key);
87
+ $returnData[$key] = $this->{$this->convertMethod}($this->serverUrlEncoding, $this->pageUrlEncoding, $value);
88
+ }
89
+ } else if (is_string($data)) {
90
+ $returnData = $this->{$this->convertMethod}($this->serverUrlEncoding, $this->pageUrlEncoding, $data);
91
+ }
92
+ } else {
93
+ $returnData = $data;
94
+ }
95
+ return $returnData;
96
+ }
97
+
98
+ /**
99
+ * converts the data from the server result for the page content
100
+ *
101
+ * @param string|array data
102
+ * @return string|array converted data
103
+ */
104
+ public function encodeServerContentForPage($data)
105
+ {
106
+ // server result data is always utf-8
107
+ if (strtolower($this->pageContentEncoding) != 'utf-8') {
108
+ if (is_array($data)) {
109
+ $returnData = array();
110
+ foreach ($data AS $key => $value) {
111
+ $key = $this->{$this->convertMethod}('UTF-8', $this->pageContentEncoding, $key);
112
+ $returnData[$key] = $this->{$this->convertMethod}('UTF-8', $this->pageContentEncoding, $value);
113
+ }
114
+ } else if (is_string($data)) {
115
+ $returnData = $this->{$this->convertMethod}('UTF-8', $this->pageContentEncoding, $data);
116
+ }
117
+ } else {
118
+ $returnData = $data;
119
+ }
120
+ return $returnData;
121
+ }
122
+
123
+ /**
124
+ * converts the data for the server url
125
+ *
126
+ * @param string|array data
127
+ * @return string|array converted data
128
+ */
129
+ public function encodeForServerUrl($data)
130
+ {
131
+ if ($this->pageContentEncoding != $this->serverUrlEncoding) {
132
+ if (is_array($data)) {
133
+ $returnData = array();
134
+ foreach ($data AS $key => $value) {
135
+ $key = $this->{$this->convertMethod}($this->pageContentEncoding, $this->serverUrlEncoding, $key);
136
+ $returnData[$key] = $this->{$this->convertMethod}($this->pageContentEncoding, $this->serverUrlEncoding, $value);
137
+ }
138
+ } else if (is_string($data)) {
139
+ $returnData = $this->{$this->convertMethod}($this->pageContentEncoding, $this->serverUrlEncoding, $data);
140
+ }
141
+ } else {
142
+ $returnData = $data;
143
+ }
144
+ return $returnData;
145
+ }
146
+
147
+ /**
148
+ * converts the data from the page for the page url
149
+ *
150
+ * @param string|array data
151
+ * @return string|array converted data
152
+ */
153
+ public function encodeForPageUrl($data)
154
+ {
155
+ if ($this->pageContentEncoding != $this->pageUrlEncoding) {
156
+ if (is_array($data)) {
157
+ $returnData = array();
158
+ foreach ($data AS $key => $value) {
159
+ $key = $this->{$this->convertMethod}($this->pageContentEncoding, $this->pageUrlEncoding, $key);
160
+ $returnData[$key] = $this->{$this->convertMethod}($this->pageContentEncoding, $this->pageUrlEncoding, $value);
161
+ }
162
+ } else if (is_string($data)) {
163
+ $returnData = $this->{$this->convertMethod}($this->pageContentEncoding, $this->pageUrlEncoding, $data);
164
+ }
165
+ } else {
166
+ $returnData = $data;
167
+ }
168
+ return $returnData;
169
+ }
170
+ }
lib/FACTFinder/Http/DataProvider.php ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * this data provider loads the data per http
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: DataProvider.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Http
9
+ */
10
+ class FACTFinder_Http_DataProvider extends FACTFinder_Abstract_DataProvider
11
+ {
12
+ private $data;
13
+ private $previousType;
14
+ private $previousParams;
15
+ private $httpHeader = array();
16
+ private $curlOptions = array();
17
+
18
+ /**
19
+ * this implementation of the data provider uses the type as request path in addition to the request context path.
20
+ * please insure that this is the full action name, i.e. "Search.ff"
21
+ *
22
+ * @param string type
23
+ */
24
+ public function setType($type)
25
+ {
26
+ $this->type = $type;
27
+ }
28
+
29
+ /**
30
+ * Set multiple options for a cURL transfer like described at {@link http://php.net/manual/en/function.curl-setopt.php}
31
+ *
32
+ * @link http://php.net/manual/en/function.curl-setopt.php
33
+ * @param array of options
34
+ * @return void
35
+ */
36
+ public function setCurlOptions(array $options) {
37
+ $this->curlOptions = $options;
38
+ }
39
+
40
+ /**
41
+ * add an array of HTTP header fields in the format array('Content-type: text/plain', 'Content-length: 100')
42
+ *
43
+ * @param array $httpHeader
44
+ * @return void
45
+ */
46
+ public function addHttpHeaderFields(array $httpHeader) {
47
+ $this->httpHeader = array_merge($this->httpHeader, $httpHeader);
48
+ }
49
+
50
+ /**
51
+ * {@inheritdoc}
52
+ * this implementation returns the data as string, no mather what content type set at the http response
53
+ *
54
+ * @return string data
55
+ */
56
+ public function getData()
57
+ {
58
+ if ($this->data == null
59
+ || $this->type != $this->previousType
60
+ || count(array_diff_assoc($this->getParams(), $this->previousParams)) > 0
61
+ ) {
62
+ $this->previousParams = $this->getParams();
63
+ $this->previousType = $this->type;
64
+ $this->data = $this->loadResponse();
65
+ }
66
+ return $this->data;
67
+ }
68
+
69
+ /**
70
+ * this function sends the request to the server and loads the response data
71
+ *
72
+ * @throws Exception on connection error
73
+ * @return response data
74
+ **/
75
+ protected function loadResponse()
76
+ {
77
+ if ($this->type == null) {
78
+ throw new Exception('request type not set! can not do a request without knowing the type.');
79
+ }
80
+ $params = $this->getParams();
81
+ $config = $this->getConfig();
82
+ if ($config->getLanguage() != '') {
83
+ $this->addHttpHeaderFields(array('Accept-Language: ' . $config->getLanguage()));
84
+ }
85
+
86
+ $url = $this->getAuthenticationUrl();
87
+ return $this->sendRequest($url);
88
+ }
89
+
90
+ /**
91
+ * this function returns the request url with the correct authentication method (set by the configuration).
92
+ *
93
+ * @return string url
94
+ */
95
+ public function getAuthenticationUrl() {
96
+ $config = $this->getConfig();
97
+ if ($config->isHttpAuthenticationType()) {
98
+ $url = $this->getHttpAuthenticationUrl();
99
+ } else if ($config->isSimpleAuthenticationType()) {
100
+ $url = $this->getSimpleAuthenticationUrl();
101
+ } else if ($config->isAdvancedAuthenticationType()) {
102
+ $url = $this->getAdvancedAuthenticationUrl();
103
+ } else {
104
+ $url = $this->getNonAuthenticationUrl();
105
+ }
106
+ return $url;
107
+ }
108
+
109
+ /**
110
+ * send request and return response data
111
+ *
112
+ * @param string url
113
+ * @return string returned http body
114
+ */
115
+ protected function sendRequest($url)
116
+ {
117
+ $cResource = curl_init($url);
118
+ curl_setopt_array($cResource, array(
119
+ CURLOPT_FOLLOWLOCATION => true,
120
+ CURLOPT_RETURNTRANSFER => true,
121
+ CURLOPT_SSL_VERIFYPEER => false,
122
+ CURLOPT_SSL_VERIFYHOST => false,
123
+ CURLOPT_MAXREDIRS => 2,
124
+ CURLOPT_CONNECTTIMEOUT => 2,
125
+ CURLOPT_TIMEOUT => 4,
126
+ CURLOPT_USERAGENT => 'FACT-Finder PHP Framework V' . $this->getConfig()->getVersion(),
127
+ CURLOPT_HTTPHEADER => $this->httpHeader
128
+ )
129
+ );
130
+ if (sizeof($this->curlOptions) > 0) {
131
+ curl_setopt_array($cResource, $this->curlOptions);
132
+ }
133
+
134
+ $response = curl_exec($cResource);
135
+ $httpCode = curl_getinfo($cResource, CURLINFO_HTTP_CODE);
136
+ $curlErr = curl_error($cResource);
137
+ curl_close($cResource);
138
+
139
+ if (intval($httpCode) >= 400) {
140
+ throw new Exception("Connection failed. HTTP code: $httpCode", $httpCode);
141
+ } else if ($httpCode == 0) {
142
+ throw new Exception("Connection refused. $curlErr");
143
+ }
144
+ return $response;
145
+ }
146
+
147
+ /**
148
+ * get url with advanced authentication encryption
149
+ *
150
+ * @return string url
151
+ */
152
+ private function getAdvancedAuthenticationUrl() {
153
+ $config = $this->getConfig();
154
+ $params = $this->getParams();
155
+
156
+ if ($config->getChannel() != '') {
157
+ $params['channel'] = $config->getChannel();
158
+ }
159
+
160
+ $ts = time() . '000'; //millisecondes needed
161
+ $prefix = $config->getAdvancedAuthPrefix();
162
+ $postfix = $config->getAdvancedAuthPostfix();
163
+ $authParams = "timestamp=$ts&username=".$config->getAuthUser()
164
+ . '&password=' . md5($prefix . $ts . md5($config->getAuthPasswort()) . $postfix);
165
+
166
+ $url = $config->getRequestProtokoll() . '://'
167
+ . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
168
+ . $config->getContext() . '/'.$this->type.'?' . http_build_query($params, '', '&')
169
+ . (count($params)?'&':'') . $authParams;
170
+ return $url;
171
+ }
172
+
173
+ /**
174
+ * get url with simple authentication encryption
175
+ *
176
+ * @return string url
177
+ */
178
+ private function getSimpleAuthenticationUrl() {
179
+ $config = $this->getConfig();
180
+ $params = $this->getParams();
181
+
182
+ if ($config->getChannel() != '') {
183
+ $params['channel'] = $config->getChannel();
184
+ }
185
+
186
+ $ts = time() . '000'; //millisecondes needed but won't be considered
187
+ $authParams = "timestamp=$ts&username=".$config->getAuthUser()
188
+ . '&password=' . md5($config->getAuthPasswort());
189
+
190
+ $url = $config->getRequestProtokoll() . '://'
191
+ . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
192
+ . $config->getContext() . '/'.$this->type.'?' . http_build_query($params, '', '&')
193
+ . (count($params)?'&':'') . $authParams;
194
+ return $url;
195
+ }
196
+
197
+ /**
198
+ * get url with http authentication
199
+ *
200
+ * @return string url
201
+ */
202
+ private function getHttpAuthenticationUrl() {
203
+ $config = $this->getConfig();
204
+ $params = $this->getParams();
205
+
206
+ if ($config->getChannel() != '') {
207
+ $params['channel'] = $config->getChannel();
208
+ }
209
+
210
+ $auth = $config->getAuthUser() . ':' . $config->getAuthPasswort() . '@';
211
+ if ($auth == ':@') $auth = '';
212
+
213
+ $url = $config->getRequestProtokoll() . '://' . $auth
214
+ . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
215
+ . $config->getContext() . '/' . $this->type . (count($params)?'?':'')
216
+ . http_build_query($params, '', '&');
217
+ return $url;
218
+ }
219
+
220
+ /**
221
+ * get url with no authentication.
222
+ *
223
+ * @return string url
224
+ */
225
+ public function getNonAuthenticationUrl() {
226
+ $config = $this->getConfig();
227
+ $params = $this->getParams();
228
+
229
+ if ($config->getChannel() != '') {
230
+ $params['channel'] = $config->getChannel();
231
+ }
232
+
233
+ $url = $config->getRequestProtokoll() . '://'
234
+ . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
235
+ . $config->getContext() . '/' . $this->type . (count($params)?'?':'')
236
+ . http_build_query($params, '', '&');
237
+
238
+ return $url;
239
+ }
240
+ }
lib/FACTFinder/Http/ScicAdapter.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * http scic adapater
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: ScicAdapter.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Http
9
+ */
10
+ class FACTFinder_Http_ScicAdapter extends FACTFinder_Abstract_ScicAdapter
11
+ {
12
+ /**
13
+ * {@inheritdoc}
14
+ */
15
+ protected function init() {
16
+ $this->getDataProvider()->setType('SCIC.ff');
17
+ }
18
+
19
+ /**
20
+ * {@inheritdoc}
21
+ *
22
+ * @return boolean $success
23
+ */
24
+ protected function applyTracking() {
25
+ $success = trim($this->getData());
26
+ return $success == 'true';
27
+ }
28
+ }
lib/FACTFinder/Http/SuggestAdapter.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * this suggest adapter requests the raw suggest data
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: SuggestAdapter.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Http
9
+ */
10
+ class FACTFinder_Http_SuggestAdapter extends FACTFinder_Abstract_SuggestAdapter
11
+ {
12
+ /**
13
+ * {@inheritdoc}
14
+ */
15
+ protected function init()
16
+ {
17
+ $this->getDataProvider()->setType('Suggest.ff');
18
+ $this->getDataProvider()->setCurlOptions(array(
19
+ CURLOPT_CONNECTTIMEOUT => 1,
20
+ CURLOPT_TIMEOUT => 2
21
+ ));
22
+ }
23
+
24
+ /**
25
+ * {@inheritdoc}
26
+ * this implementation returns raw suggestions strings
27
+ *
28
+ * @return string raw data
29
+ */
30
+ protected function createSuggestions()
31
+ {
32
+ return $this->getData();
33
+ }
34
+ }
lib/FACTFinder/Item.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * an factfinder item is a simple selectable item on a website, so it is represented by a value and an url
5
+ * it is NOT defined yet, how this item affects on the website
6
+ *
7
+ * @author Rudolf Batt <rb@omikron.net>
8
+ * @version $Id: Item.php 614 2011-02-01 16:08:47Z weller $
9
+ * @package FACTFinder\Common
10
+ **/
11
+ class FACTFinder_Item
12
+ {
13
+ private $value;
14
+ private $url;
15
+ private $isSelected;
16
+
17
+ /**
18
+ * @param string value
19
+ * @param string url
20
+ * @param boolean is selected (default: false)
21
+ */
22
+ public function __construct($value, $url, $isSelected = false){
23
+ $this->value = strval($value);
24
+ $this->url = strval($url);
25
+ $this->isSelected = $isSelected == true;
26
+ }
27
+
28
+ /**
29
+ * @return string
30
+ */
31
+ public function getValue() {
32
+ return $this->value;
33
+ }
34
+
35
+ /**
36
+ * @return string
37
+ */
38
+ public function getUrl() {
39
+ return $this->url;
40
+ }
41
+
42
+ /**
43
+ * @return boolean
44
+ */
45
+ public function isSelected() {
46
+ return $this->isSelected;
47
+ }
48
+ }
lib/FACTFinder/Loader.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * handles different loading tasks
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: Loader.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Common
9
+ */
10
+
11
+ // init
12
+ if (!defined('DS')) {
13
+ define('DS', DIRECTORY_SEPARATOR);
14
+ }
15
+ if (!defined('LIB_DIR')) {
16
+ define('LIB_DIR', dirname(dirname(__FILE__)));
17
+ }
18
+
19
+ set_include_path(LIB_DIR . PATH_SEPARATOR . get_include_path());
20
+ spl_autoload_register(array('FACTFinder_Loader', 'autoload'));
21
+
22
+ // don't know, whether I should do that
23
+ if (function_exists('__autoload') && array_search('__autoload', spl_autoload_functions()) === false) {
24
+ spl_autoload_register('__autoload');
25
+ }
26
+
27
+ final class FF extends FACTFinder_Loader{} //shortcut for the loader class
28
+ class FACTFinder_Loader
29
+ {
30
+ private static $singletons = array();
31
+ private static $classNames = array();
32
+
33
+ public static function autoload($classname)
34
+ {
35
+ $filename = self::getFilename($classname);
36
+ if (file_exists($filename)) {
37
+ include_once $filename;
38
+ }
39
+ }
40
+
41
+ private static function getFilename($classname)
42
+ {
43
+ return LIB_DIR . DS . str_replace('_', DS, $classname) . '.php';
44
+ }
45
+
46
+ private static function canLoadClass($classname)
47
+ {
48
+ return file_exists(self::getFilename($classname));
49
+ }
50
+
51
+ /**
52
+ * Creates an instance of a class taking into account classes with the prefix "Custom_" instead of "FACTFinder_".
53
+ * USE THIS method instead of the PHP "new" keyword.
54
+ * Eg. "$obj = new myclass;" should be "$obj = FACTFinder_Loader::getInstance("myclass")" instead!
55
+ * You can also pass arguments for a constructor:
56
+ * FACTFinder_Loader::getInstance('myClass', $arg1, $arg2, ..., $argN)
57
+ *
58
+ * @param string class name to instantiate
59
+ * @param mixed optional as many parameters as the class needs to be created
60
+ * @return object A reference to the object
61
+ */
62
+ public static function getInstance($name)
63
+ {
64
+ if (isset(self::$classNames[$name])) {
65
+ $className = self::$classNames[$name];
66
+ } else {
67
+ $className = self::getClassName($name);
68
+ self::$classNames[$name] = $className;
69
+ }
70
+
71
+ // this snippet is from the typo3 class "t3lib_div" writen by Kasper Skaarhoj <kasperYYYY@typo3.com>
72
+ if (func_num_args() > 1) {
73
+ // getting the constructor arguments by removing this
74
+ // method's first argument (the class name)
75
+ $constructorArguments = func_get_args();
76
+ array_shift($constructorArguments);
77
+
78
+ $reflectedClass = new ReflectionClass($className);
79
+ $instance = $reflectedClass->newInstanceArgs($constructorArguments);
80
+ } else {
81
+ $instance = new $className;
82
+ }
83
+
84
+ return $instance;
85
+ }
86
+
87
+ /**
88
+ * creates an instance of the class once and returns it everytime. uses getInstance
89
+ *
90
+ * @param string class name to instantiate
91
+ * @param mixed optional as many parameters as the class needs to be created
92
+ * @return object A reference to the object
93
+ */
94
+ public static function getSingleton($name)
95
+ {
96
+ if (!isset(self::$singletons[$name])) {
97
+ $params = func_get_args();
98
+ self::$singletons[$name] = call_user_func_array(array("self", "getInstance"), $params);
99
+ }
100
+ return self::$singletons[$name];
101
+ }
102
+
103
+ /**
104
+ * check whether there is a custom class with the prefix "Custom_" instead of "FACTFinder_"
105
+ * if non of them exists, it also checks if the name is the classname itselft
106
+ */
107
+ private static function getClassName($name)
108
+ {
109
+ $name = trim(str_replace('factfinder/', '', $name));
110
+ $name = str_replace(' ', '_', ucwords(str_replace('/', ' ', $name)));
111
+
112
+ // check whether there is a custom or lib-unrelated class
113
+ $oldCustomClassName = 'Custom_' . $name;
114
+ $customClassName = 'FACTFinderCustom_' . $name;
115
+ $factfinderClassName = 'FACTFinder_' . $name;
116
+ $defaultClassName = $name;
117
+
118
+ if (self::canLoadClass($customClassName)) {
119
+ $className = $customClassName;
120
+ } else if (self::canLoadClass($oldCustomClassName)) {
121
+ $className = $oldCustomClassName;
122
+ } else if (self::canLoadClass($factfinderClassName)) {
123
+ $className = $factfinderClassName;
124
+ } else if (class_exists($defaultClassName)) { //trigger other autload methods
125
+ $className = $defaultClassName;
126
+ } else {
127
+ throw new Exception("class '$defaultClassName' not found");
128
+ }
129
+ return $className;
130
+ }
131
+ }
lib/FACTFinder/Paging.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class for creating pagelinks on a search result page
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: Paging.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Common
9
+ **/
10
+ class FACTFinder_Paging implements IteratorAggregate
11
+ {
12
+ private $currentPage;
13
+ private $pageCount;
14
+ private $paramsParser;
15
+ private $params;
16
+ private $iterator;
17
+ private $displayPageCount = 9;
18
+
19
+ /**
20
+ * class constructor - puts paging data from the SimpleXMLElement object
21
+ * into usefull structure
22
+ *
23
+ * @param int $currentPage
24
+ * @param int $pageCount
25
+ * @param FACTFinder_ParametersParser $paramsParser because this class is creating its urls
26
+ */
27
+ public function __construct($currentPage, $pageCount, FACTFinder_ParametersParser $paramsParser)
28
+ {
29
+ $this->currentPage = intval($currentPage);
30
+ $this->pageCount = intval($pageCount);
31
+ $this->paramsParser = $paramsParser;
32
+ $this->params = $paramsParser->getRequestParams();
33
+ }
34
+
35
+ /**
36
+ * get iterator to iterate over all paging items around the current page, altogether not more than set
37
+ * by "setDisplayPageCount" (default: 9). each item is an object of FACTFinder_Item
38
+ *
39
+ * @return Traversable
40
+ */
41
+ public function getIterator()
42
+ {
43
+ $iterator = new ArrayIterator();
44
+ for($page = $this->getFirstPageNumberShown(); $page <= $this->getLastPageNumberShown(); $page++) {
45
+ $iterator->append(
46
+ FF::getInstance('item', $page, $this->getPageLink($page), ($page == $this->currentPage))
47
+ );
48
+ }
49
+ return $iterator;
50
+ }
51
+
52
+ /**
53
+ * returns the numer of all existing pages for the current result
54
+ *
55
+ * @return int pagecount
56
+ **/
57
+ public function getPageCount()
58
+ {
59
+ return $this->pageCount;
60
+ }
61
+
62
+ /**
63
+ * returns the current page number
64
+ *
65
+ * @return int pagenumber
66
+ **/
67
+ public function getCurrentPageNumber()
68
+ {
69
+ return $this->currentPage;
70
+ }
71
+
72
+ /**
73
+ * returns the url (link) for the given page. If the page does not exist,
74
+ * it returns an empty string
75
+ *
76
+ * @param int page number
77
+ * @param String optional: link target
78
+ * @return String url (link)
79
+ **/
80
+ public function getPageLink($page_number, $link_target = null)
81
+ {
82
+ if ($page_number > $this->pageCount || $page_number < 1) {
83
+ return '';
84
+ }
85
+ return $this->paramsParser->createPageLink($this->params, array('page' => $page_number), $link_target);
86
+ }
87
+
88
+ /**
89
+ * returns the url (link) for the previous page
90
+ *
91
+ * @param String optional: link target
92
+ * @return String url (link)
93
+ **/
94
+ public function getPreviousPageLink($link_target = '')
95
+ {
96
+ if ( $this->currentPage > 1) {
97
+ $previous_page_number = ($this->currentPage - 1);
98
+ } else {
99
+ return '';
100
+ }
101
+ return $this->getPageLink($previous_page_number, $link_target);
102
+ }
103
+
104
+ /**
105
+ * returns the url (link) for the next page
106
+ *
107
+ * @param String optional: link target
108
+ * @return String url (link)
109
+ **/
110
+ public function getNextPageLink($link_target = '')
111
+ {
112
+ if ( $this->currentPage < $this->pageCount) {
113
+ $previous_page_number = ($this->currentPage + 1);
114
+ } else {
115
+ return '';
116
+ }
117
+ return $this->getPageLink($previous_page_number, $link_target);
118
+ }
119
+
120
+ /**
121
+ * set maximum count of pages to display
122
+ *
123
+ * @param int count of pages to display
124
+ * @return void
125
+ */
126
+ public function setDisplayPageCount($displayPageCount)
127
+ {
128
+ $this->displayPageCount = intval($displayPageCount);
129
+ }
130
+
131
+ /**
132
+ * returns the first page number for the pagelinks to be shown
133
+ * needs the number of the maximum shown links
134
+ *
135
+ * @param int page links count
136
+ * @return int first shown page number
137
+ **/
138
+ public function getFirstPageNumberShown()
139
+ {
140
+ if ($this->currentPage <= floor($this->displayPageCount / 2) || $this->pageCount < $this->displayPageCount) {
141
+ return 1;
142
+ } else if ($this->currentPage > ($this->pageCount - $this->displayPageCount +1 )) {
143
+ return ($this->pageCount - $this->displayPageCount + 1);
144
+ } else {
145
+ return ($this->currentPage - floor($this->displayPageCount / 2));
146
+ }
147
+ }
148
+
149
+ /**
150
+ * returns the last page number for the pagelinks to be shown
151
+ * needs the number of the maximum shown links
152
+ *
153
+ * @param int page links count
154
+ * @return int first shown page number
155
+ **/
156
+ public function getLastPageNumberShown()
157
+ {
158
+ if ($this->pageCount < $this->displayPageCount) {
159
+ return $this->pageCount;
160
+ }
161
+
162
+ $first_page_number = $this->getFirstPageNumberShown($this->displayPageCount);
163
+ if ($first_page_number+$this->displayPageCount >= $this->pageCount) {
164
+ return $this->pageCount;
165
+ } else {
166
+ return $first_page_number+$this->displayPageCount;
167
+ }
168
+ }
169
+ }
lib/FACTFinder/Parameters.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * the factfinder parameters contains all relevant parameter which makes effect to the factfinder search result.
5
+ * It does NOT contain all request parameters. The parameters represents a state of a factfinder result.
6
+ *
7
+ * @author Rudolf Batt <rb@omikron.net>
8
+ * @version $Id: Parameters.php 614 2011-02-01 16:08:47Z weller $
9
+ * @package FACTFinder\Common
10
+ */
11
+ class FACTFinder_Parameters
12
+ {
13
+ private $query;
14
+ private $channel;
15
+ private $productsPerPage;
16
+ private $page;
17
+ private $filters;
18
+ private $sortings;
19
+ private $isNavigation;
20
+ private $followSearch;
21
+
22
+ /**
23
+ * @param string query
24
+ * @param string channel
25
+ * @param int productsPerPage
26
+ * @param int page
27
+ * @param array filters
28
+ * @param array sortings
29
+ * @param boolean isNavigation
30
+ * @param int followSearch
31
+ */
32
+ public function __construct($query, $channel, $productsPerPage = null, $page = 1, array $filters = array(), array $sortings = array(), $isNavigation = false, $followSearch = 10000) {
33
+ $this->query = strval($query);
34
+ $this->channel = strval($channel);
35
+ $this->productsPerPage = $productsPerPage == null ? null : intval($productsPerPage);
36
+ $this->page = intval($page);
37
+ $this->filters = $filters;
38
+ $this->sortings = $sortings;
39
+ $this->isNavigation = $isNavigation == true;
40
+ $this->followSearch = intval($followSearch);
41
+ }
42
+
43
+ /**
44
+ * @return string
45
+ */
46
+ public function getQuery()
47
+ {
48
+ return $this->query;
49
+ }
50
+
51
+ /**
52
+ * @return string
53
+ */
54
+ public function getChannel()
55
+ {
56
+ return $this->channel;
57
+ }
58
+
59
+ /**
60
+ * @return int
61
+ */
62
+ public function getProductsPerPage()
63
+ {
64
+ return $this->productsPerPage;
65
+ }
66
+
67
+ /**
68
+ * @return int
69
+ */
70
+ public function getPage()
71
+ {
72
+ return $this->page;
73
+ }
74
+
75
+ /**
76
+ * @return array string => string
77
+ */
78
+ public function getFilters()
79
+ {
80
+ return $this->filters;
81
+ }
82
+
83
+ /**
84
+ * @return array string => string
85
+ */
86
+ public function getSortings()
87
+ {
88
+ return $this->sortings;
89
+ }
90
+
91
+ /**
92
+ * @return boolean true if navigation is enabled
93
+ */
94
+ public function isNavigation()
95
+ {
96
+ return $this->isNavigation;
97
+ }
98
+
99
+ /**
100
+ * @return int follow search value
101
+ */
102
+ public function getFollowSearch()
103
+ {
104
+ return $this->followSearch;
105
+ }
106
+ }
lib/FACTFinder/ParametersParser.php ADDED
@@ -0,0 +1,349 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * this class handels the parameters conversion between the client url, the links on the webpage and the url for the
5
+ * server. it can be seen as a parameter factory.
6
+ *
7
+ * @author Rudolf Batt <rb@omikron.net>
8
+ * @version $Id: ParametersParser.php 614 2011-02-01 16:08:47Z weller $
9
+ * @package FACTFinder\Common
10
+ */
11
+ class FACTFinder_ParametersParser
12
+ {
13
+ private static $w283751Done = false;
14
+ private $requestParams;
15
+ private $requestTarget;
16
+
17
+ private $config;
18
+ private $encodingHandler;
19
+
20
+ /**
21
+ * @param FACTFinder_Abstract_IConfiguration config
22
+ * @param FACTFinder_EncodingHandler $encodingHandler
23
+ */
24
+ public function __construct(FACTFinder_Abstract_Configuration $config, FACTFinder_EncodingHandler $encodingHandler)
25
+ {
26
+ $this->config = $config;
27
+ $this->encodingHandler = $encodingHandler;
28
+ }
29
+
30
+ /**
31
+ * runs a workaround for php to restore the original parameter names from the url respectively $_SERVER['QUERY_STRING'].
32
+ * this method will only run once and change the global variables $GLOBALS, $_GET and $_REQUEST. parameters which are
33
+ * transformed by php will be left at the $_REQUEST array, the $_GET array will only contain the correct parameters
34
+ *
35
+ * @link http://stackoverflow.com/questions/283751/php-replaces-spaces-with-underlines
36
+ * @return void
37
+ */
38
+ final public static function runWorkaround283751()
39
+ {
40
+ if (self::$w283751Done === false) {
41
+ $params = self::parseParamsFromString($_SERVER['QUERY_STRING']);
42
+ $_GET = array();
43
+ $_GLOBALS['_GET'] = $_GET;
44
+ foreach($params AS $key => $value){
45
+ $_GET[$key] = $value;
46
+ $_REQUEST[$key] = $value;
47
+ $GLOBALS['_GET'][$key] = $value;
48
+ $GLOBALS['_REQUEST'][$key] = $value;
49
+ }
50
+ self::$w283751Done = true;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * returns the params of the request as string to string array
56
+ *
57
+ * @return array of params
58
+ */
59
+ public function getRequestParams()
60
+ {
61
+ if ($this->requestParams == null) {
62
+ self::runWorkaround283751();
63
+ $this->requestParams = $this->parseRequest();
64
+ }
65
+ return $this->requestParams;
66
+ }
67
+
68
+ /**
69
+ * loads the parameters from request and returns them as array
70
+ * also conciders the mapping and ignore rules
71
+ *
72
+ * @return array parameters
73
+ */
74
+ private function parseRequest()
75
+ {
76
+ $params = $this->encodingHandler->encodeUrlForPage(array_merge($_POST, $_GET)); // dont use $_REQUEST, because it also containts $_COOKIE;
77
+ return $params;
78
+ }
79
+
80
+ /**
81
+ * @param array parameters. if null, using the request parameters (default: null)
82
+ * @return FACTFinder_Parameteres object
83
+ */
84
+ public function getFactfinderParams(array $params = null)
85
+ {
86
+ if ($params == null) {
87
+ $params = $this->getServerRequestParams();
88
+ }
89
+
90
+ $filters = array();
91
+ $sortings = array();
92
+ foreach($params AS $key => $value) {
93
+ if (strpos($key, 'filter') === 0) {
94
+ $filters[str_replace('filter', '', $key)] = $value;
95
+ } else
96
+ if (strpos($key, 'sort' && ($value == 'asc' || $value == 'desc')) === 0) {
97
+ $sortings[str_replace('sort', '', $key)] = $value;
98
+ }
99
+ }
100
+
101
+ return FF::getInstance('parameters',
102
+ isset($params['query']) ? $params['query'] : '',
103
+ $this->config->getChannel(),
104
+ isset($params['productsPerPage']) ? $params['productsPerPage'] : null,
105
+ isset($params['page']) ? $params['page'] : 1,
106
+ $filters,
107
+ $sortings,
108
+ (isset($params['catalog']) && $params['catalog'] == 'true'),
109
+ isset($params['followSearch']) ? $params['followSearch'] : 10000
110
+ );
111
+ }
112
+
113
+ /**
114
+ * @param String parameters
115
+ * @return FACTFinder_Parameteres object
116
+ */
117
+ public function getFactfinderParamsFromString($paramString)
118
+ {
119
+ $params = self::parseParamsFromString($paramString);
120
+ return $this->getFactfinderParams($params);
121
+ }
122
+
123
+ /**
124
+ * converts the factfinder parameters object into a params array
125
+ *
126
+ * @return array params
127
+ */
128
+ public function parseFactfinderParams(FACTFinder_Parameteres $ffparams)
129
+ {
130
+ $filters = array();
131
+ foreach($ffparams->getFilters() AS $key => $value) {
132
+ $filters['filter'.$key] = $value;
133
+ }
134
+
135
+ $sortings = array();
136
+ foreach($ffparams->getSortings() AS $key => $value) {
137
+ $sortings['sort'.$key] = $value;
138
+ }
139
+
140
+ return array_merge(
141
+ array(
142
+ 'query' => $ffparams->getQuery(),
143
+ 'channel' => $ffparams->getChannel(),
144
+ 'productsPerPage' => $ffparams->getProductsPerPage(),
145
+ 'page' => $ffparams->getPage(),
146
+ 'followSearch' => $ffparams->getFollowSearch()
147
+ ),
148
+ $filters,
149
+ $sortings
150
+ );
151
+ }
152
+
153
+ /**
154
+ * extracts a paramenter array with name=>value pairs from an url string.
155
+ * also only url encoding is done but no further encodings.
156
+ *
157
+ * @param string url
158
+ * @return array of parameter variables
159
+ */
160
+ public static function parseParamsFromString($paramString)
161
+ {
162
+ if (strpos($paramString, '?') !== false) {
163
+ $paramString = substr($paramString, strpos($paramString, '?')+1);
164
+ }
165
+ $paramsArray = array();
166
+ $a_pairs = explode('&', $paramString);
167
+ foreach($a_pairs AS $s_pair){
168
+ $a_pair = explode('=', $s_pair);
169
+ if(count($a_pair) == 1) {
170
+ $a_pair[1] = '';
171
+ }
172
+
173
+ $a_pair[0] = urldecode($a_pair[0]);
174
+ $a_pair[1] = urldecode($a_pair[1]);
175
+
176
+ $paramsArray[$a_pair[0]] = $a_pair[1];
177
+ }
178
+ return $paramsArray;
179
+ }
180
+
181
+ /**
182
+ * the FACT-Finder result is UTF-8 encoded, so this method parses a url string from the request and also does
183
+ * utf-decoding if needed
184
+ *
185
+ * @param string from factfinder result
186
+ * @return array of paramter variables
187
+ */
188
+ public function parseParamsFromResultString($paramString)
189
+ {
190
+ $params = self::parseParamsFromString($paramString);
191
+ $params = $this->encodingHandler->encodeServerUrlForPageUrl($params);
192
+ return $params;
193
+ }
194
+
195
+ /**
196
+ * get a single value from the request or the default value, if this value does not exist
197
+ *
198
+ * @param parameter name
199
+ * @param default value (default: null)
200
+ * @return request value of parameter $name or $defaultValue if parameter does not exist
201
+ */
202
+ public function getRequestParam($name, $defaultValue = null)
203
+ {
204
+ $params = $this->getRequestParams();
205
+ return isset($params[$name]) ? trim($params[$name]) : $defaultValue;
206
+ }
207
+
208
+ /**
209
+ * returns the params array but with the server mappings and removed ignored server parameters . if params array is
210
+ * not set, the request params will be used
211
+ *
212
+ * @param array parameters (optional)
213
+ * @return array parameters without ignored parameters
214
+ */
215
+ public function getServerRequestParams(array $params = null) {
216
+ if ($params == null) {
217
+ $params = $this->getRequestParams();
218
+ }
219
+
220
+ $params = $this->doServerMappings($params);
221
+ $params = $this->removeIgnoredParams($params, $this->config->getIgnoredServerParams());
222
+ $params = $this->addRequiredParams($params, $this->config->getRequiredServerParams());
223
+ $params = $this->encodingHandler->encodeForServerUrl($params);
224
+
225
+ return $params;
226
+ }
227
+
228
+ /**
229
+ * creates the link-url for the webpage (no html code!). see {@link http://de3.php.net/manual/en/function.array-merge.php array_merge}
230
+ * and {@link http://de3.php.net/manual/en/function.http-build-query.php http_build_query} to know, how the two arrays
231
+ * are merged and how the link will be constructed. additionaly this method will remove parameters which are configured
232
+ * to be ignored
233
+ *
234
+ * @param array of parameters
235
+ * @param array (optional) additional parameters which will overwrite the first parameters if a same key is used
236
+ * @param string (optional) string which will be prepended to the link. if none is given, getRequestTarget() is used
237
+ * @return url for a page link
238
+ */
239
+ public function createPageLink(array $params, array $addParams = array(), $target = null)
240
+ {
241
+ if ($target == null) {
242
+ $target = $this->getRequestTarget();
243
+ }
244
+
245
+ $linkParams = array_merge($params, $addParams);
246
+
247
+ $linkParams = $this->doPageMappings($linkParams);
248
+ $linkParams = $this->removeIgnoredParams($linkParams, $this->config->getIgnoredPageParams());
249
+ $linkParams = $this->addRequiredParams($linkParams, $this->config->getRequiredPageParams());
250
+
251
+ return $target.'?'.http_build_query($linkParams, '', '&');
252
+ }
253
+
254
+ /**
255
+ * remove the ignored params from the params array if set
256
+ *
257
+ * @param array params
258
+ * @param array ignored params, where the param names are the array-keys
259
+ * @return array new modified params
260
+ */
261
+ private function removeIgnoredParams($params, $ignoredParams)
262
+ {
263
+ $returnParams = array();
264
+ foreach($params as $key => $value) {
265
+ // copy each param and do not set to null, because mappings are stored as references in the params array
266
+ if(!isset($ignoredParams[$key]) && !empty($value)) {
267
+ $returnParams[$key] = $value;
268
+ }
269
+ }
270
+ return $returnParams;
271
+ }
272
+
273
+ /**
274
+ * adds the params from the required params map to the params array if not already set
275
+ *
276
+ * @param array params
277
+ * @param array required params as string to string map (array-key = paramname; array-value = default param value)
278
+ * @return array new modified params
279
+ */
280
+ private function addRequiredParams($params, $requiredParams)
281
+ {
282
+ $requestParams = $this->getRequestParams();
283
+ foreach($requiredParams AS $paramName => $defaultValue) {
284
+ if (!isset($params[$paramName])) {
285
+ $params[$paramName] = isset($requestParams[$paramName]) ? $requestParams[$paramName] : $defaultValue;
286
+ }
287
+ }
288
+ return $params;
289
+ }
290
+
291
+ /**
292
+ * get target of the current request url, from "$_SERVER['REQUEST_URI']".
293
+ *
294
+ * @return string request target
295
+ */
296
+ private function getRequestTarget()
297
+ {
298
+ if ($this->requestTarget == null) {
299
+ $this->requestTarget = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
300
+ }
301
+ return $this->requestTarget;
302
+ }
303
+
304
+ /**
305
+ * do mapping for a params array with the page mapping settings from the config. so this method expects server params
306
+ * and return params for the page
307
+ *
308
+ * @param array paramters
309
+ * @return array mapped parameters
310
+ */
311
+ private function doPageMappings(array $params)
312
+ {
313
+ return $this->doMapping($params, $this->config->getPageMappings());
314
+ }
315
+
316
+ /**
317
+ * do mapping for a params array with the server mapping settings from the config. so this method expects page params
318
+ * and return params for the server
319
+ *
320
+ * @param array paramters
321
+ * @return array mapped parameters
322
+ */
323
+ private function doServerMappings(array $params) {
324
+ return $this->doMapping($params, $this->config->getServerMappings());
325
+ }
326
+
327
+ /**
328
+ * maps the keys in the array using the rules. if a "from" parameter does not exist, but the according "to" parameter
329
+ * exist, the "from" will be create - so this mapping normaly works for both directions
330
+ *
331
+ * @param array paramters
332
+ * @param mixed iterable mapping rules
333
+ * @return array mapped parameters
334
+ */
335
+ private function doMapping(array $params, array $mappingRules)
336
+ {
337
+ foreach($mappingRules AS $from => $to) {
338
+ if (isset($params[$from])) { //"from" is more important..
339
+ $params[$to] = &$params[$from];
340
+ } else if (isset($params[$to])) { //but if it does not exist but "to" exists, then "create" from
341
+ $params[$from] = &$params[$to];
342
+ } else { //if none of them exists, just create the params with a null value
343
+ $params[$from] = null;
344
+ $params[$to] = &$params[$from];
345
+ }
346
+ }
347
+ return $params;
348
+ }
349
+ }
lib/FACTFinder/ProductsPerPageOptions.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * represents the fact-finder product-per-page-options
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: ProductsPerPageOptions.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Common
9
+ **/
10
+ class FACTFinder_ProductsPerPageOptions implements IteratorAggregate
11
+ {
12
+ private $options;
13
+ private $selectedOption = null;
14
+ private $defaultOption = null;
15
+
16
+ /**
17
+ * @param array int to string map; the integer is product-per-page option and the string is the according url
18
+ * @param int default option (default: first option)
19
+ * @param int selected option (default: default option)
20
+ */
21
+ public function __construct(array $options, $defaultOption = -1, $selectedOption = -1) {
22
+ $defaultOption = intval($defaultOption);
23
+ $selectedOption = intval($selectedOption);
24
+
25
+ $this->options = new ArrayIterator();
26
+ foreach($options AS $option => $url) {
27
+ $item = FF::getInstance('item', intval($option), $url, ($option == $selectedOption));
28
+ if ($option == $selectedOption) {
29
+ $this->selectedOption = $item;
30
+ }
31
+ if ($option == $defaultOption) {
32
+ $this->defaultOption = $item;
33
+ }
34
+ $this->options->append($item);
35
+ }
36
+
37
+ if ($this->defaultOption == null && $this->options->count() > 0) {
38
+ $this->defaultOption = $this->options[0];
39
+ }
40
+ if ($this->selectedOption == null && $this->defaultOption != null) {
41
+ $this->selectedOption = $this->defaultOption;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * get iterator to iterate over all products-per-page-options. each item is an object of FACTFinder_Item
47
+ *
48
+ * @return Traversable
49
+ */
50
+ public function getIterator()
51
+ {
52
+ return $this->options;
53
+ }
54
+
55
+ /**
56
+ * @return FACTFinder_Item default products per page option
57
+ */
58
+ public function getDefaultOption()
59
+ {
60
+ return $this->defaultOption;
61
+ }
62
+
63
+ /**
64
+ * @param FACTFinder_Item
65
+ * @return boolean true, if the set object is the default product-per-page-option
66
+ */
67
+ public function isDefaultOption(FACTFinder_Item $option) {
68
+ return $this->defaultOption->getValue() == $option->getValue();
69
+ }
70
+
71
+ /**
72
+ * @return FACTFinder_Item selected products per page option
73
+ */
74
+ public function getSelectedOption()
75
+ {
76
+ return $this->selectedOption;
77
+ }
78
+ }
lib/FACTFinder/Record.php ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * represents a FACT-Finder data record
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: Record.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Common
9
+ **/
10
+ class FACTFinder_Record
11
+ {
12
+ protected $id;
13
+ protected $similarity;
14
+ protected $position;
15
+ protected $origPosition;
16
+ protected $fieldValues;
17
+ protected $fieldNames;
18
+
19
+ /**
20
+ * class constructor - creates a record using the given values. if the array contains fieldnames as array-keys, they
21
+ * could be used to get the values again
22
+ *
23
+ * @param string id
24
+ * @param double similarity
25
+ * @param int originalPosition (optional)
26
+ * @param array fieldValues (optional)
27
+ **/
28
+ public function __construct($id, $similarity, $position = 0, $origPosition = 0, array $fieldValues = null)
29
+ {
30
+ $this->id = trim($id);
31
+ $this->similarity = doubleval($similarity);
32
+ if ($this->similarity > 100.0) {
33
+ $this->similarity = 100.0;
34
+ } else if ($this->similarity < 0.0) {
35
+ $this->similarity = 0.0;
36
+ }
37
+
38
+ $this->position = intval($position);
39
+ $this->origPosition = intval($origPosition);
40
+
41
+ if (empty($fieldValues)) {
42
+ $this->fieldNames = array();
43
+ $this->fieldValues = array();
44
+ } else {
45
+ $this->setValues($fieldValues);
46
+ }
47
+ }
48
+
49
+ /**
50
+ * @return string id
51
+ */
52
+ public function getId()
53
+ {
54
+ return $this->id;
55
+ }
56
+
57
+ /**
58
+ * get FACT-Finder similarity, which lays between 0.0 and 100.0, but normaly is greater then the set minSimilarity
59
+ *
60
+ * @return double similarity
61
+ */
62
+ public function getSimilarity()
63
+ {
64
+ return $this->similarity;
65
+ }
66
+
67
+ /**
68
+ * get original position or 0 if there is no original position
69
+ *
70
+ * @return int original position
71
+ */
72
+ public function getOriginalPosition()
73
+ {
74
+ return $this->origPosition;
75
+ }
76
+
77
+ /**
78
+ * get position or 0 if there is no position
79
+ *
80
+ * @return int position
81
+ */
82
+ public function getPosition()
83
+ {
84
+ return $this->position;
85
+ }
86
+
87
+ /**
88
+ * get a value from a field defined by the argument $field, which can be a fieldnumber or a fieldname
89
+ * of the field does not exist, null will be returned
90
+ *
91
+ * @throws Exception if the argument $field is either an integer nor a string
92
+ * @param int|string fieldnumber or fieldname
93
+ * @return string fieldvalue or null if field does not exist
94
+ */
95
+ public function getValue($field)
96
+ {
97
+ $returnValue = null;
98
+ if (is_int($field)) {
99
+ $returnValue = isset($this->fieldValues[$field]) ? $this->fieldValues[$field] : null;
100
+ } else if (is_string($field)) {
101
+ //get value by number and the number by name (mapping from name to value)
102
+ $returnValue = isset($this->fieldNames[$field]) ? $this->fieldValues[$this->fieldNames[$field]] : null;
103
+ }
104
+ return $returnValue;
105
+ }
106
+
107
+ /**
108
+ * proxy method for getValue()
109
+ * @see FACTFinder_Record::getValue()
110
+ */
111
+ public function __get($name)
112
+ {
113
+ return $this->getValue($name);
114
+ }
115
+
116
+ /**
117
+ * set a value to field defined by the argument $field, which can be a fieldnumber or a fieldname
118
+ *
119
+ * @throws Exception if the argument $field is either an integer nor a string
120
+ * @param int|string fieldnumber or fieldname
121
+ * @param string fieldvalue
122
+ * @return void
123
+ */
124
+ public function setValue($field, $value)
125
+ {
126
+ if (is_int($field)) {
127
+ $this->fieldValues[$field] = $value;
128
+ } else if (is_string($field)) {
129
+ if (!isset($this->fieldNames[$field])) {
130
+ // create a new field
131
+ $this->fieldNames[$field] = sizeof($this->fieldValues);
132
+ $this->fieldValues[] = $value;
133
+ } else {
134
+ $this->fieldValues[$this->fieldNames[$field]] = $value;
135
+ }
136
+ } else {
137
+ throw new Exception("it is not (yet) possible to refer to a field using ".gettype($field));
138
+ }
139
+ }
140
+
141
+ /**
142
+ * proxy method for setValue()
143
+ * @see FACTFinder_Record::setValue()
144
+ *
145
+ * @throws Exception if the argument $field is either an integer nor a string
146
+ * @param int|string fieldnumber or fieldname
147
+ * @param string fieldvalue
148
+ * @return void
149
+ */
150
+ public function __set($name, $value)
151
+ {
152
+ return $this->setValue($name, $value);
153
+ }
154
+
155
+ /**
156
+ * set a bulk of values. if the array contains fieldnames as array-keys, they
157
+ * could be used to get the values again
158
+ *
159
+ * @param array fieldvalues with fieldnames as key
160
+ * @return void
161
+ */
162
+ public function setValues(array $fieldValues)
163
+ {
164
+ foreach ($fieldValues AS $name => $value) {
165
+ $this->setValue($name, $value);
166
+ }
167
+ }
168
+ }
lib/FACTFinder/Result.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * this class represents a fact-finder search result
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: Result.php 25893 2010-06-29 08:19:43Z rb $
8
+ * @category Collection
9
+ * @package FACTFinder\Common
10
+ */
11
+ class FACTFinder_Result extends ArrayIterator
12
+ {
13
+ private $foundRecordsCount;
14
+
15
+ /**
16
+ * @param array record (default: empty array)
17
+ * @param int number of records factfinder found for the according query (default: 0)
18
+ */
19
+ public function __construct(array $records = array(), $foundRecordsCount = 0){
20
+ parent::__construct($records);
21
+ $this->foundRecordsCount = intval($foundRecordsCount);
22
+ }
23
+
24
+ /**
25
+ * return number of records found in the whole FACT-Finder result.
26
+ * this object only contains the records for the current page, that must not be the same count
27
+ *
28
+ * @return int found records count
29
+ */
30
+ public function getFoundRecordsCount(){
31
+ return $this->foundRecordsCount;
32
+ }
33
+ }
lib/FACTFinder/SuggestQuery.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * represents a query for suggest
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: SuggestQuery.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Common
9
+ */
10
+ class FACTFinder_SuggestQuery
11
+ {
12
+ private $query;
13
+ private $url;
14
+ private $hitCount;
15
+ private $type;
16
+
17
+ /**
18
+ * @param string $value query
19
+ * @param string $hitCount number of products, which will be found with this query
20
+ * @param string $type type of the query
21
+ */
22
+ public function __construct($query, $url, $hitCount = '', $type = '') {
23
+ $this->query = strval($query);
24
+ $this->url = strval($url);
25
+ $this->hitCount = $hitCount;
26
+ $this->type = $type;
27
+ }
28
+
29
+ /**
30
+ * @return string
31
+ */
32
+ public function getQuery() {
33
+ return $this->query;
34
+ }
35
+
36
+ /**
37
+ * @return string
38
+ */
39
+ public function getUrl() {
40
+ return $this->url;
41
+ }
42
+
43
+ /**
44
+ * return int how many products will be found by this query
45
+ */
46
+ public function getHitCount() {
47
+ return $this->hitCount;
48
+ }
49
+
50
+ /**
51
+ * simple string which describes where this suggest query comes from (i.e. productname, category, logfile)
52
+ *
53
+ * @return string
54
+ */
55
+ public function getType() {
56
+ return $this->type;
57
+ }
58
+ }
lib/FACTFinder/TagQuery.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * represents a tag item for the tagcloud
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: TagQuery.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Common
9
+ */
10
+ class FACTFinder_TagQuery extends FACTFinder_Item
11
+ {
12
+ private $weight;
13
+ private $searchCount;
14
+
15
+ /**
16
+ * @param string $value query
17
+ * @param string $url
18
+ * @param boolean true if this tag lead to the current search result
19
+ * @param double $weight value between 0.0 and 1.0 (optional - default 0.0)
20
+ * @param int $searchCount how often this query was searched in the last 7 days (optional - default 0)
21
+ */
22
+ public function __construct($value, $url, $isSelected = false, $weight = 0.0, $searchCount = 0) {
23
+ parent::__construct($value, $url, $isSelected);
24
+ $this->weight = floatval($weight);
25
+ $this->searchCount = intval($searchCount);
26
+ }
27
+
28
+ /**
29
+ * @return double value between 0.0 and 1.0 to calculate the importance of the query
30
+ */
31
+ public function getWeight() {
32
+ return $this->weight;
33
+ }
34
+
35
+ /**
36
+ * @return int how often this query was searched in the last 7 days
37
+ */
38
+ public function getSearchCount() {
39
+ return $this->searchCount;
40
+ }
41
+ }
lib/FACTFinder/Util.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * util class for some repeated issues which do not fit to a single class
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: Util.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Common
9
+ **/
10
+ class FACTFinder_Util
11
+ {
12
+ private $searchAdapter;
13
+ private $ffparams;
14
+
15
+ public function __construct(FACTFinder_Parameters $ffparams, FACTFinder_Abstract_SearchAdapter $searchAdapter) {
16
+ $this->ffparams = $ffparams;
17
+ $this->searchAdapter = $searchAdapter;
18
+ }
19
+
20
+ /**
21
+ * @return string javascript method call "clickProduct" with all needed arguments
22
+ */
23
+ public function createJavaScriptClickCode($record, $title, $sid)
24
+ {
25
+ $query = $this->ffparams->getQuery();
26
+ $channel = $this->ffparams->getChannel();
27
+
28
+ $currentPageNumber = $this->searchAdapter->getPaging()->getCurrentPageNumber();
29
+ $origPageSize = $this->searchAdapter->getProductsPerPageOptions()->getDefaultOption()->getValue();
30
+ $pageSize = $this->searchAdapter->getProductsPerPageOptions()->getSelectedOption()->getValue();
31
+
32
+ $position = $record->getPosition();
33
+ if ($position != 0) {
34
+ $originalPosition = $record->getOriginalPosition();
35
+ $similarity = $record->getSimilarity();
36
+ $id = $record->getId();
37
+
38
+ $title = addslashes($title);
39
+ $sid = addslashes($sid);
40
+ $clickCode = "clickProduct('$query', '$id', '$position', '$originalPosition', '$currentPageNumber',"
41
+ ."'$similarity', '$sid', '$title', '$pageSize', '$origPageSize', '$channel', 'click');";
42
+ } else {
43
+ $clickCode = '';
44
+ }
45
+
46
+ return $clickCode;
47
+ }
48
+ }
lib/FACTFinder/Xml64/SearchAdapter.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * search adapter using the xml interface. expects a xml formated string from the dataprovider
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: SearchAdapter.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Xml64
9
+ */
10
+ class FACTFinder_Xml64_SearchAdapter extends FACTFinder_Xml65_SearchAdapter
11
+ {
12
+ private $status = null;
13
+ private $isArticleNumberSearch;
14
+
15
+ /**
16
+ * {@inheritdoc}
17
+ * the parameter for the xml result changed in FACT-Finder 6.5, so here it is set different
18
+ */
19
+ protected function init()
20
+ {
21
+ $this->getDataProvider()->setParam('xml', 'true');
22
+ $this->getDataProvider()->setType('Search.ff');
23
+ }
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ * until versio 6.4 of FACT-Finder there are no slider elements
28
+ *
29
+ * @return FACTFinder_Asn
30
+ **/
31
+ protected function createAsn()
32
+ {
33
+ $xmlResult = $this->getData();
34
+ $asn = array();
35
+
36
+ if (!empty($xmlResult->asn)) {
37
+ $encodingHandler = $this->getEncodingHandler();
38
+ $params = $this->getParamsParser()->getRequestParams();
39
+
40
+ foreach ($xmlResult->asn->group AS $xmlGroup) {
41
+ $groupName = $encodingHandler->encodeServerContentForPage((string)$xmlGroup->attributes()->name);
42
+ $groupUnit = '';
43
+ if (isset($xmlGroup->attributes()->unit)) {
44
+ $groupUnit = strval($xmlGroup->attributes()->unit);
45
+ }
46
+
47
+ $group = FF::getInstance('asnGroup',
48
+ array(),
49
+ $encodingHandler->encodeServerContentForPage((string)$xmlGroup->attributes()->name),
50
+ $encodingHandler->encodeServerContentForPage((string)$xmlGroup->attributes()->detailedLinks),
51
+ $groupUnit,
52
+ false
53
+ );
54
+
55
+ //get filters of the current group
56
+ foreach ($xmlGroup->element AS $xmlFilter) {
57
+ $filterLink = $this->getParamsParser()->createPageLink(
58
+ $this->getParamsParser()->parseParamsFromResultString(trim($xmlFilter->searchParams))
59
+ );
60
+ $filter = FF::getInstance('asnFilterItem',
61
+ $encodingHandler->encodeServerContentForPage(trim($xmlFilter->attributes()->name)),
62
+ $filterLink,
63
+ strval($xmlFilter->attributes()->selected) == 'true',
64
+ strval($xmlFilter->attributes()->count),
65
+ strval($xmlFilter->attributes()->clusterLevel),
66
+ strval($xmlFilter->attributes()->previewImage)
67
+ );
68
+
69
+ $group->addFilter($filter);
70
+ }
71
+
72
+ $asn[] = $group;
73
+ }
74
+ }
75
+ return FF::getInstance('asn', $asn);
76
+ }
77
+
78
+ /**
79
+ * {@inheritdoc}
80
+ * until version 6.4 of FACT-Finder, the products per page options are not delivered, so this method creates an
81
+ * artificial products per page options array, but uses the current set productsPerPage value from the result
82
+ *
83
+ * @return FACTFinder_ProductsPerPageOptions
84
+ */
85
+ protected function createProductsPerPageOptions()
86
+ {
87
+ $pppOptions = array(); //default
88
+ $xmlResult = $this->getData();
89
+
90
+ if (!empty($xmlResult->paging)) {
91
+ $params = $this->getParamsParser()->getRequestParams();
92
+
93
+ $selectedOption = intval($xmlResult->paging->attributes()->productsPerPage);
94
+ $defaultOption = 12;
95
+ $options = array();
96
+
97
+ if ($selectedOption < $defaultOption) {
98
+ $defaultOption = $selectedOption;
99
+ }
100
+ $options[$defaultOption] = $this->getProductsPerPageLink($defaultOption);
101
+ if ($selectedOption != $defaultOption) {
102
+ $options[$selectedOption] = $this->getProductsPerPageLink($selectedOption);
103
+ }
104
+
105
+ $pppOptions = FF::getInstance('productsPerPageOptions', $options, $defaultOption, $selectedOption);
106
+ }
107
+ return $pppOptions;
108
+ }
109
+
110
+ private function getProductsPerPageLink($pppOption) {
111
+ $params = $this->getParamsParser()->getRequestParams();
112
+ return $this->getParamsParser()->createPageLink($params, array('productsPerPage' => $pppOption));
113
+ }
114
+ }
lib/FACTFinder/Xml65/SearchAdapter.php ADDED
@@ -0,0 +1,491 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * search adapter using the xml interface. expects a xml formated string from the dataprovider
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: SearchAdapter.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Xml65
9
+ */
10
+ class FACTFinder_Xml65_SearchAdapter extends FACTFinder_Abstract_SearchAdapter
11
+ {
12
+ private $status = null;
13
+ private $isArticleNumberSearch;
14
+ private $xmlData = null;
15
+
16
+ /**
17
+ * {@inheritdoc}
18
+ */
19
+ protected function init()
20
+ {
21
+ $this->getDataProvider()->setParam('format', 'xml');
22
+ $this->getDataProvider()->setType('Search.ff');
23
+ }
24
+
25
+ /**
26
+ * try to parse data as xml
27
+ *
28
+ * @throws Exception of data is no valid XML
29
+ * @return SimpleXMLElement
30
+ */
31
+ protected function getData()
32
+ {
33
+ if ($this->xmlData == null) {
34
+ libxml_use_internal_errors(true);
35
+ $data = parent::getData();
36
+ $this->xmlData = new SimpleXMLElement($data); //throws exception on error
37
+ }
38
+ return $this->xmlData;
39
+ }
40
+
41
+ /**
42
+ * {@inheritdoc}
43
+ *
44
+ * @return string status
45
+ **/
46
+ public function getArticleNumberSearchStatus() {
47
+ if ($this->articleNumberSearchStatus == null) {
48
+
49
+ $this->isArticleNumberSearch = false;
50
+ $this->articleNumberSearchStatus = self::NO_RESULT;
51
+
52
+ if ($this->getStatus() != self::NO_RESULT) {
53
+ $this->loadArticleNumberSearchInformations();
54
+ }
55
+ }
56
+ return $this->articleNumberSearchStatus;
57
+ }
58
+
59
+ /**
60
+ * {@inheritdoc}
61
+ *
62
+ * @return boolean isArticleNumberSearch
63
+ **/
64
+ public function isArticleNumberSearch() {
65
+ if ($this->isArticleNumberSearch === null) {
66
+
67
+ $this->isArticleNumberSearch = false;
68
+
69
+ if ($this->getStatus() != self::NO_RESULT) {
70
+ $this->loadArticleNumberSearchInformations();
71
+ }
72
+ }
73
+ return $this->isArticleNumberSearch;
74
+ }
75
+
76
+ /**
77
+ * fetch article number search status from the xml result
78
+ *
79
+ * @return void
80
+ */
81
+ private function loadArticleNumberSearchInformations() {
82
+ $xmlResult = $this->getData();
83
+ switch($xmlResult->articleNumberSearchStatus){
84
+ case 'nothingFound':
85
+ $this->isArticleNumberSearch = true;
86
+ $this->articleNumberSearchStatus = self::NOTHING_FOUND;
87
+ break;
88
+ case 'resultsFound':
89
+ $this->isArticleNumberSearch = true;
90
+ $this->articleNumberSearchStatus = self::RESULTS_FOUND;
91
+ break;
92
+ case 'noArticleNumberSearch':
93
+ default:
94
+ $this->isArticleNumberSearch = false;
95
+ $this->articleNumberSearchStatus = self::NO_RESULT;
96
+ }
97
+ }
98
+
99
+ /**
100
+ * {@inheritdoc}
101
+ *
102
+ * @return boolean true if search timed out
103
+ **/
104
+ public function isSearchTimedOut()
105
+ {
106
+ $xmlResult = $this->getData();
107
+ if($xmlResult->searchTimedOut == 'true') {
108
+ return true;
109
+ } else {
110
+ return false;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * {@inheritdoc}
116
+ *
117
+ * @return string status
118
+ **/
119
+ public function getStatus()
120
+ {
121
+ if ($this->status == null) {
122
+ $xmlResult = $this->getData();
123
+ switch($xmlResult->searchStatus){
124
+ case 'nothingFound':
125
+ $this->status = self::NOTHING_FOUND;
126
+ break;
127
+ case 'resultsFound':
128
+ $this->status = self::RESULTS_FOUND;
129
+ break;
130
+ default:
131
+ $this->status = self::NO_RESULT;
132
+ }
133
+ }
134
+ return $this->status;
135
+ }
136
+
137
+ /**
138
+ * {@inheritdoc}
139
+ **/
140
+ protected function createSearchParams()
141
+ {
142
+ $breadCrumbTrail = $this->getBreadCrumbTrail();
143
+ if (sizeof($breadCrumbTrail) > 0) {
144
+ $paramString = $breadCrumbTrail[sizeof($breadCrumbTrail)-1]->getUrl();
145
+ $searchParams = $this->getParamsParser()->getFactfinderParamsFromString($paramString);
146
+ } else {
147
+ $searchParams = $this->getParamsParser()->getFactfinderParams();
148
+ }
149
+ return $searchParams;
150
+ }
151
+
152
+ /**
153
+ * {@inheritdoc}
154
+ **/
155
+ protected function createResult()
156
+ {
157
+ //init default values
158
+ $result = array();
159
+ $resultCount = 0;
160
+ $xmlResult = $this->getData();
161
+
162
+ //load result values from the xml element
163
+ if (!empty($xmlResult->results)) {
164
+ $resultCount = (int) $xmlResult->results->attributes()->count;
165
+ $encodingHandler = $this->getEncodingHandler();
166
+
167
+ $paging = $this->getPaging();
168
+ $positionOffset = ($paging->getCurrentPageNumber() - 1) * $this->getProductsPerPageOptions()->getSelectedOption()->getValue();
169
+
170
+ //load result
171
+ $positionCounter = 1;
172
+ foreach($xmlResult->results->record AS $currentRecord){
173
+ // get current position
174
+ $position = $positionOffset + $positionCounter;
175
+ $positionCounter++;
176
+
177
+ // get original position
178
+ if (isset($fieldValues['__ORIG_POSITION__'])) {
179
+ $origPosition = $fieldValues['__ORIG_POSITION__'];
180
+ unset($fieldValues['__ORIG_POSITION__']);
181
+ } else {
182
+ $origPosition = $position;
183
+ }
184
+
185
+ // fetch record values
186
+ $fieldValues = array();
187
+ foreach($currentRecord->field AS $current_field){
188
+ $currentFieldname = (string) $current_field->attributes()->name;
189
+ $fieldValues[$currentFieldname] = (string) $current_field;
190
+ }
191
+
192
+ $result[] = FF::getInstance('record',
193
+ $currentRecord->attributes()->id,
194
+ floatval($currentRecord->attributes()->relevancy),
195
+ $position,
196
+ $origPosition,
197
+ $encodingHandler->encodeServerContentForPage($fieldValues)
198
+ );
199
+ }
200
+ }
201
+ return FF::getInstance('result', $result, $resultCount);
202
+ }
203
+
204
+ /**
205
+ * {@inheritdoc}
206
+ *
207
+ * @return FACTFinder_Asn
208
+ **/
209
+ protected function createAsn()
210
+ {
211
+ $xmlResult = $this->getData();
212
+ $asn = array();
213
+
214
+ if (!empty($xmlResult->asn)) {
215
+ $encodingHandler = $this->getEncodingHandler();
216
+ $params = $this->getParamsParser()->getRequestParams();
217
+
218
+ foreach ($xmlResult->asn->group AS $xmlGroup) {
219
+ $groupName = $encodingHandler->encodeServerContentForPage((string)$xmlGroup->attributes()->name);
220
+ $groupUnit = '';
221
+ if (isset($xmlGroup->attributes()->unit)) {
222
+ $groupUnit = strval($xmlGroup->attributes()->unit);
223
+ }
224
+
225
+ $group = FF::getInstance('asnGroup',
226
+ array(),
227
+ $encodingHandler->encodeServerContentForPage((string)$xmlGroup->attributes()->name),
228
+ $encodingHandler->encodeServerContentForPage((string)$xmlGroup->attributes()->detailedLinks),
229
+ $groupUnit,
230
+ strval($xmlGroup->attributes()->style) == 'SLIDER'
231
+ );
232
+
233
+ //get filters of the current group
234
+ foreach ($xmlGroup->element AS $xmlFilter) {
235
+ $filterLink = $this->getParamsParser()->createPageLink(
236
+ $this->getParamsParser()->parseParamsFromResultString(trim($xmlFilter->searchParams))
237
+ );
238
+
239
+ if ($group->isSliderStyle()) {
240
+ // get last (empty) parameter from the search params property
241
+ $params = $this->getParamsParser()->parseParamsFromResultString(trim($xmlFilter->searchParams));
242
+ end($params);
243
+ $filterLink .= '&'.key($params).'=';
244
+
245
+ $filter = FF::getInstance('asnSliderFilter',
246
+ $filterLink,
247
+ strval($xmlFilter->attributes()->absoluteMin),
248
+ strval($xmlFilter->attributes()->absoluteMax),
249
+ strval($xmlFilter->attributes()->selectedMin),
250
+ strval($xmlFilter->attributes()->selectedMax),
251
+ isset($xmlFilter->attributes()->field) ? strval($xmlFilter->attributes()->field) : ''
252
+ );
253
+ } else {
254
+ $filter = FF::getInstance('asnFilterItem',
255
+ $encodingHandler->encodeServerContentForPage(trim($xmlFilter->attributes()->name)),
256
+ $filterLink,
257
+ strval($xmlFilter->attributes()->selected) == 'true',
258
+ strval($xmlFilter->attributes()->count),
259
+ strval($xmlFilter->attributes()->clusterLevel),
260
+ strval($xmlFilter->attributes()->previewImage),
261
+ isset($xmlFilter->attributes()->field) ? strval($xmlFilter->attributes()->field) : ''
262
+ );
263
+ }
264
+
265
+ $group->addFilter($filter);
266
+ }
267
+
268
+ $asn[] = $group;
269
+ }
270
+ }
271
+ return FF::getInstance('asn', $asn);
272
+ }
273
+
274
+ /**
275
+ * {@inheritdoc}
276
+ *
277
+ * @return array of FACTFinder_SortItem objects
278
+ **/
279
+ protected function createSorting()
280
+ {
281
+ $sorting = array();
282
+ $xmlResult = $this->getData();
283
+
284
+ if (!empty($xmlResult->sorting)) {
285
+ $encodingHandler = $this->getEncodingHandler();
286
+
287
+ foreach ($xmlResult->sorting->sort AS $xmlSortItem) {
288
+ $sortLink = $this->getParamsParser()->createPageLink(
289
+ $this->getParamsParser()->parseParamsFromResultString(trim($xmlSortItem->searchParams))
290
+ );
291
+ $sortItem = FF::getInstance('item',
292
+ $encodingHandler->encodeServerContentForPage(trim($xmlSortItem->attributes()->description)),
293
+ $sortLink,
294
+ strval($xmlSortItem->attributes()->selected) == 'true'
295
+ );
296
+ $sorting[] = $sortItem;
297
+ }
298
+ }
299
+ return $sorting;
300
+ }
301
+
302
+ /**
303
+ * {@inheritdoc}
304
+ *
305
+ * @return array of FACTFinder_Item objects
306
+ **/
307
+ protected function createPaging()
308
+ {
309
+ $paging = null;
310
+ $xmlResult = $this->getData();
311
+
312
+ if (!empty($xmlResult->paging)) {
313
+ $paging = FF::getInstance('paging',
314
+ intval(trim($xmlResult->paging->attributes()->currentPage)),
315
+ intval(trim($xmlResult->paging->attributes()->pageCount)),
316
+ $this->getParamsParser()
317
+ );
318
+ } else {
319
+ $paging = FF::getInstance('paging', 1, 1, $this->getParamsParser());
320
+ }
321
+ return $paging;
322
+ }
323
+
324
+ /**
325
+ * {@inheritdoc}
326
+ *
327
+ * @return FACTFinder_ProductsPerPageOptions
328
+ */
329
+ protected function createProductsPerPageOptions()
330
+ {
331
+ $pppOptions = array(); //default
332
+ $xmlResult = $this->getData();
333
+
334
+ if (!empty($xmlResult->productsPerPageOptions)) {
335
+ $defaultOption = intval(trim($xmlResult->productsPerPageOptions->attributes()->default));
336
+ $selectedOption = intval(trim($xmlResult->productsPerPageOptions->attributes()->selected));
337
+
338
+ $options = array();
339
+ foreach($xmlResult->productsPerPageOptions->option AS $option) {
340
+ $value = intval(trim($option->attributes()->value));
341
+ $url = $this->getParamsParser()->createPageLink(
342
+ $this->getParamsParser()->parseParamsFromResultString(trim($option->searchParams))
343
+ );
344
+ $options[$value] = $url;
345
+ }
346
+ $pppOptions = FF::getInstance('productsPerPageOptions', $options, $defaultOption, $selectedOption);
347
+ }
348
+ return $pppOptions;
349
+ }
350
+
351
+ /**
352
+ * {@inheritdoc}
353
+ *
354
+ * @return array of FACTFinder_BreadCrumbItem objects
355
+ */
356
+ protected function createBreadCrumbTrail()
357
+ {
358
+ $breadCrumbTrail = array();
359
+ $xmlResult = $this->getData();
360
+
361
+ if (!empty($xmlResult->breadCrumbTrail)) {
362
+ $encodingHandler = $this->getEncodingHandler();
363
+
364
+ $breadCrumbCount = count($xmlResult->breadCrumbTrail->item);
365
+ $i = 1;
366
+ foreach ($xmlResult->breadCrumbTrail->item AS $item) {
367
+ $link = $this->getParamsParser()->createPageLink(
368
+ $this->getParamsParser()->parseParamsFromResultString(trim($item->searchParams))
369
+ );
370
+
371
+ $fieldName = '';
372
+ $fieldUnit = '';
373
+ $breadCrumbType = $encodingHandler->encodeServerContentForPage(strval($item->attributes()->type));
374
+ if ($breadCrumbType == 'filter') {
375
+ $fieldName = $encodingHandler->encodeServerContentForPage(strval($item->attributes()->fieldName));
376
+ $fieldUnit = $encodingHandler->encodeServerContentForPage(strval($item->attributes()->fieldUnit));
377
+ }
378
+
379
+ $breadCrumb = FF::getInstance('breadCrumbItem',
380
+ $encodingHandler->encodeServerContentForPage(trim($item->attributes()->value)),
381
+ $link,
382
+ ($i == $breadCrumbCount),
383
+ $breadCrumbType,
384
+ $fieldName,
385
+ $fieldUnit
386
+ );
387
+
388
+ $breadCrumbTrail[] = $breadCrumb;
389
+ $i++;
390
+ }
391
+ }
392
+ return $breadCrumbTrail;
393
+ }
394
+
395
+ /**
396
+ * {@inheritdoc}
397
+ *
398
+ * @return array of FACTFinder_Campaign objects
399
+ */
400
+ protected function createCampaigns()
401
+ {
402
+ $campaigns = array();
403
+ $xmlResult = $this->getData();
404
+
405
+ if (!empty($xmlResult->campaigns)) {
406
+ $encodingHandler = $this->getEncodingHandler();
407
+
408
+ foreach ($xmlResult->campaigns->campaign AS $xmlCampaign) {
409
+ //get redirect
410
+ $redirectUrl = '';
411
+ if (!empty($xmlCampaign->target->destination)) {
412
+ $redirectUrl = $encodingHandler->encodeServerUrlForPageUrl(strval($xmlCampaign->target->destination));
413
+ }
414
+
415
+ $campaign = FF::getInstance('campaign',
416
+ $encodingHandler->encodeServerContentForPage(strval($xmlCampaign->attributes()->name)),
417
+ $encodingHandler->encodeServerContentForPage(strval($xmlCampaign->attributes()->category)),
418
+ $redirectUrl
419
+ );
420
+
421
+ //get feedback
422
+ if (!empty($xmlCampaign->feedback)) {
423
+ $feedback = array();
424
+ foreach ($xmlCampaign->feedback->text as $text) {
425
+ $nr = intval(trim($text->attributes()->nr));
426
+ $feedback[$nr] = $encodingHandler->encodeServerContentForPage((string)$text);
427
+ }
428
+ $campaign->addFeedback($feedback);
429
+ }
430
+
431
+ //get pushed products
432
+ if (!empty($xmlCampaign->pushedProducts)) {
433
+ $pushedProducts = array();
434
+ foreach ($xmlCampaign->pushedProducts->product AS $xmlProduct) {
435
+ $product = FF::getInstance('record', $xmlProduct->attributes()->id, 100);
436
+
437
+ // fetch product values
438
+ $fieldValues = array();
439
+ foreach($xmlProduct->field AS $current_field){
440
+ $currentFieldname = (string) $current_field->attributes()->name;
441
+ $fieldValues[$currentFieldname] = (string) $current_field;
442
+ }
443
+ $product->setValues($encodingHandler->encodeServerContentForPage($fieldValues));
444
+ $pushedProducts[] = $product;
445
+ }
446
+ $campaign->addPushedProducts($pushedProducts);
447
+ }
448
+
449
+ $campaigns[] = $campaign;
450
+ }
451
+ }
452
+ $campaignIterator = FF::getInstance('campaignIterator', $campaigns);
453
+ return $campaignIterator;
454
+ }
455
+
456
+ /**
457
+ * {@inheritdoc}
458
+ *
459
+ * @return array of FACTFinder_SuggestQuery objects
460
+ */
461
+ protected function createSingleWordSearch() {
462
+ $xmlResult = $this->getData();
463
+ $singleWordSearch = array();
464
+ if (isset($xmlResult->singleWordSearch)) {
465
+ foreach ($xmlResult->singleWordSearch->item AS $item) {
466
+ $query = strval($item->attributes()->word);
467
+ $singleWordSearch[] = FF::getInstance('suggestQuery',
468
+ $query,
469
+ $this->getParamsParser()->createPageLink(array('query' => $query)),
470
+ intval(trim($item->attributes()->count))
471
+ );
472
+ }
473
+ }
474
+ return $singleWordSearch;
475
+ }
476
+
477
+ /**
478
+ * get error if there is one
479
+ *
480
+ * @return string if error exists, else null
481
+ */
482
+ public function getError()
483
+ {
484
+ $error = null;
485
+ $xmlResult = $this->getData();
486
+ if (!empty($xmlResult->error)) {
487
+ $error = trim(strval($xmlResult->error));
488
+ }
489
+ return $error;
490
+ }
491
+ }
lib/FACTFinder/Xml65/SuggestAdapter.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * suggest adapter using the xml interface. expects a xml formated string from the dataprovider
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: SuggestAdapter.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Xml65
9
+ */
10
+ class FACTFinder_Xml65_SuggestAdapter extends FACTFinder_Http_SuggestAdapter
11
+ {
12
+ /**
13
+ * {@inheritdoc}
14
+ */
15
+ protected function init()
16
+ {
17
+ parent::init();
18
+ $this->getDataProvider()->setParam('format', 'xml');
19
+ }
20
+
21
+ /**
22
+ * try to parse data as xml
23
+ *
24
+ * @throws Exception of data is no valid XML
25
+ * @return SimpleXMLElement
26
+ */
27
+ protected function getData()
28
+ {
29
+ libxml_use_internal_errors(true);
30
+ return new SimpleXMLElement(parent::getData()); //throws exception on error
31
+ }
32
+
33
+ /**
34
+ * {@inheritdoc}
35
+ * this implementation returns raw suggestions strings
36
+ *
37
+ * @return array of FACTFinder_SuggestQuery objects
38
+ */
39
+ protected function createSuggestions()
40
+ {
41
+ $xmlResult = $this->getData();
42
+ $encodingHandler = $this->getEncodingHandler();
43
+ $paramsParser = $this->getParamsParser();
44
+ $suggest = array();
45
+ if (!empty($xmlResult->suggest)) {
46
+ foreach($xmlResult->suggest AS $xmlSuggestQuery) {
47
+ $query = strval($xmlSuggestQuery->attributes()->query);
48
+ $suggest[] = FF::getInstance('suggestQuery',
49
+ $encodingHandler->encodeServerContentForPage($query),
50
+ $paramsParser->createPageLink(array('query' => $query)),
51
+ strval($xmlSuggestQuery->attributes()->hitcount),
52
+ $encodingHandler->encodeServerContentForPage(strval($xmlSuggestQuery->attributes()->type))
53
+ );
54
+ }
55
+ }
56
+ return $suggest;
57
+ }
58
+ }
lib/FACTFinder/Xml65/TagCloudAdapter.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * tag cloud adapter using the xml interface
5
+ *
6
+ * @author Rudolf Batt <rb@omikron.net>
7
+ * @version $Id: TagCloudAdapter.php 614 2011-02-01 16:08:47Z weller $
8
+ * @package FACTFinder\Xml65
9
+ */
10
+ class FACTFinder_Xml65_TagCloudAdapter extends FACTFinder_Abstract_TagCloudAdapter
11
+ {
12
+ /**
13
+ * {@inheritdoc}
14
+ *
15
+ * @return void
16
+ **/
17
+ public function init()
18
+ {
19
+ $this->getDataProvider()->setType('WhatsHot.ff');
20
+ $this->getDataProvider()->setParam('do', 'getTagCloud');
21
+ }
22
+
23
+ /**
24
+ * try to parse data as xml
25
+ *
26
+ * @throws Exception of data is no valid XML
27
+ * @return SimpleXMLElement
28
+ */
29
+ protected function getData()
30
+ {
31
+ libxml_use_internal_errors(true);
32
+ return new SimpleXMLElement(parent::getData()); //throws exception on error
33
+ }
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ *
38
+ * @return array $tagCloud list of FACTFinder_TagQuery items
39
+ **/
40
+ protected function createTagCloud()
41
+ {
42
+ $tagCloud = array();
43
+ $xmlTagCloud = $this->getData();
44
+ if (!empty($xmlTagCloud->entry)) {
45
+ $encodingHandler = $this->getEncodingHandler();
46
+ $ffparams = $this->getParamsParser()->getFactfinderParams();
47
+ foreach($xmlTagCloud->entry AS $xmlEntry) {
48
+ $query = $encodingHandler->encodeServerContentForPage(strval($xmlEntry));
49
+ $tagCloud[] = FF::getInstance('tagQuery',
50
+ $query,
51
+ $this->getParamsParser()->createPageLink(array('query' => $query)),
52
+ ($ffparams->getQuery() == $query),
53
+ $xmlEntry->attributes()->weight,
54
+ $xmlEntry->attributes()->searchCount
55
+ );
56
+ }
57
+ }
58
+ return $tagCloud;
59
+ }
60
+ }
lib/FACTFinderCustom/Configuration.php ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * this class implements the FACTFinder configuration interface and uses the Zend_Config class. so it's like a decorator
5
+ * for the Zend_Config
6
+ *
7
+ * @package FACTFinder\Common
8
+ */
9
+ class FACTFinderCustom_Configuration implements FACTFinder_Abstract_Configuration
10
+ {
11
+ const HTTP_AUTH = 'http';
12
+ const SIMPLE_AUTH = 'simple';
13
+ const ADVANCED_AUTH = 'advanced';
14
+ const XML_CONFIG_PATH = 'factfinder/search/';
15
+
16
+ private $config;
17
+ private $authType;
18
+ private $pageMappings;
19
+ private $serverMappings;
20
+ private $pageIgnores;
21
+ private $serverIgnores;
22
+ private $requiredPageParams;
23
+ private $requiredServerParams;
24
+
25
+ public function __construct($config = null)
26
+ {
27
+ $this->config = new Varien_Object($config);
28
+ if(is_array($config)){
29
+ $this->config->setData($config);
30
+ }
31
+ }
32
+
33
+ /**
34
+ * @return string
35
+ */
36
+ public function getVersion() {
37
+ return $this->getCustomValue('version');
38
+ }
39
+
40
+ /**
41
+ * @return boolean
42
+ */
43
+ public function isDebugEnabled() {
44
+ return $this->getCustomValue('debug') == 'true';
45
+ }
46
+
47
+ /**
48
+ * @param string name
49
+ * @return string value
50
+ */
51
+ public function getCustomValue($name)
52
+ {
53
+ $value = null;
54
+ if($this->config->getData($name)){
55
+ $value = $this->config->getData($name);
56
+ }else{
57
+ $value = Mage::getStoreConfig(self::XML_CONFIG_PATH.$name);
58
+ }
59
+ return $value;
60
+ }
61
+
62
+ /**
63
+ * @return string
64
+ */
65
+ public function getRequestProtokoll() {
66
+ return $this->getCustomValue('protokoll');
67
+ }
68
+
69
+ /**
70
+ * @return string
71
+ */
72
+ public function getServerAddress() {
73
+ return $this->getCustomValue('address');
74
+ }
75
+
76
+ /**
77
+ * @return int
78
+ */
79
+ public function getServerPort() {
80
+ return $this->getCustomValue('port');
81
+ }
82
+
83
+ /**
84
+ * @return string
85
+ */
86
+ public function getContext() {
87
+ return $this->getCustomValue('context');
88
+ }
89
+
90
+ /**
91
+ * @return string
92
+ */
93
+ public function getChannel() {
94
+ return $this->getCustomValue('channel');
95
+ }
96
+
97
+ /**
98
+ * @return string
99
+ */
100
+ public function getLanguage() {
101
+ return $this->getCustomValue('language');
102
+ }
103
+
104
+ /**
105
+ * @return string
106
+ */
107
+ public function getAuthUser() {
108
+ return $this->getCustomValue('auth_user');
109
+ }
110
+
111
+ /**
112
+ * @return string
113
+ */
114
+ public function getAuthPasswort() {
115
+ return $this->getCustomValue('auth_password');
116
+ }
117
+
118
+ /**
119
+ * @return boolean
120
+ */
121
+ public function isHttpAuthenticationType() {
122
+ return $this->getAuthType() == self::HTTP_AUTH;
123
+ }
124
+
125
+ /**
126
+ * @return boolean
127
+ */
128
+ public function isSimpleAuthenticationType() {
129
+ return $this->getAuthType() == self::SIMPLE_AUTH;
130
+ }
131
+
132
+ /**
133
+ * @return boolean
134
+ */
135
+ public function isAdvancedAuthenticationType() {
136
+ return $this->getAuthType() == self::ADVANCED_AUTH;
137
+ }
138
+
139
+ private function getAuthType() {
140
+ if ($this->authType == null) {
141
+ $this->authType = $this->getCustomValue('auth_type');
142
+ if ( $this->authType != self::HTTP_AUTH
143
+ && $this->authType != self::SIMPLE_AUTH
144
+ && $this->authType != self::ADVANCED_AUTH ) {
145
+ $this->authType = self::HTTP_AUTH;
146
+ }
147
+ }
148
+ return $this->authType;
149
+ }
150
+
151
+ /**
152
+ * @return string
153
+ */
154
+ public function getAdvancedAuthPrefix() {
155
+ return $this->getCustomValue('auth_advancedPrefix');
156
+ }
157
+
158
+ /**
159
+ * @return string
160
+ */
161
+ public function getAdvancedAuthPostfix(){
162
+ return $this->getCustomValue('auth_advancedPostfix');
163
+ }
164
+
165
+ /**
166
+ * {@inheritdoc}
167
+ *
168
+ * @return array
169
+ */
170
+ public function getPageMappings() {
171
+ return array();
172
+ }
173
+
174
+ /**
175
+ * {@inheritdoc}
176
+ *
177
+ * @return array
178
+ */
179
+ public function getServerMappings() {
180
+ return array();
181
+ return array(
182
+ 'q' => 'query',
183
+ 'p' => 'page',
184
+ );
185
+ }
186
+
187
+ /**
188
+ * {@inheritdoc}
189
+ *
190
+ * @return array with string as key and boolean true as value for each of them
191
+ */
192
+ public function getIgnoredPageParams() {
193
+ return array();
194
+ }
195
+
196
+ /**
197
+ * {@inheritdoc}
198
+ *
199
+ * @return array with string as key and boolean true as value for each of them
200
+ */
201
+ public function getIgnoredServerParams() {
202
+ return array();
203
+ }
204
+
205
+ /**
206
+ * {@inheritdoc}
207
+ *
208
+ * @return array string to string map (param-name as array-key; default value as array-value)
209
+ */
210
+ public function getRequiredPageParams(){
211
+ return array();
212
+ }
213
+
214
+ /**
215
+ * {@inheritdoc}
216
+ *
217
+ * @return array string to string map (param-name as array-key; default value as array-value)
218
+ */
219
+ function getRequiredServerParams(){
220
+ return array();
221
+ }
222
+
223
+
224
+ /**
225
+ * {@inheritdoc}
226
+ *
227
+ * @return string
228
+ */
229
+ function getPageContentEncoding() {
230
+ return $this->getCustomValue('pageContent');
231
+ }
232
+
233
+ /**
234
+ * {@inheritdoc}
235
+ *
236
+ * @return string
237
+ */
238
+ function getPageUrlEncoding() {
239
+ return $this->getCustomValue('pageURI');
240
+ }
241
+
242
+ /**
243
+ * {@inheritdoc}
244
+ *
245
+ * @return string
246
+ */
247
+ function getServerUrlEncoding() {
248
+ return $this->getCustomValue('serverURI');
249
+ }
250
+ }
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>FactFinder</name>
4
+ <version>3.0.1</version>
5
+ <stability>stable</stability>
6
+ <license>GPL</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Integrates the FACT-Finder for improved product search functionality.</summary>
10
+ <description>Integrates the FACT-Finder for improved product search functionality.</description>
11
+ <notes>- initial Release</notes>
12
+ <authors><author><name>Flagbit GmbH Co. KG</name><user>auto-converted</user><email>magento@flagbit.de</email></author></authors>
13
+ <date>2011-02-23</date>
14
+ <time>18:17:25</time>
15
+ <contents><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="factfinder.xml" hash="0389b14e8f5f3a491e1d21ff06fda964"/></dir><dir name="template"><dir name="factfinder"><file name="cockpit.phtml" hash="ca1a67e095028779d8796c4a4aa71a23"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="factfinder.xml" hash="6b089b7feee9c3cdfbaeb9150aceb2c7"/></dir><dir name="template"><dir name="factfinder"><dir name="filter"><file name="slider.phtml" hash="a801167a6959d153df4fdc8077c88f4e"/></dir><file name="form.mini.phtml" hash="1e95de3325d50950418bbdfba8ebd5c2"/><file name="logo.phtml" hash="4b4636c1ecb90ecf9fae3e6e50c9c58b"/></dir></dir></dir></dir></dir></target><target name="magelib"><dir name="FACTFinder"><dir name="Abstract"><file name="Adapter.php" hash="286ff623f62935502322c4083a6d89dc"/><file name="Configuration.php" hash="7afba70db9c6b461f88532d3ec412868"/><file name="DataProvider.php" hash="d12a42c741c7884183cb623f2bdcd355"/><file name="ScicAdapter.php" hash="8b3fde7b1c5205f594776736a165bfa6"/><file name="SearchAdapter.php" hash="ba8c26d9069c8089b269530194e64cc9"/><file name="SuggestAdapter.php" hash="206f081b4a693d1e668e94c6818c8983"/><file name="TagCloudAdapter.php" hash="69dc7236204a0fb5ccd64e750187f79f"/></dir><dir name="Http"><file name="DataProvider.php" hash="a42eb307edcc7990ab5708d5de45e7bd"/><file name="ScicAdapter.php" hash="f2ba0871501f8e59ebe91b861ca846a3"/><file name="SuggestAdapter.php" hash="325501cc046b3600821b7840e24c10a0"/></dir><dir name="Xml64"><file name="SearchAdapter.php" hash="c7489159264fa21e31d85958adfc0434"/></dir><dir name="Xml65"><file name="SearchAdapter.php" hash="9777f877e3ec15b0a5bae8244137612b"/><file name="SuggestAdapter.php" hash="33157e6d02670bd4a9eed39173cb07b6"/><file name="TagCloudAdapter.php" hash="46228b5d71296d55796cc36543be67c3"/></dir><file name="Asn.php" hash="b6a35035be782613a90ad40a1ead479f"/><file name="AsnFilterItem.php" hash="5e1a5463d589e9ed960822edbd854988"/><file name="AsnGroup.php" hash="e417480049155015456f2b28c8e9d4f7"/><file name="AsnSliderFilter.php" hash="fe1a3999cd157535c79d4e608b472ba0"/><file name="BreadCrumbItem.php" hash="3a075c0368404f4088a8772b394fbbec"/><file name="Campaign.php" hash="3d1ee0982e9c9c3a551172d00a7d3d59"/><file name="CampaignIterator.php" hash="b0df7068d7cd549c535e5413a27464d2"/><file name="Configuration.php" hash="4452d98eb88c5e4a17d71fe4c2cedc26"/><file name="EncodingHandler.php" hash="caaf26e8f992e3e823bdfe90c860a2e6"/><file name="Item.php" hash="bc53765464668d2daeaf3076f801c29e"/><file name="Loader.php" hash="43c4a9efd8eeb7daf4ea20a815dbb038"/><file name="Paging.php" hash="b78fc03ef06c9df5c5ae8bd78ab0031f"/><file name="Parameters.php" hash="2c060954f6df87138683bbed443ccb69"/><file name="ParametersParser.php" hash="07cf433669fdc52c10a69619eafa8006"/><file name="ProductsPerPageOptions.php" hash="a77723f2ba131534cd8e2bdbcb229be5"/><file name="Record.php" hash="91e2ce5c3b1568e0d0270324699d1ebf"/><file name="Result.php" hash="c5fc336dc39e648e94b920b7e3cc487b"/><file name="SuggestQuery.php" hash="74a5eed59cbc1a829aa1efb587dc8d97"/><file name="TagQuery.php" hash="50b805995dda0bd39e04406e11f3ad7e"/><file name="Util.php" hash="f82a2ab55149fb30ad9dcf5ef821fcc6"/></dir><dir name="FACTFinderCustom"><file name="Configuration.php" hash="7fce914861ffe509c3ee2a3d63fc7a04"/></dir></target><target name="magecommunity"><dir name="Flagbit"><dir name="FactFinder"><dir name="Block"><dir name="Adminhtml"><file name="Cockpit.php" hash="ff50199c3680c00e33fc7d3d5de6b935"/></dir><dir name="Filter"><file name="Slider.php" hash="6110983b301878e0a19073b17ce28e96"/></dir><dir name="Layer"><file name="Abstract.php" hash="70c119e32bae73f5a74598329eec416f"/></dir><dir name="XmlConnect"><dir name="Catalog"><dir name="Product"><file name="List.php" hash="3af5dac4ecad3761511aa4807c4a79d8"/></dir><dir name="Search"><file name="Suggest.php" hash="77e20bb08a96dd9e29a39879f307c934"/></dir><file name="Search.php" hash="dc5ad07de699fb831941cfe417e5c55b"/></dir></dir><file name="Layer.php" hash="cd8fc3610903cfa00fb920607477ca6d"/></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Factfinder"><file name="CockpitController.php" hash="7369f2fff764a51328e1c712d122d68d"/></dir></dir><file name="ExportController.php" hash="bab2e63423f63e613c99951db07fa336"/></dir><dir name="etc"><file name="adminhtml.xml" hash="3d262871a3a3afe71d7218a0ba43fb50"/><file name="config.xml" hash="7437f1fc00201afb871008bcb71b66dc"/><file name="system.xml" hash="20d83db26fa0ecda0032b97e2e1c2102"/></dir><dir name="Helper"><file name="Data.php" hash="b7e50e42c6cf2dccb7fff9ad74c7e050"/><file name="Debug.php" hash="073fe89bb85081bff6ea3680204c934a"/><file name="Search.php" hash="940a351e6ab3f327fe92f6b73dc8cc7d"/></dir><dir name="Model"><dir name="Export"><file name="Price.php" hash="7bed26b43b252b65c1188f0004f50053"/><file name="Product.php" hash="6ad0b09cf89345ede2e50fdce5905c3e"/><file name="Stock.php" hash="a07efecd3300c1367125f7e303b159df"/></dir><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="21454aefd537553c2656c23111d95cba"/><file name="Item.php" hash="1a230f9e48f2af6e3d96e75087858adf"/></dir></dir><dir name="Mysql4"><dir name="Product"><dir name="Attribute"><file name="Collection.php" hash="0ebfad0e9bfd04a25886adfca36b9917"/></dir></dir><dir name="Search"><file name="Collection.php" hash="08a6ba4ca7c74e74eb5c40eaede2e292"/><file name="Engine.php" hash="0d16d096efb818ca9ec1d6047d293d20"/></dir></dir><dir name="System"><dir name="Config"><dir name="Backend"><file name="Enabled.php" hash="da2bd6274937f1d8ea9d0cf4d0eb0203"/></dir><dir name="Source"><file name="Authtype.php" hash="e9d719da382007b41911e7ba1d8bf939"/><file name="Identifier.php" hash="cf792cfe8c84b67b94666900f6a268d0"/></dir></dir></dir><file name="Adapter.php" hash="b16384488a7afc39eb4a4f5ee1132d95"/><file name="Layer.php" hash="43491d6e99f7c59d294f55126a0833c1"/></dir></dir></dir></target><target name="mage"><dir name="js"><dir name="factfinder"><file name="jXHR.js" hash="3a0b8c93554d7eab73533e289b3db134"/><file name="suggest.js" hash="6b46f334104cd36abffac13be91db6c8"/></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Flagbit_FactFinder.xml" hash="99c6b4e5981ac7592830a9fb3f5e5a0e"/></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies/>
18
+ </package>