Flagbit_Factfinder - Version 3.4.0

Version Notes

new features:
* added support for FACT-Finder 6.8
* new Suggest template system
* including two new alternative suggest templates
* Suggest image size is configurable in backend
* Alternative slider template that uses script.aculo.us instead of Omikron's OneTouchSlider
* Secondary Channels (searching one or more additional database(s) - for example "content", "community" etc.)
* Use of parallel requests between Magento and FACT-Finder
* Parallel data exports are now prevented; this is relevant for large shops whose exports might take hours (and could be requested more frequently)
* Optional fallback to Magento in case of FACT-Finder server problems
* Added support for shopping cart campaigns
* extended error reporting at the installation process, for a better usability at the integration process
* FACT-Finder Configuration displays export link
* FACT-Finder version is configurable

bugfixes since last release:
* Explicit export attributes work now even if they are not searchable or filterable
* Click tracking for product details works now with automatic redirect for single result searches
* Click tracking for product details works now even if detail page is loaded very quickly
* HTML tags in export data will not result in unseparated words any more

Download this release

Release Info

Developer Magento Core Team
Extension Flagbit_Factfinder
Version 3.4.0
Comparing to
See all releases


Code changes from version 3.3.12 to 3.4.0

Files changed (86) hide show
  1. app/code/community/Flagbit/FactFinder/Block/Adminhtml/Cockpit.php +2 -2
  2. app/code/community/Flagbit/FactFinder/Block/Adminhtml/Exportlink.php +23 -7
  3. app/code/community/Flagbit/FactFinder/Block/Campaign/Advisory.php +8 -1
  4. app/code/community/Flagbit/FactFinder/Block/Campaign/Cart/Advisory.php +26 -21
  5. app/code/community/Flagbit/FactFinder/Block/Campaign/Cart/Feedback.php +18 -6
  6. app/code/community/Flagbit/FactFinder/Block/Campaign/Feedback.php +8 -1
  7. app/code/community/Flagbit/FactFinder/Block/Campaign/Product/Advisory.php +20 -8
  8. app/code/community/Flagbit/FactFinder/Block/Campaign/Product/Feedback.php +12 -3
  9. app/code/community/Flagbit/FactFinder/Block/Cart/Crosssell.php +23 -26
  10. app/code/community/Flagbit/FactFinder/Block/Layer.php +34 -13
  11. app/code/community/Flagbit/FactFinder/Block/Product/List/Crosssell.php +12 -3
  12. app/code/community/Flagbit/FactFinder/Block/Product/List/Upsell.php +23 -37
  13. app/code/community/Flagbit/FactFinder/Block/Secondaryresult.php +8 -3
  14. app/code/community/Flagbit/FactFinder/Block/TagCloud.php +35 -27
  15. app/code/community/Flagbit/FactFinder/Block/XmlConnect/Catalog/Search/Suggest.php +5 -3
  16. app/code/community/Flagbit/FactFinder/Helper/Backend.php +7 -7
  17. app/code/community/Flagbit/FactFinder/Helper/Search.php +164 -24
  18. app/code/community/Flagbit/FactFinder/Model/Adapter.php +0 -936
  19. app/code/community/Flagbit/FactFinder/Model/Export/Product.php +4 -4
  20. app/code/community/Flagbit/FactFinder/Model/Facade.php +377 -0
  21. app/code/community/Flagbit/FactFinder/Model/Handler/Abstract.php +45 -0
  22. app/code/community/Flagbit/FactFinder/Model/Handler/CheckStatus.php +141 -0
  23. app/code/community/Flagbit/FactFinder/Model/Handler/ProductCampaign.php +75 -0
  24. app/code/community/Flagbit/FactFinder/Model/Handler/ProductDetailCampaign.php +27 -0
  25. app/code/community/Flagbit/FactFinder/Model/Handler/Recommendations.php +51 -0
  26. app/code/community/Flagbit/FactFinder/Model/Handler/Search.php +424 -0
  27. app/code/community/Flagbit/FactFinder/Model/Handler/SecondarySearch.php +46 -0
  28. app/code/community/Flagbit/FactFinder/Model/Handler/ShoppingCartCampaign.php +27 -0
  29. app/code/community/Flagbit/FactFinder/Model/Handler/Suggest.php +106 -0
  30. app/code/community/Flagbit/FactFinder/Model/Handler/TagCloud.php +71 -0
  31. app/code/community/Flagbit/FactFinder/Model/Mysql4/Campaign/Pushedproducts/Collection.php +3 -3
  32. app/code/community/Flagbit/FactFinder/Model/Mysql4/Product/Attribute/Collection.php +6 -6
  33. app/code/community/Flagbit/FactFinder/Model/Mysql4/Search/Collection.php +11 -12
  34. app/code/community/Flagbit/FactFinder/Model/Observer.php +54 -12
  35. app/code/community/Flagbit/FactFinder/Model/Processor.php +22 -17
  36. app/code/community/Flagbit/FactFinder/Model/System/Config/Source/Ffversion.php +4 -0
  37. app/code/community/Flagbit/FactFinder/controllers/ExportController.php +52 -5
  38. app/code/community/Flagbit/FactFinder/controllers/ProxyController.php +1 -1
  39. app/code/community/Flagbit/FactFinder/etc/config.xml +14 -1
  40. app/code/community/Flagbit/FactFinder/etc/system.xml +46 -7
  41. app/design/adminhtml/default/default/template/factfinder/cockpit.phtml +22 -0
  42. app/design/frontend/base/default/layout/factfinder.xml +17 -8
  43. app/design/frontend/base/default/template/factfinder/campaign/product/advisory.phtml +0 -12
  44. app/design/frontend/base/default/template/factfinder/campaign/product/feedback.phtml +0 -6
  45. app/design/frontend/base/default/template/factfinder/filter/scriptaculousSlider.phtml +103 -0
  46. app/design/frontend/base/default/template/factfinder/form.advancedsuggest.phtml +95 -0
  47. app/design/frontend/base/default/template/factfinder/form.advancedsuggest68.phtml +103 -0
  48. app/design/frontend/base/default/template/factfinder/form.mini.phtml +23 -7
  49. app/design/frontend/base/default/template/factfinder/scic.phtml +2 -1
  50. app/locale/de_DE/Flagbit_FactFinder.csv +47 -17
  51. js/factfinder/scic.js +6 -2
  52. js/factfinder/suggest.js +63 -25
  53. lib/FACTFinder/Abstract/Adapter.php +10 -0
  54. lib/FACTFinder/Abstract/Configuration.php +65 -1
  55. lib/FACTFinder/Abstract/DataProvider.php +5 -2
  56. lib/FACTFinder/Abstract/RecommendationAdapter.php +19 -2
  57. lib/FACTFinder/Abstract/ScicAdapter.php +56 -29
  58. lib/FACTFinder/AsnGroup.php +14 -0
  59. lib/FACTFinder/Configuration.php +79 -0
  60. lib/FACTFinder/Http/DataProvider.php +182 -181
  61. lib/FACTFinder/Http/ParallelDataProvider.php +130 -33
  62. lib/FACTFinder/Http/ScicAdapter.php +7 -2
  63. lib/FACTFinder/Http/StatusHelper.php +153 -0
  64. lib/FACTFinder/Http/SuggestAdapter.php +2 -2
  65. lib/FACTFinder/Http/UrlBuilder.php +234 -0
  66. lib/FACTFinder/ProductsPerPageOptions.php +31 -11
  67. lib/FACTFinder/Xml65/ImportAdapter.php +2 -2
  68. lib/FACTFinder/Xml65/SearchAdapter.php +22 -2
  69. lib/FACTFinder/Xml65/SuggestAdapter.php +1 -1
  70. lib/FACTFinder/Xml65/TagCloudAdapter.php +1 -0
  71. lib/FACTFinder/Xml67/SearchAdapter.php +1 -1
  72. lib/FACTFinder/Xml68/CompareAdapter.php +19 -0
  73. lib/FACTFinder/Xml68/ImportAdapter.php +19 -0
  74. lib/FACTFinder/Xml68/ProductCampaignAdapter.php +20 -0
  75. lib/FACTFinder/Xml68/RecommendationAdapter.php +19 -0
  76. lib/FACTFinder/Xml68/SearchAdapter.php +19 -0
  77. lib/FACTFinder/Xml68/SimilarRecordsAdapter.php +19 -0
  78. lib/FACTFinder/Xml68/SuggestAdapter.php +20 -0
  79. lib/FACTFinder/Xml68/TagCloudAdapter.php +19 -0
  80. lib/FACTFinderCustom/Configuration.php +147 -9
  81. lib/SAI/Curl.php +100 -0
  82. lib/SAI/Curl/Handle.php +8 -0
  83. lib/SAI/CurlInterface.php +25 -0
  84. lib/SAI/CurlStub.php +382 -0
  85. package.xml +26 -7
  86. skin/frontend/base/default/css/factfinder.css +25 -0
app/code/community/Flagbit/FactFinder/Block/Adminhtml/Cockpit.php CHANGED
@@ -25,9 +25,9 @@ class Flagbit_FactFinder_Block_Adminhtml_Cockpit extends Mage_Adminhtml_Block_Te
25
  *
26
  * @return string
27
  */
28
- public function getAuthenticationUrl()
29
  {
30
- return Mage::getSingleton('factfinder/adapter')->getAuthenticationUrl();
31
  }
32
 
33
  }
25
  *
26
  * @return string
27
  */
28
+ public function getManagementUrl()
29
  {
30
+ return Mage::getSingleton('factfinder/facade')->getManagementUrl();
31
  }
32
 
33
  }
app/code/community/Flagbit/FactFinder/Block/Adminhtml/Exportlink.php CHANGED
@@ -36,13 +36,29 @@ class Flagbit_FactFinder_Block_Adminhtml_Exportlink extends Mage_Adminhtml_Block
36
  protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
37
  {
38
  $this->setElement($element);
39
- $shopdomain = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
40
- $password = Mage::getStoreConfig('factfinder/search/auth_password');
41
- $store = $this->getRequest()->getParam('store');
42
- if ($store) $storeParam = '&store='.(int)Mage::getConfig()->getNode('stores/' . $store . '/system/store/id');
43
- else $storeParam = '';
44
- $linktext = Mage::helper('factfinder')->__('Download export'); //TODO: translate
45
- $html = '<a href="'.$shopdomain.'factfinder/export/product?key='.md5($password).$storeParam.'" target="_blank">'.$linktext.'</a>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  return $html;
47
  }
48
  }
36
  protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
37
  {
38
  $this->setElement($element);
39
+ $shopdomain = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
40
+ $activeStore = '';
41
+ $store = $this->getRequest()->getParam('store');
42
+ if(Mage::getStoreConfig('web/url/use_store'))
43
+ {
44
+ if ($store)
45
+ {
46
+ $activeStore = $store.'/';
47
+ }
48
+ else
49
+ {
50
+ $websites = Mage::app()->getWebsites();
51
+ $activeStore = $websites[1]->getDefaultStore()->getCode().'/';
52
+ }
53
+ }
54
+
55
+ $password = Mage::getStoreConfig('factfinder/search/auth_password');
56
+
57
+ if ($store) $storeParam = '&store='.(int)Mage::getConfig()->getNode('stores/' . $store . '/system/store/id');
58
+ else $storeParam = '';
59
+ $linktext = Mage::helper('factfinder')->__('Download export');
60
+
61
+ $html = '<a href="'.$shopdomain.$activeStore.'factfinder/export/product?key='.md5($password).$storeParam.'" target="_blank">'.$linktext.'</a>';
62
  return $html;
63
  }
64
  }
app/code/community/Flagbit/FactFinder/Block/Campaign/Advisory.php CHANGED
@@ -2,6 +2,13 @@
2
 
3
  class Flagbit_FactFinder_Block_Campaign_Advisory extends Mage_Core_Block_Template
4
  {
 
 
 
 
 
 
 
5
  /**
6
  * get Campaign Text
7
  *
@@ -12,7 +19,7 @@ class Flagbit_FactFinder_Block_Campaign_Advisory extends Mage_Core_Block_Templat
12
  $questions = array();
13
 
14
  if(Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign')){
15
- $_campaigns = Mage::getSingleton('factfinder/adapter')->getCampaigns();
16
  if($_campaigns && $_campaigns->hasActiveQuestions()){
17
  $questions = $_campaigns->getActiveQuestions();
18
  }
2
 
3
  class Flagbit_FactFinder_Block_Campaign_Advisory extends Mage_Core_Block_Template
4
  {
5
+ protected $_searchHandler;
6
+
7
+ protected function _prepareLayout()
8
+ {
9
+ $this->_searchHandler = Mage::getSingleton('factfinder/handler_search');
10
+ }
11
+
12
  /**
13
  * get Campaign Text
14
  *
19
  $questions = array();
20
 
21
  if(Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign')){
22
+ $_campaigns = $this->_searchHandler->getCampaigns();
23
  if($_campaigns && $_campaigns->hasActiveQuestions()){
24
  $questions = $_campaigns->getActiveQuestions();
25
  }
app/code/community/Flagbit/FactFinder/Block/Campaign/Cart/Advisory.php CHANGED
@@ -18,6 +18,21 @@
18
  */
19
  class Flagbit_FactFinder_Block_Campaign_Cart_Advisory extends Mage_Core_Block_Template
20
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  /**
22
  * get campaign questions and answers
23
  *
@@ -27,30 +42,20 @@ class Flagbit_FactFinder_Block_Campaign_Cart_Advisory extends Mage_Core_Block_Te
27
  {
28
  Mage::getSingleton('core/session', array('name'=>'frontend'));
29
 
30
- if (!Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign')) {
31
- return array();
32
- }
33
-
34
- // only display campaign right after a new product was added to cart
35
- if (!Mage::getSingleton('checkout/session')->getLastAddedProductId()) {
36
- return array();
37
- }
38
-
39
  $questions = array();
40
-
41
- $_product = Mage::getModel('catalog/product')->load(Mage::getSingleton('checkout/session')->getLastAddedProductId());
42
- if (!$_product->getData(Mage::helper('factfinder/search')->getIdFieldName())) {
43
- return array();
44
- }
45
-
46
- $_campaigns = Mage::helper('factfinder/search')->getProductCampaigns(array(
47
- $_product->getData(Mage::helper('factfinder/search')->getIdFieldName())
48
- ));
49
-
50
- if($_campaigns && $_campaigns->hasActiveQuestions()){
51
- $questions = $_campaigns->getActiveQuestions();
52
  }
53
 
54
  return $questions;
55
  }
 
 
 
 
 
 
 
 
56
  }
18
  */
19
  class Flagbit_FactFinder_Block_Campaign_Cart_Advisory extends Mage_Core_Block_Template
20
  {
21
+ protected $_product;
22
+ protected $_productCampaignHandler;
23
+
24
+ protected function _prepareLayout()
25
+ {
26
+ $this->_product = Mage::getModel('catalog/product')->load(Mage::getSingleton('checkout/session')->getLastAddedProductId());
27
+
28
+ $productIds = array(
29
+ $this->_product->getData(Mage::helper('factfinder/search')->getIdFieldName())
30
+ );
31
+
32
+ $this->_productCampaignHandler = Mage::getSingleton('factfinder/handler_shoppingCartCampaign', array($productIds, true));
33
+ return parent::_prepareLayout();
34
+ }
35
+
36
  /**
37
  * get campaign questions and answers
38
  *
42
  {
43
  Mage::getSingleton('core/session', array('name'=>'frontend'));
44
 
 
 
 
 
 
 
 
 
 
45
  $questions = array();
46
+
47
+ if ($this->canCampaignBeDisplayed()) {
48
+ $questions = $this->_productCampaignHandler->getActiveAdvisorQuestions();
 
 
 
 
 
 
 
 
 
49
  }
50
 
51
  return $questions;
52
  }
53
+
54
+ protected function canCampaignBeDisplayed()
55
+ {
56
+ return
57
+ Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign') &&
58
+ Mage::getSingleton('checkout/session')->getLastAddedProductId() &&
59
+ $this->_product->getData(Mage::helper('factfinder/search')->getIdFieldName());
60
+ }
61
  }
app/code/community/Flagbit/FactFinder/Block/Campaign/Cart/Feedback.php CHANGED
@@ -18,6 +18,21 @@
18
  */
19
  class Flagbit_FactFinder_Block_Campaign_Cart_Feedback extends Mage_Core_Block_Template
20
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  /**
22
  * get campaign questions and answers
23
  *
@@ -33,15 +48,12 @@ class Flagbit_FactFinder_Block_Campaign_Cart_Feedback extends Mage_Core_Block_Te
33
  }
34
 
35
  $feedback = array();
36
-
37
- $_product = Mage::getModel('catalog/product')->load(Mage::getSingleton('checkout/session')->getLastAddedProductId());
38
- if (!$_product->getData(Mage::helper('factfinder/search')->getIdFieldName())) {
39
  return array();
40
  }
41
 
42
- $_campaigns = Mage::helper('factfinder/search')->getProductCampaigns(array(
43
- $_product->getData(Mage::helper('factfinder/search')->getIdFieldName())
44
- ));
45
 
46
  if($_campaigns && $_campaigns->hasFeedback()){
47
  $feedback = $_campaigns;
18
  */
19
  class Flagbit_FactFinder_Block_Campaign_Cart_Feedback extends Mage_Core_Block_Template
20
  {
21
+ protected $_product;
22
+ protected $_productCampaignHandler;
23
+
24
+ protected function _prepareLayout()
25
+ {
26
+ $this->_product = Mage::getModel('catalog/product')->load(Mage::getSingleton('checkout/session')->getLastAddedProductId());
27
+
28
+ $productIds = array(
29
+ $this->_product->getData(Mage::helper('factfinder/search')->getIdFieldName())
30
+ );
31
+
32
+ $this->_productCampaignHandler = Mage::getSingleton('factfinder/handler_shoppingCartCampaign', array($productIds, true));
33
+ return parent::_prepareLayout();
34
+ }
35
+
36
  /**
37
  * get campaign questions and answers
38
  *
48
  }
49
 
50
  $feedback = array();
51
+
52
+ if (!$this->_product->getData(Mage::helper('factfinder/search')->getIdFieldName())) {
 
53
  return array();
54
  }
55
 
56
+ $_campaigns = $this->_productCampaignHandler->getCampaigns();
 
 
57
 
58
  if($_campaigns && $_campaigns->hasFeedback()){
59
  $feedback = $_campaigns;
app/code/community/Flagbit/FactFinder/Block/Campaign/Feedback.php CHANGED
@@ -27,6 +27,13 @@ class Flagbit_FactFinder_Block_Campaign_Feedback extends Mage_Core_Block_Templat
27
  */
28
  protected $_pushedProductsCollection = null;
29
 
 
 
 
 
 
 
 
30
  /**
31
  * get Campaign Text
32
  *
@@ -37,7 +44,7 @@ class Flagbit_FactFinder_Block_Campaign_Feedback extends Mage_Core_Block_Templat
37
  $text = '';
38
 
39
  if(Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign')){
40
- $_campaigns = Mage::getSingleton('factfinder/adapter')->getCampaigns();
41
  if($_campaigns && $_campaigns->hasFeedback() && $this->getTextNumber()){
42
  $text = $_campaigns->getFeedback($this->getTextNumber() - 1);
43
  }
27
  */
28
  protected $_pushedProductsCollection = null;
29
 
30
+ protected $_searchHandler;
31
+
32
+ protected function _prepareLayout()
33
+ {
34
+ $this->_searchHandler = Mage::getSingleton('factfinder/handler_search');
35
+ }
36
+
37
  /**
38
  * get Campaign Text
39
  *
44
  $text = '';
45
 
46
  if(Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign')){
47
+ $_campaigns = $this->_searchHandler->getCampaigns();
48
  if($_campaigns && $_campaigns->hasFeedback() && $this->getTextNumber()){
49
  $text = $_campaigns->getFeedback($this->getTextNumber() - 1);
50
  }
app/code/community/Flagbit/FactFinder/Block/Campaign/Product/Advisory.php CHANGED
@@ -18,6 +18,17 @@
18
  */
19
  class Flagbit_FactFinder_Block_Campaign_Product_Advisory extends Mage_Core_Block_Template
20
  {
 
 
 
 
 
 
 
 
 
 
 
21
  /**
22
  * get campaign questions and answers
23
  *
@@ -27,16 +38,17 @@ class Flagbit_FactFinder_Block_Campaign_Product_Advisory extends Mage_Core_Block
27
  {
28
  $questions = array();
29
 
30
- if (Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign') && Mage::registry('current_product')) {
31
- $_campaigns = Mage::helper('factfinder/search')->getProductCampaigns(array(
32
- Mage::registry('current_product')->getData(Mage::helper('factfinder/search')->getIdFieldName()),
33
- ));
34
-
35
- if($_campaigns && $_campaigns->hasActiveQuestions()){
36
- $questions = $_campaigns->getActiveQuestions();
37
- }
38
  }
39
 
40
  return $questions;
41
  }
 
 
 
 
 
 
 
42
  }
18
  */
19
  class Flagbit_FactFinder_Block_Campaign_Product_Advisory extends Mage_Core_Block_Template
20
  {
21
+ protected $_productCampaignHandler;
22
+
23
+ protected function _prepareLayout()
24
+ {
25
+ $productIds = array(
26
+ Mage::registry('current_product')->getData(Mage::helper('factfinder/search')->getIdFieldName())
27
+ );
28
+ $this->_productCampaignHandler = Mage::getSingleton('factfinder/handler_productDetailCampaign', $productIds);
29
+ return parent::_prepareLayout();
30
+ }
31
+
32
  /**
33
  * get campaign questions and answers
34
  *
38
  {
39
  $questions = array();
40
 
41
+ if ($this->canCampaignBeDisplay()) {
42
+ $questions = $this->_productCampaignHandler->getActiveAdvisorQuestions();
 
 
 
 
 
 
43
  }
44
 
45
  return $questions;
46
  }
47
+
48
+ protected function canCampaignBeDisplay()
49
+ {
50
+ return
51
+ Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign') &&
52
+ Mage::registry('current_product');
53
+ }
54
  }
app/code/community/Flagbit/FactFinder/Block/Campaign/Product/Feedback.php CHANGED
@@ -18,6 +18,17 @@
18
  */
19
  class Flagbit_FactFinder_Block_Campaign_Product_Feedback extends Mage_Core_Block_Template
20
  {
 
 
 
 
 
 
 
 
 
 
 
21
  /**
22
  * get campaign feedback
23
  *
@@ -28,9 +39,7 @@ class Flagbit_FactFinder_Block_Campaign_Product_Feedback extends Mage_Core_Block
28
  $feedback = array();
29
 
30
  if (Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign') && Mage::registry('current_product')) {
31
- $_campaigns = Mage::helper('factfinder/search')->getProductCampaigns(array(
32
- Mage::registry('current_product')->getData(Mage::helper('factfinder/search')->getIdFieldName()),
33
- ));
34
 
35
  if($_campaigns && $_campaigns->hasFeedback()){
36
  $feedback = $_campaigns;
18
  */
19
  class Flagbit_FactFinder_Block_Campaign_Product_Feedback extends Mage_Core_Block_Template
20
  {
21
+ protected $_productCampaignHandler;
22
+
23
+ protected function _prepareLayout()
24
+ {
25
+ $productIds = array(
26
+ Mage::registry('current_product')->getData(Mage::helper('factfinder/search')->getIdFieldName())
27
+ );
28
+ $this->_productCampaignHandler = Mage::getSingleton('factfinder/handler_productDetailCampaign', $productIds);
29
+ return parent::_prepareLayout();
30
+ }
31
+
32
  /**
33
  * get campaign feedback
34
  *
39
  $feedback = array();
40
 
41
  if (Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign') && Mage::registry('current_product')) {
42
+ $_campaigns = $this->_productCampaignHandler->getCampaigns();
 
 
43
 
44
  if($_campaigns && $_campaigns->hasFeedback()){
45
  $feedback = $_campaigns;
app/code/community/Flagbit/FactFinder/Block/Cart/Crosssell.php CHANGED
@@ -20,6 +20,15 @@
20
  */
21
  class Flagbit_FactFinder_Block_Cart_Crosssell extends Mage_Checkout_Block_Cart_Crosssell
22
  {
 
 
 
 
 
 
 
 
 
23
  /**
24
  * Overwritten function. Gets information from FACT-Finder Collection instead of product link collection.
25
  */
@@ -31,35 +40,23 @@ class Flagbit_FactFinder_Block_Cart_Crosssell extends Mage_Checkout_Block_Cart_C
31
 
32
  $items = $this->getData('items');
33
  if (is_null($items)) {
34
- try {
35
- $items = array();
36
- $ninProductIds = $this->_getCartProductIds();
37
- if ($ninProductIds) {
38
- $lastAdded = (int) $this->_getLastAddedProductId();
39
- if ($lastAdded) {
40
- $searchHelper = Mage::helper('factfinder/search');
41
- $idFieldName = $searchHelper->getIdFieldName();
42
-
43
- $recommendationAdapter = Mage::getModel('factfinder/adapter')->getRecommendationAdapter();
44
- $attributeValue = Mage::getModel('catalog/product')->getResource()->getAttributeRawValue($lastAdded, $idFieldName, Mage::app()->getStore()->getId());
45
-
46
- $collection = $this->_getCollection()
47
- ->setRecommendations($recommendationAdapter->getRecommendations($attributeValue));
48
- if (!empty($ninProductIds)) {
49
- $collection->addExcludeProductFilter($ninProductIds);
50
- }
51
-
52
- foreach ($collection as $item) {
53
- $items[] = $item;
54
- }
55
- }
56
 
 
 
57
  }
58
  }
59
- catch (Exception $e) {
60
- Mage::logException($e);
61
- $items = array();
62
- }
63
 
64
  $this->setData('items', $items);
65
  }
20
  */
21
  class Flagbit_FactFinder_Block_Cart_Crosssell extends Mage_Checkout_Block_Cart_Crosssell
22
  {
23
+ protected $_recommendationsHandler;
24
+
25
+ protected function _prepareLayout()
26
+ {
27
+ $productIds = $this->_getCartProductIds();
28
+ $this->_recommendationsHandler = Mage::getSingleton('factfinder/handler_recommendations', $productIds);
29
+ return parent::_prepareLayout();
30
+ }
31
+
32
  /**
33
  * Overwritten function. Gets information from FACT-Finder Collection instead of product link collection.
34
  */
40
 
41
  $items = $this->getData('items');
42
  if (is_null($items)) {
43
+ $items = array();
44
+ $ninProductIds = $this->_getCartProductIds();
45
+ if ($ninProductIds) {
46
+ $collection = $this->_getCollection()
47
+ ->setRecommendations($this->_recommendationsHandler->getRecommendations());
48
+ if (!empty($ninProductIds)) {
49
+ // Before FF 6.7 only one product id will be considered.
50
+ // In that case (only) it could happen that another product in the cart is among the
51
+ // recommendations.
52
+ // TODO: This filter does not seem to work.
53
+ $collection->addExcludeProductFilter($ninProductIds);
54
+ }
 
 
 
 
 
 
 
 
 
 
55
 
56
+ foreach ($collection as $item) {
57
+ $items[] = $item;
58
  }
59
  }
 
 
 
 
60
 
61
  $this->setData('items', $items);
62
  }
app/code/community/Flagbit/FactFinder/Block/Layer.php CHANGED
@@ -20,6 +20,9 @@
20
  */
21
  class Flagbit_FactFinder_Block_Layer extends Flagbit_FactFinder_Block_Layer_Abstract
22
  {
 
 
 
23
 
24
  /**
25
  * Prepare child blocks
@@ -27,24 +30,43 @@ class Flagbit_FactFinder_Block_Layer extends Flagbit_FactFinder_Block_Layer_Abst
27
  * @return Mage_Catalog_Block_Layer_View
28
  */
29
  protected function _prepareLayout()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  {
31
  if(Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign')){
32
  // handle redirects
33
- $redirect = Mage::getSingleton('factfinder/adapter')->getRedirect();
34
  if($redirect){
35
  Mage::app()->getResponse()->setRedirect($redirect);
36
  }
37
  }
 
38
 
39
- if(!Mage::helper('factfinder/search')->getIsEnabled(false, 'asn')){
40
- return parent::_prepareLayout();
41
- }
 
42
 
43
  // set default sort Order
44
  if(Mage::getSingleton('catalog/session')->getSortOrder()){
45
  Mage::getSingleton('catalog/session')->setSortOrder('relevance');
46
  }
47
-
48
  $stateBlock = $this->getLayout()->createBlock('catalog/layer_state')
49
  ->setLayer($this->getLayer());
50
 
@@ -55,12 +77,12 @@ class Flagbit_FactFinder_Block_Layer extends Flagbit_FactFinder_Block_Layer_Abst
55
  $filterBlockName = $this->_getAttributeFilterBlockName();
56
 
57
  $filterBlock = $this->getLayout()->createBlock($filterBlockName)
58
- ->setLayer($this->getLayer())
59
- ->setAttributeModel($attribute)
60
- ->init();
61
 
62
  switch($attribute->getType()){
63
-
64
  case 'slider':
65
  if(!($this->getLayout()->getBlock('ffslider') instanceof Flagbit_FactFinder_Block_Filter_Slider)){
66
  $this->getLayout()->getBlock('head')->setChild('ffslider', $this->getLayout()->createBlock('factfinder/filter_slider'));
@@ -70,13 +92,12 @@ class Flagbit_FactFinder_Block_Layer extends Flagbit_FactFinder_Block_Layer_Abst
70
  $filterBlock->setUnit($attribute->getUnit());
71
  break;
72
  }
73
-
74
  $this->setChild($attribute->getAttributeCode().'_filter', $filterBlock);
75
  }
76
-
77
  $this->getLayer()->apply();
78
- return Mage_Core_Block_Template::_prepareLayout();
79
- }
80
 
81
  /**
82
  * Get category filter block
20
  */
21
  class Flagbit_FactFinder_Block_Layer extends Flagbit_FactFinder_Block_Layer_Abstract
22
  {
23
+ protected $_searchHandler;
24
+
25
+ protected $_usesAsn = false;
26
 
27
  /**
28
  * Prepare child blocks
30
  * @return Mage_Catalog_Block_Layer_View
31
  */
32
  protected function _prepareLayout()
33
+ {
34
+ $this->_searchHandler = Mage::getSingleton('factfinder/handler_search');
35
+
36
+ $this->_usesAsn = Mage::helper('factfinder/search')->getIsEnabled(false, 'asn');
37
+
38
+ if(!$this->_usesAsn){
39
+ return parent::_prepareLayout();
40
+ }
41
+
42
+ // Make this block globally known so that initializeAfterSearchNavigation can be called on this instance
43
+ // when the controller_action_layout_generate_blocks_after event is fired
44
+ Mage::register(Flagbit_FactFinder_Model_Observer::_asnBlockRegistryKey, $this);
45
+
46
+ return Mage_Core_Block_Template::_prepareLayout();
47
+ }
48
+
49
+ public function handleCampaignRedirect()
50
  {
51
  if(Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign')){
52
  // handle redirects
53
+ $redirect = $this->_searchHandler->getRedirect();
54
  if($redirect){
55
  Mage::app()->getResponse()->setRedirect($redirect);
56
  }
57
  }
58
+ }
59
 
60
+ public function initializeAfterSearchNavigation()
61
+ {
62
+ if(!$this->_usesAsn)
63
+ return;
64
 
65
  // set default sort Order
66
  if(Mage::getSingleton('catalog/session')->getSortOrder()){
67
  Mage::getSingleton('catalog/session')->setSortOrder('relevance');
68
  }
69
+
70
  $stateBlock = $this->getLayout()->createBlock('catalog/layer_state')
71
  ->setLayer($this->getLayer());
72
 
77
  $filterBlockName = $this->_getAttributeFilterBlockName();
78
 
79
  $filterBlock = $this->getLayout()->createBlock($filterBlockName)
80
+ ->setLayer($this->getLayer())
81
+ ->setAttributeModel($attribute)
82
+ ->init();
83
 
84
  switch($attribute->getType()){
85
+
86
  case 'slider':
87
  if(!($this->getLayout()->getBlock('ffslider') instanceof Flagbit_FactFinder_Block_Filter_Slider)){
88
  $this->getLayout()->getBlock('head')->setChild('ffslider', $this->getLayout()->createBlock('factfinder/filter_slider'));
92
  $filterBlock->setUnit($attribute->getUnit());
93
  break;
94
  }
95
+
96
  $this->setChild($attribute->getAttributeCode().'_filter', $filterBlock);
97
  }
98
+
99
  $this->getLayer()->apply();
100
+ }
 
101
 
102
  /**
103
  * Get category filter block
app/code/community/Flagbit/FactFinder/Block/Product/List/Crosssell.php CHANGED
@@ -20,6 +20,16 @@
20
  */
21
  class Flagbit_FactFinder_Block_Product_List_Crosssell extends Mage_Catalog_Block_Product_List_Crosssell
22
  {
 
 
 
 
 
 
 
 
 
 
23
  /**
24
  * Method overwritten. Data is not read from product link collection but from FACT-Finder interface instead.
25
  */
@@ -40,9 +50,8 @@ class Flagbit_FactFinder_Block_Product_List_Crosssell extends Mage_Catalog_Block
40
  ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
41
  ->addStoreFilter();
42
 
43
- $recommendationAdapter = Mage::getModel('factfinder/adapter')->getRecommendationAdapter();
44
- $recommendationAdapter->setProductId($product->getData($idFieldName));
45
- $recommendations = $recommendationAdapter->getRecommendations();
46
  $this->_itemCollection->setRecommendations($recommendations);
47
 
48
  Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($this->_itemCollection);
20
  */
21
  class Flagbit_FactFinder_Block_Product_List_Crosssell extends Mage_Catalog_Block_Product_List_Crosssell
22
  {
23
+ protected $_recommendationsHandler;
24
+
25
+ protected function _prepareLayout()
26
+ {
27
+ $productIds = array(
28
+ Mage::registry('product')->getData(Mage::helper('factfinder/search')->getIdFieldName())
29
+ );
30
+ $this->_recommendationsHandler = Mage::getSingleton('factfinder/handler_recommendations', $productIds);
31
+ return parent::_prepareLayout();
32
+ }
33
  /**
34
  * Method overwritten. Data is not read from product link collection but from FACT-Finder interface instead.
35
  */
50
  ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
51
  ->addStoreFilter();
52
 
53
+ $recommendations = $this->_recommendationsHandler->getRecommendations();
54
+
 
55
  $this->_itemCollection->setRecommendations($recommendations);
56
 
57
  Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($this->_itemCollection);
app/code/community/Flagbit/FactFinder/Block/Product/List/Upsell.php CHANGED
@@ -21,6 +21,19 @@
21
  */
22
  class Flagbit_FactFinder_Block_Product_List_Upsell extends Mage_Catalog_Block_Product_List_Upsell
23
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  /**
25
  * Method overwritten. Data is not read from product link collection but from FACT-Finder interface instead.
26
  */
@@ -33,7 +46,7 @@ class Flagbit_FactFinder_Block_Product_List_Upsell extends Mage_Catalog_Block_Pr
33
 
34
  $recommendations = array();
35
  if (Mage::getStoreConfigFlag('factfinder/activation/upsell')) {
36
- $recommendations = $this->getRecommendations();
37
  }
38
 
39
  // if there are no recommendations or pushed products, use default magento upselling
@@ -99,49 +112,22 @@ class Flagbit_FactFinder_Block_Product_List_Upsell extends Mage_Catalog_Block_Pr
99
  }
100
  }
101
 
102
- /**
103
- * get products from the ff recommendation engine
104
- *
105
- * @return array (ArrayIterator)
106
- */
107
- protected function getRecommendations()
108
- {
109
- $recommendations = array();
110
- try {
111
- $product = Mage::registry('product');
112
- /* @var $product Mage_Catalog_Model_Product */
113
-
114
- $searchHelper = Mage::helper('factfinder/search');
115
- $idFieldName = $searchHelper->getIdFieldName();
116
-
117
- $recommendationAdapter = Mage::getModel('factfinder/adapter')->getRecommendationAdapter();
118
- $recommendationAdapter->setProductId($product->getData($idFieldName));
119
- $recommendations = $recommendationAdapter->getRecommendations();
120
- }
121
- catch (Exception $e) {
122
- Mage::logException($e);
123
- }
124
- return $recommendations;
125
- }
126
-
127
  /**
128
  * get pushed products to combine with recommendations
129
  *
130
  * @return array
131
  */
132
- protected function getPushedProducts()
133
  {
134
  $pushedProducts = array();
135
-
136
- $_campaigns = Mage::helper('factfinder/search')->getProductCampaigns(array(
137
- Mage::registry('current_product')->getData(Mage::helper('factfinder/search')->getIdFieldName()),
138
- ));
139
 
140
- if($_campaigns && $_campaigns->hasPushedProducts()){
141
- $pushedProducts = $_campaigns->getPushedProducts();
142
- }
143
-
144
- return $pushedProducts;
145
- }
 
 
146
 
147
  }
21
  */
22
  class Flagbit_FactFinder_Block_Product_List_Upsell extends Mage_Catalog_Block_Product_List_Upsell
23
  {
24
+ protected $_productCampaignHandler;
25
+ protected $_recommendationsHandler;
26
+
27
+ protected function _prepareLayout()
28
+ {
29
+ $productIds = array(
30
+ Mage::registry('current_product')->getData(Mage::helper('factfinder/search')->getIdFieldName())
31
+ );
32
+ $this->_productCampaignHandler = Mage::getSingleton('factfinder/handler_productDetailCampaign', $productIds);
33
+ $this->_recommendationsHandler = Mage::getSingleton('factfinder/handler_recommendations', $productIds);
34
+ return parent::_prepareLayout();
35
+ }
36
+
37
  /**
38
  * Method overwritten. Data is not read from product link collection but from FACT-Finder interface instead.
39
  */
46
 
47
  $recommendations = array();
48
  if (Mage::getStoreConfigFlag('factfinder/activation/upsell')) {
49
+ $recommendations = $this->_recommendationsHandler->getRecommendations();
50
  }
51
 
52
  // if there are no recommendations or pushed products, use default magento upselling
112
  }
113
  }
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  /**
116
  * get pushed products to combine with recommendations
117
  *
118
  * @return array
119
  */
120
+ protected function getPushedProducts()
121
  {
122
  $pushedProducts = array();
 
 
 
 
123
 
124
+ $_campaigns = $this->_productCampaignHandler->getCampaigns();
125
+
126
+ if($_campaigns && $_campaigns->hasPushedProducts()){
127
+ $pushedProducts = $_campaigns->getPushedProducts();
128
+ }
129
+
130
+ return $pushedProducts;
131
+ }
132
 
133
  }
app/code/community/Flagbit/FactFinder/Block/Secondaryresult.php CHANGED
@@ -1,11 +1,16 @@
1
  <?php
2
  class Flagbit_FactFinder_Block_Secondaryresult extends Mage_Core_Block_Template
3
  {
 
 
 
 
 
 
 
4
  protected function getSecondaryResult($channel)
5
  {
6
- $adapter = Mage::getSingleton('factfinder/adapter');
7
-
8
- $result = $adapter->getSecondarySearchResult($channel);
9
 
10
  return $result;
11
  }
1
  <?php
2
  class Flagbit_FactFinder_Block_Secondaryresult extends Mage_Core_Block_Template
3
  {
4
+ protected $_searchHandler;
5
+
6
+ protected function _prepareLayout()
7
+ {
8
+ $this->_searchHandler = Mage::getSingleton('factfinder/handler_secondarySearch');
9
+ }
10
+
11
  protected function getSecondaryResult($channel)
12
  {
13
+ $result = $this->_searchHandler->getSecondarySearchResult($channel);
 
 
14
 
15
  return $result;
16
  }
app/code/community/Flagbit/FactFinder/Block/TagCloud.php CHANGED
@@ -1,6 +1,20 @@
1
  <?php
2
  class Flagbit_FactFinder_Block_TagCloud extends Mage_CatalogSearch_Block_Term
3
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  protected function _loadTerms()
5
  {
6
  if (!Mage::helper('factfinder/search')->getIsEnabled(false, 'tagcloud')) {
@@ -8,37 +22,31 @@ class Flagbit_FactFinder_Block_TagCloud extends Mage_CatalogSearch_Block_Term
8
  }
9
 
10
  if (empty($this->_terms)) {
11
- $terms = Mage::getSingleton('factfinder/adapter')->getTagCloud();
12
 
13
- if (count($terms) == 0) {
14
  return $this;
15
- }
16
-
17
- $this->_maxPopularity = 0;
18
- $this->_minPopularity = 1;
19
-
20
- for ($i = 0; $i < count($terms); $i++) {
21
- $term = $terms[$i];
22
-
23
- $termArray = array();
24
- $termArray['name'] = $term->getValue();
25
- $termArray['url'] = $term->getUrl();
26
- $termArray['popularity'] = $term->getWeight();
27
- $termArray['ratio'] = $term->getWeight();
28
-
29
- if ($term->getWeight() > $this->_maxPopularity) {
30
- $this->_maxPopularity = $term->getWeight();
31
- }
32
- if ($term->getWeight() < $this->_minPopularity) {
33
- $this->_minPopularity = $term->getWeight();
34
- }
35
-
36
- $terms[$i] = new Varien_Object($termArray);
37
- }
38
-
39
- $this->_terms = $terms;
40
  }
41
 
42
  return $this;
43
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
1
  <?php
2
  class Flagbit_FactFinder_Block_TagCloud extends Mage_CatalogSearch_Block_Term
3
  {
4
+ /**
5
+ * @var Flagbit_FactFinder_Model_Handler_TagCloud
6
+ */
7
+ protected $_tagCloudHandler;
8
+
9
+ protected function _prepareLayout()
10
+ {
11
+ $this->_tagCloudHandler = Mage::getSingleton('factfinder/handler_tagCloud');
12
+ return parent::_prepareLayout();
13
+ }
14
+
15
+ /**
16
+ * @return Flagbit_FactFinder_Block_TagCloud|Mage_CatalogSearch_Block_Term
17
+ */
18
  protected function _loadTerms()
19
  {
20
  if (!Mage::helper('factfinder/search')->getIsEnabled(false, 'tagcloud')) {
22
  }
23
 
24
  if (empty($this->_terms)) {
25
+ $this->_terms = $this->_tagCloudHandler->getTerms();
26
 
27
+ if (count($this->_terms) == 0)
28
  return $this;
29
+
30
+ $this->determineMinMaxPopularity();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
 
33
  return $this;
34
  }
35
+
36
+ /**
37
+ * Determines minimum and maximum popularity among terms
38
+ */
39
+ protected function determineMinMaxPopularity()
40
+ {
41
+ $this->_maxPopularity = 0;
42
+ $this->_minPopularity = 1;
43
+
44
+ foreach ($this->_terms as $term) {
45
+ if ($term->getPopularity() > $this->_maxPopularity)
46
+ $this->_maxPopularity = $term->getPopularity();
47
+
48
+ if ($term->getPopularity() < $this->_minPopularity)
49
+ $this->_minPopularity = $term->getPopularity();
50
+ }
51
+ }
52
  }
app/code/community/Flagbit/FactFinder/Block/XmlConnect/Catalog/Search/Suggest.php CHANGED
@@ -33,9 +33,11 @@ class Flagbit_FactFinder_Block_XmlConnect_Catalog_Search_Suggest extends Mage_Xm
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
  }
33
  if (!$this->getRequest()->getParam('q', false)) {
34
  return $suggestXmlObj->asNiceXml();
35
  }
36
+
37
+ $handler = Mage::getSingleton('factfinder/handler_suggest', array($this->getRequest()->getParam('q')));
38
+
39
+ $suggestData = $handler->getSuggestionsAsArray();
40
+
41
  if (!($count = count($suggestData))) {
42
  return $suggestXmlObj->asNiceXml();
43
  }
app/code/community/Flagbit/FactFinder/Helper/Backend.php CHANGED
@@ -32,21 +32,21 @@ class Flagbit_FactFinder_Helper_Backend extends Mage_Core_Helper_Abstract
32
  $errors = array();
33
 
34
  if (stripos($data->getAddress(), 'http://') === 0 || strpos($data->getAddress(), '/') !== false) {
35
- $errors[] = Mage::helper('factfinder')->__('servername should only contain the IP address or the domain - no "http://" or any slashes!');
36
  }
37
 
38
  if ($data->getPort() == '') {
39
  $port = 80;
40
  }
41
  elseif (!is_numeric($data->getPort())) {
42
- $errors[] = Mage::helper('factfinder')->__('the value for "port" must be numeric!');
43
  }
44
  elseif(intval($data->getPort()) < 80) { //is there any http port lower 80?
45
- $errors[] = Mage::helper('factfinder')->__('the value for "port" must be a number greater or equals 80!');
46
  }
47
 
48
  if ($data->getAuthPassword() != '' && $data->getAuthUser() == '') {
49
- $errors[] = Mage::helper('factfinder')->__('there must be a username, if a password should be used');
50
  }
51
 
52
  $conflicts = Mage::helper('factfinder/debug')->getRewriteConflicts();
@@ -57,9 +57,9 @@ class Flagbit_FactFinder_Helper_Backend extends Mage_Core_Helper_Abstract
57
  }
58
 
59
  if (count($errors) == 0) {
60
- $adapter = Mage::getSingleton('factfinder/adapter');
61
- if(!$adapter->checkStatus($dataArray)){
62
- $errors[] = Mage::helper('factfinder')->__('WARNING: was not able to connect to FACT-Finder.');
63
  }
64
  }
65
 
32
  $errors = array();
33
 
34
  if (stripos($data->getAddress(), 'http://') === 0 || strpos($data->getAddress(), '/') !== false) {
35
+ $errors[] = Mage::helper('factfinder')->__('The server name should contain only the IP address or the domain - no "http://" or any slashes!');
36
  }
37
 
38
  if ($data->getPort() == '') {
39
  $port = 80;
40
  }
41
  elseif (!is_numeric($data->getPort())) {
42
+ $errors[] = Mage::helper('factfinder')->__('The value for "port" must be an integer!');
43
  }
44
  elseif(intval($data->getPort()) < 80) { //is there any http port lower 80?
45
+ $errors[] = Mage::helper('factfinder')->__('The value for "port" must be an integer greater or equals 80!');
46
  }
47
 
48
  if ($data->getAuthPassword() != '' && $data->getAuthUser() == '') {
49
+ $errors[] = Mage::helper('factfinder')->__('A user name must be provided if a password is to be used.');
50
  }
51
 
52
  $conflicts = Mage::helper('factfinder/debug')->getRewriteConflicts();
57
  }
58
 
59
  if (count($errors) == 0) {
60
+ $checkStatusHandler = Mage::getSingleton('factfinder/handler_checkStatus', $dataArray);
61
+ if(!$checkStatusHandler->checkStatus($data->getFfversion())){
62
+ $errors = $checkStatusHandler->getErrorMessages();
63
  }
64
  }
65
 
app/code/community/Flagbit/FactFinder/Helper/Search.php CHANGED
@@ -34,7 +34,17 @@ class Flagbit_FactFinder_Helper_Search extends Mage_Core_Helper_Abstract {
34
  * @var string
35
  */
36
  const XML_CONFIG_PATH_USE_PROXY = 'factfinder/config/proxy';
 
 
 
 
37
 
 
 
 
 
 
 
38
  /**
39
  * if FACT-Finder enabled?
40
  *
@@ -44,7 +54,8 @@ class Flagbit_FactFinder_Helper_Search extends Mage_Core_Helper_Abstract {
44
  {
45
  if (!Mage::getStoreConfigFlag('factfinder/search/enabled')
46
  || Mage::getStoreConfigFlag('advanced/modules_disable_output/Flagbit_FactFinder')
47
- || ($searchPageCheck == true && !$this->getIsOnSearchPage() && !Mage::getStoreConfigFlag('factfinder/activation/navigation'))) {
 
48
  return false;
49
  }
50
 
@@ -77,6 +88,154 @@ class Flagbit_FactFinder_Helper_Search extends Mage_Core_Helper_Abstract {
77
 
78
  return $result;
79
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
  /**
82
  * get Module Status depending on Module
@@ -137,14 +296,16 @@ class Flagbit_FactFinder_Helper_Search extends Mage_Core_Helper_Abstract {
137
  */
138
  public function getSuggestUrl()
139
  {
140
- $url = Mage::getSingleton('factfinder/adapter')->getSuggestUrl();
141
  if (Mage::getStoreConfig(self::XML_CONFIG_PATH_USE_PROXY)) {
142
  $params = array();
143
  if (Mage::app()->getStore()->isCurrentlySecure()) {
144
  $params['_secure'] = true;
145
  }
146
  $url = $this->_getUrl('factfinder/proxy/suggest', $params);
147
- }
 
 
148
  return $url;
149
  }
150
 
@@ -212,25 +373,4 @@ class Flagbit_FactFinder_Helper_Search extends Mage_Core_Helper_Abstract {
212
  {
213
  return Mage::helper('catalogsearch')->getQueryText();
214
  }
215
-
216
-
217
- /**
218
- * return product campaings
219
- *
220
- * @param array $productIds
221
- * @return FACTFinder_CampaignIterator
222
- */
223
- public function getProductCampaigns($productIds)
224
- {
225
- try {
226
- // get productcampaign adapter and set product id or sku array
227
- $productCampaignAdapter = Mage::getModel('factfinder/adapter')->getProductCampaignAdapter();
228
- $productCampaignAdapter->setProductIds($productIds);
229
- $productCampaignAdapter->makeProductCampaign();
230
-
231
- return $productCampaignAdapter->getCampaigns();
232
- } catch(Exception $e) {
233
- return array();
234
- }
235
- }
236
  }
34
  * @var string
35
  */
36
  const XML_CONFIG_PATH_USE_PROXY = 'factfinder/config/proxy';
37
+
38
+ const CACHE_TAG = 'FACTFINDER';
39
+ const CACHE_ID = "FallbackCache";
40
+ const REQUEST_ID_PREFIX = 'FACTFINDER_';
41
 
42
+ protected static $_skipFactFinder = null;
43
+
44
+ protected static $_isFallbackActive = null;
45
+
46
+ protected static $_failedAttemptRegistered = false;
47
+
48
  /**
49
  * if FACT-Finder enabled?
50
  *
54
  {
55
  if (!Mage::getStoreConfigFlag('factfinder/search/enabled')
56
  || Mage::getStoreConfigFlag('advanced/modules_disable_output/Flagbit_FactFinder')
57
+ || ($searchPageCheck == true && !$this->getIsOnSearchPage() && !Mage::getStoreConfigFlag('factfinder/activation/navigation'))
58
+ || $this->_skipFactFinder()) {
59
  return false;
60
  }
61
 
88
 
89
  return $result;
90
  }
91
+
92
+ /**
93
+ * Determines whether the fallback should be used
94
+ *
95
+ * @return bool
96
+ **/
97
+ protected function _isFallbackActive()
98
+ {
99
+ if(self::$_isFallbackActive === null)
100
+ {
101
+ self::$_isFallbackActive = Mage::getStoreConfig('factfinder/fallback/use_fallback');
102
+ }
103
+
104
+ return self::$_isFallbackActive;
105
+ }
106
+
107
+ /**
108
+ * Determines whether FACT-Finder should be skipped completely, because it has failed to respond too often
109
+ * The check is made lazily so that it will return the same result for every call during one request to Magento.
110
+ *
111
+ * @return bool
112
+ **/
113
+ protected function _skipFactFinder()
114
+ {
115
+ if(self::$_skipFactFinder === null)
116
+ {
117
+ if(!$this->_isFallbackActive())
118
+ {
119
+ self::$_skipFactFinder = false;
120
+ }
121
+ else
122
+ {
123
+ $failedAttempts = $this->_loadFailedAttempts();
124
+ $failedAttempts = $this->_removeOldEntries($failedAttempts);
125
+ $this->saveFailedAttempts($failedAttempts);
126
+
127
+ self::$_skipFactFinder = (count($failedAttempts) >= 3);
128
+
129
+ if(self::$_skipFactFinder)
130
+ {
131
+ Mage::helper('factfinder/debug')->log('Failed to connect to FACT-Finder 3 times. Falling back to Magento\'s search.');
132
+ }
133
+ }
134
+ }
135
+
136
+ return self::$_skipFactFinder;
137
+ }
138
+
139
+ protected function _getCacheId()
140
+ {
141
+ return self::REQUEST_ID_PREFIX . self::CACHE_ID;
142
+ }
143
+
144
+ /**
145
+ * Registers that FACT-Finder has failed to respond.
146
+ * The attempt will be represented as an integer corresponding to attempt's timestamp in minutes.
147
+ * Only one failed attempt per lifetime of this object will be registered.
148
+ **/
149
+ public function registerFailedAttempt()
150
+ {
151
+ if(self::$_failedAttemptRegistered)
152
+ return;
153
+
154
+ $failedAttempts = $this->_loadFailedAttempts();
155
+ $failedAttempts[] = intval(time() / 60);
156
+ $this->saveFailedAttempts($failedAttempts);
157
+
158
+ self::$_failedAttemptRegistered = true;
159
+
160
+ Mage::helper('factfinder/debug')->log('Registered failed attempt to connect to FACT-Finder. '.count($failedAttempts).' failed attempts registered.');
161
+ if(count($failedAttempts) >= 3)
162
+ {
163
+ $delay = Mage::getStoreConfig('factfinder/fallback/wait_time');
164
+
165
+ $title = 'FACT-Finder unreachable! Falling back to Magento\'s search for '.$delay.' minutes.';
166
+ $message = 'FACT-Finder did not respond for the third time. Magento will now use its own search for '.$delay.' minutes before trying to reach FACT-Finder again. If the problem persists, please check your FACT-Finder server and the settings in Magento\'s FACT-Finder configuration.';
167
+
168
+ $versionInfo = Mage::getVersionInfo();
169
+
170
+ if ($versionInfo['major'] > 1 ||
171
+ $versionInfo['major'] >= 1 &&
172
+ $versionInfo['minor'] >= 7)
173
+ {
174
+ Mage::getModel('adminnotification/inbox')->addMajor($title, $message);
175
+ }
176
+ else
177
+ {
178
+ $severity = Mage_AdminNotification_Model_Inbox::SEVERITY_MAJOR;
179
+
180
+ $date = date('Y-m-d H:i:s');
181
+ Mage::getModel('adminnotification/inbox')->parse(array(
182
+ array(
183
+ 'severity' => $severity,
184
+ 'date_added' => $date,
185
+ 'title' => $title,
186
+ 'description' => $message,
187
+ 'url' => '',
188
+ 'internal' => true
189
+ )
190
+ ));
191
+ }
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Loads previously registered failed attempts from cache, if they exist.
197
+ * Returns an empty array, otherwise.
198
+ *
199
+ * @return array of int
200
+ **/
201
+ protected function _loadFailedAttempts()
202
+ {
203
+ $cachedContent = Mage::app()->loadCache($this->_getCacheId());
204
+ $failedAttempts = array();
205
+ if($cachedContent)
206
+ $failedAttempts = unserialize($cachedContent);
207
+
208
+ return $failedAttempts;
209
+ }
210
+
211
+ /**
212
+ * Save failed attempts to cache.
213
+ *
214
+ * @param array of int failed attempts
215
+ **/
216
+ public function saveFailedAttempts($failedAttempts)
217
+ {
218
+ Mage::app()->saveCache(serialize($failedAttempts), $this->_getCacheId(), array(self::CACHE_TAG));
219
+ }
220
+
221
+ /**
222
+ * Removes entries from a list of minute-timestamps which are older than a given delay set within the configuration
223
+ *
224
+ * @param array of int entries
225
+ **/
226
+ protected function _removeOldEntries($entries)
227
+ {
228
+ $delay = Mage::getStoreConfig('factfinder/fallback/wait_time');
229
+ $newEntries = array();
230
+
231
+ foreach($entries as $entry)
232
+ {
233
+ if(intval(time() / 60) - $entry < $delay)
234
+ $newEntries[] = $entry;
235
+ }
236
+
237
+ return $newEntries;
238
+ }
239
 
240
  /**
241
  * get Module Status depending on Module
296
  */
297
  public function getSuggestUrl()
298
  {
299
+
300
  if (Mage::getStoreConfig(self::XML_CONFIG_PATH_USE_PROXY)) {
301
  $params = array();
302
  if (Mage::app()->getStore()->isCurrentlySecure()) {
303
  $params['_secure'] = true;
304
  }
305
  $url = $this->_getUrl('factfinder/proxy/suggest', $params);
306
+ } else {
307
+ $url = Mage::getSingleton('factfinder/facade')->getSuggestUrl();
308
+ }
309
  return $url;
310
  }
311
 
373
  {
374
  return Mage::helper('catalogsearch')->getQueryText();
375
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
  }
app/code/community/Flagbit/FactFinder/Model/Adapter.php DELETED
@@ -1,936 +0,0 @@
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 906 2011-09-30 14:10:05Z tuerk $
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 Scic Adapter
58
- * @var FACTFinder_Abstract_ScicAdapter
59
- */
60
- protected $_scicAdapter = null;
61
-
62
- /**
63
- * FACT-Finder Recommendation Adapter
64
- * @var FACTFinder_Abstract_RecommendationAdapter
65
- */
66
- protected $_recommendationAdapter = null;
67
-
68
- /**
69
- * FACT-Finder Product Campaign Adapter
70
- * @var FACTFinder_Abstract_ProductCampaignAdapter
71
- */
72
- protected $_productCampaignAdapter = null;
73
-
74
- /**
75
- * FACT-Finder TagCloudadapter
76
- * @var FACTFinder_Abstract_TagCloudAdapter
77
- */
78
- protected $_tagCloudAdapter = null;
79
-
80
- /**
81
- * FACT-Finder After Search Navigation
82
- * @var array
83
- */
84
- protected $_afterSearchNavigation = null;
85
-
86
- /**
87
- * FACT-Finder product IDs of primary search result
88
- * @var array
89
- */
90
- protected $_searchResultProductIds = null;
91
-
92
- /**
93
- * FACT-Finder secondary search results
94
- * @var array
95
- */
96
- protected $_secondarySearchResults = null;
97
-
98
-
99
- /**
100
- * current FACT-Finder Category Path
101
- * @var array
102
- */
103
- protected $_currentFactfinderCategoryPath = null;
104
-
105
- /**
106
- * logger object to log all module interna
107
- * @var FACTFinder_Abstract_Logger
108
- */
109
- protected $_logger = null;
110
-
111
- public function __construct($arg = null)
112
- {
113
- if ($arg != null && $arg instanceof FACTFinder_Abstract_Logger) {
114
- FF::setLogger($arg);
115
- $this->_logger = $arg;
116
- } else {
117
- $logger = Mage::helper('factfinder/debug');
118
- FF::setLogger($logger);
119
- $this->_logger = $logger;
120
- }
121
- }
122
-
123
- /**
124
- * get FactFinder SearchAdapter
125
- *
126
- * @return FACTFinder_Abstract_SearchAdapter
127
- */
128
- protected function _getSearchAdapter($collectParams = true)
129
- {
130
- if ($this->_searchAdapter == null) {
131
- $config = $this->_getConfiguration();
132
- $encodingHandler = FF::getSingleton('encodingHandler', $config);
133
- $dataProvider = $this->_getDataProvider();
134
- $this->_searchAdapter = FF::getSingleton(
135
- 'xml'.Mage::getStoreConfig('factfinder/search/ffversion').'/searchAdapter',
136
- $dataProvider,
137
- $this->_getParamsParser(),
138
- $encodingHandler
139
- );
140
-
141
- if($collectParams == true){
142
- $this->_collectParams();
143
- }
144
- }
145
-
146
- return $this->_searchAdapter;
147
- }
148
-
149
- protected function _collectParams()
150
- {
151
- // search Helper
152
- $helper = Mage::helper('factfinder/search');
153
- $_request = Mage::app()->getRequest();
154
- $params = $this->_getParamsParser()->getRequestParams();
155
-
156
- if (strpos(Mage::getStoreConfig('factfinder/config/internal_ip'), Mage::helper('core/http')->getRemoteAddr()) !== false) {
157
- $this->_setParam('log', 'internal');
158
- }
159
-
160
- switch($_request->getModuleName()){
161
-
162
- case "xmlconnect":
163
- $_query = $helper->getQueryText();
164
- $this->_setParam('idsOnly', 'true')
165
- ->_setParam('query', $_query);
166
-
167
- $count = $params['count'];
168
- if ($count > 0) {
169
- $this->_setParam('productsPerPage', $count)
170
- ->_setParam('page', ($params['offset'] / $count) + 1);
171
- }
172
-
173
- // add Sorting Param
174
- foreach($params as $key => $value){
175
- if(substr($key, 0, 6) == 'order_'){
176
- $key = substr($key, 6);
177
- if(!in_array($key, array('position', 'relevance'))){
178
- $this->_setParam('sort'.$key, $value);
179
- }
180
- }
181
- }
182
-
183
- // add Filter Params
184
- foreach($params as $key => $value){
185
- $value = base64_decode($value);
186
- if(strpos($value, '|')){
187
- $param = explode('|', $value);
188
- if($key == 'Category'){
189
- $categories = array_merge(array_slice(explode('/', $param[0]), 1), array($param[1]));
190
- foreach($categories AS $k => $v) { $categories[$k] = urldecode($v); }
191
- $filterkey = '';
192
- foreach($categories as $category){
193
- $category = str_replace('%2F', '/', str_replace('%2B', '+', $category));
194
- $this->_setParam('filtercategoryROOT'.$filterkey, $category);
195
- $filterkey .= '/'.str_replace('+', '%2B', str_replace('/', '%2F', $category));
196
- }
197
- }else{
198
- $this->_setParam('filter'.$param[0], $param[1]);
199
- }
200
- }
201
- }
202
-
203
- break;
204
-
205
- case "catalog":
206
- $_query = '*';
207
- if (!isset($params['Category'])) {
208
- $params['Category'] = $this->_getCurrentFactfinderCategoryPath();
209
- }
210
-
211
- case "catalogsearch":
212
- default:
213
- if ($_request->getModuleName() == 'catalogsearch') {
214
- $_query = $helper->getQueryText();
215
- }
216
-
217
- // add Default Params
218
- $this->_setParam('idsOnly', 'true')
219
- ->_setParam('productsPerPage', $helper->getPageLimit())
220
- ->_setParam('query', $_query)
221
- ->_setParam('page', $helper->getCurrentPage());
222
-
223
- // add Sorting Param, but only if it was set explicit via url
224
- foreach($params as $key => $value){
225
- if($key == 'order'
226
- && $helper->getCurrentOrder()
227
- && $helper->getCurrentDirection()
228
- && $helper->getCurrentOrder() != 'position'
229
- && $helper->getCurrentOrder() != 'relevance'){
230
- $this->_setParam('sort'.$helper->getCurrentOrder(), $helper->getCurrentDirection());
231
- }
232
- }
233
-
234
- // add Filter Params
235
- foreach($params as $key => $value){
236
- if(strpos($value, '|')){
237
- $param = explode('|', $value);
238
- switch($param[1]){
239
-
240
- case 'slider':
241
- $subparam = explode(':', $param[2]);
242
- $this->_setParam($subparam[0], $subparam[1]);
243
- $subparam = explode(':', $param[3]);
244
- $this->_setParam($subparam[0], $subparam[1]);
245
- break;
246
-
247
- default:
248
- if($key == 'Category'){
249
- $categories = array_merge(array_slice(explode('/', $param[0]), 1), array($param[1]));
250
- foreach($categories AS $k => $v) { $categories[$k] = $v; }
251
- $filterkey = '';
252
- foreach($categories as $category){
253
- $category = str_replace('%2F', '/', str_replace('%2B', '+', $category));
254
- $this->_setParam('filtercategoryROOT'.$filterkey, $category);
255
- $filterkey .= '/'.str_replace('+', '%2B', str_replace('/', '%2F', $category));
256
- }
257
-
258
- }else{
259
- $this->_setParam('filter'.$param[0], $param[1]);
260
- }
261
- break;
262
- }
263
- }
264
- }
265
- break;
266
-
267
- }
268
- }
269
-
270
-
271
- /**
272
- * execute search
273
- */
274
- public function checkStatus($configarray = null)
275
- {
276
- $status = false;
277
- try {
278
- $this->_getConfiguration($configarray);
279
- $this->_setParam('query', 'FACT-Finder Version');
280
- $this->_setParam('productsPerPage', '1');
281
-
282
- $status = $this->_getSearchAdapter(false)->getStatus() == 'resultsFound';
283
- } catch (Exception $e) {
284
- $status = false;
285
- }
286
- return $status;
287
- }
288
-
289
- /**
290
- * get Redirect URL if there is set one
291
- *
292
- * @return string
293
- */
294
- public function getRedirect()
295
- {
296
- $url = null;
297
- $campaigns = $this->getCampaigns();
298
-
299
- if (!empty($campaigns) && $campaigns->hasRedirect()) {
300
- $url = $campaigns->getRedirectUrl();
301
- }
302
- return $url;
303
- }
304
-
305
- /**
306
- *
307
- */
308
- public function getCampaigns()
309
- {
310
- $campaigns = null;
311
- try {
312
- $campaigns = $this->_getSearchAdapter()->getCampaigns();
313
- }
314
- catch (Exception $e) {
315
- Mage::logException($e);
316
- }
317
- return $campaigns;
318
- }
319
-
320
- /**
321
- * get Search Suggest URL
322
- *
323
- * @return string
324
- */
325
- public function getSuggestUrl()
326
- {
327
- $dataprovider = $this->_getDataProvider();
328
- $dataprovider->setType('Suggest.ff');
329
- $dataprovider->setParams(array());
330
-
331
- return $dataprovider->getNonAuthenticationUrl();
332
- }
333
-
334
- /**
335
- * get Suggest Adapter
336
- *
337
- * @return FACTFinder_Abstract_SuggestAdapter
338
- */
339
- protected function _getSuggestAdapter()
340
- {
341
- if ($this->_suggestAdapter == null) {
342
- $config = $this->_getConfiguration();
343
- $encodingHandler = FF::getSingleton('encodingHandler', $config);
344
- $params = $this->_getParamsParser()->getServerRequestParams();
345
- $dataProvider = $this->_getDataProvider();
346
- $this->_suggestAdapter = FF::getSingleton('http/suggestAdapter', $dataProvider, $this->_getParamsParser(), $encodingHandler);
347
- }
348
-
349
- return $this->_suggestAdapter;
350
- }
351
-
352
- /**
353
- * get Suggest Results as Array
354
- *
355
- * @param string $query
356
- * @return array
357
- */
358
- public function getSuggestResult($query)
359
- {
360
- $this->_setParam('query', $query);
361
- $this->_setParam('format', 'json');
362
-
363
- return Zend_Json_Decoder::decode($this->_getSuggestAdapter()->getSuggestions());
364
- }
365
-
366
- /**
367
- * get Suggest Results as JSON
368
- *
369
- * @param string $query
370
- * @return string json
371
- */
372
- public function getSuggestResultJsonp($query, $jqueryCallback)
373
- {
374
- $this->_setParam('query', $query, false);
375
- $this->_setParam('format', 'jsonp', false);
376
-
377
- return $this->_getSuggestAdapter()->getSuggestions();
378
- }
379
-
380
- /**
381
- * get FactFinder TagCloudAdapter
382
- *
383
- * @return FACTFinder_Abstract_TagCloudAdapter
384
- */
385
- protected function _getTagCloudAdapter()
386
- {
387
- if ($this->_tagCloudAdapter == null) {
388
- $config = $this->_getConfiguration();
389
- $encodingHandler = FF::getSingleton('encodingHandler', $config);
390
- $dataProvider = $this->_getDataProvider();
391
- $this->_tagCloudAdapter = FF::getSingleton(
392
- 'xml'.Mage::getStoreConfig('factfinder/search/ffversion').'/tagCloudAdapter',
393
- $dataProvider,
394
- $this->_getParamsParser(),
395
- $encodingHandler
396
- );
397
-
398
- }
399
-
400
- return $this->_tagCloudAdapter;
401
- }
402
-
403
- /**
404
- * get tag cloud information as Array
405
- *
406
- * @param string $query
407
- * @return array
408
- */
409
- public function getTagCloud()
410
- {
411
- try {
412
- return $this->_getTagCloudAdapter()->getTagCloud();
413
- } catch (Exception $e) {
414
- Mage::logException($e);
415
- return array();
416
- }
417
- }
418
-
419
- /**
420
- * get Scic Adapter
421
- *
422
- * @return FACTFinder_Abstract_ScicAdapter
423
- */
424
- public function getScicAdapter()
425
- {
426
- if ($this->_scicAdapter == null) {
427
- $config = $this->_getConfiguration();
428
- $encodingHandler = FF::getSingleton('encodingHandler', $config);
429
- $params = $this->_getParamsParser()->getServerRequestParams();
430
- $dataProvider = $this->_getDataProvider();
431
- $this->_scicAdapter = FF::getSingleton('http/scicAdapter', $dataProvider, $this->_getParamsParser(), $encodingHandler);
432
- }
433
- return $this->_scicAdapter;
434
- }
435
-
436
- /**
437
- * get Recommendation Adapter
438
- *
439
- * @return FACTFinder_Abstract_RecommendationAdapter
440
- */
441
- public function getRecommendationAdapter()
442
- {
443
- if ($this->_recommendationAdapter == null) {
444
- $config = $this->_getConfiguration();
445
- $encodingHandler = FF::getSingleton('encodingHandler', $config);
446
- $params = $this->_getParamsParser()->getServerRequestParams();
447
- $dataProvider = $this->_getDataProvider();
448
- $dataProvider->setParam('idsOnly', 'true');
449
- $this->_recommendationAdapter = FF::getSingleton('xml'.Mage::getStoreConfig('factfinder/search/ffversion').'/recommendationAdapter', $dataProvider, $this->_getParamsParser(), $encodingHandler);
450
- }
451
- return $this->_recommendationAdapter;
452
- }
453
-
454
- /**
455
- * get Product Campaign Adapter
456
- *
457
- * @return FACTFinder_Abstract_ProductCampaignAdapter
458
- */
459
- public function getProductCampaignAdapter()
460
- {
461
- // Note: this will only work as long as version numbers are used with the same amount of decimal points
462
- if (Mage::getStoreConfig('factfinder/search/ffversion') < 67)
463
- throw new Exception('Feature not supported by used FACT-Finder version.');
464
-
465
- if ($this->_productCampaignAdapter == null) {
466
- $config = $this->_getConfiguration();
467
- $encodingHandler = FF::getSingleton('encodingHandler', $config);
468
- $params = $this->_getParamsParser()->getServerRequestParams();
469
- $dataProvider = $this->_getDataProvider();
470
- $dataProvider->setParam('idsOnly', 'true');
471
- $this->_productCampaignAdapter = FF::getSingleton('xml'.Mage::getStoreConfig('factfinder/search/ffversion').'/productCampaignAdapter', $dataProvider, $this->_getParamsParser(), $encodingHandler);
472
- }
473
- return $this->_productCampaignAdapter;
474
- }
475
-
476
- /**
477
- * get Search Result Count
478
- *
479
- * @return int
480
- */
481
- public function getSearchResultCount()
482
- {
483
- $count = 0;
484
- try {
485
- $count = $this->_getSearchAdapter()->getResult()->getFoundRecordsCount();
486
- }
487
- catch (Exception $e) {
488
- Mage::logException($e);
489
- }
490
-
491
- return $count;
492
- }
493
-
494
- /**
495
- * get After Search Navigation as Array
496
- * this simulates Magento Filter Attributes with Options
497
- *
498
- * @return array
499
- */
500
- public function getAfterSearchNavigation()
501
- {
502
- if($this->_afterSearchNavigation == null){
503
- $this->_afterSearchNavigation = array();
504
-
505
- $result = array();
506
- try {
507
- $result = $this->_getSearchAdapter()->getAsn();
508
- }
509
- catch (Exception $e) {
510
- Mage::logException($e);
511
- }
512
-
513
-
514
- if ($result instanceof FACTFinder_Asn
515
- && count($result)){
516
-
517
- foreach ($result as $row) {
518
- $this->_afterSearchNavigation[] = array(
519
- 'attribute_code' => $row->getName(),
520
- 'name' => $row->getName(),
521
- 'unit' => $row->getUnit(),
522
- 'items' => $this->_getAttributeOptions($row->getArrayCopy(), $row->getUnit()),
523
- 'count' => $row->count(),
524
- 'type' => $this->_getFilterType($row->getArrayCopy()),
525
- 'store_label' => $row->getName()
526
- );
527
- }
528
- }
529
- }
530
-
531
- return $this->_afterSearchNavigation;
532
- }
533
-
534
- /**
535
- * get Filter Type by FACT-Finder FilterItem
536
- *
537
- * @param array $options
538
- * @return string
539
- */
540
- protected function _getFilterType($options)
541
- {
542
- $defaultType = 'item';
543
- foreach($options as $option){
544
- if(!$option->getType()){
545
- continue;
546
- }
547
- $defaultType = $option->getType();
548
- break;
549
- }
550
- return $defaultType;
551
- }
552
-
553
- /**
554
- * get Attribute Options Array from FactFinder FilterGroupItems
555
- *
556
- * @param FACTFinder_AsnFilterItem $options
557
- * @return array
558
- */
559
- protected function _getAttributeOptions($options, $unit = '')
560
- {
561
- $attributeOption = array();
562
- if (!empty($unit)) $unit = ' ' . $unit;
563
- $_currentCategoryPath = $this->_getCurrentFactfinderCategoryPath(true);
564
- $helper = Mage::helper('factfinder/search');
565
- foreach($options as $option){
566
-
567
- switch ($option->getType()){
568
-
569
- case "slider":
570
- $attributeOption[] = array(
571
- 'type' => $option->getType(),
572
- 'label' => 'slider',
573
- 'value' => $this->_getAttributeOptionValue($option),
574
- 'absolute_min' => $option->getAbsoluteMin(),
575
- 'absolute_max' => $option->getAbsoluteMax(),
576
- 'selected_min' => $option->getSelectedMin(),
577
- 'selected_max' => $option->getSelectedMax(),
578
- 'count' => true,
579
- 'selected' => false //$option->isSelected()
580
- );
581
- break;
582
-
583
- default:
584
- if (!Mage::helper('core/string')->strlen($option->getValue())) {
585
- continue;
586
- }
587
- // remove Categories from top Level Navigation
588
- $_value = $this->_getAttributeOptionValue($option);
589
- if(Mage::getStoreConfigFlag('factfinder/activation/navigation')
590
- && !$helper->getIsOnSearchPage()
591
- && (
592
- empty($_value) === true
593
- || in_array($_value, $_currentCategoryPath)
594
- && $_currentCategoryPath[count($_currentCategoryPath)-1] != $_value
595
- )){
596
- continue;
597
- }
598
-
599
- $attributeOption[] = array(
600
- 'type' => 'attribute',
601
- 'label' => $option->getValue() . $unit,
602
- 'value' => $_value,
603
- 'count' => $option->getMatchCount(),
604
- 'selected' => $option->isSelected(),
605
- 'clusterLevel' => $option->getClusterLevel()
606
- );
607
- break;
608
- }
609
- }
610
- return $attributeOption;
611
- }
612
-
613
- /**
614
- * get current FACT-Finder Catgory Path
615
- *
616
- * @return string
617
- */
618
- protected function _getCurrentFactfinderCategoryPath($all = false)
619
- {
620
- $returnValue = '';
621
- if($this->_currentFactfinderCategoryPath == null && Mage::getStoreConfigFlag('factfinder/activation/navigation') && Mage::registry('current_category')){
622
- $this->_currentFactfinderCategoryPath = array();
623
- /* @var $category Mage_Catalog_Model_Category */
624
- $category = Mage::registry('current_category');
625
-
626
- $pathInStore = $category->getPathInStore();
627
- $pathIds = array_reverse(explode(',', $pathInStore));
628
-
629
- $categories = $category->getParentCategories();
630
- $mainCategoriesString = '';
631
- foreach ($pathIds as $categoryId) {
632
- if (isset($categories[$categoryId]) && $categories[$categoryId]->getName()) {
633
- if(empty($mainCategoriesString)){
634
- $this->_currentFactfinderCategoryPath[] = 'categoryROOT|'.$categories[$categoryId]->getName();
635
- }else{
636
- $this->_currentFactfinderCategoryPath[] = 'categoryROOT'.$mainCategoriesString.'|'.$categories[$categoryId]->getName();
637
- }
638
- $mainCategoriesString .= '/'. str_replace('/', '%2F', $categories[$categoryId]->getName());
639
- }
640
- }
641
- } else {
642
- $this->_currentFactfinderCategoryPath = array();
643
- }
644
-
645
- if($all === false){
646
- if (isset($this->_currentFactfinderCategoryPath[count($this->_currentFactfinderCategoryPath)-1])) {
647
- $returnValue = $this->_currentFactfinderCategoryPath[count($this->_currentFactfinderCategoryPath)-1];
648
- }
649
- else {
650
- $returnValue = false;
651
- }
652
- } else {
653
- $returnValue = $this->_currentFactfinderCategoryPath;
654
- }
655
-
656
- return $returnValue;
657
- }
658
-
659
- /**
660
- * get Attribute option Value
661
- *
662
- * @param string $option
663
- * @return string
664
- */
665
- protected function _getAttributeOptionValue($option)
666
- {
667
- $selectOptions = $this->_getSearchAdapter()->getSearchParams()->getFilters();
668
- $value = null;
669
- switch ($option->getType()) {
670
-
671
- // handle Slider Attributes
672
- case "slider";
673
- $value = $option->getField().'|'.$option->getType().'|'.str_replace(array('&', '='), array('|', ':'), $option->getValue()).'[VALUE]';
674
- break;
675
-
676
- // handle default Attributes
677
- default:
678
- $value = $option->getField();
679
- if($option->isSelected()){
680
-
681
- // handle multiselectable Attributes
682
- if(!empty($selectOptions[$option->getField()]) ){
683
- if(strpos($option->getField(), 'categoryROOT') === false){
684
- $values = explode('~~~', $selectOptions[$option->getField()]);
685
- unset($values[array_search($option->getValue(), $values)]);
686
- $value .= '|'.implode('~~~', $values);
687
-
688
- }else{
689
- $values = explode('/',str_replace('|'.$selectOptions[$option->getField()], '', $value));
690
- $valueCount = count($values);
691
- $value = '';
692
- if($valueCount > 1){
693
- for($i=0 ; $valueCount > $i ; $i++){
694
- $value .= ($i != 0 ? ($i == $valueCount-1 ? '|' : '/') : '').$values[$i];
695
- }
696
- }
697
- }
698
- }
699
- }else{
700
- $value .= '|'.$option->getValue();
701
- // handle multiselectable Attributes
702
- if(!empty($selectOptions[$option->getField()])){
703
- $value .= '~~~'.$selectOptions[$option->getField()];
704
- }
705
- }
706
- break;
707
- }
708
- return $value;
709
- }
710
-
711
-
712
- /**
713
- * get Search Result Product Ids and additional Data
714
- *
715
- * @return array Products Ids
716
- */
717
- public function getSearchResultProductIds()
718
- {
719
- if($this->_searchResultProductIds == null){
720
- try {
721
- $result = $this->_getSearchAdapter()->getResult();
722
-
723
- $this->_searchResultProductIds = array();
724
- if($result instanceof FACTFinder_Result){
725
- foreach ($result AS $record){
726
- if(isset($this->_searchResultProductIds[$record->getId()])){
727
- continue;
728
- }
729
- $this->_searchResultProductIds[$record->getId()] = new Varien_Object(
730
- array(
731
- 'similarity' => $record->getSimilarity(),
732
- 'position' => $record->getPosition(),
733
- 'original_position' => $record->getOriginalPosition()
734
- )
735
- );
736
- }
737
- }
738
- }
739
- catch (Exception $e) {
740
- Mage::logException($e);
741
- $this->_searchResultProductIds = array();
742
- }
743
- }
744
-
745
- return $this->_searchResultProductIds;
746
- }
747
-
748
- /**
749
- * get secondary Search Results
750
- *
751
- * @return array Products Ids
752
- */
753
- public function getSecondarySearchResult($channel)
754
- {
755
- // array_filter() is used to turn a one-element array into an empty array in the case of an empty config-string
756
- $channels = array_filter(explode(';', Mage::getStoreConfig('factfinder/search/secondary_channels')));
757
-
758
- if(!in_array($channel, $channels))
759
- {
760
- Mage::logException(new Exception("Tried to query a channel that was not configured as a secondary channel."));
761
- return array();
762
- }
763
-
764
- if($this->_secondarySearchResults == null)
765
- {
766
- $this->_secondarySearchResults = array();
767
-
768
- $query = Mage::helper('factfinder/search')->getQueryText();
769
-
770
- $searchAdapters = array();
771
-
772
- foreach($channels AS $currentChannel)
773
- {
774
- try {
775
- $searchAdapters[$currentChannel] = $this->_getSecondarySearchAdapter($currentChannel, $query);
776
- }
777
- catch (Exception $e) {
778
- Mage::logException($e);
779
- }
780
- }
781
-
782
- FACTFinder_Http_ParallelDataProvider::loadAllData();
783
-
784
- foreach($searchAdapters AS $currentChannel => $searchAdapter)
785
- {
786
- try {
787
- $this->_secondarySearchResults[$currentChannel] = $searchAdapter->getResult();
788
- }
789
- catch (Exception $e) {
790
- Mage::logException($e);
791
- }
792
- }
793
- }
794
-
795
- if(!array_key_exists($channel, $this->_secondarySearchResults))
796
- {
797
- Mage::logException(new Exception("Result for channel '".$channel."' could not be retrieved."));
798
- return array();
799
- }
800
-
801
- return $this->_secondarySearchResults[$channel];
802
- }
803
-
804
- /**
805
- * get a (new) FactFinder SearchAdapter for a secondary channel
806
- *
807
- * @return FACTFinder_Abstract_SearchAdapter
808
- */
809
- protected function _getSecondarySearchAdapter($channel, $query)
810
- {
811
- $config = $this->_getConfiguration();
812
- $encodingHandler = FF::getSingleton('encodingHandler', $config);
813
- $dataProvider = $this->_getParallelDataProvider($channel);
814
-
815
- // Overwrite the channel set by the configuration
816
- $dataProvider->setParam('channel', $channel);
817
- $dataProvider->setParam('query', $query);
818
-
819
- $searchAdapter = FF::getInstance(
820
- 'xml'.Mage::getStoreConfig('factfinder/search/ffversion').'/searchAdapter',
821
- $dataProvider,
822
- $this->_getParamsParser(),
823
- $encodingHandler
824
- );
825
-
826
- return $searchAdapter;
827
- }
828
-
829
- /**
830
- * get a (new) FactFinder DataProvider that works in parallel
831
- *
832
- * @return FACTFinder_Abstract_Dataprovider
833
- **/
834
- protected function _getParallelDataProvider()
835
- {
836
- $config = $this->_getConfiguration();
837
- $params = $this->_getParamsParser()->getServerRequestParams();
838
-
839
- $dp = FACTFinder_Http_ParallelDataProvider::getDataProvider($params, $config);
840
-
841
- return $dp;
842
- }
843
-
844
- /**
845
- * set single parameter, which will be looped through to the FACT-Finder request
846
- *
847
- * @param string name
848
- * @param string value
849
- */
850
- protected function _setParam($name, $value, $log = true)
851
- {
852
- if($log){
853
- Mage::helper('factfinder/debug')->log('set Param:'.$name.' => '.$value);
854
- }
855
- $this->_getDataProvider()->setParam($name, $value);
856
- return $this;
857
- }
858
-
859
- /**
860
- * get FactFinder DataProvider
861
- *
862
- * @return FACTFinder_Abstract_DataProvider
863
- */
864
- protected function _getDataProvider()
865
- {
866
- if ($this->_dataProvider == null) {
867
- $config = $this->_getConfiguration();
868
- $params = $this->_getParamsParser()->getServerRequestParams();
869
-
870
- $this->_dataProvider = FF::getInstance('http/dataProvider', $params, $config);
871
- }
872
- return $this->_dataProvider;
873
- }
874
-
875
- /**
876
- * get Autentivation URL
877
- *
878
- * @return string
879
- */
880
- public function getAuthenticationUrl()
881
- {
882
- $dataprovider = $this->_getDataProvider();
883
- $dataprovider->setType('Management.ff');
884
- return $dataprovider->getNonAuthenticationUrl();
885
- }
886
-
887
- /**
888
- * get FactFinder Params Parser
889
- *
890
- * @return FACTFinder_ParametersParser
891
- */
892
- protected function _getParamsParser()
893
- {
894
- if ($this->_paramsParser == null) {
895
- $config = $this->_getConfiguration();
896
- $encodingHandler = FF::getSingleton('encodingHandler', $config);
897
- $this->_paramsParser = FF::getInstance('parametersParser', $config, $encodingHandler);
898
- }
899
- return $this->_paramsParser;
900
- }
901
-
902
- /**
903
- * set FactFinder Configuration
904
- *
905
- * @param array $configarray
906
- */
907
- public function setConfiguration($configarray)
908
- {
909
- $this->_config = FF::getSingleton('configuration', $configarray);
910
- }
911
-
912
- /**
913
- * get FactFinder Configuration
914
- *
915
- * @return FACTFinder_Abstract_Configuration config
916
- */
917
- protected function _getConfiguration($configarray = null)
918
- {
919
- if ($this->_config == null) {
920
- $this->_config = FF::getSingleton('configuration', $configarray);
921
- }
922
- return $this->_config;
923
- }
924
-
925
-
926
- /**
927
- * Set StoreId for current configuration
928
- *
929
- * @param unknown_type $storeId
930
- */
931
- public function setStoreId($storeId) {
932
- $this->_getConfiguration()->setStoreId($storeId);
933
-
934
- return $this;
935
- }
936
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Flagbit/FactFinder/Model/Export/Product.php CHANGED
@@ -195,8 +195,8 @@ class Flagbit_FactFinder_Model_Export_Product extends Mage_CatalogSearch_Model_M
195
  }
196
  }
197
 
198
- $productIndexes = array();
199
- $productAttributes = $this->_getProductAttributes($storeId, $productAttributes, $dynamicFields);
200
  foreach ($products as $productData) {
201
  if (!isset($productAttributes[$productData['entity_id']])) {
202
  continue;
@@ -223,14 +223,14 @@ class Flagbit_FactFinder_Model_Export_Product extends Mage_CatalogSearch_Model_M
223
  $product = Mage::getModel("catalog/product");
224
  $product->load($productData['entity_id']);
225
 
226
- $productIndex[] = $this->_imageHelper->init($product, 'image')->resize(120)->__toString();
227
  $productIndex[] = $product->getProductUrl();
228
  }
229
 
230
  $this->_getAttributesRowArray($productIndex, $protductAttr, $storeId);
231
 
232
  $this->_addCsvRow($productIndex);
233
-
234
  if ($productChilds = $productRelations[$productData['entity_id']]) {
235
  foreach ($productChilds as $productChild) {
236
  if (isset($productAttributes[$productChild['entity_id']])) {
195
  }
196
  }
197
 
198
+ $productIndexes = array();
199
+ $productAttributes = $this->_getProductAttributes($storeId, $productAttributes, $dynamicFields);
200
  foreach ($products as $productData) {
201
  if (!isset($productAttributes[$productData['entity_id']])) {
202
  continue;
223
  $product = Mage::getModel("catalog/product");
224
  $product->load($productData['entity_id']);
225
 
226
+ $productIndex[] = $this->_imageHelper->init($product, 'image')->resize(intval(Mage::getStoreConfig('factfinder/export/suggest_image_size')))->__toString();
227
  $productIndex[] = $product->getProductUrl();
228
  }
229
 
230
  $this->_getAttributesRowArray($productIndex, $protductAttr, $storeId);
231
 
232
  $this->_addCsvRow($productIndex);
233
+
234
  if ($productChilds = $productRelations[$productData['entity_id']]) {
235
  foreach ($productChilds as $productChild) {
236
  if (isset($productAttributes[$productChild['entity_id']])) {
app/code/community/Flagbit/FactFinder/Model/Facade.php ADDED
@@ -0,0 +1,377 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Facade that hides FACT-Finder API Framework for 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: Facade.php 906 2011-09-30 14:10:05Z tuerk $
22
+ */
23
+ class Flagbit_FactFinder_Model_Facade
24
+ {
25
+ /**
26
+ * Two-dimensional array of FACT-Finder adapters
27
+ * First-dimension key corresponds to type
28
+ * Second-dimension key corresponds to channel
29
+ * @var array of FACTFinder_Abstract_Adapter
30
+ */
31
+ protected $_adapters = array();
32
+
33
+ /**
34
+ * Key corresponds to channel
35
+ * @var array of FACTFinder_Http_StatusHelper
36
+ */
37
+ protected $_statusHelpers = array();
38
+
39
+ /**
40
+ * @var FACTFinder_Abstract_Configuration
41
+ */
42
+ protected $_config = null;
43
+
44
+ /**
45
+ * @var FACTFinder_ParametersParser
46
+ */
47
+ protected $_paramsParser = null;
48
+
49
+ /**
50
+ * @var FACTFinder_Http_UrlBuilder
51
+ */
52
+ protected $_urlBuilder = null;
53
+
54
+ /**
55
+ * logger object to log all module internals
56
+ * @var FACTFinder_Abstract_Logger
57
+ */
58
+ protected $_logger = null;
59
+
60
+ public function __construct($arg = null)
61
+ {
62
+ if ($arg === null || !($arg instanceof FACTFinder_Abstract_Logger)) {
63
+ $arg = Mage::helper('factfinder/debug');
64
+ }
65
+ FF::setLogger($arg);
66
+ $this->_logger = $arg;
67
+ }
68
+
69
+ /**
70
+ * Used to allow and delegate generic methods. Valid signatures:
71
+ * get_____Adapter($channel = null)
72
+ * configure____Adapter($params = array(), $channel = null)
73
+ *
74
+ * @param string $function
75
+ * @param array $arguments
76
+ * @return FACTFinder_Abstract_Adapter|null
77
+ * @throws Exception
78
+ */
79
+ public function __call($function, $arguments)
80
+ {
81
+ $matches = array();
82
+ $configureAdapter = false;
83
+ $channelArgPos = 0;
84
+ if (preg_match('/^get(.+)Adapter$/', $function, $matches))
85
+ {
86
+ // We have a get______Adapter($channel) method!
87
+ // The first argument (if any) will be treated as a channel
88
+
89
+ $channelArgPos = 0;
90
+
91
+ }
92
+ elseif (preg_match('/^configure(.+)Adapter$/', $function, $matches))
93
+ {
94
+ // We have a configure_____Adapter($params, $channel) method!
95
+ // The first argument (if any) will be treated as an array of params as key-value pairs
96
+ // The second argument (if any) will be treated as a channel
97
+
98
+ $configureAdapter = true;
99
+ $channelArgPos = 1;
100
+ }
101
+ else
102
+ {
103
+ throw new Exception("Call to undefined method ".$function."() in file ".__FILE__." on line ".__LINE__);
104
+ }
105
+
106
+ $type = $matches[1];
107
+ $type[0] = strtolower($type[0]);
108
+
109
+ $format = $this->_getFormat($type);
110
+
111
+ $channel = null;
112
+ if(count($arguments) > $channelArgPos)
113
+ $channel = $arguments[$channelArgPos];
114
+
115
+ $adapter = $this->_getAdapter($format, $type, $channel);
116
+
117
+ if($configureAdapter && count($arguments))
118
+ {
119
+ foreach($arguments[0] as $key => $value)
120
+ $adapter->setParam($key, $value);
121
+
122
+ return null;
123
+ }
124
+ else
125
+ {
126
+ return $adapter;
127
+ }
128
+ }
129
+
130
+ protected function _getFormat($type)
131
+ {
132
+ $format = 'http';
133
+ if ($type != 'scic' && $type != 'suggest') {
134
+ $version = $this->_getConfiguration()->getFactFinderVersion();
135
+ $format = 'xml' . $version;
136
+ return $format;
137
+ }
138
+ return $format;
139
+ }
140
+
141
+ /**
142
+ * @return FACTFinder_Abstract_Adapter
143
+ */
144
+ protected function _getAdapter($format, $type, $channel = null)
145
+ {
146
+ if(!$channel)
147
+ $channel = $this->_getConfiguration()->getChannel();
148
+ if(!isset($this->_adapters[$type][$channel]))
149
+ {
150
+ $config = $this->_getConfiguration();
151
+ $encodingHandler = FF::getSingleton('encodingHandler', $config);
152
+ $dataProvider = $this->_getParallelDataProvider();
153
+ $dataProvider->setParam('channel', $channel);
154
+ $this->_adapters[$type][$channel] = FF::getInstance(
155
+ $format.'/'.$type.'Adapter',
156
+ $dataProvider,
157
+ $this->_getParamsParser(),
158
+ $encodingHandler,
159
+ $this->_logger
160
+ );
161
+ }
162
+ return $this->_adapters[$type][$channel];
163
+ }
164
+
165
+ public function configureStatusHelper($channel = null)
166
+ {
167
+ if(!$channel)
168
+ $channel = $this->_getConfiguration()->getChannel();
169
+ if(!isset($this->_statusHelpers[$channel]))
170
+ {
171
+ $config = $this->_getConfiguration();
172
+ $encodingHandler = FF::getSingleton('encodingHandler', $config);
173
+ $this->_statusHelpers[$channel] = FF::getInstance(
174
+ 'http/statusHelper',
175
+ $config,
176
+ $this->_logger,
177
+ $channel
178
+ );
179
+ }
180
+ }
181
+
182
+ /**
183
+ * @return FACTFinderCustom_Configuration config
184
+ */
185
+ protected function _getConfiguration($configArray = null)
186
+ {
187
+ if ($this->_config == null) {
188
+ $this->_config = FF::getSingleton('configuration', $configArray);
189
+ }
190
+ return $this->_config;
191
+ }
192
+
193
+ public function setConfiguration($configArray)
194
+ {
195
+ $this->_config = FF::getSingleton('configuration', $configArray);
196
+ }
197
+
198
+ /**
199
+ * @param int $storeId
200
+ * @return \Flagbit_FactFinder_Model_Facade
201
+ */
202
+ public function setStoreId($storeId) {
203
+ $this->_getConfiguration()->setStoreId($storeId);
204
+
205
+ return $this;
206
+ }
207
+
208
+ /**
209
+ * @return FACTFinder_Abstract_DataProvider
210
+ **/
211
+ protected function _getParallelDataProvider()
212
+ {
213
+ $config = $this->_getConfiguration();
214
+ $params = $this->_getParamsParser()->getServerRequestParams();
215
+ $dp = FACTFinder_Http_ParallelDataProvider::getDataProvider($params, $config, $this->_logger);
216
+ return $dp;
217
+ }
218
+
219
+ /**
220
+ * @return FACTFinder_ParametersParser
221
+ */
222
+ protected function _getParamsParser()
223
+ {
224
+ if ($this->_paramsParser == null) {
225
+ $config = $this->_getConfiguration();
226
+ $encodingHandler = FF::getSingleton('encodingHandler', $config);
227
+ $this->_paramsParser = FF::getInstance('parametersParser', $config, $encodingHandler);
228
+ }
229
+ return $this->_paramsParser;
230
+ }
231
+
232
+ public function getManagementUrl()
233
+ {
234
+ $urlBuilder = $this->_getUrlBuilder();
235
+ $urlBuilder->setAction('Management.ff');
236
+ return $urlBuilder->getNonAuthenticationUrl();
237
+ }
238
+
239
+ public function getSuggestUrl()
240
+ {
241
+ $urlBuilder = $this->_getUrlBuilder();
242
+ $urlBuilder->setAction('Suggest.ff');
243
+ $urlBuilder->setParams(array());
244
+
245
+ return $urlBuilder->getNonAuthenticationUrl();
246
+ }
247
+
248
+ protected function _getUrlBuilder()
249
+ {
250
+ if($this->_urlBuilder === null) {
251
+ $config = $this->_getConfiguration();
252
+ $params = $this->_getParamsParser()->getServerRequestParams();
253
+
254
+ $this->_urlBuilder = FF::getInstance('http/urlBuilder', $params, $config, $this->_logger);
255
+ }
256
+ return $this->_urlBuilder;
257
+ }
258
+
259
+ public function applyTracking($channel = null)
260
+ {
261
+ return $this->_getFactFinderObject("Scic", "applyTracking", $channel);
262
+ }
263
+
264
+ public function getAfterSearchNavigation($channel = null)
265
+ {
266
+ return $this->_getFactFinderObject("Search", "getAsn", $channel);
267
+ }
268
+
269
+ public function getCampaigns($channel = null)
270
+ {
271
+ return $this->_getFactFinderObject("Search", "getCampaigns", $channel);
272
+ }
273
+
274
+ public function getProductCampaigns($channel = null)
275
+ {
276
+ return $this->_getFactFinderObject("ProductCampaign", "getCampaigns", $channel);
277
+ }
278
+
279
+ public function getRecommendations($channel = null)
280
+ {
281
+ return $this->_getFactFinderObject("Recommendation", "getRecommendations", $channel);
282
+ }
283
+
284
+ public function getSearchError($channel = null)
285
+ {
286
+ return $this->_getFactFinderObject("Search", "getError", $channel);
287
+ }
288
+
289
+ public function getSearchParams($channel = null)
290
+ {
291
+ return $this->_getFactFinderObject("Search", "getSearchParams", $channel);
292
+ }
293
+
294
+ public function getSearchResult($channel = null)
295
+ {
296
+ return $this->_getFactFinderObject("Search", "getResult", $channel);
297
+ }
298
+
299
+ public function getSearchStackTrace($channel = null)
300
+ {
301
+ return $this->_getFactFinderObject("Search", "getStackTrace", $channel);
302
+ }
303
+
304
+ public function getSearchStatus($channel = null)
305
+ {
306
+ return $this->_getFactFinderObject("Search", "getStatus", $channel);
307
+ }
308
+
309
+ public function getSuggestions($channel = null)
310
+ {
311
+ return $this->_getFactFinderObject("Suggest", "getSuggestions", $channel);
312
+ }
313
+
314
+ public function getTagCloud($channel = null)
315
+ {
316
+ return $this->_getFactFinderObject("TagCloud", "getTagCloud", $channel);
317
+ }
318
+
319
+ protected function _getFactFinderObject($adapterType, $objectGetter, $channel = null)
320
+ {
321
+ try {
322
+ $this->_loadAllData();
323
+ $adapterGetter = "get".$adapterType."Adapter";
324
+ return $this->$adapterGetter($channel)->$objectGetter();
325
+ } catch (Exception $e) {
326
+ Mage::logException($e);
327
+ return null;
328
+ }
329
+ }
330
+
331
+ public function getActualFactFinderVersion()
332
+ {
333
+ try {
334
+ $channel = $this->_getConfiguration()->getChannel();
335
+ $this->_loadAllData();
336
+ return $this->_statusHelpers[$channel]->getVersionNumber();
337
+ } catch (Exception $e) {
338
+ Mage::logException($e);
339
+ return null;
340
+ }
341
+ }
342
+
343
+ public function getActualFactFinderVersionString()
344
+ {
345
+ try {
346
+ $channel = $this->_getConfiguration()->getChannel();
347
+ $this->_loadAllData();
348
+ return $this->_statusHelpers[$channel]->getVersionString();
349
+ } catch (Exception $e) {
350
+ Mage::logException($e);
351
+ return null;
352
+ }
353
+ }
354
+
355
+ public function getFactFinderStatus($channel = null)
356
+ {
357
+ try {
358
+ if(!$channel)
359
+ $channel = $this->_getConfiguration()->getChannel();
360
+ $this->_loadAllData();
361
+ return $this->_statusHelpers[$channel]->getStatusCode();
362
+ } catch (Exception $e) {
363
+ Mage::logException($e);
364
+ return null;
365
+ }
366
+ }
367
+
368
+ protected function _loadAllData()
369
+ {
370
+ FACTFinder_Http_ParallelDataProvider::loadAllData();
371
+ }
372
+
373
+ public function getRequestParams()
374
+ {
375
+ return $this->_getParamsParser()->getRequestParams();
376
+ }
377
+ }
app/code/community/Flagbit/FactFinder/Model/Handler/Abstract.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Abstract class for Fact Finder object handlers
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ * @author Martin Buettner <martin.buettner@omikron.net>
9
+ * @version $Id: Abstract.php 13.09.12 14:19 $
10
+ *
11
+ **/
12
+ abstract class Flagbit_FactFinder_Model_Handler_Abstract
13
+ {
14
+ /**
15
+ * @var Flagbit_FactFinder_Model_Facade
16
+ **/
17
+ protected $_facade;
18
+
19
+ /**
20
+ *
21
+ */
22
+ public function __construct()
23
+ {
24
+ $this->configureFacade();
25
+ }
26
+
27
+ /**
28
+ * Implement this method to set up any adapters the handler will need later on.
29
+ * WARNING: You will always have to configure...() the adapter once, even if you do not set any parameters.
30
+ * This will register the adapter with the Facade and lets it query all data in parallel.
31
+ */
32
+ abstract protected function configureFacade();
33
+
34
+ /**
35
+ * @return Flagbit_FactFinder_Model_Facade
36
+ */
37
+ protected function _getFacade()
38
+ {
39
+ if($this->_facade === null)
40
+ {
41
+ $this->_facade = Mage::getSingleton('factfinder/facade');
42
+ }
43
+ return $this->_facade;
44
+ }
45
+ }
app/code/community/Flagbit/FactFinder/Model/Handler/CheckStatus.php ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Checks whether the configuration is working
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ * @author Martin Buettner <martin.buettner@omikron.net>
9
+ * @version $Id: CheckStatus.php 17.09.12 15:00 $
10
+ *
11
+ **/
12
+ class Flagbit_FactFinder_Model_Handler_CheckStatus
13
+ extends Flagbit_FactFinder_Model_Handler_Abstract
14
+ {
15
+ protected $_configArray;
16
+
17
+ protected $_errorMessages = array();
18
+
19
+ protected $_helper;
20
+
21
+ protected $_secondaryChannels;
22
+
23
+ public function __construct($configArray = null)
24
+ {
25
+ $this->_configArray = $configArray;
26
+ parent::__construct();
27
+ }
28
+
29
+ protected function configureFacade()
30
+ {
31
+ FF::getSingleton('configuration', $this->_configArray);
32
+
33
+ $this->_secondaryChannels = FF::getSingleton('configuration')->getSecondaryChannels();
34
+
35
+ $this->_getFacade()->configureStatusHelper();
36
+ foreach($this->_secondaryChannels AS $channel)
37
+ $this->_getFacade()->configureStatusHelper($channel);
38
+
39
+ }
40
+
41
+ public function checkStatus($configuredVersion)
42
+ {
43
+ // uncomment to see debug output
44
+ //ob_start();
45
+
46
+ $statusOkay = true;
47
+ $this->_errorMessage = array();
48
+
49
+ $primaryStatus = $this->_getFacade()->getFactFinderStatus();
50
+ if($primaryStatus !== FFE_OK)
51
+ {
52
+ $this->_errorMessages[] = $this->_retrieveErrorMessage($primaryStatus);
53
+ $statusOkay = false;
54
+ }
55
+ foreach($this->_secondaryChannels AS $channel)
56
+ {
57
+ $secondaryStatus = $this->_getFacade()->getFactFinderStatus($channel);
58
+ if($secondaryStatus !== FFE_OK)
59
+ {
60
+ $this->_errorMessages[] = $this->_retrieveErrorMessage($secondaryStatus, $channel);
61
+ $statusOkay = false;
62
+ }
63
+ }
64
+
65
+ $actualVersion = $this->_getFacade()->getActualFactFinderVersion();
66
+ $actualVersionString = $this->_getFacade()->getActualFactFinderVersionString();
67
+
68
+ if($statusOkay && $actualVersion < $configuredVersion)
69
+ {
70
+ $this->_errorMessages[] = $this->_getHelper()->__(
71
+ 'The configured FACT-Finder version is higher than the actual version of your FACT-Finder. '.
72
+ 'Consider upgrading your FACT-Finder, or reduce the configured version to '
73
+ ).$actualVersionString;
74
+ $statusOkay = false;
75
+ }
76
+
77
+ // uncomment to see debug output
78
+ //$this->_errorMessages[] = ob_get_clean();
79
+
80
+ return $statusOkay;
81
+ }
82
+
83
+ protected function _retrieveErrorMessage($statusCode, $channel = null)
84
+ {
85
+ $helper = $this->_getHelper();
86
+ if($channel === null)
87
+ $errorMessage = $helper->__('Error in Primary Channel') . ': ';
88
+ else
89
+ $errorMessage = $helper->__('Error in Channel').' "'.$channel.'": ';
90
+
91
+ switch($statusCode)
92
+ {
93
+ case FFE_WRONG_CONTEXT:
94
+ $errorMessage .= $helper->__('FACT-Finder not found on server. Please check your context setting.');
95
+ return $errorMessage;
96
+ case FFE_CHANNEL_DOES_NOT_EXIST:
97
+ $errorMessage .= $helper->__('Channel does not exist or the specified user does not have sufficient rights.');
98
+ return $errorMessage;
99
+ case FFE_WRONG_CREDENTIALS:
100
+ $errorMessage .= $helper->__('Could not log into FACT-Finder with the given settings. Please check username, password, prefix and postfix.');
101
+ return $errorMessage;
102
+ case FFE_SERVER_TIME_MISMATCH:
103
+ $errorMessage .= $helper->__('Your server\'s clock does not agree with FACT-Finder\'s. Please make sure your clock is set correctly.');
104
+ return $errorMessage;
105
+ }
106
+
107
+ $codeType = floor($statusCode / 1000) * 1000;
108
+
109
+ switch($codeType)
110
+ {
111
+ case FFE_CURL_ERROR:
112
+ $errorMessage .= $helper->__('Could not establish HTTP connection.');
113
+ $errorMessage .= ' cURL Error Code: '.($statusCode - $codeType);
114
+ break;
115
+ case FFE_HTTP_ERROR:
116
+ $errorMessage .= $helper->__('Could not contact FACT-Finder.');
117
+ $errorMessage .= ' HTTP Status Code: '.($statusCode - $codeType);
118
+ break;
119
+ case FFE_FACT_FINDER_ERROR:
120
+ $errorMessage .= $helper->__('There is a problem with FACT-Finder. Please contact FACT-Finder Support.');
121
+ break;
122
+ default:
123
+ $errorMessage .= $helper->__('An unknown error has occurred. Please contact FACT-Finder Support.');
124
+ break;
125
+ }
126
+
127
+ return $errorMessage;
128
+ }
129
+
130
+ protected function _getHelper()
131
+ {
132
+ if($this->_helper === null)
133
+ $this->_helper = Mage::helper('factfinder');
134
+ return $this->_helper;
135
+ }
136
+
137
+ public function getErrorMessages()
138
+ {
139
+ return $this->_errorMessages;
140
+ }
141
+ }
app/code/community/Flagbit/FactFinder/Model/Handler/ProductCampaign.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handles product campaign data
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ * @author Martin Buettner <martin.buettner@omikron.net>
9
+ * @version $Id: ProductCampaign.php 14.09.12 08:42 $
10
+ *
11
+ **/
12
+ abstract class Flagbit_FactFinder_Model_Handler_ProductCampaign
13
+ extends Flagbit_FactFinder_Model_Handler_Abstract
14
+ {
15
+ protected $_productIds = array();
16
+
17
+ protected $_campaigns;
18
+
19
+ protected $_featureAvailable = true;
20
+
21
+ public function __construct($productIds)
22
+ {
23
+ $this->_productIds = $productIds;
24
+ parent::__construct();
25
+ }
26
+
27
+ /**
28
+ * {@inheritdoc}
29
+ */
30
+ protected function configureFacade()
31
+ {
32
+ $params = array();
33
+ $params['do'] = $this->_getDoParam();
34
+ $params['productNumber'] = $this->_getProductNumberParam();
35
+ $params['idsOnly'] = 'true';
36
+
37
+ try {
38
+ $adapter = $this->_getFacade()->configureProductCampaignAdapter($params);
39
+ } catch(Exception $e) {
40
+ Mage::helper('factfinder/debug')->log('Product Campaigns not available before FACT-Finder 6.7.');
41
+ $this->_featureAvailable = false;
42
+ return;
43
+ }
44
+ }
45
+
46
+ abstract protected function _getDoParam();
47
+ abstract protected function _getProductNumberParam();
48
+
49
+ public function getActiveAdvisorQuestions()
50
+ {
51
+ $campaigns = $this->getCampaigns();
52
+
53
+ $questions = array();
54
+
55
+ if($campaigns && $campaigns->hasActiveQuestions()){
56
+ $questions = $campaigns->getActiveQuestions();
57
+ }
58
+
59
+ return $questions;
60
+ }
61
+
62
+ public function getCampaigns()
63
+ {
64
+ if(!$this->_featureAvailable)
65
+ $this->_campaigns = array();
66
+
67
+ if($this->_campaigns === null)
68
+ {
69
+ $this->_campaigns = $this->_getFacade()->getProductCampaigns();
70
+ if ($this->_campaigns === null)
71
+ $this->_campaigns = array();
72
+ }
73
+ return $this->_campaigns;
74
+ }
75
+ }
app/code/community/Flagbit/FactFinder/Model/Handler/ProductDetailCampaign.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handles product campaign data on product detail pages
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ * @author Martin Buettner <martin.buettner@omikron.net>
9
+ * @version $Id: ProductCampaign.php 14.09.12 08:42 $
10
+ *
11
+ **/
12
+ class Flagbit_FactFinder_Model_Handler_ProductDetailCampaign
13
+ extends Flagbit_FactFinder_Model_Handler_ProductCampaign
14
+ {
15
+ protected function _getDoParam()
16
+ {
17
+ return 'getProductCampaigns';
18
+ }
19
+
20
+ protected function _getProductNumberParam()
21
+ {
22
+ if(is_array($this->_productIds))
23
+ return $this->_productIds[0];
24
+ else
25
+ return $this->_productIds;
26
+ }
27
+ }
app/code/community/Flagbit/FactFinder/Model/Handler/Recommendations.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handles product campaign data
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ * @author Martin Buettner <martin.buettner@omikron.net>
9
+ * @version $Id: Recommendations.php 14.09.12 11:53 $
10
+ *
11
+ **/
12
+ class Flagbit_FactFinder_Model_Handler_Recommendations
13
+ extends Flagbit_FactFinder_Model_Handler_Abstract
14
+ {
15
+ protected $_productIds = array();
16
+
17
+ protected $_recommendations;
18
+
19
+ public function __construct($productIds)
20
+ {
21
+ $this->_productIds = $productIds;
22
+ parent::__construct();
23
+ }
24
+
25
+ protected function configureFacade()
26
+ {
27
+ $params = array();
28
+ $params['idsOnly'] = 'true';
29
+ $params['id'] = $this->_getIdParam();
30
+ $this->_getFacade()->configureRecommendationAdapter($params);
31
+ }
32
+
33
+ public function getRecommendations()
34
+ {
35
+ if($this->_recommendations === null)
36
+ {
37
+ $this->_recommendations = $this->_getFacade()->getRecommendations();
38
+ if ($this->_recommendations === null)
39
+ $this->_recommendations = array();
40
+ }
41
+ return $this->_recommendations;
42
+ }
43
+
44
+ protected function _getIdParam()
45
+ {
46
+ if(is_array($this->_productIds))
47
+ return $this->_productIds;
48
+ else
49
+ return array($this->_productIds);
50
+ }
51
+ }
app/code/community/Flagbit/FactFinder/Model/Handler/Search.php ADDED
@@ -0,0 +1,424 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handles Search data for secondary channels
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ * @author Martin Buettner <martin.buettner@omikron.net>
9
+ * @version $Id: Search.php 17.09.12 11:50 $
10
+ *
11
+ **/
12
+ class Flagbit_FactFinder_Model_Handler_Search
13
+ extends Flagbit_FactFinder_Model_Handler_Abstract
14
+ {
15
+ protected $_currentFactFinderCategoryPath;
16
+
17
+ protected $_searchResult;
18
+ protected $_searchResultCount;
19
+ protected $_campaigns;
20
+ protected $_afterSearchNavigation;
21
+
22
+ protected function configureFacade()
23
+ {
24
+ $params = $this->_collectParams();
25
+
26
+ $this->_getFacade()->configureSearchAdapter($params);
27
+ }
28
+
29
+ /**
30
+ * prepares all request parameters for the primary search adapter
31
+ **/
32
+
33
+ protected function _collectParams()
34
+ {
35
+ // search Helper
36
+ $helper = Mage::helper('factfinder/search');
37
+ $_request = Mage::app()->getRequest();
38
+ $requestParams = $this->_getFacade()->getRequestParams();
39
+ $params = array();
40
+
41
+ if (strpos(Mage::getStoreConfig('factfinder/config/internal_ip'), Mage::helper('core/http')->getRemoteAddr()) !== false) {
42
+ $params['log'] = 'internal';
43
+ }
44
+
45
+ switch($_request->getModuleName()) {
46
+
47
+ case "xmlconnect":
48
+ $_query = $helper->getQueryText();
49
+ $params['idsOnly'] = FF::getSingleton('configuration')->getIdsOnly() ? 'true' : 'false';
50
+ $params['query'] = $_query;
51
+
52
+ $count = $requestParams['count'];
53
+ if ($count > 0) {
54
+ $params['productsPerPage'] = $count;
55
+ $params['page'] = ($requestParams['offset'] / $count) + 1;
56
+ }
57
+
58
+ // add Sorting Param
59
+ foreach($requestParams as $key => $value){
60
+ if(substr($key, 0, 6) == 'order_') {
61
+ $key = substr($key, 6);
62
+ if(!in_array($key, array('position', 'relevance'))) {
63
+ $params['sort'.$key] = $value;
64
+ }
65
+ }
66
+ }
67
+
68
+ // add Filter Params
69
+ foreach($requestParams as $key => $value){
70
+ $value = base64_decode($value);
71
+ if(strpos($value, '|')) {
72
+ $param = explode('|', $value);
73
+ if($key == 'Category') {
74
+ $categories = array_merge(array_slice(explode('/', $param[0]), 1), array($param[1]));
75
+ foreach($categories AS $k => $v) { $categories[$k] = urldecode($v); }
76
+ $filterKey = '';
77
+ foreach($categories as $category){
78
+ $category = str_replace('%2F', '/', str_replace('%2B', '+', $category));
79
+ $params['filtercategoryROOT'.$filterKey] = $category;
80
+ $filterKey .= '/'.str_replace('+', '%2B', str_replace('/', '%2F', $category));
81
+ }
82
+ } else {
83
+ $params['filter'.$param[0]] = $param[1];
84
+ }
85
+ }
86
+ }
87
+
88
+ break;
89
+
90
+ case "catalog":
91
+ if (!isset($requestParams['Category'])) {
92
+ $params['Category'] = $this->_getCurrentFactFinderCategoryPath();
93
+ }
94
+
95
+ case "catalogsearch":
96
+ default:
97
+ $_query = '*';
98
+ if ($_request->getModuleName() == 'catalogsearch') {
99
+ $_query = $helper->getQueryText();
100
+ }
101
+
102
+ // add Default Params
103
+ $params['idsOnly'] = FF::getSingleton('configuration')->getIdsOnly() ? 'true' : 'false';
104
+ $params['productsPerPage'] = $helper->getPageLimit();
105
+ $params['query'] = $_query;
106
+ $params['page'] = $helper->getCurrentPage();
107
+
108
+ // add Sorting Param, but only if it was set explicitly via url
109
+ foreach($requestParams as $key => $value) {
110
+ if($key == 'order'
111
+ && $helper->getCurrentOrder()
112
+ && $helper->getCurrentDirection()
113
+ && $helper->getCurrentOrder() != 'position'
114
+ && $helper->getCurrentOrder() != 'relevance')
115
+ {
116
+ $params['sort'.$helper->getCurrentOrder()] = $helper->getCurrentDirection();
117
+ }
118
+ }
119
+
120
+ // add Filter Params
121
+ foreach($requestParams as $key => $value) {
122
+ if(strpos($value, '|')) {
123
+ $param = explode('|', $value);
124
+ switch($param[1]) {
125
+
126
+ case 'slider':
127
+ $subParam = explode(':', $param[2]);
128
+ $params[$subParam[0]] = $subParam[1];
129
+ $subParam = explode(':', $param[3]);
130
+ $params[$subParam[0]] = $subParam[1];
131
+ break;
132
+
133
+ default:
134
+ if($key == 'Category') {
135
+ $categories = array_merge(array_slice(explode('/', $param[0]), 1), array($param[1]));
136
+ foreach($categories AS $k => $v) { $categories[$k] = $v; }
137
+ $filterKey = '';
138
+ foreach($categories as $category) {
139
+ $category = str_replace('%2F', '/', str_replace('%2B', '+', $category));
140
+ $params['filtercategoryROOT'.$filterKey] = $category;
141
+ $filterKey .= '/'.str_replace('+', '%2B', str_replace('/', '%2F', $category));
142
+ }
143
+
144
+ } else {
145
+ $params['filter'.$param[0]] = $param[1];
146
+ }
147
+ break;
148
+ }
149
+ }
150
+ }
151
+ break;
152
+
153
+ }
154
+
155
+ return $params;
156
+ }
157
+
158
+ protected function _getCurrentFactFinderCategoryPath($all = false)
159
+ {
160
+ $returnValue = '';
161
+ if($this->_currentFactFinderCategoryPath == null && Mage::getStoreConfigFlag('factfinder/activation/navigation') && Mage::registry('current_category')){
162
+ $this->_currentFactFinderCategoryPath = array();
163
+ /* @var $category Mage_Catalog_Model_Category */
164
+ $category = Mage::registry('current_category');
165
+
166
+ $pathInStore = $category->getPathInStore();
167
+ $pathIds = array_reverse(explode(',', $pathInStore));
168
+
169
+ $categories = $category->getParentCategories();
170
+ $mainCategoriesString = '';
171
+ foreach ($pathIds as $categoryId) {
172
+ if (isset($categories[$categoryId]) && $categories[$categoryId]->getName()) {
173
+ if(empty($mainCategoriesString)){
174
+ $this->_currentFactFinderCategoryPath[] = 'categoryROOT|'.$categories[$categoryId]->getName();
175
+ }else{
176
+ $this->_currentFactFinderCategoryPath[] = 'categoryROOT'.$mainCategoriesString.'|'.$categories[$categoryId]->getName();
177
+ }
178
+ $mainCategoriesString .= '/'. str_replace('/', '%2F', $categories[$categoryId]->getName());
179
+ }
180
+ }
181
+ } else {
182
+ $this->_currentFactFinderCategoryPath = array();
183
+ }
184
+
185
+ if($all === false){
186
+ if (isset($this->_currentFactFinderCategoryPath[count($this->_currentFactFinderCategoryPath)-1])) {
187
+ $returnValue = $this->_currentFactFinderCategoryPath[count($this->_currentFactFinderCategoryPath)-1];
188
+ }
189
+ else {
190
+ $returnValue = false;
191
+ }
192
+ } else {
193
+ $returnValue = $this->_currentFactFinderCategoryPath;
194
+ }
195
+
196
+ return $returnValue;
197
+ }
198
+
199
+ public function getAfterSearchNavigation()
200
+ {
201
+ if($this->_afterSearchNavigation == null) {
202
+ $this->_afterSearchNavigation = array();
203
+
204
+ $result = $this->_getFacade()->getAfterSearchNavigation();
205
+
206
+ if ($result instanceof FACTFinder_Asn
207
+ && count($result)) {
208
+
209
+ foreach ($result as $row) {
210
+ $this->_afterSearchNavigation[] = array(
211
+ 'attribute_code' => $row->getName(),
212
+ 'name' => $row->getName(),
213
+ 'unit' => $row->getUnit(),
214
+ 'items' => $this->_getAttributeOptions($row->getArrayCopy(), $row->getUnit()),
215
+ 'count' => $row->count(),
216
+ 'type' => $this->_getFilterType($row->getArrayCopy()),
217
+ 'store_label' => $row->getName()
218
+ );
219
+ }
220
+ }
221
+ }
222
+ return $this->_afterSearchNavigation;
223
+ }
224
+
225
+ /**
226
+ * get Filter Type by FACT-Finder FilterItem
227
+ *
228
+ * @param array $options
229
+ * @return string
230
+ */
231
+ protected function _getFilterType($options)
232
+ {
233
+ $defaultType = 'item';
234
+ foreach($options as $option){
235
+ if(!$option->getType()){
236
+ continue;
237
+ }
238
+ $defaultType = $option->getType();
239
+ break;
240
+ }
241
+ return $defaultType;
242
+ }
243
+
244
+ /**
245
+ * get Attribute Options Array from FactFinder FilterGroupItems
246
+ *
247
+ * @param FACTFinder_AsnFilterItem $options
248
+ * @param string $unit
249
+ * @return array
250
+ */
251
+ protected function _getAttributeOptions($options, $unit = '')
252
+ {
253
+ $attributeOption = array();
254
+ if (!empty($unit)) $unit = ' ' . $unit;
255
+ $_currentCategoryPath = $this->_getCurrentFactfinderCategoryPath(true);
256
+ $helper = Mage::helper('factfinder/search');
257
+ foreach($options as $option){
258
+
259
+ switch ($option->getType()){
260
+
261
+ case "slider":
262
+ $attributeOption[] = array(
263
+ 'type' => $option->getType(),
264
+ 'label' => 'slider',
265
+ 'value' => $this->_getAttributeOptionValue($option),
266
+ 'absolute_min' => $option->getAbsoluteMin(),
267
+ 'absolute_max' => $option->getAbsoluteMax(),
268
+ 'selected_min' => $option->getSelectedMin(),
269
+ 'selected_max' => $option->getSelectedMax(),
270
+ 'count' => true,
271
+ 'selected' => false //$option->isSelected()
272
+ );
273
+ break;
274
+
275
+ default:
276
+ if (!Mage::helper('core/string')->strlen($option->getValue())) {
277
+ continue;
278
+ }
279
+ // remove Categories from top Level Navigation
280
+ $_value = $this->_getAttributeOptionValue($option);
281
+ if(Mage::getStoreConfigFlag('factfinder/activation/navigation')
282
+ && !$helper->getIsOnSearchPage()
283
+ && (
284
+ empty($_value) === true
285
+ || in_array($_value, $_currentCategoryPath)
286
+ && $_currentCategoryPath[count($_currentCategoryPath)-1] != $_value
287
+ )){
288
+ continue;
289
+ }
290
+
291
+ $attributeOption[] = array(
292
+ 'type' => 'attribute',
293
+ 'label' => $option->getValue() . $unit,
294
+ 'value' => $_value,
295
+ 'count' => $option->getMatchCount(),
296
+ 'selected' => $option->isSelected(),
297
+ 'clusterLevel' => $option->getClusterLevel()
298
+ );
299
+ break;
300
+ }
301
+ }
302
+ return $attributeOption;
303
+ }
304
+
305
+ /**
306
+ * get Attribute option Value
307
+ *
308
+ * @param string $option
309
+ * @return string
310
+ */
311
+ protected function _getAttributeOptionValue($option)
312
+ {
313
+ $searchParams = $this->_getFacade()->getSearchParams();
314
+ if($searchParams instanceof FACTFinder_Parameters)
315
+ $selectOptions = $searchParams->getFilters();
316
+
317
+ $value = null;
318
+ switch ($option->getType()) {
319
+
320
+ // handle Slider Attributes
321
+ case "slider":
322
+ $value = $option->getField().'|'.$option->getType().'|'.str_replace(array('&', '='), array('|', ':'), $option->getValue()).'[VALUE]';
323
+ break;
324
+
325
+ // handle default Attributes
326
+ default:
327
+ $value = $option->getField();
328
+ if($option->isSelected()) {
329
+
330
+ // handle multi-selectable Attributes
331
+ if(isset($selectOptions[$option->getField()]) ){
332
+ if(strpos($option->getField(), 'categoryROOT') === false) {
333
+ $values = explode('~~~', $selectOptions[$option->getField()]);
334
+ unset($values[array_search($option->getValue(), $values)]);
335
+ $value .= '|'.implode('~~~', $values);
336
+
337
+ } else {
338
+ $values = explode('/',str_replace('|'.$selectOptions[$option->getField()], '', $value));
339
+ $valueCount = count($values);
340
+ $value = '';
341
+ if($valueCount > 1) {
342
+ for($i=0 ; $valueCount > $i ; $i++) {
343
+ $value .= ($i != 0 ? ($i == $valueCount-1 ? '|' : '/') : '').$values[$i];
344
+ }
345
+ }
346
+ }
347
+ }
348
+ } else {
349
+ $value .= '|'.$option->getValue();
350
+ // handle multi-selectable Attributes
351
+ if(isset($selectOptions[$option->getField()])) {
352
+ $value .= '~~~'.$selectOptions[$option->getField()];
353
+ }
354
+ }
355
+ break;
356
+ }
357
+ return $value;
358
+ }
359
+
360
+ public function getRedirect()
361
+ {
362
+ $url = null;
363
+ $campaigns = $this->getCampaigns();
364
+
365
+ if (!empty($campaigns) && $campaigns->hasRedirect()) {
366
+ $url = $campaigns->getRedirectUrl();
367
+ }
368
+ return $url;
369
+ }
370
+
371
+ public function getCampaigns()
372
+ {
373
+ if($this->_campaigns === null)
374
+ {
375
+ $this->_campaigns = $this->_getFacade()->getCampaigns();
376
+ }
377
+ return $this->_campaigns;
378
+ }
379
+
380
+ public function getSearchResultCount()
381
+ {
382
+ if($this->_searchResultCount === null)
383
+ {
384
+ $result = $this->_getFacade()->getSearchResult();
385
+ if($result instanceof FACTFinder_Result)
386
+ $this->_searchResultCount = $result->getFoundRecordsCount();
387
+ if($this->_searchResultCount === null)
388
+ $this->_searchResultCount = 0;
389
+ }
390
+ return $this->_searchResultCount;
391
+ }
392
+
393
+ public function getSearchResult()
394
+ {
395
+ if($this->_searchResult === null) {
396
+ $result = $this->_getFacade()->getSearchResult();
397
+ $error = $this->_getFacade()->getSearchError();
398
+ if($result === null || $error)
399
+ {
400
+ Mage::helper('factfinder/search')->registerFailedAttempt();
401
+ Mage::logException(new Exception($error));
402
+ }
403
+ $this->_searchResult = array();
404
+ if($result instanceof FACTFinder_Result) {
405
+ foreach ($result AS $record){
406
+ if(isset($this->_searchResult[$record->getId()])) {
407
+ continue;
408
+ }
409
+ $this->_searchResult[$record->getId()] = new Varien_Object(
410
+ array(
411
+ 'similarity' => $record->getSimilarity(),
412
+ 'position' => $record->getPosition(),
413
+ 'original_position' => $record->getOriginalPosition()
414
+ )
415
+ );
416
+ }
417
+ }
418
+ }
419
+
420
+ return $this->_searchResult;
421
+ }
422
+
423
+
424
+ }
app/code/community/Flagbit/FactFinder/Model/Handler/SecondarySearch.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handles Search data for secondary channels
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ * @author Martin Buettner <martin.buettner@omikron.net>
9
+ * @version $Id: SecondarySearch.php 17.09.12 11:02 $
10
+ *
11
+ **/
12
+ class Flagbit_FactFinder_Model_Handler_SecondarySearch
13
+ extends Flagbit_FactFinder_Model_Handler_Abstract
14
+ {
15
+ protected $_secondaryChannels;
16
+ protected $_secondarySearchResults = array();
17
+
18
+ protected function configureFacade()
19
+ {
20
+ $params = array();
21
+ $params['query'] = Mage::helper('factfinder/search')->getQueryText();
22
+ $this->_secondaryChannels = FF::getSingleton('configuration')->getSecondaryChannels();
23
+
24
+ foreach($this->_secondaryChannels AS $channel)
25
+ {
26
+ $params['channel'] = $channel;
27
+ $this->_getFacade()->configureSearchAdapter($params, $channel);
28
+ }
29
+ }
30
+
31
+ public function getSecondarySearchResult($channel)
32
+ {
33
+ if(!in_array($channel, $this->_secondaryChannels))
34
+ {
35
+ Mage::logException(new Exception("Tried to query a channel that was not configured as a secondary channel."));
36
+ return array();
37
+ }
38
+
39
+ if(!isset($this->_secondarySearchResults[$channel]))
40
+ {
41
+ $this->_secondarySearchResults[$channel] = $this->_getFacade()->getSearchResult($channel);
42
+ }
43
+
44
+ return $this->_secondarySearchResults[$channel];
45
+ }
46
+ }
app/code/community/Flagbit/FactFinder/Model/Handler/ShoppingCartCampaign.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handles product campaign data on shopping cart page
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ * @author Martin Buettner <martin.buettner@omikron.net>
9
+ * @version $Id: ProductCampaign.php 14.09.12 08:42 $
10
+ *
11
+ **/
12
+ class Flagbit_FactFinder_Model_Handler_ShoppingCartCampaign
13
+ extends Flagbit_FactFinder_Model_Handler_ProductCampaign
14
+ {
15
+ protected function _getDoParam()
16
+ {
17
+ return 'getShoppingCartCampaigns';
18
+ }
19
+
20
+ protected function _getProductNumberParam()
21
+ {
22
+ if(is_array($this->_productIds))
23
+ return $this->_productIds;
24
+ else
25
+ return array($this->_productIds);
26
+ }
27
+ }
app/code/community/Flagbit/FactFinder/Model/Handler/Suggest.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handles Suggest data
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ * @author Martin Buettner <martin.buettner@omikron.net>
9
+ * @version $Id: Suggest.php 17.09.12 08:58 $
10
+ *
11
+ **/
12
+ class Flagbit_FactFinder_Model_Handler_Suggest
13
+ extends Flagbit_FactFinder_Model_Handler_Abstract
14
+ {
15
+ protected $_query;
16
+ protected $_jqueryCallback;
17
+ protected $_suggestResult;
18
+ protected $_suggestResultAsArray;
19
+
20
+ protected $_primaryChannel;
21
+ protected $_secondaryChannels;
22
+
23
+ /**
24
+ * We might need to supply the facade manually, because we might not have a full Magento
25
+ * context and we cannot call Mage::getSingleton().
26
+ */
27
+ public function __construct($query, $jqueryCallback = '', $facade = null)
28
+ {
29
+ $this->_facade = $facade;
30
+ $this->_query = $query;
31
+ $this->_jqueryCallback = $jqueryCallback;
32
+ parent::__construct();
33
+ }
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected function configureFacade()
39
+ {
40
+ $params = array();
41
+ $params['format'] = 'json';
42
+ $params['query'] = $this->_query;
43
+
44
+ $this->_primaryChannel = FF::getSingleton('configuration')->getChannel();
45
+ $this->_secondaryChannels = FF::getSingleton('configuration')->getSecondaryChannels();
46
+
47
+ $this->_getFacade()->configureSuggestAdapter($params);
48
+ foreach($this->_secondaryChannels AS $channel)
49
+ $this->_getFacade()->configureSuggestAdapter($params, $channel);
50
+
51
+ }
52
+
53
+ public function getSuggestions()
54
+ {
55
+ if($this->_suggestResult === null)
56
+ {
57
+ $this->_suggestResult = $this->_assembleSuggestResult();
58
+ }
59
+ return $this->_suggestResult;
60
+ }
61
+
62
+ public function getSuggestionsAsArray()
63
+ {
64
+ if($this->_suggestResultAsArray === null)
65
+ {
66
+ $this->_suggestResultAsArray = $this->_assembleSuggestResultAsArray();
67
+ }
68
+ return $this->_suggestResultAsArray;
69
+ }
70
+
71
+ protected function _assembleSuggestResult()
72
+ {
73
+ // Retrieve and merge all suggestions
74
+ // Add a new "channel" field in the process
75
+
76
+ $suggestResult = Zend_Json_Decoder::decode($this->_getAndSanitizeSuggestions());
77
+ foreach($suggestResult as &$item)
78
+ $item["channel"] = $this->_primaryChannel;
79
+
80
+ foreach($this->_secondaryChannels AS $channel)
81
+ {
82
+ $result = Zend_Json_Decoder::decode($this->_getAndSanitizeSuggestions($channel));
83
+ foreach($result as &$item)
84
+ $item["channel"] = $channel;
85
+
86
+ $suggestResult = array_merge($suggestResult, $result);
87
+ }
88
+
89
+ return $this->_jqueryCallback.'('.Zend_Json_Encoder::encode($suggestResult).');';
90
+ }
91
+
92
+ protected function _assembleSuggestResultAsArray()
93
+ {
94
+ // TODO: Multiple channels
95
+ return Zend_Json_Decoder::decode($this->_getAndSanitizeSuggestions());
96
+ }
97
+
98
+ protected function _getAndSanitizeSuggestions($channel = null)
99
+ {
100
+ $result = $this->_getFacade()->getSuggestions($channel);
101
+ if($result === null)
102
+ $result = '';
103
+
104
+ return $result;
105
+ }
106
+ }
app/code/community/Flagbit/FactFinder/Model/Handler/TagCloud.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handles TagCloud data
4
+ *
5
+ * @category Mage
6
+ * @package Flagbit_FactFinder
7
+ * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
+ * @author Martin Buettner <martin.buettner@omikron.net>
9
+ * @version $Id: TagCloud.php 13.09.12 14:10 $
10
+ *
11
+ **/
12
+ class Flagbit_FactFinder_Model_Handler_TagCloud
13
+ extends Flagbit_FactFinder_Model_Handler_Abstract
14
+ {
15
+ /**
16
+ * @var array
17
+ */
18
+ protected $_tagCloud;
19
+
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected function configureFacade()
24
+ {
25
+ // Registering the needed tag cloud adapter
26
+ $this->_getFacade()->configureTagCloudAdapter();
27
+ }
28
+
29
+ /**
30
+ * @return array
31
+ */
32
+ public function getTerms()
33
+ {
34
+ $tagCloud = $this->_getTagCloud();
35
+
36
+ $terms = array();
37
+ foreach ($tagCloud as $item) {
38
+ $terms[] = new Varien_Object($this->assembleTermArray($item));
39
+ }
40
+
41
+ return $terms;
42
+ }
43
+
44
+ /**
45
+ * @param FACTFinder_TagQuery $item
46
+ * @return array
47
+ */
48
+ protected function assembleTermArray($item)
49
+ {
50
+ $termArray = array();
51
+ $termArray['name'] = $item->getValue();
52
+ $termArray['url'] = $item->getUrl();
53
+ $termArray['popularity'] = $item->getWeight();
54
+ $termArray['ratio'] = $item->getWeight();
55
+ return $termArray;
56
+ }
57
+
58
+ /**
59
+ * @return array of FACTFinder_TagQuery
60
+ */
61
+ protected function _getTagCloud()
62
+ {
63
+ if($this->_tagCloud === null)
64
+ {
65
+ $this->_tagCloud = $this->_getFacade()->getTagCloud();
66
+ if ($this->_tagCloud === null)
67
+ $this->_tagCloud = array();
68
+ }
69
+ return $this->_tagCloud;
70
+ }
71
+ }
app/code/community/Flagbit/FactFinder/Model/Mysql4/Campaign/Pushedproducts/Collection.php CHANGED
@@ -32,14 +32,14 @@ class Flagbit_FactFinder_Model_Mysql4_Campaign_Pushedproducts_Collection
32
  }
33
 
34
  /**
35
- * get Factfinder Search Adapter
36
  *
37
- * @return Flagbit_FactFinder_Model_Adapter
38
  */
39
  protected function _getCampaign()
40
  {
41
  if(Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign')){
42
- return Mage::getSingleton('factfinder/adapter')->getCampaigns();
43
  }
44
 
45
  return null;
32
  }
33
 
34
  /**
35
+ * get Campaign
36
  *
37
+ * @return FACTFinder_Campaign
38
  */
39
  protected function _getCampaign()
40
  {
41
  if(Mage::helper('factfinder/search')->getIsEnabled(false, 'campaign')){
42
+ return Mage::getSingleton('factfinder/handler_search')->getCampaigns();
43
  }
44
 
45
  return null;
app/code/community/Flagbit/FactFinder/Model/Mysql4/Product/Attribute/Collection.php CHANGED
@@ -31,17 +31,17 @@ class Flagbit_FactFinder_Model_Mysql4_Product_Attribute_Collection extends Mage_
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
  /**
@@ -55,7 +55,7 @@ class Flagbit_FactFinder_Model_Mysql4_Product_Attribute_Collection extends Mage_
55
  return $this;
56
  }
57
 
58
- $result = $this->_getAdapter()->getAfterSearchNavigation();
59
 
60
  if (count($result)) {
61
  $this->resetData();
31
  */
32
  public function getSize()
33
  {
34
+ return count($this->_getSearchHandler()->getAfterSearchNavigation());
35
  }
36
 
37
  /**
38
+ * get Facade
39
  *
40
+ * @return Flagbit_FactFinder_Model_Facade
41
  */
42
+ protected function _getSearchHandler()
43
  {
44
+ return Mage::getSingleton('factfinder/handler_search');
45
  }
46
 
47
  /**
55
  return $this;
56
  }
57
 
58
+ $result = $this->_getSearchHandler()->getAfterSearchNavigation();
59
 
60
  if (count($result)) {
61
  $this->resetData();
app/code/community/Flagbit/FactFinder/Model/Mysql4/Search/Collection.php CHANGED
@@ -28,17 +28,17 @@ class Flagbit_FactFinder_Model_Mysql4_Search_Collection
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
  /**
@@ -48,14 +48,13 @@ class Flagbit_FactFinder_Model_Mysql4_Search_Collection
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'=>array_keys($productIds))
28
  */
29
  public function getSize()
30
  {
31
+ return $this->_getSearchHandler()->getSearchResultCount();
32
  }
33
 
34
  /**
35
+ * get Factfinder Facade
36
  *
37
+ * @return Flagbit_FactFinder_Model_Handler_Search
38
  */
39
+ protected function _getSearchHandler()
40
  {
41
+ return Mage::getSingleton('factfinder/handler_search');
42
  }
43
 
44
  /**
48
  */
49
  public function _loadEntities($printQuery = false, $logQuery = false)
50
  {
51
+ // get product IDs from Fact-Finder
52
+ $productIds = $this->_getSearchHandler()->getSearchResult();
53
+
54
+ if (!empty($productIds)) {
55
+ $idFieldName = Mage::helper('factfinder/search')->getIdFieldName();
56
 
57
+ // add Filter to Query
 
 
 
 
 
 
58
  $this->addFieldToFilter(
59
  $idFieldName,
60
  array('in'=>array_keys($productIds))
app/code/community/Flagbit/FactFinder/Model/Observer.php CHANGED
@@ -20,6 +20,7 @@
20
  */
21
  class Flagbit_FactFinder_Model_Observer
22
  {
 
23
 
24
  /**
25
  * Observer method.
@@ -47,8 +48,14 @@ class Flagbit_FactFinder_Model_Observer
47
  }
48
 
49
  try {
50
- $scic = Mage::getModel('factfinder/adapter')->getScicAdapter();
51
- $result = $scic->trackCart($product->getData($idFieldName), md5(Mage::getSingleton('core/session')->getSessionId()), $qty, $product->getFinalPrice($qty), $customerId);
 
 
 
 
 
 
52
  }
53
  catch (Exception $e) {
54
  Mage::helper('factfinder/debug')->log($e->getMessage());
@@ -116,12 +123,20 @@ class Flagbit_FactFinder_Model_Observer
116
  $scic = null;
117
  foreach ($collection as $item) {
118
  try {
 
119
  if ($item->getStoreId() != $storeId) {
120
- $scic = Mage::getModel('factfinder/adapter')->setStoreId($item->getStoreId())->getScicAdapter();
121
  $storeId = $item->getStoreId();
122
  }
 
 
 
 
 
 
 
 
123
 
124
- $scic->trackCheckout($item->getProductId(), $item->getSid(), $item->getCount(), $item->getPrice(), $item->getUserid());
125
  $item->delete($item);
126
  }
127
  catch (Exception $e) {
@@ -169,7 +184,10 @@ class Flagbit_FactFinder_Model_Observer
169
  $errors = Mage::helper('factfinder/backend')->checkConfigData($groups['search']['fields']);
170
  if (!empty($errors)) {
171
  $groups['search']['fields']['enabled']['errors'] = $errors;
172
- }
 
 
 
173
 
174
  // if we have an error - unset inherit field so that Backend model processing is activated
175
  if (!empty($errors) && isset($groups['search']['fields']['enabled']['inherit'])) {
@@ -203,7 +221,7 @@ class Flagbit_FactFinder_Model_Observer
203
  $pattern = '/(\<a[^\>]*href=\"([^\"]*)\"[^\>]*)\>\w*\<span\>\w*' . $label . '\w*\<\/span\>/msU';
204
  preg_match($pattern, $html, $matches);
205
 
206
- $url = Mage::getSingleton('factfinder/adapter')->getAuthenticationUrl();
207
  $replace = str_replace($matches[2], $url, $matches[1]) . ' target="_blank"';
208
 
209
  $transport->setHtml(str_replace($matches[1], $replace, $html));
@@ -220,6 +238,19 @@ class Flagbit_FactFinder_Model_Observer
220
  $layout = $observer->getLayout();
221
  $update = $layout->getUpdate();
222
  $update->addHandle('factfinder_suggest_enabled');
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  }
224
  if (Mage::helper('factfinder/search')->getIsEnabled(false, 'advisory')) {
225
  $layout = $observer->getLayout();
@@ -268,12 +299,13 @@ class Flagbit_FactFinder_Model_Observer
268
  $searchHelper = Mage::helper('factfinder/search');
269
 
270
  try {
271
- $scic = Mage::getModel('factfinder/adapter')->getScicAdapter();
272
- $idFieldName = $searchHelper->getIdFieldName();
273
- if ($idFieldName == 'entity_id') {
274
- $idFieldName = 'product_id'; // sales_order_item does not contain a entity_id
275
- }
276
- $result = $scic->trackClick(
 
277
  $product->getData($idFieldName),
278
  md5(Mage::getSingleton('core/session')->getSessionId()),
279
  $searchHelper->getQuery()->getQueryText(),
@@ -284,6 +316,7 @@ class Flagbit_FactFinder_Model_Observer
284
  $product->getName(),
285
  $searchHelper->getPageLimit(),
286
  $searchHelper->getDefaultPerPageValue());
 
287
  }
288
  catch (Exception $e) {
289
  Mage::helper('factfinder/debug')->log($e->getMessage());
@@ -302,4 +335,13 @@ class Flagbit_FactFinder_Model_Observer
302
  $response->setHeader('Pragma', null, true);
303
  }
304
 
 
 
 
 
 
 
 
 
 
305
  }
20
  */
21
  class Flagbit_FactFinder_Model_Observer
22
  {
23
+ const _asnBlockRegistryKey = 'FACTFINDER__asnBlock';
24
 
25
  /**
26
  * Observer method.
48
  }
49
 
50
  try {
51
+ $facade = Mage::getModel('factfinder/facade');
52
+ $facade->getScicAdapter()->setupCartTracking(
53
+ $product->getData($idFieldName),
54
+ md5(Mage::getSingleton('core/session')->getSessionId()),
55
+ $qty,
56
+ $product->getFinalPrice($qty),
57
+ $customerId);
58
+ $facade->applyTracking();
59
  }
60
  catch (Exception $e) {
61
  Mage::helper('factfinder/debug')->log($e->getMessage());
123
  $scic = null;
124
  foreach ($collection as $item) {
125
  try {
126
+ $facade = Mage::getModel('factfinder/facade');
127
  if ($item->getStoreId() != $storeId) {
128
+ $facade->setStoreId($item->getStoreId());
129
  $storeId = $item->getStoreId();
130
  }
131
+ $facade->getScicAdapter()->setupCheckoutTracking(
132
+ $item->getProductId(),
133
+ $item->getSid(),
134
+ $item->getCount(),
135
+ $item->getPrice(),
136
+ $item->getUserid());
137
+
138
+ $facade->applyTracking();
139
 
 
140
  $item->delete($item);
141
  }
142
  catch (Exception $e) {
184
  $errors = Mage::helper('factfinder/backend')->checkConfigData($groups['search']['fields']);
185
  if (!empty($errors)) {
186
  $groups['search']['fields']['enabled']['errors'] = $errors;
187
+ } else {
188
+ // If there were no errors, reset the fallback feature
189
+ Mage::helper('factfinder/search')->saveFailedAttempts(array());
190
+ }
191
 
192
  // if we have an error - unset inherit field so that Backend model processing is activated
193
  if (!empty($errors) && isset($groups['search']['fields']['enabled']['inherit'])) {
221
  $pattern = '/(\<a[^\>]*href=\"([^\"]*)\"[^\>]*)\>\w*\<span\>\w*' . $label . '\w*\<\/span\>/msU';
222
  preg_match($pattern, $html, $matches);
223
 
224
+ $url = Mage::getSingleton('factfinder/facade')->getManagementUrl();
225
  $replace = str_replace($matches[2], $url, $matches[1]) . ' target="_blank"';
226
 
227
  $transport->setHtml(str_replace($matches[1], $replace, $html));
238
  $layout = $observer->getLayout();
239
  $update = $layout->getUpdate();
240
  $update->addHandle('factfinder_suggest_enabled');
241
+
242
+ if (Mage::getStoreConfig('factfinder/search/ffversion') <= 67)
243
+ {
244
+ $layout = $observer->getLayout();
245
+ $update = $layout->getUpdate();
246
+ $update->addHandle('factfinder_suggest_version_lt67');
247
+ }
248
+ else
249
+ {
250
+ $layout = $observer->getLayout();
251
+ $update = $layout->getUpdate();
252
+ $update->addHandle('factfinder_suggest_version_gt68');
253
+ }
254
  }
255
  if (Mage::helper('factfinder/search')->getIsEnabled(false, 'advisory')) {
256
  $layout = $observer->getLayout();
299
  $searchHelper = Mage::helper('factfinder/search');
300
 
301
  try {
302
+ $idFieldName = $searchHelper->getIdFieldName();
303
+ if ($idFieldName == 'entity_id') {
304
+ $idFieldName = 'product_id'; // sales_order_item does not contain a entity_id
305
+ }
306
+
307
+ $facade = Mage::getModel('factfinder/facade');
308
+ $facade->getScicAdapter()->setupClickTracking(
309
  $product->getData($idFieldName),
310
  md5(Mage::getSingleton('core/session')->getSessionId()),
311
  $searchHelper->getQuery()->getQueryText(),
316
  $product->getName(),
317
  $searchHelper->getPageLimit(),
318
  $searchHelper->getDefaultPerPageValue());
319
+ $facade->applyTracking();
320
  }
321
  catch (Exception $e) {
322
  Mage::helper('factfinder/debug')->log($e->getMessage());
335
  $response->setHeader('Pragma', null, true);
336
  }
337
 
338
+ public function initializeAfterSearchNavigation()
339
+ {
340
+ $asnBlock = Mage::registry(self::_asnBlockRegistryKey);
341
+ if($asnBlock instanceof Flagbit_FactFinder_Block_Layer)
342
+ {
343
+ $asnBlock->handleCampaignRedirect();
344
+ $asnBlock->initializeAfterSearchNavigation();
345
+ }
346
+ }
347
  }
app/code/community/Flagbit/FactFinder/Model/Processor.php CHANGED
@@ -7,6 +7,8 @@
7
  * @copyright Copyright (c) 2010 Flagbit GmbH & Co. KG (http://www.flagbit.de/)
8
  */
9
 
 
 
10
  /**
11
  * Model class
12
  *
@@ -27,10 +29,10 @@ class Flagbit_FactFinder_Model_Processor
27
 
28
 
29
  /**
30
- * Search Adapter
31
- * @var Flagbit_FactFinder_Model_Adapter
32
  */
33
- protected $_searchAdapter;
34
 
35
  /**
36
  * Class constructor
@@ -45,17 +47,18 @@ class Flagbit_FactFinder_Model_Processor
45
  }
46
 
47
  /**
48
- * get Fact-Finder Search Adapter
 
49
  *
50
- * @return Flagbit_FactFinder_Model_Adapter
51
  */
52
- public function getSearchAdapter()
53
  {
54
- if($this->_searchAdapter === null){
55
  $logger = new Flagbit_FactFinder_Helper_Debug();
56
- $this->_searchAdapter = new Flagbit_FactFinder_Model_Adapter($logger);
57
  }
58
- return $this->_searchAdapter;
59
  }
60
 
61
 
@@ -117,7 +120,7 @@ class Flagbit_FactFinder_Model_Processor
117
  if(!is_array($config) || empty($config)){
118
  return;
119
  }
120
- $this->getSearchAdapter()->setConfiguration($config);
121
  return $this->_handleRequest($request);
122
  }
123
 
@@ -129,17 +132,19 @@ class Flagbit_FactFinder_Model_Processor
129
  */
130
  protected function _handleRequest($request)
131
  {
132
- switch ($request){
133
-
134
  case 'factfinder_proxy_scic':
135
- $scic = $this->getSearchAdapter()->getScicAdapter();
136
- return $scic->doTrackingFromRequest();
137
  break;
138
 
139
  case 'factfinder_proxy_suggest':
140
- return $this->getSearchAdapter()->getSuggestResultJsonp($this->_getRequestParam('query'), $this->_getRequestParam('jquery_callback'));
 
 
 
 
141
  break;
142
-
143
  }
144
  }
145
 
@@ -215,7 +220,7 @@ class Flagbit_FactFinder_Model_Processor
215
  */
216
  public function getRequestId()
217
  {
218
- return $this->_requestId;
219
  }
220
 
221
  /**
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
  *
29
 
30
 
31
  /**
32
+ * FactFinder Facade
33
+ * @var Flagbit_FactFinder_Model_Facade
34
  */
35
+ protected $_facade;
36
 
37
  /**
38
  * Class constructor
47
  }
48
 
49
  /**
50
+ * get Fact-Finder Facade
51
+ * we do it manually, because we do not have the full magento context
52
  *
53
+ * @return Flagbit_FactFinder_Model_Facade
54
  */
55
+ protected function _getFacade()
56
  {
57
+ if($this->_facade === null){
58
  $logger = new Flagbit_FactFinder_Helper_Debug();
59
+ $this->_facade = new Flagbit_FactFinder_Model_Facade($logger);
60
  }
61
+ return $this->_facade;
62
  }
63
 
64
 
120
  if(!is_array($config) || empty($config)){
121
  return;
122
  }
123
+ $this->_getFacade()->setConfiguration($config);
124
  return $this->_handleRequest($request);
125
  }
126
 
132
  */
133
  protected function _handleRequest($request)
134
  {
135
+ switch ($request) {
 
136
  case 'factfinder_proxy_scic':
137
+ $this->_getFacade()->getScicAdapter()->setupTrackingFromRequest();
138
+ return $this->_getFacade()->applyTracking();
139
  break;
140
 
141
  case 'factfinder_proxy_suggest':
142
+ $handler = new Flagbit_FactFinder_Model_Handler_Suggest(
143
+ $this->_getRequestParam('query'),
144
+ $this->_getRequestParam('jquery_callback'),
145
+ $this->_getFacade());
146
+ return $handler->getSuggestions();
147
  break;
 
148
  }
149
  }
150
 
220
  */
221
  public function getRequestId()
222
  {
223
+ return $this->_requestId . (isset($_COOKIE['store']) ? $_COOKIE['store'] : '');
224
  }
225
 
226
  /**
app/code/community/Flagbit/FactFinder/Model/System/Config/Source/Ffversion.php CHANGED
@@ -28,6 +28,10 @@ class Flagbit_FactFinder_Model_System_Config_Source_Ffversion
28
  public function toOptionArray()
29
  {
30
  return array(
 
 
 
 
31
  array(
32
  'value' => 67,
33
  'label' => '6.7'
28
  public function toOptionArray()
29
  {
30
  return array(
31
+ array(
32
+ 'value' => 68,
33
+ 'label' => '6.8'
34
+ ),
35
  array(
36
  'value' => 67,
37
  'label' => '6.7'
app/code/community/Flagbit/FactFinder/controllers/ExportController.php CHANGED
@@ -58,11 +58,36 @@ class Flagbit_FactFinder_ExportController extends Mage_Core_Controller_Front_Act
58
  * Initialize Product Export
59
  */
60
  public function productAction()
61
- {
62
- $exportModel = Mage::getModel('factfinder/export_product');
63
- $exportModel->doExport(
64
- $this->_getStoreId()
65
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
 
68
  /**
@@ -86,4 +111,26 @@ class Flagbit_FactFinder_ExportController extends Mage_Core_Controller_Front_Act
86
  $this->_getStoreId()
87
  );
88
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  }
58
  * Initialize Product Export
59
  */
60
  public function productAction()
61
+ {
62
+ try
63
+ {
64
+ $this->lockSemaphore();
65
+ }
66
+ catch(RuntimeException $e)
67
+ {
68
+ // TODO: use a proper template
69
+ echo
70
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
71
+ '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">',
72
+ '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head>',
73
+ '<body>',
74
+ $this->__('Another export is already running. Please wait for it to finish before you start a new export.'), "<br>\n",
75
+ $this->__('If you receive this message after another export has failed, please delete the file "ffexport.lock" within your Magento directory.'),
76
+ '</body></html>';
77
+ flush();
78
+ return;
79
+ }
80
+
81
+ try {
82
+ $exportModel = Mage::getModel('factfinder/export_product');
83
+ $exportModel->doExport(
84
+ $this->_getStoreId()
85
+ );
86
+ $this->releaseSemaphore(); // finally-workaround
87
+ } catch(Exception $e) {
88
+ $this->releaseSemaphore(); // finally-workaround
89
+ throw $e;
90
+ }
91
  }
92
 
93
  /**
111
  $this->_getStoreId()
112
  );
113
  }
114
+
115
+ /**
116
+ * Locks the semaphore
117
+ * Throws an exception, if semaphore is already locked
118
+ **/
119
+ protected function lockSemaphore()
120
+ {
121
+ $mtime = @filemtime("ffexport.lock");
122
+ if($mtime && time() - $mtime < FF::getSingleton('configuration')->getSemaphoreTimeout())
123
+ {
124
+ throw new RuntimeException();
125
+ }
126
+ @touch("ffexport.lock");
127
+ }
128
+
129
+ /**
130
+ * Release the semaphore
131
+ **/
132
+ protected function releaseSemaphore()
133
+ {
134
+ @unlink("ffexport.lock");
135
+ }
136
  }
app/code/community/Flagbit/FactFinder/controllers/ProxyController.php CHANGED
@@ -41,6 +41,6 @@ class Flagbit_FactFinder_ProxyController extends Mage_Core_Controller_Front_Acti
41
  $this->getResponse()->setHeader("Content-Type:", "text/javascript;charset=utf-8", true);
42
  $this->getResponse()->setBody(
43
  Mage::getModel('factfinder/processor')->handleInAppRequest($this->getFullActionName())
44
- );
45
  }
46
  }
41
  $this->getResponse()->setHeader("Content-Type:", "text/javascript;charset=utf-8", true);
42
  $this->getResponse()->setBody(
43
  Mage::getModel('factfinder/processor')->handleInAppRequest($this->getFullActionName())
44
+ );
45
  }
46
  }
app/code/community/Flagbit/FactFinder/etc/config.xml CHANGED
@@ -22,7 +22,7 @@
22
  <modules>
23
  <Flagbit_FactFinder>
24
  <active>true</active>
25
- <version>3.3.11</version>
26
  </Flagbit_FactFinder>
27
  </modules>
28
  <global>
@@ -162,6 +162,14 @@
162
  </redirectToProductIfSingleResult>
163
  </observers>
164
  </core_block_abstract_to_html_before>
 
 
 
 
 
 
 
 
165
  </events>
166
  <translate>
167
  <modules>
@@ -267,8 +275,13 @@
267
  <channel></channel>
268
  <language></language>
269
  </search>
 
 
 
 
270
  <export>
271
  <urls>0</urls>
 
272
  <track_carts>1</track_carts>
273
  <track_checkout>1</track_checkout>
274
  </export>
22
  <modules>
23
  <Flagbit_FactFinder>
24
  <active>true</active>
25
+ <version>3.3.12</version>
26
  </Flagbit_FactFinder>
27
  </modules>
28
  <global>
162
  </redirectToProductIfSingleResult>
163
  </observers>
164
  </core_block_abstract_to_html_before>
165
+ <controller_action_layout_generate_blocks_after>
166
+ <observers>
167
+ <initializeAfterSearchNavigation>
168
+ <class>factfinder/observer</class>
169
+ <method>initializeAfterSearchNavigation</method>
170
+ </initializeAfterSearchNavigation>
171
+ </observers>
172
+ </controller_action_layout_generate_blocks_after>
173
  </events>
174
  <translate>
175
  <modules>
275
  <channel></channel>
276
  <language></language>
277
  </search>
278
+ <fallback>
279
+ <use_fallback>0</use_fallback>
280
+ <wait_time>15</wait_time>
281
+ </fallback>
282
  <export>
283
  <urls>0</urls>
284
+ <suggest_image_size>40</suggest_image_size>
285
  <track_carts>1</track_carts>
286
  <track_checkout>1</track_checkout>
287
  </export>
app/code/community/Flagbit/FactFinder/etc/system.xml CHANGED
@@ -73,7 +73,7 @@
73
  </context>
74
  <ffversion translate="label comment">
75
  <label>FACT-Finder version</label>
76
- <comment>Choose the version of the FACT-Finder application you are using for all its features to work.</comment>
77
  <frontend_type>select</frontend_type>
78
  <source_model>factfinder/system_config_source_ffversion</source_model>
79
  <sort_order>45</sort_order>
@@ -82,7 +82,7 @@
82
  <show_in_store>1</show_in_store>
83
  </ffversion>
84
  <auth_user translate="label comment">
85
- <label>User Name</label>
86
  <comment>User name for authentication</comment>
87
  <frontend_type>text</frontend_type>
88
  <sort_order>50</sort_order>
@@ -109,7 +109,7 @@
109
  </channel>
110
  <secondary_channels translate="label">
111
  <label>Secondary Channels</label>
112
- <comment>Enter any secondary channels you want to search. Multiple channels can be separated by semicolons.</comment>
113
  <frontend_type>text</frontend_type>
114
  <sort_order>75</sort_order>
115
  <show_in_default>1</show_in_default>
@@ -153,6 +153,35 @@
153
  </auth_advancedPostfix>
154
  </fields>
155
  </search>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  <export translate="label">
157
  <label>FACT-Finder Export Configuration</label>
158
  <frontend_type>text</frontend_type>
@@ -170,6 +199,15 @@
170
  <show_in_website>1</show_in_website>
171
  <show_in_store>1</show_in_store>
172
  </urls>
 
 
 
 
 
 
 
 
 
173
  <clicktracking translate="label">
174
  <label>Track product-clicks</label>
175
  <frontend_type>select</frontend_type>
@@ -234,7 +272,7 @@
234
  <show_in_store>1</show_in_store>
235
  </identifier>
236
  <redirectOnSingleResult>
237
- <label>Redirect to product page if single result</label>
238
  <frontend_type>select</frontend_type>
239
  <source_model>adminhtml/system_config_source_yesno</source_model>
240
  <sort_order>20</sort_order>
@@ -244,6 +282,7 @@
244
  </redirectOnSingleResult>
245
  <proxy translate="label">
246
  <label>Use Proxy for Suggest</label>
 
247
  <frontend_type>select</frontend_type>
248
  <source_model>adminhtml/system_config_source_yesno</source_model>
249
  <sort_order>30</sort_order>
@@ -253,7 +292,7 @@
253
  </proxy>
254
  <internal_ip translate="label">
255
  <label>Internal IPs</label>
256
- <comment>Enter your internal IP addresses. Multiple IP addresses can be separated by semicolons.</comment>
257
  <frontend_type>text</frontend_type>
258
  <sort_order>40</sort_order>
259
  <show_in_default>1</show_in_default>
@@ -316,7 +355,7 @@
316
  <show_in_store>1</show_in_store>
317
  </navigation>
318
  <upsell translate="label">
319
- <label>Use FACT-Finder for Product Upsells</label>
320
  <frontend_type>select</frontend_type>
321
  <source_model>adminhtml/system_config_source_yesno</source_model>
322
  <sort_order>60</sort_order>
@@ -325,7 +364,7 @@
325
  <show_in_store>1</show_in_store>
326
  </upsell>
327
  <crosssell translate="label">
328
- <label>Use FACT-Finder for Product Crosssells</label>
329
  <frontend_type>select</frontend_type>
330
  <source_model>adminhtml/system_config_source_yesno</source_model>
331
  <sort_order>70</sort_order>
73
  </context>
74
  <ffversion translate="label comment">
75
  <label>FACT-Finder version</label>
76
+ <comment>Please select the version of your FACT-Finder application to enable all of its features.</comment>
77
  <frontend_type>select</frontend_type>
78
  <source_model>factfinder/system_config_source_ffversion</source_model>
79
  <sort_order>45</sort_order>
82
  <show_in_store>1</show_in_store>
83
  </ffversion>
84
  <auth_user translate="label comment">
85
+ <label>User name</label>
86
  <comment>User name for authentication</comment>
87
  <frontend_type>text</frontend_type>
88
  <sort_order>50</sort_order>
109
  </channel>
110
  <secondary_channels translate="label">
111
  <label>Secondary Channels</label>
112
+ <comment>Enter any secondary channels you want to search. Multiple channels should be separated by semicolons. NOTE: Secondary channels will only be considered for Suggest results if the proxy is used (see option in section "FACT-Finder Config Data")!</comment>
113
  <frontend_type>text</frontend_type>
114
  <sort_order>75</sort_order>
115
  <show_in_default>1</show_in_default>
153
  </auth_advancedPostfix>
154
  </fields>
155
  </search>
156
+ <fallback translate="label">
157
+ <label>FACT-Finder Fallback Configuration</label>
158
+ <frontend_type>text</frontend_type>
159
+ <sort_order>15</sort_order>
160
+ <show_in_default>1</show_in_default>
161
+ <show_in_website>1</show_in_website>
162
+ <show_in_store>1</show_in_store>
163
+ <fields>
164
+ <use_fallback translate="label comment">
165
+ <label>Use Fallback</label>
166
+ <comment>If activated and FACT-Finder cannot be contacted, Magento's built-in search will be used instead.</comment>
167
+ <frontend_type>select</frontend_type>
168
+ <source_model>adminhtml/system_config_source_yesno</source_model>
169
+ <sort_order>10</sort_order>
170
+ <show_in_default>1</show_in_default>
171
+ <show_in_website>1</show_in_website>
172
+ <show_in_store>1</show_in_store>
173
+ </use_fallback>
174
+ <wait_time translate="label comment">
175
+ <label>Minutes before next attempt</label>
176
+ <comment>After three failed attempts, the module can revert to using Magento for searches. After the specified amount of time has passed, the module will try to contact FACT-Finder again. If you enter 0, the module will first attempt to contact FACT-Finder for every search.</comment>
177
+ <frontend_type>text</frontend_type>
178
+ <sort_order>20</sort_order>
179
+ <show_in_default>1</show_in_default>
180
+ <show_in_website>1</show_in_website>
181
+ <show_in_store>1</show_in_store>
182
+ </wait_time>
183
+ </fields>
184
+ </fallback>
185
  <export translate="label">
186
  <label>FACT-Finder Export Configuration</label>
187
  <frontend_type>text</frontend_type>
199
  <show_in_website>1</show_in_website>
200
  <show_in_store>1</show_in_store>
201
  </urls>
202
+ <suggest_image_size translate="label comment">
203
+ <label>Size of Suggest images</label>
204
+ <comment>Please enter the desired edge length of the Suggest images in pixels. If you do not want them to be resized, enter 0.</comment>
205
+ <frontend_type>text</frontend_type>
206
+ <sort_order>15</sort_order>
207
+ <show_in_default>1</show_in_default>
208
+ <show_in_website>1</show_in_website>
209
+ <show_in_store>1</show_in_store>
210
+ </suggest_image_size>
211
  <clicktracking translate="label">
212
  <label>Track product-clicks</label>
213
  <frontend_type>select</frontend_type>
272
  <show_in_store>1</show_in_store>
273
  </identifier>
274
  <redirectOnSingleResult>
275
+ <label>Redirect to product details page for single results</label>
276
  <frontend_type>select</frontend_type>
277
  <source_model>adminhtml/system_config_source_yesno</source_model>
278
  <sort_order>20</sort_order>
282
  </redirectOnSingleResult>
283
  <proxy translate="label">
284
  <label>Use Proxy for Suggest</label>
285
+ <comment>This option must be enabled if secondary channels are to be considered for Suggest results.</comment>
286
  <frontend_type>select</frontend_type>
287
  <source_model>adminhtml/system_config_source_yesno</source_model>
288
  <sort_order>30</sort_order>
292
  </proxy>
293
  <internal_ip translate="label">
294
  <label>Internal IPs</label>
295
+ <comment>Enter your internal IP addresses. Multiple IP addresses should be separated by semicolons.</comment>
296
  <frontend_type>text</frontend_type>
297
  <sort_order>40</sort_order>
298
  <show_in_default>1</show_in_default>
355
  <show_in_store>1</show_in_store>
356
  </navigation>
357
  <upsell translate="label">
358
+ <label>Use FACT-Finder for product upselling</label>
359
  <frontend_type>select</frontend_type>
360
  <source_model>adminhtml/system_config_source_yesno</source_model>
361
  <sort_order>60</sort_order>
364
  <show_in_store>1</show_in_store>
365
  </upsell>
366
  <crosssell translate="label">
367
+ <label>Use FACT-Finder for product cross-selling</label>
368
  <frontend_type>select</frontend_type>
369
  <source_model>adminhtml/system_config_source_yesno</source_model>
370
  <sort_order>70</sort_order>
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$
20
+ */
21
+ ?>
22
+ <iframe src="<?php echo $this->getManagementUrl();?>" id="factfinder_cockpit_frame" style="width:100%; height:600px;" name="factfinder_cockpit_frame" scrolling="auto"></iframe>
app/design/frontend/base/default/layout/factfinder.xml CHANGED
@@ -19,16 +19,25 @@
19
  */
20
  -->
21
  <layout version="0.1.0">
22
-
23
  <factfinder_suggest_enabled>
24
- <reference name="top.search">
25
- <action method="setTemplate"><template>factfinder/form.mini.phtml</template></action>
26
- </reference>
27
  <reference name="head">
28
  <action method="addJs"><script>factfinder/jXHR.js</script></action>
29
  <action method="addJs"><script>factfinder/suggest.js</script></action>
 
30
  </reference>
31
  </factfinder_suggest_enabled>
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  <catalogsearch_result_index>
34
  <reference name="content">
@@ -43,19 +52,19 @@
43
 
44
  <catalog_product_view>
45
  <reference name="content">
46
- <!-- <block type="factfinder/campaign_product_advisory" before="product.info" template="factfinder/campaign/product/advisory.phtml" /-->
47
  <block type="factfinder/campaign_product_feedback" before="product.info" template="factfinder/campaign/product/feedback.phtml" />
48
  </reference>
49
  <reference>
50
  <block name="product.info.upsell">
51
  <action method="setItemLimit"><type>upsell</type><limit>20</limit></action>
52
- </block>
53
- </reference>
54
  </catalog_product_view>
55
 
56
  <checkout_cart_index>
57
  <reference name="checkout.cart.form.before">
58
- <!-- <block type="factfinder/campaign_cart_advisory" before="-" template="factfinder/campaign/cart/advisory.phtml" /-->
59
  <block type="factfinder/campaign_cart_feedback" before="-" template="factfinder/campaign/cart/feedback.phtml" />
60
  </reference>
61
  </checkout_cart_index>
19
  */
20
  -->
21
  <layout version="0.1.0">
 
22
  <factfinder_suggest_enabled>
 
 
 
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
+ <action method="addCss"><stylesheet>css/factfinder.css</stylesheet></action>
27
  </reference>
28
  </factfinder_suggest_enabled>
29
+
30
+ <factfinder_suggest_version_lt67>
31
+ <reference name="top.search">
32
+ <action method="setTemplate"><template>factfinder/form.advancedsuggest.phtml</template></action>
33
+ </reference>
34
+ </factfinder_suggest_version_lt67>
35
+
36
+ <factfinder_suggest_version_gt68>
37
+ <reference name="top.search">
38
+ <action method="setTemplate"><template>factfinder/form.advancedsuggest68.phtml</template></action>
39
+ </reference>
40
+ </factfinder_suggest_version_gt68>
41
 
42
  <catalogsearch_result_index>
43
  <reference name="content">
52
 
53
  <catalog_product_view>
54
  <reference name="content">
55
+ <block type="factfinder/campaign_product_advisory" before="product.info" template="factfinder/campaign/product/advisory.phtml" />
56
  <block type="factfinder/campaign_product_feedback" before="product.info" template="factfinder/campaign/product/feedback.phtml" />
57
  </reference>
58
  <reference>
59
  <block name="product.info.upsell">
60
  <action method="setItemLimit"><type>upsell</type><limit>20</limit></action>
61
+ </block>
62
+ </reference>
63
  </catalog_product_view>
64
 
65
  <checkout_cart_index>
66
  <reference name="checkout.cart.form.before">
67
+ <block type="factfinder/campaign_cart_advisory" before="-" template="factfinder/campaign/cart/advisory.phtml" />
68
  <block type="factfinder/campaign_cart_feedback" before="-" template="factfinder/campaign/cart/feedback.phtml" />
69
  </reference>
70
  </checkout_cart_index>
app/design/frontend/base/default/template/factfinder/campaign/product/advisory.phtml DELETED
@@ -1,12 +0,0 @@
1
- <?php if ($questions = $this->getActiveQuestions()): ?>
2
- <?php foreach ($questions as $question): ?>
3
- <div class="factfinder-advisorCampaign">
4
- <p class="factfinder-advisorCampaign-question"><?php echo $question->getText() ?></p>
5
- <p>
6
- <?php foreach ($question->getAnswers() as $answer): ?>
7
- <a class="factfinder-advisorCampaign-answer" href="<?php echo $answer->getParams() ?>"><?php echo $answer->getText() ?></a>
8
- <?php endforeach; ?>
9
- </p>
10
- </div>
11
- <?php endforeach; ?>
12
- <?php endif; ?>
 
 
 
 
 
 
 
 
 
 
 
 
app/design/frontend/base/default/template/factfinder/campaign/product/feedback.phtml DELETED
@@ -1,6 +0,0 @@
1
- <?php if ($feedback = $this->getActiveFeedback()): ?>
2
- <?php $feedbackIds = array(0,1); ?>
3
- <?php foreach ($feedbackIds as $feedbackId): ?>
4
- <p class="factfinder-feedbackCampaign"><?php echo $feedback->getFeedback($feedbackId) ?></p>
5
- <?php endforeach; ?>
6
- <?php endif; ?>
 
 
 
 
 
 
app/design/frontend/base/default/template/factfinder/filter/scriptaculousSlider.phtml ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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$
18
+ */
19
+ ?>
20
+
21
+ <style type="text/css"><!--
22
+ input.slider-label {
23
+ background-color: #F1F1F1;
24
+ border: 1px solid #ACACAC;
25
+ font-size: 9px;
26
+ height: 20px;
27
+ margin: 10px 0 0;
28
+ text-align: center;
29
+ width: 40px;
30
+ }
31
+
32
+ input.slider-range-min {
33
+ float: left;
34
+ }
35
+
36
+ input.slider-range-max {
37
+ float: right;
38
+ }
39
+
40
+ div.slider {
41
+ margin: 10px 0;
42
+ background-color: #555;
43
+ height:10px;
44
+ position: relative;
45
+ }
46
+
47
+ span.slider-span {
48
+ position: absolute;
49
+ background-color: #6683B4;
50
+ height: 10px;
51
+ }
52
+
53
+ div.slider div.handle {
54
+ width: 10px;
55
+ height: 18px;
56
+ background-color: #F6F6F6;
57
+ border: 1px solid #7F7F7F;
58
+ cursor:move;
59
+ position: absolute;
60
+ margin-top: -5px;
61
+ }
62
+ --></style>
63
+
64
+ <ol>
65
+ <?php foreach ($this->getItems() as $_item): ?>
66
+ <li>
67
+ <input type="text" readonly="readonly" class="slider-label slider-range-min" value="<?php echo $this->getSelectedMin(), ' ', $this->getUnit(); ?>" />
68
+ <input type="text" readonly="readonly" class="slider-label slider-range-max" value="<?php echo $this->getSelectedMax(), ' ', $this->getUnit(); ?>" />
69
+ <div style="clear: both;"></div>
70
+ <div id="<?php echo base64_encode($this->getValue());?>_slider" class="slider" style="width: 170px;">
71
+ <span id="<?php echo base64_encode($this->getValue());?>_span" class="slider-span"></span>
72
+ <div class="handle"></div>
73
+ <div class="handle"></div>
74
+ </div>
75
+ <script type="text/javascript" language="javascript">
76
+ //<![CDATA[
77
+
78
+ (function() {
79
+ var slider = $('<?php echo base64_encode($this->getValue());?>_slider');
80
+ var minLabel = slider.siblings().grep(new Selector('.slider-range-min'))[0];
81
+ var maxLabel = slider.siblings().grep(new Selector('.slider-range-max'))[0];
82
+
83
+ new Control.Slider(slider.select('.handle'), slider, {
84
+ range: $R(<?php echo $this->getAbsoluteMin();?>, <?php echo $this->getAbsoluteMax();?>),
85
+ values: $R(<?php echo $this->getAbsoluteMin();?>, <?php echo $this->getAbsoluteMax();?>),
86
+ sliderValue: [<?php echo $this->getSelectedMin();?>, <?php echo $this->getSelectedMax();?>],
87
+ restricted: true,
88
+ spans: ["<?php echo base64_encode($this->getValue());?>_span"],
89
+ onSlide: function(values) {
90
+ minLabel.setValue(values[0] + " <?php echo $this->getUnit();?>");
91
+ maxLabel.setValue(values[1] + " <?php echo $this->getUnit();?>");
92
+ },
93
+ onChange: function(values) {
94
+ var url = decodeURI('<?php echo $_item->getUrl() ?>');
95
+ window.location.href= url.replace('[VALUE]',values[0] + '+-+' + values[1]);
96
+ }
97
+ });
98
+ })();
99
+ //]]>
100
+ </script>
101
+ </li>
102
+ <?php endforeach ?>
103
+ </ol>
app/design/frontend/base/default/template/factfinder/form.advancedsuggest.phtml ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Advanced Template to replace Javascript Suggest
12
+ * NOTICE: This template will only work if suggests are requested from the proxy (see option in section "FACT-Finder Config Data" in Magento's backend)!
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$
19
+ */
20
+ ?>
21
+
22
+ <form id="search_mini_form" action="<?php echo $this->helper('catalogsearch')->getResultUrl() ?>" method="get">
23
+ <div class="form-search">
24
+ <label for="search"><?php echo $this->__('Search:') ?></label>
25
+ <input id="search" type="text" name="<?php echo $this->helper('catalogsearch')->getQueryParamName() ?>" value="<?php echo $this->helper('catalogsearch')->getEscapedQueryText() ?>" class="input-text ff-basic-autocomplete" />
26
+ <button type="submit" title="<?php echo $this->__('Search') ?>" class="button"><span><span><?php echo $this->__('Search') ?></span></span></button>
27
+ <div id="search_autocomplete" class="search-autocomplete advanced-suggest"></div>
28
+ <script type="text/javascript">
29
+ //<![CDATA[
30
+ <?php if (Mage::helper('factfinder/search')->getIsEnabled(false, 'suggest')):?>
31
+
32
+ var loadDataCallback = function(data) {
33
+ // Internationalization lookup:
34
+ // Add a new anonymous object for every string you want to internationalize (with the property being the string).
35
+ // These objects consist of one string for each locale, where the property is the locale code.
36
+ var i18n = {
37
+ <?php
38
+ $channels = array_filter(explode(';', Mage::getStoreConfig('factfinder/search/secondary_channels')));
39
+ $output = array();
40
+ foreach($channels as $channel)
41
+ $output[] = '"Channel: '.$channel.'" : "'.$this->__('Channel: '.$channel).'"';
42
+ echo implode(',', $output);
43
+ ?>
44
+ };
45
+ var translate = function(string) {
46
+ if(i18n[string] == undefined)
47
+ return string;
48
+ else
49
+ return i18n[string];
50
+ }
51
+
52
+ var content = '<ul>';
53
+ content += '<li style="display: none" class="selected selectable-item"></li>';
54
+ var currentChannel = '';
55
+ if(data.length) {
56
+ if(data[0].channel == '<?php echo Mage::getStoreConfig('factfinder/search/channel'); ?>') {
57
+ content += '<li class="delimiter"><?php echo $this->__('Products'); ?></li>';
58
+ } else {
59
+ content += '<li class="delimiter">' + translate('Channel: ' + data[0].channel) + '</li>';
60
+ }
61
+ currentChannel = data[0].channel;
62
+ }
63
+
64
+ for(var i = 0; i < data.length; i++) {
65
+ var item = data[i];
66
+ if(item.channel != currentChannel)
67
+ {
68
+ content += '<li class="delimiter">' + translate('Channel: ' + item.channel) + '</li>';
69
+ currentChannel = item.channel;
70
+ }
71
+ var temp = '';
72
+ temp += '<li title="' + item.query + '" class="selectable-item ' + item.type + '">';
73
+ temp += '<span class="amount">' + (item.hitCount == 0 ? '' : item.hitCount) + '</span>';
74
+ if(item.imageURL)
75
+ {
76
+ temp += '<img src="' + item.imageURL + '" title="' + item.query + '" class="thumbnail"/>';
77
+ }
78
+ temp += item.query;
79
+ temp += '</li>';
80
+ content += temp;
81
+ }
82
+ content += '</ul>';
83
+ return content;
84
+ };
85
+
86
+ var searchForm = new FactFinderSuggest('search_mini_form', 'search', '<?php echo $this->__('Search entire shop here...') ?>', loadDataCallback);
87
+ searchForm.initAutocomplete('<?php echo $this->helper('factfinder/search')->getSuggestUrl() ?>', 'search_autocomplete');
88
+ <?php else:?>
89
+ var searchForm = new Varien.searchForm('search_mini_form', 'search', '<?php echo $this->__('Search entire shop here...') ?>');
90
+ searchForm.initAutocomplete('<?php echo $this->helper('catalogsearch')->getSuggestUrl() ?>', 'search_autocomplete');
91
+ <?php endif;?>
92
+ //]]>
93
+ </script>
94
+ </div>
95
+ </form>
app/design/frontend/base/default/template/factfinder/form.advancedsuggest68.phtml ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Advanced Template to replace Javascript Suggest
12
+ * NOTICE: This template will only work if suggests are requested from the proxy (see option in section "FACT-Finder Config Data" in Magento's backend)!
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$
19
+ */
20
+ ?>
21
+
22
+ <form id="search_mini_form" action="<?php echo $this->helper('catalogsearch')->getResultUrl() ?>" method="get">
23
+ <div class="form-search">
24
+ <label for="search"><?php echo $this->__('Search:') ?></label>
25
+ <input id="search" type="text" name="<?php echo $this->helper('catalogsearch')->getQueryParamName() ?>" value="<?php echo $this->helper('catalogsearch')->getEscapedQueryText() ?>" class="input-text ff-basic-autocomplete" />
26
+ <button type="submit" title="<?php echo $this->__('Search') ?>" class="button"><span><span><?php echo $this->__('Search') ?></span></span></button>
27
+ <div id="search_autocomplete" class="search-autocomplete advanced-suggest"></div>
28
+ <script type="text/javascript">
29
+ //<![CDATA[
30
+ <?php if (Mage::helper('factfinder/search')->getIsEnabled(false, 'suggest')):?>
31
+
32
+ var loadDataCallback = function(data) {
33
+ // Internationalization lookup:
34
+ // Add a new anonymous object for every string you want to internationalize (with the property being the string).
35
+ // These objects consist of one string for each locale, where the property is the locale code.
36
+ var i18n = {
37
+ <?php
38
+ $channels = array_filter(explode(';', Mage::getStoreConfig('factfinder/search/secondary_channels')));
39
+ $output = array();
40
+ foreach($channels as $channel)
41
+ $output[] = '"Channel: '.$channel.'" : "'.$this->__('Channel: '.$channel).'"';
42
+ echo implode(',', $output);
43
+ ?>
44
+ };
45
+ var translate = function(string) {
46
+ if(i18n[string] == undefined)
47
+ return string;
48
+ else
49
+ return i18n[string];
50
+ }
51
+
52
+ console.log(data);
53
+
54
+ var content = '<ul>';
55
+ content += '<li style="display: none" class="selected selectable-item"></li>';
56
+ var currentChannel = '';
57
+ if(data.length) {
58
+ if(data[0].channel == '<?php echo Mage::getStoreConfig('factfinder/search/channel'); ?>') {
59
+ content += '<li class="delimiter"><?php echo $this->__('Products'); ?></li>';
60
+ } else {
61
+ content += '<li class="delimiter">' + translate('Channel: ' + data[0].channel) + '</li>';
62
+ }
63
+ currentChannel = data[0].channel;
64
+ }
65
+
66
+ for(var i = 0; i < data.length; i++) {
67
+ var item = data[i];
68
+ if(item.channel != currentChannel)
69
+ {
70
+ content += '<li class="delimiter">' + translate('Channel: ' + item.channel) + '</li>';
71
+ currentChannel = item.channel;
72
+ }
73
+ var temp = '';
74
+ temp += '<li title="' + item.name + '" class="selectable-item ' + item.type + '"';
75
+ if(item.attributes.deeplink != undefined && item.attributes.deeplink != '')
76
+ {
77
+ temp += ' rel="' + item.attributes.deeplink + '"';
78
+ }
79
+ temp += '>';
80
+
81
+ temp += '<span class="amount">' + (item.hitCount == 0 ? '' : item.hitCount) + '</span>';
82
+ if(item.image)
83
+ {
84
+ temp += '<img src="' + item.image + '" title="' + item.name + '" class="thumbnail"/>';
85
+ }
86
+ temp += item.name;
87
+ temp += '</li>';
88
+ content += temp;
89
+ }
90
+ content += '</ul>';
91
+ return content;
92
+ };
93
+
94
+ var searchForm = new FactFinderSuggest('search_mini_form', 'search', '<?php echo $this->__('Search entire shop here...') ?>', loadDataCallback);
95
+ searchForm.initAutocomplete('<?php echo $this->helper('factfinder/search')->getSuggestUrl() ?>', 'search_autocomplete');
96
+ <?php else:?>
97
+ var searchForm = new Varien.searchForm('search_mini_form', 'search', '<?php echo $this->__('Search entire shop here...') ?>');
98
+ searchForm.initAutocomplete('<?php echo $this->helper('catalogsearch')->getSuggestUrl() ?>', 'search_autocomplete');
99
+ <?php endif;?>
100
+ //]]>
101
+ </script>
102
+ </div>
103
+ </form>
app/design/frontend/base/default/template/factfinder/form.mini.phtml CHANGED
@@ -8,7 +8,7 @@
8
  */
9
 
10
  /**
11
- * Template to replace Javascript Suguest
12
  *
13
  * @category Mage
14
  * @package Flagbit_FactFinder
@@ -20,17 +20,33 @@
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, 'suggest')):?>
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>
8
  */
9
 
10
  /**
11
+ * Template to replace Javascript Suggest
12
  *
13
  * @category Mage
14
  * @package Flagbit_FactFinder
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 ff-basic-autocomplete" />
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, 'suggest')):?>
29
+
30
+ var loadDataCallback = function(data) {
31
+ var content = '<ul>';
32
+ content += '<li style="display: none;" class="selected selectable-item"></li>';
33
+ data.each(function(item) {
34
+ var temp = '';
35
+ temp += '<li title="' + item.query + '" class="selectable-item">';
36
+ temp += '<span class="amount">' + (item.hitCount == 0 ? '' : item.hitCount) + '</span>';
37
+ temp += item.query;
38
+ temp += '</li>';
39
+ content += temp;
40
+ });
41
+ content += '</ul>';
42
+ return content;
43
+ };
44
+
45
+ var searchForm = new FactFinderSuggest('search_mini_form', 'search', '<?php echo $this->__('Search entire shop here...') ?>', loadDataCallback);
46
+ searchForm.initAutocomplete('<?php echo $this->helper('factfinder/search')->getSuggestUrl() ?>', 'search_autocomplete');
47
  <?php else:?>
48
+ var searchForm = new Varien.searchForm('search_mini_form', 'search', '<?php echo $this->__('Search entire shop here...') ?>');
49
+ searchForm.initAutocomplete('<?php echo $this->helper('catalogsearch')->getSuggestUrl() ?>', 'search_autocomplete');
50
  <?php endif;?>
51
  //]]>
52
  </script>
app/design/frontend/base/default/template/factfinder/scic.phtml CHANGED
@@ -22,7 +22,8 @@ var factfinderSCIC = new FactfinderSCIC(
22
  '.col-main',
23
  $H(<?php echo $this->getJsonDataObject();?>),
24
  $H(<?php echo $this->getJsonUrlToIdMappingObject();?>),
25
- '<?php echo $this->getUrl('factfinder/proxy/scic'); ?>'
 
26
  );
27
 
28
  Event.observe(document, 'dom:loaded', function(event) {
22
  '.col-main',
23
  $H(<?php echo $this->getJsonDataObject();?>),
24
  $H(<?php echo $this->getJsonUrlToIdMappingObject();?>),
25
+ '<?php echo $this->getUrl('factfinder/proxy/scic'); ?>',
26
+ false
27
  );
28
 
29
  Event.observe(document, 'dom:loaded', function(event) {
app/locale/de_DE/Flagbit_FactFinder.csv CHANGED
@@ -1,59 +1,89 @@
1
  "advanced", "fortgeschritten"
2
  "Advanced Authentication Postfix", "Suffix für fortgeschrittene Authentifizierung"
3
  "Advanced Authentication Prefix", "Präfix für fortgeschrittene Authentifizierung"
 
 
 
4
  "Authentication Type", "Authentifizierungstyp"
5
  "Catalog", "Katalog"
6
  "Channel", "Channel"
 
 
 
7
  "Context Name", "Kontext-Name"
 
 
 
8
  "Debug Log", "Debug Log"
9
  "Download export", "Export herunterladen"
10
  "Enabled", "Aktiviert"
11
- "Enter your internal IP addresses. Multiple IP addresses can be separated by semicolons.", "Geben Sie hier Ihre internen IP-Adressen ein. Mehrere IP-Adressen werden mit Semikolon getrennt."
12
- "Enter any secondary channels you want to search. Multiple channels can be separated by semicolons.", "Geben Sie hier weitere Channel an, die Sie durchsuchen wollen. Mehrere Channel werden mit Semikolon getrennt."
 
 
13
  "Export Images and Deeplinks", "Bilder und Deeplinks exportieren"
14
  "FACT-Finder", "FACT-Finder"
15
- "FACT-Finder Access Data", "FACT-Finder Zugangsdaten"
16
  "FACT-Finder Business User Cockpit", "FACT-Finder Business User Cockpit"
17
  "FACT-Finder can provide multiple search indexes, each represented by a ""channel"". Enter the channel that will be filled with your Magento export. Leave empty to use the default channel.", "FACT-Finder kann mehrere Such-Indizes zur Verfügung stellen. Jeder Index wird durch einen ""Channel"" dargestellt. Tragen Sie den Channel ein, der mit Ihrem Magento-Export gefüllt wird. Wenn kein Wert angegeben ist, wird der Standard-Channel genutzt."
18
  "FACT-Finder cannot be activated:", "FACT-Finder konnte nicht aktiviert werden:"
19
- "FACT-Finder Config Data", "FACT-Finder Konfigurationsdaten"
20
- "FACT-Finder Export Configuration", "FACT-Finder Export-Konfiguration"
 
 
 
21
  "FACT-Finder Status", "FACT-Finder Status"
 
22
  "http", "http"
 
23
  "Internal IPs", "Interne IPs"
24
  "Language", "Sprache"
 
25
  "Name of the FACT-Finder application", "Name der FACT-Finder-Applikation"
26
  "No", "Nein"
27
  "Password", "Passwort"
 
28
  "Primary Channel", "Primärer Channel"
29
  "Product ID (default)", "Produkt-ID (Standard)"
30
- "Product Identifier", "Produkt Identifizierung"
31
  "Product SKU", "Produkt-SKU (Artikelnummer)"
32
- "Redirect to product page if single result", "Bei eindeutigem Resultat auf Produkt-Detailseite weiterleiten"
 
33
  "Secondary Result", "Sekundäre Ergebnisse"
34
  "Search", "Suche"
35
- "Search entire store here...", "Den gesamten Shop durchsuchen..."
36
  "Search:", "Suche:"
37
  "Secondary Channels", "Sekundäre Channel"
38
- "Server Port", "Servers-Port"
39
  "Server URL", "Server-URL"
40
- "servername should only contain the IP address or the domain - no ""http://"" or any slashes!", "Der Servername sollte ausschließlih die IP-Adresse oder die Domain enthalten - kein ""http://"" und keine Slashes (\)!"
41
  "simple", "einfach"
 
42
  "Some text strings come directly from FACT-Finder. Enter the language code here. Leave empty to use the language specified by the user's browser.", "Einige Texte kommen direkt von FACT-Finder. Mit dem Sprach-Code in diesem Feld können Sie die Sprache festlegen. Bei leerem Wert erhält der Benutzer Labels in seiner angegebenen Browser-Sprache."
43
  "The advanced authentication post- and prefix are only used when the authentication type is ""advanced"".", "Die Werte der Prä- und Suffixes werden ausschließlich bei fortgeschrittener Authentifizierung verwendet."
44
- "the value for ""port"" must be numeric!", "Der Wert für den Server-Port muss numerisch sein!"
45
- "the value for ""port"" must be a number greater or equals 80!", "Der Wert für den Server-Port muss größer oder gleich 80 sein!"
 
 
 
46
  "There is a Class Rewrite Conflict: ""%s"" already overwritten by ""%s""", "Es besteht ein Klassen-Rewrite-Konflikt: ""%s"" wurde bereits durch ""%s"" überschrieben!"
47
- "there must be a username, if a password should be used", "Sie müssen einen Benutzernamen verwenden."
 
 
48
  "Track ""Add to cart"" events", "Warenkorb-Events tracken"
49
  "Track checkout", "Verkaufte Produkte tracken"
 
 
 
50
  "Use FACT-Finder for Layered Navigation", "FACT-Finder für Layered Navigation einsetzen"
51
- "Use FACT-Finder for Product Crosssells", "FACT-Finder für Cross-Sells einsetzen"
52
- "Use FACT-Finder for Product Upsells", "FACT-Finder für Upsells einsetzen"
53
  "Use FACT-Finder for tag cloud computation", "FACT-Finder für die Berechnung der TagCloud verwenden"
54
  "Use FACT-Finder Search", "FACT-Finder-Suche nutzen"
 
 
55
  "Use Proxy for Suggest", "Proxy für Autovervollständigung nutzen"
56
- "User Name", "Benutzername"
57
  "User name for authentication", "Benutzername für Authentifizierung"
58
  "Yes", "Ja"
59
- "WARNING: was not able to connect to FACT-Finder.", "WARNUNG: Konnte nicht mit dem FACT-Finder-Server verbinden."
1
  "advanced", "fortgeschritten"
2
  "Advanced Authentication Postfix", "Suffix für fortgeschrittene Authentifizierung"
3
  "Advanced Authentication Prefix", "Präfix für fortgeschrittene Authentifizierung"
4
+ "After three failed attempts, the module can revert to using Magento for searches. After the specified amount of time has passed, the module will try to contact FACT-Finder again. If you enter 0, the module will first attempt to contact FACT-Finder for every search.", "Nach drei fehlgeschlagenen Versuchen, kann das Modul dauerhaft Magentos Suche benutzen. Nachdem die hier eingegebene Zeit verstrichen ist, versucht das Modul dann erneut FACT-Finder zu verwenden. Wenn Sie 0 eingeben, wird das Modul für alle Suchanfragen zunächst versuchen FACT-Finder zu erreichen."
5
+ "Another export is already running. Please wait for it to finish before you start a new export.", "Ein anderer Export wurde bereits gestartet. Bitte warten Sie auf dessen Fertigstellung, bevor Sie ein neuen Export beginnen."
6
+ "If you receive this message after another export has failed, please delete the file ""export.lock"" within your Magento directory.", "Wenn Sie diese Meldung sehen, nachdem ein anderer Export abgebrochen wurde, löschen Sie bitte die Datei ""export.lock"" aus Ihrem Magento-Verzeichnis."
7
  "Authentication Type", "Authentifizierungstyp"
8
  "Catalog", "Katalog"
9
  "Channel", "Channel"
10
+ "Channel does not exist or the specified user does not have sufficient rights.", "Channel existiert nicht oder der verwendete User hat nicht die benötigten Rechte."
11
+ "Channel: dev-content", "Inhalte"
12
+ "Please select the version of your FACT-Finder application to enable all of its features.", "Wählen Sie die Version Ihrer FACT-Finder-Applikation um alle Funktionen nutzen zu können."
13
  "Context Name", "Kontext-Name"
14
+ "Could not establish HTTP connection.", "HTTP-Verbindung konnte nicht hergestellt werden."
15
+ "Could not log into FACT-Finder with the given settings. Please check username, password, prefix and postfix.", "FACT-Finder-Login mit gegebenen Einstellungen nicht möglich. Bitte überprüfen Sie Benutzernamen, Passwort, Präfix und Suffix."
16
+ "Could not contact FACT-Finder.", "FACT-Finder konnte nicht erreicht werden."
17
  "Debug Log", "Debug Log"
18
  "Download export", "Export herunterladen"
19
  "Enabled", "Aktiviert"
20
+ "Enter your internal IP addresses. Multiple IP addresses should be separated by semicolons.", "Geben Sie hier Ihre internen IP-Adressen ein. Mehrere IP-Adressen werden mit Semikolon getrennt."
21
+ "Enter any secondary channels you want to search. Multiple channels should be separated by semicolons. NOTE: Secondary channels will only be considered for Suggest results if the proxy is used (see option in section ""FACT-Finder Config Data"")!", "Geben Sie hier weitere Channels an, die Sie durchsuchen wollen. Mehrere Channels werden mit Semikolon getrennt. Hinweis: Damit sekundäre Channels in der Autovervollständigung berücksichtigt werden, muss der Proxy verwendet werden (siehe Option im Abschnitt ""FACT-Finder Konfigurationsdaten"")!"
22
+ "Error in Channel", "Fehler in Channel"
23
+ "Error in Primary Channel", "Fehler im primären Channel"
24
  "Export Images and Deeplinks", "Bilder und Deeplinks exportieren"
25
  "FACT-Finder", "FACT-Finder"
26
+ "FACT-Finder Access Data", "FACT-Finder: Zugangsdaten"
27
  "FACT-Finder Business User Cockpit", "FACT-Finder Business User Cockpit"
28
  "FACT-Finder can provide multiple search indexes, each represented by a ""channel"". Enter the channel that will be filled with your Magento export. Leave empty to use the default channel.", "FACT-Finder kann mehrere Such-Indizes zur Verfügung stellen. Jeder Index wird durch einen ""Channel"" dargestellt. Tragen Sie den Channel ein, der mit Ihrem Magento-Export gefüllt wird. Wenn kein Wert angegeben ist, wird der Standard-Channel genutzt."
29
  "FACT-Finder cannot be activated:", "FACT-Finder konnte nicht aktiviert werden:"
30
+ "FACT-Finder Config Data", "FACT-Finder-Konfigurationsdaten"
31
+ "FACT-Finder Export Configuration", "FACT-Finder: Export-Konfiguration"
32
+ "FACT-Finder Fallback Configuration", "FACT-Finder: Fallback-Konfiguration"
33
+ "FACT-Finder Module Activation", "FACT-Finder: Modul-Auswahl"
34
+ "FACT-Finder not found on server. Please check your context setting.", "FACT-Finder konnte auf dem Server nicht gefunden werden. Bitte überprüfen Sie Ihre Kontexteinstellung."
35
  "FACT-Finder Status", "FACT-Finder Status"
36
+ "FACT-Finder version", "FACT-Finder-Version"
37
  "http", "http"
38
+ "If activated and FACT-Finder cannot be contacted, Magento's built-in search will be used instead.", "Wenn diese Option aktiviert ist und FACT-Finder nicht erreicht werden kann, wird stattdessen Magentos eingebaute Suche verwendet."
39
  "Internal IPs", "Interne IPs"
40
  "Language", "Sprache"
41
+ "Minutes before next attempt", "Minuten bis zum erneuten Versuch"
42
  "Name of the FACT-Finder application", "Name der FACT-Finder-Applikation"
43
  "No", "Nein"
44
  "Password", "Passwort"
45
+ "Please enter the desired edge length of the Suggest images in pixels. If you do not want them to be resized, enter 0.", "Bitte tragen Sie die gewünschte Seitenlänge der Autovervollständigungs-Bilder in Pixeln ein. Wenn die Bilder in Originalgröße abgelegt werden sollen, tragen Sie 0 ein."
46
  "Primary Channel", "Primärer Channel"
47
  "Product ID (default)", "Produkt-ID (Standard)"
48
+ "Product Identifier", "Produkt-Identifizierung"
49
  "Product SKU", "Produkt-SKU (Artikelnummer)"
50
+ "Products", "Produkte"
51
+ "Redirect to product details page for single results", "Bei eindeutigem Resultat auf Produkt-Detailseite weiterleiten"
52
  "Secondary Result", "Sekundäre Ergebnisse"
53
  "Search", "Suche"
54
+ "Search entire shop here...", "Den gesamten Shop durchsuchen..."
55
  "Search:", "Suche:"
56
  "Secondary Channels", "Sekundäre Channel"
57
+ "Server Port", "Server-Port"
58
  "Server URL", "Server-URL"
59
+ "The server name should contain only the IP address or the domain - no ""http://"" or any slashes!", "Der Servername sollte ausschließlich die IP-Adresse oder die Domain enthalten - kein ""http://"" und keine Slashes (/ oder \)!"
60
  "simple", "einfach"
61
+ "Size of Suggest images", "Größe der Autovervollständigungs-Bilder"
62
  "Some text strings come directly from FACT-Finder. Enter the language code here. Leave empty to use the language specified by the user's browser.", "Einige Texte kommen direkt von FACT-Finder. Mit dem Sprach-Code in diesem Feld können Sie die Sprache festlegen. Bei leerem Wert erhält der Benutzer Labels in seiner angegebenen Browser-Sprache."
63
  "The advanced authentication post- and prefix are only used when the authentication type is ""advanced"".", "Die Werte der Prä- und Suffixes werden ausschließlich bei fortgeschrittener Authentifizierung verwendet."
64
+ "The configuration has been saved.", "Die Konfigurationsdaten wurden gespeichert."
65
+ "The configured FACT-Finder version is higher than the actual version of your FACT-Finder. Consider upgrading your FACT-Finder, or reduce the configured version to ", "Die eingestellte FACT-Finder-Version ist höher als die tatsächliche Version Ihres FACT-Finders. Überlegen Sie Ihren FACT-Finder zu erneuern, oder reduzieren Sie die eingestellte Version auf "
66
+ "The value for ""port"" must be an integer!", "Der Wert für den Server-Port muss numerisch sein!"
67
+ "The value for ""port"" must be an integer greater or equals 80!", "Der Wert für den Server-Port muss größer oder gleich 80 sein!"
68
+ "An unknown error has occurred. Please contact FACT-Finder Support.", "Unbekannter Fehler aufgetreten. Bitte kontaktieren Sie Ihren FACT-Finder-Support."
69
  "There is a Class Rewrite Conflict: ""%s"" already overwritten by ""%s""", "Es besteht ein Klassen-Rewrite-Konflikt: ""%s"" wurde bereits durch ""%s"" überschrieben!"
70
+ "There is a problem with FACT-Finder. Please contact FACT-Finder Support.", "Es besteht ein Problem mit FACT-Finder. Bitte kontaktieren Sie Ihren FACT-Finder-Support."
71
+ "A user name must be provided if a password is to be used.", "Sie müssen einen Benutzernamen verwenden."
72
+ "This option must be enabled if secondary channels are to be considered for Suggest results.", "Diese Option muss aktiviert sein, damit sekundäre Channels in der Autovervollständigung berücksichtigt werden."
73
  "Track ""Add to cart"" events", "Warenkorb-Events tracken"
74
  "Track checkout", "Verkaufte Produkte tracken"
75
+ "Track product-clicks", "Produkt-Klicks tracken"
76
+ "Use FACT-Finder After Search Navigation Functionality", "FACT-Finders After Search Navigation einsetzen"
77
+ "Use FACT-Finder Campaign Functionality", "FACT-Finder-Kampagnen einsetzen"
78
  "Use FACT-Finder for Layered Navigation", "FACT-Finder für Layered Navigation einsetzen"
79
+ "Use FACT-Finder for product cross-selling", "FACT-Finder für Cross-Sells einsetzen"
80
+ "Use FACT-Finder for product upselling", "FACT-Finder für Upsells einsetzen"
81
  "Use FACT-Finder for tag cloud computation", "FACT-Finder für die Berechnung der TagCloud verwenden"
82
  "Use FACT-Finder Search", "FACT-Finder-Suche nutzen"
83
+ "Use FACT-Finder Suggest Functionality", "FACT-Finder für Autovervollständigung verwenden"
84
+ "Use Fallback", "Fallback verwenden"
85
  "Use Proxy for Suggest", "Proxy für Autovervollständigung nutzen"
86
+ "User name", "Benutzername"
87
  "User name for authentication", "Benutzername für Authentifizierung"
88
  "Yes", "Ja"
89
+ "Your server's clock does not agree with FACT-Finder's. Please make sure your clock is set correctly.", "Ihre Serverzeit stimmt nicht mit der von FACT-Finder überein. Bitte stellen Sie sicher, dass Ihre Serverzeit korrekt eingestellt ist."
js/factfinder/scic.js CHANGED
@@ -5,11 +5,14 @@ var FactfinderSCIC = Class.create({
5
  mapping: null,
6
  request: null,
7
  regex: new RegExp(/product\/([0-9]+)\//),
8
- initialize: function(classname, data, mapping, url) {
 
9
  this.classname = classname;
10
  this.data = data;
11
  this.mapping = mapping;
12
  this.url = url;
 
 
13
  },
14
 
15
  init: function() {
@@ -49,8 +52,9 @@ var FactfinderSCIC = Class.create({
49
 
50
  var data = this.data.get(id);
51
  data.event = eventType;
52
-
53
  this.request = new Ajax.Request(this.url, {
 
54
  method: 'post',
55
  parameters: data
56
  });
5
  mapping: null,
6
  request: null,
7
  regex: new RegExp(/product\/([0-9]+)\//),
8
+ asynchronous: true,
9
+ initialize: function(classname, data, mapping, url, asynchronous) {
10
  this.classname = classname;
11
  this.data = data;
12
  this.mapping = mapping;
13
  this.url = url;
14
+ if(typeof asynchronous !== 'undefined')
15
+ this.asynchronous = asynchronous;
16
  },
17
 
18
  init: function() {
52
 
53
  var data = this.data.get(id);
54
  data.event = eventType;
55
+
56
  this.request = new Ajax.Request(this.url, {
57
+ asynchronous: this.asynchronous,
58
  method: 'post',
59
  parameters: data
60
  });
js/factfinder/suggest.js CHANGED
@@ -112,27 +112,68 @@ FactFinderAjax.Request = Class.create(Ajax.Request, {
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){
@@ -148,7 +189,7 @@ var FactFinderSuggest = Class.create(Varien.searchForm, {
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
@@ -156,30 +197,27 @@ var FactFinderSuggest = Class.create(Varien.searchForm, {
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
- var hitCount = item.hitCount == '0' ? '' : item.hitCount;
169
- content += '<li title="'+item.query+'"><span class="amount">' + hitCount + '</span>' + item.query + '</li>';
170
- });
171
- content += '</ul>';
172
-
173
- this.request.updateChoices(content);
174
  },
175
 
176
- _selectAutocompleteItem : function(element){
177
- if(element.title){
 
 
178
  this.form.insert('<input type="hidden" name="queryFromSuggest" value="true" />');
179
  this.form.insert('<input type="hidden" name="userInput" value="'+this.field.value+'" />');
180
 
181
  this.field.value = element.title;
 
 
182
  }
183
- this.form.submit();
184
  }
185
  });
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
+ updateChoices: function(choices) {
135
+ if(!this.changed && this.hasFocus) {
136
+ this.update.innerHTML = choices;
137
+ Element.cleanWhitespace(this.update);
138
+ Element.cleanWhitespace(this.update.down());
139
+
140
+ if(this.update.firstChild && this.update.select('.selectable-item')) {
141
+ this.entryCount =
142
+ this.update.select('.selectable-item').length;
143
+ for (var i = 0; i < this.entryCount; i++) {
144
+ var entry = this.getEntry(i);
145
+ entry.autocompleteIndex = i;
146
+ this.addObservers(entry);
147
+ }
148
+ } else {
149
+ this.entryCount = 0;
150
+ }
151
+
152
+ this.stopIndicator();
153
+ this.index = 0;
154
+
155
+ if(this.entryCount==1 && this.options.autoSelect) {
156
+ this.selectEntry();
157
+ this.hide();
158
+ } else {
159
+ this.render();
160
+ }
161
+ }
162
+ },
163
+
164
+ getEntry: function(index) {
165
+ return this.update.select('.selectable-item')[index];
166
+ }
167
  })
168
 
169
  var FactFinderSuggest = Class.create(Varien.searchForm, {
170
+ initialize : function($super, form, field, emptyText, loadDataCallback) {
171
+ $super(form, field, emptyText);
172
+ this.loadDataCallback = loadDataCallback;
173
+ },
174
+
175
+ loadDataCallback: null,
176
+
177
  request: null,
178
 
179
  initAutocomplete : function(url, destinationElement){
189
  updateElement: this._selectAutocompleteItem.bind(this),
190
  onShow : function(element, update) {
191
  if(!update.style.position || update.style.position=='absolute') {
192
+ update.style.position = 'absolute';
193
  Position.clone(element, update, {
194
  setHeight: false,
195
  offsetTop: element.offsetHeight
197
  }
198
  Effect.Appear(update,{duration:0});
199
  }
200
+ // uncomment for debugging
201
+ //, onHide : function(element, update) {}
202
  }
203
  );
204
  this.request.caller = this;
205
  },
206
 
207
  _loadData: function(data) {
208
+ this.request.updateChoices(this.loadDataCallback(data));
 
 
 
 
 
 
 
 
209
  },
210
 
211
+ _selectAutocompleteItem : function(element){
212
+ if(element.attributes.rel) {
213
+ document.location.href = element.attributes.rel.nodeValue;
214
+ } else if(element.title) {
215
  this.form.insert('<input type="hidden" name="queryFromSuggest" value="true" />');
216
  this.form.insert('<input type="hidden" name="userInput" value="'+this.field.value+'" />');
217
 
218
  this.field.value = element.title;
219
+
220
+ this.form.submit();
221
  }
 
222
  }
223
  });
lib/FACTFinder/Abstract/Adapter.php CHANGED
@@ -46,6 +46,16 @@ abstract class FACTFinder_Abstract_Adapter
46
  * @return void
47
  */
48
  protected function init(){}
 
 
 
 
 
 
 
 
 
 
49
 
50
  /**
51
  * returns the data lazily. if it isn't available yet, it will be requested from the dataprovider.
46
  * @return void
47
  */
48
  protected function init(){}
49
+
50
+ public function setParam($name, $value)
51
+ {
52
+ $this->getDataProvider()->setParam($name, $value);
53
+ }
54
+
55
+ public function setParams($params)
56
+ {
57
+ $this->getDataProvider()->setParams($params);
58
+ }
59
 
60
  /**
61
  * returns the data lazily. if it isn't available yet, it will be requested from the dataprovider.
lib/FACTFinder/Abstract/Configuration.php CHANGED
@@ -135,7 +135,71 @@ interface FACTFinder_Abstract_Configuration
135
  * @return array string to string map (param-name as array-key; default value as array-value)
136
  */
137
  function getRequiredServerParams();
138
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  /**
140
  * get encoding of the page content
141
  *
135
  * @return array string to string map (param-name as array-key; default value as array-value)
136
  */
137
  function getRequiredServerParams();
138
+
139
+ /**
140
+ * get default connect timeout for all adapters
141
+ *
142
+ * @return string
143
+ **/
144
+
145
+ function getDefaultConnectTimeout();
146
+
147
+ /**
148
+ * get default timeout for all adapters
149
+ *
150
+ * @return string
151
+ **/
152
+
153
+ function getDefaultTimeout();
154
+
155
+ /**
156
+ * get connect timeout for suggest adapter
157
+ *
158
+ * @return string
159
+ **/
160
+
161
+ function getSuggestConnectTimeout();
162
+
163
+ /**
164
+ * get timeout for suggest adapter
165
+ *
166
+ * @return string
167
+ **/
168
+
169
+ function getSuggestTimeout();
170
+
171
+ /**
172
+ * get connect timeout for scic adapter
173
+ *
174
+ * @return string
175
+ **/
176
+
177
+ function getScicConnectTimeout();
178
+
179
+ /**
180
+ * get timeout for scic adapter
181
+ *
182
+ * @return string
183
+ **/
184
+
185
+ function getScicTimeout();
186
+
187
+ /**
188
+ * get connect timeout for import adapter
189
+ *
190
+ * @return string
191
+ **/
192
+
193
+ function getImportConnectTimeout();
194
+
195
+ /**
196
+ * get timeout for import adapter
197
+ *
198
+ * @return string
199
+ **/
200
+
201
+ function getImportTimeout();
202
+
203
  /**
204
  * get encoding of the page content
205
  *
lib/FACTFinder/Abstract/DataProvider.php CHANGED
@@ -22,7 +22,8 @@ abstract class FACTFinder_Abstract_DataProvider
22
 
23
  protected $log;
24
 
25
- public function __construct(array $params = null, FACTFinder_Abstract_Configuration $config = null, FACTFinder_Abstract_Logger $log = null)
 
26
  {
27
  if(isset($log))
28
  $this->log = $log;
@@ -113,9 +114,11 @@ abstract class FACTFinder_Abstract_DataProvider
113
  }
114
 
115
  /**
 
 
116
  * @return FACTFinder_Abstract_IConfiguration
117
  **/
118
- protected function getConfig()
119
  {
120
  return $this->config;
121
  }
22
 
23
  protected $log;
24
 
25
+ public function __construct(array $params = null, FACTFinder_Abstract_Configuration $config = null,
26
+ FACTFinder_Abstract_Logger $log = null)
27
  {
28
  if(isset($log))
29
  $this->log = $log;
114
  }
115
 
116
  /**
117
+ * This is public, so that adapters don't need their own config objects.
118
+ *
119
  * @return FACTFinder_Abstract_IConfiguration
120
  **/
121
+ public function getConfig()
122
  {
123
  return $this->config;
124
  }
lib/FACTFinder/Abstract/RecommendationAdapter.php CHANGED
@@ -52,7 +52,21 @@ abstract class FACTFinder_Abstract_RecommendationAdapter extends FACTFinder_Abst
52
  $this->getDataProvider()->setParam('id', $productId);
53
  $this->recommendationUpToDate = false;
54
  }
55
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  public function setIdsOnly($idsOnly) {
57
  // Reset the recommendations, if more detail is wanted than before
58
  if($this->idsOnly && !$idsOnly) $recommendationUpToDate = false;
@@ -76,8 +90,11 @@ abstract class FACTFinder_Abstract_RecommendationAdapter extends FACTFinder_Abst
76
  **/
77
  public function getRecommendations() {
78
  if (empty($this->productIds)) {
 
79
  $requestParams = $this->getParamsParser()->getRequestParams();
80
- if (isset($requestParams['id'])) {
 
 
81
  $this->productIds = array($requestParams['id']);
82
  }
83
  if (empty($this->productIds)) {
52
  $this->getDataProvider()->setParam('id', $productId);
53
  $this->recommendationUpToDate = false;
54
  }
55
+
56
+ /**
57
+ * Set ids of multiple products to base recommendation on
58
+ * This feature is only available in FF 6.7 and later
59
+ * Earlier versions will simply use the first product in the list
60
+ *
61
+ * @param array $productIds
62
+ * @return void
63
+ */
64
+ public function setProductIds($productIds) {
65
+ $this->productIds = array($productIds[0]);
66
+ $this->getDataProvider()->setParam('id', $this->productIds);
67
+ $this->recommendationUpToDate = false;
68
+ }
69
+
70
  public function setIdsOnly($idsOnly) {
71
  // Reset the recommendations, if more detail is wanted than before
72
  if($this->idsOnly && !$idsOnly) $recommendationUpToDate = false;
90
  **/
91
  public function getRecommendations() {
92
  if (empty($this->productIds)) {
93
+ $dataProviderParams = $this->getDataProvider()->getParams();
94
  $requestParams = $this->getParamsParser()->getRequestParams();
95
+ if (isset($dataProviderParams['id'])) {
96
+ $this->productIds = $dataProviderParams['id'];
97
+ } elseif (isset($requestParams['id'])) {
98
  $this->productIds = array($requestParams['id']);
99
  }
100
  if (empty($this->productIds)) {
lib/FACTFinder/Abstract/ScicAdapter.php CHANGED
@@ -21,7 +21,7 @@ abstract class FACTFinder_Abstract_ScicAdapter extends FACTFinder_Abstract_Adapt
21
  *
22
  * @return boolean $success
23
  */
24
- abstract protected function applyTracking();
25
 
26
  /**
27
  * if all needed parameters are available at the request like described in the documentation, just use this method to
@@ -33,6 +33,12 @@ abstract class FACTFinder_Abstract_ScicAdapter extends FACTFinder_Abstract_Adapt
33
  * @return boolean $success
34
  */
35
  public function doTrackingFromRequest($sid = null)
 
 
 
 
 
 
36
  {
37
  $params = $this->getParamsParser()->getServerRequestParams();
38
  if (strlen($sid) > 0) {
@@ -41,7 +47,6 @@ abstract class FACTFinder_Abstract_ScicAdapter extends FACTFinder_Abstract_Adapt
41
  $params['sid'] = session_id();
42
  }
43
  $this->getDataProvider()->setParams($params);
44
- return $this->applyTracking();
45
  }
46
 
47
  /**
@@ -53,16 +58,23 @@ abstract class FACTFinder_Abstract_ScicAdapter extends FACTFinder_Abstract_Adapt
53
  * @param int $pos position of product in the search result
54
  * @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)
55
  * @param int $page page number where the product was clicked (optional - is 1 by default)
56
- * @param double $simi similiarity of the product (optional - is 100.00 by default)
57
  * @param string $title title of product (optional - is empty by default)
58
  * @param int $pageSize size of the page where the product was found (optional - is 12 by default)
59
  * @param int $origPageSize original size of the page before the user could have changed it (optional - is set equals to $page by default)
60
  * @return boolean $success
61
  */
62
  public function trackClick($id, $sid = null, $query, $pos, $origPos = -1, $page = 1, $simi = 100.0, $title = '',
63
- $pageSize = 12, $origPageSize = -1)
 
 
 
 
 
 
 
64
  {
65
- if (strlen($sid) == 0) $sid = session_id();
66
  if ($origPos == -1) $origPos = $pos;
67
  if ($origPageSize == -1) $origPageSize = $pageSize;
68
 
@@ -81,7 +93,6 @@ abstract class FACTFinder_Abstract_ScicAdapter extends FACTFinder_Abstract_Adapt
81
  'origPageSize' => $origPageSize
82
  )
83
  );
84
- return $this->applyTracking();
85
  }
86
 
87
  /**
@@ -90,24 +101,29 @@ abstract class FACTFinder_Abstract_ScicAdapter extends FACTFinder_Abstract_Adapt
90
  * @param string $id id of product
91
  * @param string $sid session id (if empty, then try to set using the function session_id() )
92
  * @param int $count number of items purchased for each product (optional - default 1)
93
- * @param double $price this is the single unit price (optional)
94
  * @return boolean $success
95
  */
96
  public function trackCart($id, $sid = null, $count = 1, $price = null, $userid = null)
97
  {
98
- if (strlen($sid) == 0) $sid = session_id();
 
 
 
 
 
 
99
  $params = array(
100
- 'id' => $id,
101
- 'sid' => $sid,
102
- 'count' => $count,
103
- 'event' => 'cart'
104
- );
105
 
106
  if (strlen($price) > 0) $params['price'] = $price;
107
  if (strlen($userid) > 0) $params['userid'] = $userid;
108
 
109
  $this->getDataProvider()->setParams($params);
110
- return $this->applyTracking();
111
  }
112
 
113
  /**
@@ -116,24 +132,30 @@ abstract class FACTFinder_Abstract_ScicAdapter extends FACTFinder_Abstract_Adapt
116
  * @param string $id id of product
117
  * @param string $sid session id (if empty, then try to set using the function session_id() )
118
  * @param int $count number of items purchased for each product (optional - default 1)
119
- * @param double $price this is the single unit price (optional)
 
120
  * @return boolean $success
121
  */
122
  public function trackCheckout($id, $sid = null, $count = 1, $price = null, $userid = null)
123
  {
124
- if (strlen($sid) == 0) $sid = session_id();
 
 
 
 
 
 
125
  $params = array(
126
- 'id' => $id,
127
- 'sid' => $sid,
128
- 'count' => $count,
129
- 'event' => 'checkout'
130
- );
131
 
132
  if (strlen($price) > 0) $params['price'] = $price;
133
  if (strlen($userid) > 0) $params['userid'] = $userid;
134
 
135
  $this->getDataProvider()->setParams($params);
136
- return $this->applyTracking();
137
  }
138
 
139
  /**
@@ -146,14 +168,19 @@ abstract class FACTFinder_Abstract_ScicAdapter extends FACTFinder_Abstract_Adapt
146
  */
147
  public function trackRecommendationClick($id, $sid = null, $mainId)
148
  {
149
- if (strlen($sid) == 0) $sid = session_id();
 
 
 
 
 
 
150
  $params = array(
151
- 'id' => $id,
152
- 'sid' => $sid,
153
- 'mainId' => $mainId,
154
- 'event' => 'recommendationClick'
155
- );
156
  $this->getDataProvider()->setParams($params);
157
- return $this->applyTracking();
158
  }
159
  }
21
  *
22
  * @return boolean $success
23
  */
24
+ abstract public function applyTracking();
25
 
26
  /**
27
  * if all needed parameters are available at the request like described in the documentation, just use this method to
33
  * @return boolean $success
34
  */
35
  public function doTrackingFromRequest($sid = null)
36
+ {
37
+ $this->setupTrackingFromRequest($sid);
38
+ return $this->applyTracking();
39
+ }
40
+
41
+ public function setupTrackingFromRequest($sid = null)
42
  {
43
  $params = $this->getParamsParser()->getServerRequestParams();
44
  if (strlen($sid) > 0) {
47
  $params['sid'] = session_id();
48
  }
49
  $this->getDataProvider()->setParams($params);
 
50
  }
51
 
52
  /**
58
  * @param int $pos position of product in the search result
59
  * @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)
60
  * @param int $page page number where the product was clicked (optional - is 1 by default)
61
+ * @param float $simi similiarity of the product (optional - is 100.00 by default)
62
  * @param string $title title of product (optional - is empty by default)
63
  * @param int $pageSize size of the page where the product was found (optional - is 12 by default)
64
  * @param int $origPageSize original size of the page before the user could have changed it (optional - is set equals to $page by default)
65
  * @return boolean $success
66
  */
67
  public function trackClick($id, $sid = null, $query, $pos, $origPos = -1, $page = 1, $simi = 100.0, $title = '',
68
+ $pageSize = 12, $origPageSize = -1)
69
+ {
70
+ $this->setupClickTracking($id, $sid, $query, $pos, $origPos, $page, $simi, $title, $pageSize, $origPageSize);
71
+ return $this->applyTracking();
72
+ }
73
+
74
+ public function setupClickTracking($id, $sid = null, $query, $pos, $origPos = -1, $page = 1, $simi = 100.0,
75
+ $title = '', $pageSize = 12, $origPageSize = -1)
76
  {
77
+ if (strlen($sid) == 0) $sid = session_id();
78
  if ($origPos == -1) $origPos = $pos;
79
  if ($origPageSize == -1) $origPageSize = $pageSize;
80
 
93
  'origPageSize' => $origPageSize
94
  )
95
  );
 
96
  }
97
 
98
  /**
101
  * @param string $id id of product
102
  * @param string $sid session id (if empty, then try to set using the function session_id() )
103
  * @param int $count number of items purchased for each product (optional - default 1)
104
+ * @param float $price this is the single unit price (optional)
105
  * @return boolean $success
106
  */
107
  public function trackCart($id, $sid = null, $count = 1, $price = null, $userid = null)
108
  {
109
+ $this->setupCartTracking($id, $sid, $count, $price, $userid);
110
+ return $this->applyTracking();
111
+ }
112
+
113
+ public function setupCartTracking($id, $sid = null, $count = 1, $price = null, $userid = null)
114
+ {
115
+ if (strlen($sid) == 0) $sid = session_id();
116
  $params = array(
117
+ 'id' => $id,
118
+ 'sid' => $sid,
119
+ 'count' => $count,
120
+ 'event' => 'cart'
121
+ );
122
 
123
  if (strlen($price) > 0) $params['price'] = $price;
124
  if (strlen($userid) > 0) $params['userid'] = $userid;
125
 
126
  $this->getDataProvider()->setParams($params);
 
127
  }
128
 
129
  /**
132
  * @param string $id id of product
133
  * @param string $sid session id (if empty, then try to set using the function session_id() )
134
  * @param int $count number of items purchased for each product (optional - default 1)
135
+ * @param float $price this is the single unit price (optional)
136
+ * @param string $userid id of user checking out
137
  * @return boolean $success
138
  */
139
  public function trackCheckout($id, $sid = null, $count = 1, $price = null, $userid = null)
140
  {
141
+ $this->setupCheckoutTracking($id, $sid, $count, $price, $userid);
142
+ return $this->applyTracking();
143
+ }
144
+
145
+ public function setupCheckoutTracking($id, $sid = null, $count = 1, $price = null, $userid = null)
146
+ {
147
+ if (strlen($sid) == 0) $sid = session_id();
148
  $params = array(
149
+ 'id' => $id,
150
+ 'sid' => $sid,
151
+ 'count' => $count,
152
+ 'event' => 'checkout'
153
+ );
154
 
155
  if (strlen($price) > 0) $params['price'] = $price;
156
  if (strlen($userid) > 0) $params['userid'] = $userid;
157
 
158
  $this->getDataProvider()->setParams($params);
 
159
  }
160
 
161
  /**
168
  */
169
  public function trackRecommendationClick($id, $sid = null, $mainId)
170
  {
171
+ $this->setupRecommendationClickTracking($id, $sid, $mainId);
172
+ return $this->applyTracking();
173
+ }
174
+
175
+ public function setupRecommendationClickTracking($id, $sid = null, $mainId)
176
+ {
177
+ if (strlen($sid) == 0) $sid = session_id();
178
  $params = array(
179
+ 'id' => $id,
180
+ 'sid' => $sid,
181
+ 'mainId' => $mainId,
182
+ 'event' => 'recommendationClick'
183
+ );
184
  $this->getDataProvider()->setParams($params);
 
185
  }
186
  }
lib/FACTFinder/AsnGroup.php CHANGED
@@ -59,6 +59,20 @@ class FACTFinder_AsnGroup extends ArrayIterator
59
  public function isColorStyle() {
60
  return $this->style == 'COLOR';
61
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  /**
64
  * @return boolean
59
  public function isColorStyle() {
60
  return $this->style == 'COLOR';
61
  }
62
+
63
+ /**
64
+ * @return boolean
65
+ */
66
+ public function isMultiSelectStyle() {
67
+ return $this->style == 'MULTISELECT';
68
+ }
69
+
70
+ /**
71
+ * @return boolean
72
+ */
73
+ public function isTreeStyle() {
74
+ return $this->style == 'TREE';
75
+ }
76
 
77
  /**
78
  * @return boolean
lib/FACTFinder/Configuration.php CHANGED
@@ -339,6 +339,85 @@ class FACTFinder_Configuration implements FACTFinder_Abstract_Configuration
339
  return $this->requiredServerParams;
340
  }
341
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
 
343
  /**
344
  * get encoding for the webpage
339
  return $this->requiredServerParams;
340
  }
341
 
342
+ /**
343
+ * get default connect timeout for all adapters
344
+ *
345
+ * @return string
346
+ **/
347
+
348
+ function getDefaultConnectTimeout() {
349
+ return $this->zendConfig->search->timeouts->defaultConnectTimeout;
350
+ }
351
+
352
+ /**
353
+ * get default timeout for all adapters
354
+ *
355
+ * @return string
356
+ **/
357
+
358
+ function getDefaultTimeout() {
359
+ return $this->zendConfig->search->timeouts->defaultTimeout;
360
+ }
361
+
362
+ /**
363
+ * get connect timeout for suggest adapter
364
+ *
365
+ * @return string
366
+ **/
367
+
368
+ function getSuggestConnectTimeout() {
369
+ return $this->zendConfig->search->timeouts->suggestConnectTimeout;
370
+ }
371
+
372
+ /**
373
+ * get timeout for suggest adapter
374
+ *
375
+ * @return string
376
+ **/
377
+
378
+ function getSuggestTimeout() {
379
+ return $this->zendConfig->search->timeouts->suggestTimeout;
380
+ }
381
+
382
+ /**
383
+ * get connect timeout for scic adapter
384
+ *
385
+ * @return string
386
+ **/
387
+
388
+ function getScicConnectTimeout() {
389
+ return $this->zendConfig->search->timeouts->scicConnectTimeout;
390
+ }
391
+
392
+ /**
393
+ * get timeout for scic adapter
394
+ *
395
+ * @return string
396
+ **/
397
+
398
+ function getScicTimeout() {
399
+ return $this->zendConfig->search->timeouts->scicTimeout;
400
+ }
401
+
402
+ /**
403
+ * get connect timeout for import adapter
404
+ *
405
+ * @return string
406
+ **/
407
+
408
+ function getImportConnectTimeout() {
409
+ return $this->zendConfig->search->timeouts->importConnectTimeout;
410
+ }
411
+
412
+ /**
413
+ * get timeout for import adapter
414
+ *
415
+ * @return string
416
+ **/
417
+
418
+ function getImportTimeout() {
419
+ return $this->zendConfig->search->timeouts->importTimeout;
420
+ }
421
 
422
  /**
423
  * get encoding for the webpage
lib/FACTFinder/Http/DataProvider.php CHANGED
@@ -14,19 +14,93 @@
14
  * @version $Id: DataProvider.php 25893 2010-06-29 08:19:43Z rb $
15
  * @package FACTFinder\Http
16
  */
 
 
 
17
  class FACTFinder_Http_DataProvider extends FACTFinder_Abstract_DataProvider
18
  {
 
 
 
 
 
19
  protected $data;
20
- protected $previousUrl;
 
 
 
 
 
21
  protected $httpHeader = array();
22
  protected $curlOptions = array(
23
  CURLOPT_RETURNTRANSFER => true,
24
  CURLOPT_SSL_VERIFYPEER => false,
25
- CURLOPT_SSL_VERIFYHOST => false,
26
- CURLOPT_CONNECTTIMEOUT => 2,
27
- CURLOPT_TIMEOUT => 4
28
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  /**
31
  * this implementation of the data provider uses the type as request path in addition to the request context path.
32
  * please ensure that this is the full action name, i.e. "Search.ff"
@@ -35,7 +109,20 @@ class FACTFinder_Http_DataProvider extends FACTFinder_Abstract_DataProvider
35
  */
36
  public function setType($type)
37
  {
38
- $this->type = $type;
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  }
40
 
41
  /**
@@ -84,13 +171,27 @@ class FACTFinder_Http_DataProvider extends FACTFinder_Abstract_DataProvider
84
  */
85
  public function getData()
86
  {
87
- $url = $this->getAuthenticationUrl();
88
- if ($this->data == null || $url != $this->previousUrl) {
89
- $this->previousUrl = $url;
90
- $this->data = $this->loadResponse($url);
91
  }
92
  return $this->data;
93
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  /**
96
  * this function sends the request to the server and loads the response data
@@ -98,212 +199,112 @@ class FACTFinder_Http_DataProvider extends FACTFinder_Abstract_DataProvider
98
  * @throws Exception on connection error
99
  * @return response data
100
  **/
101
- protected function loadResponse($url)
102
  {
103
- if ($this->type == null) {
104
- $this->log->error("Request type missing.");
105
- throw new Exception('request type not set! can not do a request without knowing the type.');
106
- }
107
 
108
- $config = $this->getConfig();
109
- if ($config->getLanguage() != '') {
110
- $this->addHttpHeaderFields(array('Accept-Language: ' . $config->getLanguage()));
111
- }
112
 
113
- if ($this->getConfig()->isDebugEnabled()) {
114
- $url .= '&verbose=true';
115
- if (isset($_SERVER['HTTP_REFERER'])) $this->setCurlOption(CURLOPT_REFERER, $_SERVER['HTTP_REFERER'], false);
116
- }
117
- return $this->sendRequest($url);
118
- }
119
 
120
- /**
121
- * this function returns the request url with the correct authentication method (set by the configuration).
122
- *
123
- * @return string url
124
- */
125
- public function getAuthenticationUrl() {
126
- $config = $this->getConfig();
127
- if ($config->isHttpAuthenticationType()) {
128
- $url = $this->getHttpAuthenticationUrl();
129
- } else if ($config->isSimpleAuthenticationType()) {
130
- $url = $this->getSimpleAuthenticationUrl();
131
- } else if ($config->isAdvancedAuthenticationType()) {
132
- $url = $this->getAdvancedAuthenticationUrl();
133
- } else {
134
- $url = $this->getNonAuthenticationUrl();
135
  }
136
- return $url;
 
137
  }
138
 
139
  /**
140
- * send request and return response data
141
  *
142
- * @param string url
143
- * @return string returned http body
144
  */
145
- protected function sendRequest($url)
146
  {
147
- $this->log->info("Trying to send request to ".$url."...");
148
- $cResource = curl_init($url);
149
-
150
- if (!empty($this->httpHeader)) {
151
- $this->curlOptions[CURLOPT_HTTPHEADER] = $this->httpHeader;
152
- }
153
 
154
- if (sizeof($this->curlOptions) > 0) {
155
- curl_setopt_array($cResource, $this->curlOptions);
 
156
  }
157
 
158
- $response = curl_exec($cResource);
159
- $httpCode = curl_getinfo($cResource, CURLINFO_HTTP_CODE);
160
- $curlErr = curl_error($cResource);
161
- curl_close($cResource);
162
-
163
- if (intval($httpCode) >= 400) {
164
- $this->log->error("Conntection failed. HTTP code: $httpCode");
165
- throw new Exception("Connection failed. HTTP code: $httpCode", $httpCode);
166
- } else if ($httpCode == 0) {
167
- $this->log->error("Connection refused. $curlErr");
168
- throw new Exception("Connection refused. $curlErr");
169
- } else if (floor(intval($httpCode) / 100) == 2) { // all successful status codes (2**)
170
- $this->log->info("Received response from ".$url.".");
171
- }
172
-
173
- return $response;
174
- }
175
 
176
- /**
177
- * get url with advanced authentication encryption
178
- *
179
- * @return string url
180
- */
181
- protected function getAdvancedAuthenticationUrl() {
182
- $config = $this->getConfig();
183
- $params = $this->getParams();
184
- $this->log->info("Server Request Params: ".http_build_query($params, '', ', '));
185
 
186
- $channel = $this->getChannel($params, $config);
187
- if ($channel != '') {
188
- $params['channel'] = $channel;
189
- }
190
 
191
- $ts = time() . '000'; //millisecondes needed
192
- $prefix = $config->getAdvancedAuthPrefix();
193
- $postfix = $config->getAdvancedAuthPostfix();
194
- $authParams = "timestamp=$ts&username=".$config->getAuthUser()
195
- . '&password=' . md5($prefix . $ts . md5($config->getAuthPasswort()) . $postfix);
196
 
197
- $url = $config->getRequestProtocol() . '://'
198
- . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
199
- . $config->getContext() . '/'.$this->type.'?' . http_build_query($params, '', '&')
200
- . (count($params)?'&':'') . $authParams;
201
-
202
- // The following line removes all []-indices from array parameters, because tomcat doesn't need them
203
- $url = preg_replace("/%5B[A-Za-z0-9]*%5D/", "", $url);
204
- $this->log->info("Request Url: ".$url);
205
- return $url;
206
  }
207
 
208
  /**
209
- * get url with simple authentication encryption
210
  *
211
  * @return string url
212
  */
213
- protected function getSimpleAuthenticationUrl() {
214
  $config = $this->getConfig();
215
- $params = $this->getParams();
216
- $this->log->info("Server Request Params: ".http_build_query($params, '', ', '));
217
-
218
- $channel = $this->getChannel($params, $config);
219
- if ($channel != '') {
220
- $params['channel'] = $channel;
221
- }
222
-
223
- $ts = time() . '000'; //millisecondes needed but won't be considered
224
- $authParams = "timestamp=$ts&username=".$config->getAuthUser()
225
- . '&password=' . md5($config->getAuthPasswort());
226
-
227
- $url = $config->getRequestProtocol() . '://'
228
- . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
229
- . $config->getContext() . '/'.$this->type.'?' . http_build_query($params, '', '&')
230
- . (count($params)?'&':'') . $authParams;
231
-
232
- // The following line removes all []-indices from array parameters, because tomcat doesn't need them
233
- $url = preg_replace("/%5B[A-Za-z0-9]*%5D/", "", $url);
234
- $this->log->info("Request Url: ".$url);
235
  return $url;
236
  }
237
 
238
- /**
239
- * get url with http authentication
240
- *
241
- * @return string url
242
- */
243
- protected function getHttpAuthenticationUrl() {
244
- $config = $this->getConfig();
245
- $params = $this->getParams();
246
- $this->log->info("Server Request Params: ".http_build_query($params, '', ', '));
247
-
248
- $channel = $this->getChannel($params, $config);
249
- if ($channel != '') {
250
- $params['channel'] = $channel;
251
- }
252
 
253
- $auth = $config->getAuthUser() . ':' . $config->getAuthPasswort() . '@';
254
- if ($auth == ':@') $auth = '';
 
 
255
 
256
- $url = $config->getRequestProtocol() . '://' . $auth
257
- . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
258
- . $config->getContext() . '/' . $this->type . (count($params)?'?':'')
259
- . http_build_query($params, '', '&');
260
-
261
- // The following line removes all []-indices from array parameters, because tomcat doesn't need them
262
- $url = preg_replace("/%5B[A-Za-z0-9]*%5D/", "", $url);
263
- $this->log->info("Request Url: ".$url);
264
- return $url;
265
  }
266
 
267
- /**
268
- * get url with no authentication.
269
- *
270
- * @return string url
271
- */
272
- public function getNonAuthenticationUrl() {
273
- $config = $this->getConfig();
274
- $params = $this->getParams();
275
- $this->log->info("Server Request Params: ".http_build_query($params, '', ', '));
276
 
277
- $channel = $this->getChannel($params, $config);
278
- if ($channel != '') {
279
- $params['channel'] = $channel;
280
- }
281
 
282
- $url = $config->getRequestProtocol() . '://'
283
- . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
284
- . $config->getContext() . '/' . $this->type . (count($params)?'?':'')
285
- . http_build_query($params, '', '&');
286
 
287
- // The following line removes all []-indices from array parameters, because tomcat doesn't need them
288
- $url = preg_replace("/%5B[A-Za-z0-9]*%5D/", "", $url);
289
- $this->log->info("Request Url: ".$url);
290
- return $url;
291
  }
292
-
293
- /**
294
- * get channel from params or config (params override config)
295
- *
296
- * @param array parameterse
297
- * @param FACTFinderAbstractConfiguration config
298
- * @return string channel
299
- */
300
- protected function getChannel($params, $config) {
301
- $channel = '';
302
- if (isset($params['channel']) && strlen($params['channel']) > 0) {
303
- $channel = $params['channel'];
304
- } else if($config->getChannel() != '') {
305
- $channel = $config->getChannel();
306
- }
307
- return $channel;
308
- }
309
  }
14
  * @version $Id: DataProvider.php 25893 2010-06-29 08:19:43Z rb $
15
  * @package FACTFinder\Http
16
  */
17
+
18
+ include_once LIB_DIR . DS . 'SAI' . DS . 'Curl.php';
19
+
20
  class FACTFinder_Http_DataProvider extends FACTFinder_Abstract_DataProvider
21
  {
22
+ /**
23
+ * @var SAI_CurlInterface
24
+ */
25
+ protected $curl;
26
+
27
  protected $data;
28
+
29
+ /**
30
+ * @var FACTFinder_Http_UrlBuilder
31
+ */
32
+ protected $urlBuilder;
33
+ protected $previousUrl = '';
34
  protected $httpHeader = array();
35
  protected $curlOptions = array(
36
  CURLOPT_RETURNTRANSFER => true,
37
  CURLOPT_SSL_VERIFYPEER => false,
38
+ CURLOPT_SSL_VERIFYHOST => false
 
 
39
  );
40
+ protected $lastHttpCode = null;
41
+ protected $lastCurlErrno = null;
42
+ protected $lastCurlError = null;
43
+
44
+ function __construct(array $params = null, FACTFinder_Abstract_Configuration $config = null, FACTFinder_Abstract_Logger $log = null, SAI_CurlInterface $curl = null) {
45
+ if($curl === null)
46
+ {
47
+ $curl = new SAI_Curl();
48
+ }
49
+ $this->curl = $curl;
50
+ $this->urlBuilder = FF::getInstance('http/urlBuilder', $params, $config, $log);
51
+ parent::__construct($params, $config, $log);
52
+ $this->setCurlOptions(array(
53
+ CURLOPT_CONNECTTIMEOUT => $this->getConfig()->getDefaultConnectTimeout(),
54
+ CURLOPT_TIMEOUT => $this->getConfig()->getDefaultTimeout()
55
+ ));
56
+ }
57
+
58
+ /**
59
+ * sets factfinder params object
60
+ *
61
+ * @param array params
62
+ * @return void
63
+ **/
64
+ public function setParams(array $params)
65
+ {
66
+ $this->urlBuilder->setParams($params);
67
+ }
68
 
69
+ /**
70
+ * set single param
71
+ *
72
+ * @param string name
73
+ * @param string value
74
+ * @return void
75
+ **/
76
+ public function setParam($name, $value)
77
+ {
78
+ $this->urlBuilder->setParam($name, $value);
79
+ }
80
+
81
+ /**
82
+ * unset single param
83
+ *
84
+ * @param string name
85
+ * @return void
86
+ **/
87
+ public function unsetParam($name)
88
+ {
89
+ $this->urlBuilder->unsetParam($name);
90
+ }
91
+
92
+ /**
93
+ * set single param with multiple values
94
+ *
95
+ * @param string name
96
+ * @param array of strings values
97
+ * @return void
98
+ **/
99
+ public function setArrayParam($name, $values)
100
+ {
101
+ $this->urlBuilder->setArrayParam($name, $values);
102
+ }
103
+
104
  /**
105
  * this implementation of the data provider uses the type as request path in addition to the request context path.
106
  * please ensure that this is the full action name, i.e. "Search.ff"
109
  */
110
  public function setType($type)
111
  {
112
+ $this->urlBuilder->setAction($type);
113
+ }
114
+
115
+ protected function getType()
116
+ {
117
+ return $this->urlBuilder->getAction();
118
+ }
119
+
120
+ /**
121
+ * @return array
122
+ **/
123
+ public function getParams()
124
+ {
125
+ return $this->urlBuilder->getParams();
126
  }
127
 
128
  /**
171
  */
172
  public function getData()
173
  {
174
+ if ($this->hasUrlChanged()) {
175
+ $this->data = $this->loadResponse();
 
 
176
  }
177
  return $this->data;
178
  }
179
+
180
+ /**
181
+ * sets the URL that was used for the most recent request
182
+ **/
183
+ public function setPreviousUrl($url)
184
+ {
185
+ $this->previousUrl = $url;
186
+ }
187
+
188
+ /**
189
+ * checks whether the URL (and thus the parameters) have changed since last loading the data
190
+ **/
191
+ public function hasUrlChanged()
192
+ {
193
+ return $this->urlBuilder->getNonAuthenticationUrl() != $this->previousUrl;
194
+ }
195
 
196
  /**
197
  * this function sends the request to the server and loads the response data
199
  * @throws Exception on connection error
200
  * @return response data
201
  **/
202
+ protected function loadResponse()
203
  {
204
+ $this->prepareRequest();
 
 
 
205
 
206
+ $cResource = $this->curl->curl_init();
 
 
 
207
 
208
+ if (sizeof($this->curlOptions) > 0) {
209
+ $this->curl->curl_setopt_array($cResource, $this->curlOptions);
210
+ }
 
 
 
211
 
212
+ $response = $this->curl->curl_exec($cResource);
213
+ $this->lastHttpCode = $this->curl->curl_getinfo($cResource, CURLINFO_HTTP_CODE);
214
+ $this->lastCurlErrno = $this->curl->curl_errno($cResource);
215
+ $this->lastCurlError = $this->curl->curl_error($cResource);
216
+ $this->curl->curl_close($cResource);
217
+
218
+ if (intval($this->lastHttpCode) >= 400) {
219
+ $this->log->error("Connection failed. HTTP code: $this->lastHttpCode");
220
+ } else if ($this->lastHttpCode == 0) {
221
+ $this->log->error("Connection refused. $this->lastCurlError");
222
+ } else if (floor(intval($this->lastHttpCode) / 100) == 2) { // all successful status codes (2**)
223
+ $this->log->info("Received response!");
 
 
 
224
  }
225
+
226
+ return $response;
227
  }
228
 
229
  /**
230
+ * Sets up curl all necessary cURL options (including URL!)
231
  *
232
+ * @throws Exception
 
233
  */
234
+ public function prepareRequest()
235
  {
236
+ if ($this->getType() === null) {
237
+ $this->log->error("Request type missing.");
238
+ throw new Exception('Request type was not set! Cannot send request without knowing the type.');
239
+ }
 
 
240
 
241
+ $config = $this->getConfig();
242
+ if ($config->getLanguage() != '') {
243
+ $this->addHttpHeaderFields(array('Accept-Language: ' . $config->getLanguage()));
244
  }
245
 
246
+ $url = $this->getAuthenticationUrl();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
 
248
+ if ($this->getConfig()->isDebugEnabled()) {
249
+ $url .= '&verbose=true';
250
+ if (isset($_SERVER['HTTP_REFERER'])) $this->setCurlOption(CURLOPT_REFERER, $_SERVER['HTTP_REFERER'], false);
251
+ }
 
 
 
 
 
252
 
253
+ if (!empty($this->httpHeader)) {
254
+ $this->setCurlOption(CURLOPT_HTTPHEADER, $this->httpHeader);
255
+ }
 
256
 
257
+ $this->setCurlOption(CURLOPT_URL, $url);
 
 
 
 
258
 
259
+ $this->setPreviousUrl($this->urlBuilder->getNonAuthenticationUrl());
260
+ $this->log->info("Trying to send request to " . $url . "...");
 
 
 
 
 
 
 
261
  }
262
 
263
  /**
264
+ * this function returns the request url with the correct authentication method (set by the configuration).
265
  *
266
  * @return string url
267
  */
268
+ public function getAuthenticationUrl() {
269
  $config = $this->getConfig();
270
+ if ($config->isHttpAuthenticationType()) {
271
+ $url = $this->urlBuilder->getHttpAuthenticationUrl();
272
+ } else if ($config->isSimpleAuthenticationType()) {
273
+ $url = $this->urlBuilder->getSimpleAuthenticationUrl();
274
+ } else if ($config->isAdvancedAuthenticationType()) {
275
+ $url = $this->urlBuilder->getAdvancedAuthenticationUrl();
276
+ } else {
277
+ $url = $this->urlBuilder->getNonAuthenticationUrl();
278
+ }
 
 
 
 
 
 
 
 
 
 
 
279
  return $url;
280
  }
281
 
282
+ public function getNonAuthenticationUrl()
283
+ {
284
+ return $this->urlBuilder->getNonAuthenticationUrl();
285
+ }
 
 
 
 
 
 
 
 
 
 
286
 
287
+ public function getLastHttpCode()
288
+ {
289
+ if($this->lastHttpCode === null)
290
+ throw new Exception("Cannot return last HTTP code. No request has been sent.");
291
 
292
+ return $this->lastHttpCode;
 
 
 
 
 
 
 
 
293
  }
294
 
295
+ public function getLastCurlError()
296
+ {
297
+ if($this->lastCurlError === null)
298
+ throw new Exception("Cannot return last curl error. No request has been sent.");
 
 
 
 
 
299
 
300
+ return $this->lastCurlError;
301
+ }
 
 
302
 
303
+ public function getLastCurlErrno()
304
+ {
305
+ if($this->lastCurlErrno === null)
306
+ throw new Exception("Cannot return last curl errno. No request has been sent.");
307
 
308
+ return $this->lastCurlErrno;
 
 
 
309
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  }
lib/FACTFinder/Http/ParallelDataProvider.php CHANGED
@@ -15,13 +15,23 @@
15
  * @version $Id: DataProvider.php 25893 2010-06-29 08:19:43Z rb $
16
  * @package FACTFinder\Http
17
  */
 
18
  class FACTFinder_Http_ParallelDataProvider
19
  {
20
- protected static $instance;
21
- protected static $dataProvider = array();
22
- protected static $dataLoaded = false;
 
 
 
 
 
 
23
 
24
- protected $data;
 
 
 
25
 
26
  /**
27
  * singleton
@@ -31,15 +41,15 @@ class FACTFinder_Http_ParallelDataProvider
31
  /**
32
  * @return FACTFinder_Abstract_DataProvider
33
  */
34
- public static function getDataProvider(array $params = null, FACTFinder_Abstract_Configuration $config = null) {
35
  if (self::$instance == null) {
36
  self::$instance = new FACTFinder_Http_ParallelDataProvider();
37
  }
38
- $id = 'proxy' . count(self::$dataProvider); // use prefix so the id is a string
39
- self::$dataProvider[$id] = new FACTFinder_Http_DataProviderProxy($params, $config);
40
- self::$dataProvider[$id]->register($id, self::$instance);
41
 
42
- return self::$dataProvider[$id];
43
  }
44
 
45
  /**
@@ -49,33 +59,35 @@ class FACTFinder_Http_ParallelDataProvider
49
  **/
50
  public static function loadAllData()
51
  {
52
- if (self::$instance == null) {
53
- throw new Exception("no dataprovider initialized");
54
  }
55
 
56
  // TODO: optimize:
57
- // - deny multiple loading of single requests that were already loaded
58
  // - warn if several loadings were done
59
  // - add logging
60
 
61
  // init handles
62
  $multiHandle = curl_multi_init();
63
  $handles = self::initHandles($multiHandle);
64
- $data = self::executeHandles($multiHandle, $handles);
65
-
66
- self::$instance->setData($data);
67
- self::$dataLoaded = true;
68
  }
69
 
70
  protected static function initHandles($multiHandle) {
71
  $handles = array();
72
- foreach(self::$dataProvider AS $id => $dataProvider) {
73
- $handle = curl_init($dataProvider->getAuthenticationUrl());
74
-
75
- $curlOptions = $dataProvider->getCurlOptions();
76
- $curlOptions[CURLOPT_HTTPHEADER] = $dataProvider->getHttpHeader();
77
- $curlOptions[CURLOPT_RETURNTRANSFER] = true; // this is a must have option, so the data can be saved
78
- curl_setopt_array($handle, $curlOptions);
 
 
 
 
 
 
79
 
80
  $handles[$id] = $handle;
81
  curl_multi_add_handle($multiHandle,$handle);
@@ -103,21 +115,66 @@ class FACTFinder_Http_ParallelDataProvider
103
 
104
  //close the handles
105
  $data = array();
 
 
 
106
  foreach($handles AS $id => $handle) {
 
 
 
 
 
107
  $data[$id] = curl_multi_getcontent($handle);
 
 
 
 
108
  curl_multi_remove_handle($multiHandle, $handle);
 
109
  }
110
  curl_multi_close($multiHandle);
111
- return $data;
 
 
 
 
112
  }
113
-
114
- /**
115
- *
116
- * internal method to apply data to
117
- */
118
  protected function setData(array $data) {
119
- $this->data = $data;
 
 
 
 
 
120
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
  /**
123
  * this method is called by the proxy data providers on the one and only existing instance
@@ -126,11 +183,35 @@ class FACTFinder_Http_ParallelDataProvider
126
  */
127
  public function getData($id)
128
  {
129
- if (!self::$dataLoaded) {
130
- throw new DataNotLoadedException("Implementation Error: please use 'FACTFinder_Http_ParallelDataProvider::loadAllData' before trying to get data");
131
  }
132
  return isset($this->data[$id]) ? $this->data[$id] : null;
133
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  }
135
 
136
  /**
@@ -142,7 +223,11 @@ class FACTFinder_Http_ParallelDataProvider
142
  class FACTFinder_Http_DataProviderProxy extends FACTFinder_Http_DataProvider
143
  {
144
  private $id;
145
- private $master;
 
 
 
 
146
 
147
  public function register($id, FACTFinder_Http_ParallelDataProvider $master) {
148
  $this->id = $id;
@@ -152,6 +237,18 @@ class FACTFinder_Http_DataProviderProxy extends FACTFinder_Http_DataProvider
152
  public function getData() {
153
  return $this->master->getData($this->id);
154
  }
 
 
 
 
 
 
 
 
 
 
 
 
155
 
156
  public function getCurlOptions() {
157
  return $this->curlOptions;
15
  * @version $Id: DataProvider.php 25893 2010-06-29 08:19:43Z rb $
16
  * @package FACTFinder\Http
17
  */
18
+
19
  class FACTFinder_Http_ParallelDataProvider
20
  {
21
+ /**
22
+ * @var FACTFinder_Http_ParallelDataProvider
23
+ */
24
+ protected static $instance;
25
+
26
+ /**
27
+ * @var array of FACTFinder_Http_DataProviderProxy
28
+ */
29
+ protected static $dataProviders = array();
30
 
31
+ protected $data = array();
32
+ protected $httpCodes = array();
33
+ protected $curlErrnos = array();
34
+ protected $curlErrors = array();
35
 
36
  /**
37
  * singleton
41
  /**
42
  * @return FACTFinder_Abstract_DataProvider
43
  */
44
+ public static function getDataProvider(array $params = null, FACTFinder_Abstract_Configuration $config = null, $log = null) {
45
  if (self::$instance == null) {
46
  self::$instance = new FACTFinder_Http_ParallelDataProvider();
47
  }
48
+ $id = 'proxy' . count(self::$dataProviders); // use prefix so the id is a string
49
+ self::$dataProviders[$id] = new FACTFinder_Http_DataProviderProxy($params, $config, $log);
50
+ self::$dataProviders[$id]->register($id, self::$instance);
51
 
52
+ return self::$dataProviders[$id];
53
  }
54
 
55
  /**
59
  **/
60
  public static function loadAllData()
61
  {
62
+ if (self::$instance == null || count(self::$dataProviders) == 0) {
63
+ return;
64
  }
65
 
66
  // TODO: optimize:
 
67
  // - warn if several loadings were done
68
  // - add logging
69
 
70
  // init handles
71
  $multiHandle = curl_multi_init();
72
  $handles = self::initHandles($multiHandle);
73
+ self::executeHandles($multiHandle, $handles);
 
 
 
74
  }
75
 
76
  protected static function initHandles($multiHandle) {
77
  $handles = array();
78
+ foreach(self::$dataProviders AS $id => $dataProvider) {
79
+ /**
80
+ * @var $dataProvider FACTFinder_Http_DataProviderProxy
81
+ */
82
+ if(!$dataProvider->hasUrlChanged())
83
+ {
84
+ $handles[$id] = null;
85
+ continue;
86
+ }
87
+ $dataProvider->prepareRequest();
88
+
89
+ $handle = curl_init();
90
+ curl_setopt_array($handle, $dataProvider->getCurlOptions());
91
 
92
  $handles[$id] = $handle;
93
  curl_multi_add_handle($multiHandle,$handle);
115
 
116
  //close the handles
117
  $data = array();
118
+ $httpCodes = array();
119
+ $curlErrnos = array();
120
+ $curlErrors = array();
121
  foreach($handles AS $id => $handle) {
122
+ if($handle == null)
123
+ {
124
+ $data[$id] = null;
125
+ continue;
126
+ }
127
  $data[$id] = curl_multi_getcontent($handle);
128
+ $httpCodes[$id] = curl_getinfo($handle, CURLINFO_HTTP_CODE);
129
+ $curlErrnos[$id] = curl_errno($handle);
130
+ $curlErrors[$id] = curl_error($handle);
131
+
132
  curl_multi_remove_handle($multiHandle, $handle);
133
+ curl_close($handle);
134
  }
135
  curl_multi_close($multiHandle);
136
+
137
+ self::$instance->setData($data);
138
+ self::$instance->setHttpCodes($httpCodes);
139
+ self::$instance->setCurlErrnos($curlErrnos);
140
+ self::$instance->setCurlErrors($curlErrors);
141
  }
142
+
 
 
 
 
143
  protected function setData(array $data) {
144
+ foreach($data as $id => $dataItem)
145
+ {
146
+ if($dataItem == null)
147
+ continue;
148
+ $this->data[$id] = $dataItem;
149
+ }
150
  }
151
+
152
+ protected function setHttpCodes(array $httpCodes) {
153
+ foreach($httpCodes as $id => $httpCode)
154
+ {
155
+ if($httpCode == null)
156
+ continue;
157
+ $this->httpCodes[$id] = $httpCode;
158
+ }
159
+ }
160
+
161
+ protected function setCurlErrnos(array $curlErrnos) {
162
+ foreach($curlErrnos as $id => $curlErrno)
163
+ {
164
+ if($curlErrno == null)
165
+ continue;
166
+ $this->curlErrnos[$id] = $curlErrno;
167
+ }
168
+ }
169
+
170
+ protected function setCurlErrors(array $curlErrors) {
171
+ foreach($curlErrors as $id => $curlError)
172
+ {
173
+ if($curlError == null)
174
+ continue;
175
+ $this->curlErrors[$id] = $curlError;
176
+ }
177
+ }
178
 
179
  /**
180
  * this method is called by the proxy data providers on the one and only existing instance
183
  */
184
  public function getData($id)
185
  {
186
+ if (self::$dataProviders[$id]->hasUrlChanged()) {
187
+ throw new DataNotLoadedException("Implementation Error: the data is not up to date. Please use 'FACTFinder_Http_ParallelDataProvider::loadAllData' before trying to get data!");
188
  }
189
  return isset($this->data[$id]) ? $this->data[$id] : null;
190
  }
191
+
192
+ public function getLastHttpCode($id)
193
+ {
194
+ if (self::$dataProviders[$id]->hasUrlChanged()) {
195
+ throw new DataNotLoadedException("Implementation Error: the data is not up to date. Please use 'FACTFinder_Http_ParallelDataProvider::loadAllData' before trying to get data!");
196
+ }
197
+ return isset($this->httpCodes[$id]) ? $this->httpCodes[$id] : null;
198
+ }
199
+
200
+ public function getLastCurlErrno($id)
201
+ {
202
+ if (self::$dataProviders[$id]->hasUrlChanged()) {
203
+ throw new DataNotLoadedException("Implementation Error: the data is not up to date. Please use 'FACTFinder_Http_ParallelDataProvider::loadAllData' before trying to get data!");
204
+ }
205
+ return isset($this->curlErrnos[$id]) ? $this->curlErrnos[$id] : null;
206
+ }
207
+
208
+ public function getLastCurlError($id)
209
+ {
210
+ if (self::$dataProviders[$id]->hasUrlChanged()) {
211
+ throw new DataNotLoadedException("Implementation Error: the data is not up to date. Please use 'FACTFinder_Http_ParallelDataProvider::loadAllData' before trying to get data!");
212
+ }
213
+ return isset($this->curlErrors[$id]) ? $this->curlErrors[$id] : null;
214
+ }
215
  }
216
 
217
  /**
223
  class FACTFinder_Http_DataProviderProxy extends FACTFinder_Http_DataProvider
224
  {
225
  private $id;
226
+
227
+ /**
228
+ * @var FACTFinder_Http_ParallelDataProvider
229
+ */
230
+ private $master;
231
 
232
  public function register($id, FACTFinder_Http_ParallelDataProvider $master) {
233
  $this->id = $id;
237
  public function getData() {
238
  return $this->master->getData($this->id);
239
  }
240
+
241
+ public function getLastHttpCode() {
242
+ return $this->master->getLastHttpCode($this->id);
243
+ }
244
+
245
+ public function getLastCurlErrno() {
246
+ return $this->master->getLastCurlErrno($this->id);
247
+ }
248
+
249
+ public function getLastCurlError() {
250
+ return $this->master->getLastCurlError($this->id);
251
+ }
252
 
253
  public function getCurlOptions() {
254
  return $this->curlOptions;
lib/FACTFinder/Http/ScicAdapter.php CHANGED
@@ -19,9 +19,14 @@ class FACTFinder_Http_ScicAdapter extends FACTFinder_Abstract_ScicAdapter
19
  /**
20
  * init
21
  */
22
- protected function init() {
 
23
  $this->log->info("Initializing new SCIC adapter.");
24
  $this->getDataProvider()->setType('SCIC.ff');
 
 
 
 
25
  }
26
 
27
  /**
@@ -29,7 +34,7 @@ class FACTFinder_Http_ScicAdapter extends FACTFinder_Abstract_ScicAdapter
29
  *
30
  * @return boolean $success
31
  */
32
- protected function applyTracking() {
33
  $success = trim($this->getData());
34
  return $success == 'true';
35
  }
19
  /**
20
  * init
21
  */
22
+ protected function init()
23
+ {
24
  $this->log->info("Initializing new SCIC adapter.");
25
  $this->getDataProvider()->setType('SCIC.ff');
26
+ $this->getDataProvider()->setCurlOptions(array(
27
+ CURLOPT_CONNECTTIMEOUT => $this->getDataProvider()->getConfig()->getScicConnectTimeout(),
28
+ CURLOPT_TIMEOUT => $this->getDataProvider()->getConfig()->getScicTimeout()
29
+ ));
30
  }
31
 
32
  /**
34
  *
35
  * @return boolean $success
36
  */
37
+ public function applyTracking() {
38
  $success = trim($this->getData());
39
  return $success == 'true';
40
  }
lib/FACTFinder/Http/StatusHelper.php ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FACT-Finder PHP Framework
4
+ *
5
+ * @category Library
6
+ * @package FACTFinder\Http
7
+ * @copyright Copyright (c) 2012 Omikron Data Quality GmbH (www.omikron.net)
8
+ */
9
+
10
+ /**
11
+ * tries to query FACT-Finder and aggregates errors and status info from HTTP code, cURL error and FACT-Finder errors
12
+ *
13
+ * @author Martin Buettner <martin.buettner@omikron.net>
14
+ * @version $Id: StatusHelper.php 2012-09-25 16:19:43Z mb $
15
+ * @package FACTFinder\Http
16
+ *
17
+ **/
18
+ class FACTFinder_Http_StatusHelper
19
+ {
20
+ /**
21
+ * @var FACTFinder_Abstract_Configuration
22
+ */
23
+ protected $config;
24
+
25
+ /**
26
+ * @var FACTFinder_Abstract_Logger
27
+ */
28
+ protected $log;
29
+
30
+ /**
31
+ * @var FACTFinder_Http_DataProvider
32
+ */
33
+ protected $dataProvider;
34
+
35
+ /**
36
+ * @var FACTFinder_Xml65_SearchAdapter
37
+ */
38
+ protected $searchAdapter;
39
+
40
+ public function __construct(FACTFinder_Abstract_Configuration $config,
41
+ FACTFinder_Abstract_Logger $log = null,
42
+ $channel = null)
43
+ {
44
+ if(isset($log))
45
+ $this->log = $log;
46
+ else
47
+ $this->log = FF::getSingleton('nullLogger');
48
+ $this->log->info("Initializing Status Helper.");
49
+ if ($config != null) $this->config = $config;
50
+
51
+ $this->dataProvider = FACTFinder_Http_ParallelDataProvider::getDataProvider(
52
+ null,
53
+ $config,
54
+ $log
55
+ );
56
+
57
+ $encodingHandler = FF::getInstance('encodingHandler', $config);
58
+ $paramsParser = FF::getInstance('parametersParser', $config, $encodingHandler);
59
+
60
+ $this->searchAdapter = FF::getInstance(
61
+ 'xml65/searchAdapter',
62
+ $this->dataProvider,
63
+ $paramsParser,
64
+ $encodingHandler
65
+ );
66
+
67
+ if($channel !== null)
68
+ $this->searchAdapter->setParam('channel', $channel);
69
+
70
+ $this->searchAdapter->setParam('query', 'FACT-Finder Version');
71
+ $this->searchAdapter->setParam('productsPerPage', '1');
72
+ $this->searchAdapter->setParam('verbose', 'true');
73
+ }
74
+
75
+ public function getVersionNumber()
76
+ {
77
+ $resultCount = $this->searchAdapter->getResult()->getFoundRecordsCount();
78
+ return intval(substr($resultCount, 0, 2));
79
+ }
80
+
81
+ public function getVersionString()
82
+ {
83
+ $versionNumber = ''.$this->getVersionNumber();
84
+ return $versionNumber[0].'.'.$versionNumber[1];
85
+ }
86
+
87
+ public function getStatusCode()
88
+ {
89
+ try
90
+ {
91
+ $ffError = $this->searchAdapter->getError();
92
+ }
93
+ catch(Exception $e)
94
+ {
95
+ $ffError = $e->getMessage();
96
+ }
97
+
98
+ $curlErrno = $this->dataProvider->getLastCurlErrno();
99
+
100
+ switch($curlErrno)
101
+ {
102
+ case 0: // no cURL error!
103
+ break;
104
+ default:
105
+ return FFE_CURL_ERROR + $this->dataProvider->getLastCurlError();
106
+ }
107
+
108
+ // cURL was able to connect to the server, check HTTP Code next
109
+
110
+ $httpCode = intval($this->dataProvider->getLastHttpCode());
111
+
112
+ switch($httpCode)
113
+ {
114
+ case 200: // success!
115
+ return FFE_OK;
116
+ case 500: // server error, check error output
117
+ break;
118
+ default:
119
+ return FFE_HTTP_ERROR + $httpCode;
120
+ }
121
+
122
+ $stackTrace = $this->searchAdapter->getStackTrace();
123
+ preg_match('/^(.+?):?\s/', $stackTrace, $matches);
124
+ $ffException = $matches[1];
125
+
126
+ switch($ffException)
127
+ {
128
+ case 'de.factfinder.security.exception.ChannelDoesNotExistException':
129
+ return FFE_CHANNEL_DOES_NOT_EXIST;
130
+ case 'de.factfinder.security.exception.WrongUserPasswordException':
131
+ return FFE_WRONG_CREDENTIALS;
132
+ case 'de.factfinder.security.exception.PasswordExpiredException':
133
+ return FFE_SERVER_TIME_MISMATCH;
134
+ case 'de.factfinder.jni.FactFinderException':
135
+ default:
136
+ return FFE_FACT_FINDER_ERROR;
137
+ }
138
+ }
139
+ }
140
+
141
+ // Possible status/error codes
142
+
143
+ define('FFE_OK', 16180000);
144
+
145
+ define('FFE_CURL_ERROR', 16181000); // add the result of curl_errno() to this
146
+
147
+ define('FFE_HTTP_ERROR', 16182000); // add the HTTP code to this
148
+ define('FFE_WRONG_CONTEXT', 16182404); //
149
+
150
+ define('FFE_FACT_FINDER_ERROR', 16183000); // unspecified exception from FF; contact support
151
+ define('FFE_CHANNEL_DOES_NOT_EXIST', 16183001);
152
+ define('FFE_WRONG_CREDENTIALS', 16183002);
153
+ define('FFE_SERVER_TIME_MISMATCH', 16183003); // server time is not consistent with FF's server time
lib/FACTFinder/Http/SuggestAdapter.php CHANGED
@@ -24,8 +24,8 @@ class FACTFinder_Http_SuggestAdapter extends FACTFinder_Abstract_SuggestAdapter
24
  $this->log->info("Initializing new suggest adapter.");
25
  $this->getDataProvider()->setType('Suggest.ff');
26
  $this->getDataProvider()->setCurlOptions(array(
27
- CURLOPT_CONNECTTIMEOUT => 1,
28
- CURLOPT_TIMEOUT => 2
29
  ));
30
  }
31
 
24
  $this->log->info("Initializing new suggest adapter.");
25
  $this->getDataProvider()->setType('Suggest.ff');
26
  $this->getDataProvider()->setCurlOptions(array(
27
+ CURLOPT_CONNECTTIMEOUT => $this->getDataProvider()->getConfig()->getSuggestConnectTimeout(),
28
+ CURLOPT_TIMEOUT => $this->getDataProvider()->getConfig()->getSuggestTimeout()
29
  ));
30
  }
31
 
lib/FACTFinder/Http/UrlBuilder.php ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FACT-Finder PHP Framework
4
+ *
5
+ * @category Library
6
+ * @package FACTFinder\Http
7
+ * @copyright Copyright (c) 2012 Omikron Data Quality GmbH (www.omikron.net)
8
+ */
9
+
10
+ /**
11
+ * assembles URLs for different kinds of authentication from params and config
12
+ *
13
+ * @author Martin Buettner <martin.buettner@omikron.net>
14
+ * @version $Id: UrlBuilder.php 2012-09-17 16:19:43Z mb $
15
+ * @package FACTFinder\Http
16
+ *
17
+ **/
18
+ class FACTFinder_Http_UrlBuilder
19
+ {
20
+ protected $params = array();
21
+ protected $config = array();
22
+ protected $action;
23
+
24
+ protected $log;
25
+
26
+
27
+ public function __construct(array $params = null, FACTFinder_Abstract_Configuration $config = null,
28
+ FACTFinder_Abstract_Logger $log = null)
29
+ {
30
+ if(isset($log))
31
+ $this->log = $log;
32
+ else
33
+ $this->log = FF::getSingleton('nullLogger');
34
+ $this->log->info("Initializing URL Builder.");
35
+ if ($params != null) $this->params = $params;
36
+ if ($config != null) $this->config = $config;
37
+ }
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
+ * unset single param
64
+ *
65
+ * @param string name
66
+ * @return void
67
+ **/
68
+ public function unsetParam($name)
69
+ {
70
+ unset($this->params[$name]);
71
+ }
72
+
73
+ /**
74
+ * set single param with multiple values
75
+ *
76
+ * @param string name
77
+ * @param array of strings values
78
+ * @return void
79
+ **/
80
+ public function setArrayParam($name, $values)
81
+ {
82
+ $this->params[$name] = $values;
83
+ }
84
+
85
+ public function setAction($action)
86
+ {
87
+ $this->action = $action;
88
+ }
89
+
90
+ public function getAction()
91
+ {
92
+ return $this->action;
93
+ }
94
+
95
+ /**
96
+ * @return array
97
+ **/
98
+ public function getParams()
99
+ {
100
+ return $this->params;
101
+ }
102
+
103
+ /**
104
+ * get url with advanced authentication encryption
105
+ *
106
+ * @return string url
107
+ */
108
+ public function getAdvancedAuthenticationUrl() {
109
+ $config = $this->config;
110
+ $params = $this->params;
111
+
112
+ $channel = $this->getChannel($params, $config);
113
+ if ($channel != '') {
114
+ $params['channel'] = $channel;
115
+ }
116
+
117
+ $ts = time() . '000'; //milliseconds needed
118
+ $prefix = $config->getAdvancedAuthPrefix();
119
+ $postfix = $config->getAdvancedAuthPostfix();
120
+ $authParams = "timestamp=$ts&username=".$config->getAuthUser()
121
+ . '&password=' . md5($prefix . $ts . md5($config->getAuthPasswort()) . $postfix);
122
+
123
+ $url = $config->getRequestProtocol() . '://'
124
+ . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
125
+ . $config->getContext() . '/'.$this->action.'?' . http_build_query($params, '', '&')
126
+ . (count($params)?'&':'') . $authParams;
127
+
128
+ // The following line removes all []-indices from array parameters, because tomcat doesn't need them
129
+ $url = preg_replace("/%5B[A-Za-z0-9]*%5D/", "", $url);
130
+ $this->log->info("Request Url: ".$url);
131
+ return $url;
132
+ }
133
+
134
+ /**
135
+ * get url with simple authentication encryption
136
+ *
137
+ * @return string url
138
+ */
139
+ public function getSimpleAuthenticationUrl() {
140
+ $config = $this->config;
141
+ $params = $this->params;
142
+
143
+ $channel = $this->getChannel($params, $config);
144
+ if ($channel != '') {
145
+ $params['channel'] = $channel;
146
+ }
147
+
148
+ $ts = time() . '000'; //milliseconds needed but won't be considered
149
+ $authParams = "timestamp=$ts&username=".$config->getAuthUser()
150
+ . '&password=' . md5($config->getAuthPasswort());
151
+
152
+ $url = $config->getRequestProtocol() . '://'
153
+ . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
154
+ . $config->getContext() . '/'.$this->action.'?' . http_build_query($params, '', '&')
155
+ . (count($params)?'&':'') . $authParams;
156
+
157
+ // The following line removes all []-indices from array parameters, because tomcat doesn't need them
158
+ $url = preg_replace("/%5B[A-Za-z0-9]*%5D/", "", $url);
159
+ $this->log->info("Request Url: ".$url);
160
+ return $url;
161
+ }
162
+
163
+ /**
164
+ * get url with http authentication
165
+ *
166
+ * @return string url
167
+ */
168
+ public function getHttpAuthenticationUrl() {
169
+ $config = $this->config;
170
+ $params = $this->params;
171
+
172
+ $channel = $this->getChannel($params, $config);
173
+ if ($channel != '') {
174
+ $params['channel'] = $channel;
175
+ }
176
+
177
+ $auth = $config->getAuthUser() . ':' . $config->getAuthPasswort() . '@';
178
+ if ($auth == ':@') $auth = '';
179
+
180
+ $url = $config->getRequestProtocol() . '://' . $auth
181
+ . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
182
+ . $config->getContext() . '/' . $this->action . (count($params)?'?':'')
183
+ . http_build_query($params, '', '&');
184
+
185
+ // The following line removes all []-indices from array parameters, because tomcat doesn't need them
186
+ $url = preg_replace("/%5B[A-Za-z0-9]*%5D/", "", $url);
187
+ $this->log->info("Request Url: ".$url);
188
+ return $url;
189
+ }
190
+
191
+ /**
192
+ * get url with no authentication.
193
+ *
194
+ * @return string url
195
+ */
196
+ public function getNonAuthenticationUrl() {
197
+ $config = $this->config;
198
+ $params = $this->params;
199
+
200
+ $channel = $this->getChannel($params, $config);
201
+ if ($channel != '') {
202
+ $params['channel'] = $channel;
203
+ }
204
+
205
+ $url = $config->getRequestProtocol() . '://'
206
+ . $config->getServerAddress() . ':' . $config->getServerPort() . '/'
207
+ . $config->getContext() . '/' . $this->action . (count($params)?'?':'')
208
+ . http_build_query($params, '', '&');
209
+
210
+ // The following line removes all []-indices from array parameters, because tomcat doesn't need them
211
+ $url = preg_replace("/%5B[A-Za-z0-9]*%5D/", "", $url);
212
+ // Include the following line only for debugging purposes
213
+ // This method is called quite often for several checking tasks
214
+ //$this->log->info("Request Url: ".$url);
215
+ return $url;
216
+ }
217
+
218
+ /**
219
+ * get channel from params or config (params override config)
220
+ *
221
+ * @param array $params
222
+ * @param FACTFinder_Abstract_Configuration $config
223
+ * @return string channel
224
+ */
225
+ protected function getChannel($params, $config) {
226
+ $channel = '';
227
+ if (isset($params['channel']) && strlen($params['channel']) > 0) {
228
+ $channel = $params['channel'];
229
+ } else if($config->getChannel() != '') {
230
+ $channel = $config->getChannel();
231
+ }
232
+ return $channel;
233
+ }
234
+ }
lib/FACTFinder/ProductsPerPageOptions.php CHANGED
@@ -31,17 +31,37 @@ class FACTFinder_ProductsPerPageOptions implements IteratorAggregate
31
  $selectedOption = intval($selectedOption);
32
 
33
  $this->options = new ArrayIterator();
34
- foreach($options AS $option => $url) {
35
- $item = FF::getInstance('item', intval($option), $url, ($option == $selectedOption));
36
- if ($option == $selectedOption) {
37
- $this->selectedOption = $item;
38
- }
39
- if ($option == $defaultOption) {
40
- $this->defaultOption = $item;
41
- }
42
- $this->options->append($item);
43
- }
44
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  if ($this->defaultOption == null && $this->options->count() > 0) {
46
  $this->defaultOption = $this->options[0];
47
  }
31
  $selectedOption = intval($selectedOption);
32
 
33
  $this->options = new ArrayIterator();
34
+
35
+ if(!empty($options))
36
+ {
37
+ foreach($options AS $option => $url) {
38
+ $item = FF::getInstance('item', intval($option), $url, ($option == $selectedOption));
39
+ if ($option == $selectedOption) {
40
+ $this->selectedOption = $item;
41
+ }
42
+ if ($option == $defaultOption) {
43
+ $this->defaultOption = $item;
44
+ }
45
+ $this->options->append($item);
46
+ }
47
+ }
48
+ else // FF 6.7 may occasionally return stripped down results
49
+ {
50
+ $defaultItem = FF::getInstance('item', $defaultOption, $defaultOption == $selectedOption);
51
+ $this->defaultOption = $defaultItem;
52
+ $this->options->append($defaultItem);
53
+ if($defaultOption == $selectedOption)
54
+ {
55
+ $this->selectedOption = $defaultItem;
56
+ }
57
+ else
58
+ {
59
+ $selectedItem = FF::getInstance('item', $selectedOption, true);
60
+ $this->selectedOption = $selectedItem;
61
+ $this->options->append($selectedItem);
62
+ }
63
+ }
64
+
65
  if ($this->defaultOption == null && $this->options->count() > 0) {
66
  $this->defaultOption = $this->options[0];
67
  }
lib/FACTFinder/Xml65/ImportAdapter.php CHANGED
@@ -45,8 +45,8 @@ class FACTFinder_Xml65_ImportAdapter extends FACTFinder_Abstract_ImportAdapter
45
  protected function triggerImport($download, $type = 'data')
46
  {
47
  $this->getDataProvider()->setCurlOptions(array(
48
- CURLOPT_CONNECTTIMEOUT => 10,
49
- CURLOPT_TIMEOUT => 360
50
  ));
51
 
52
  $this->getDataProvider()->setParam('download', $download ? 'true' : 'false');
45
  protected function triggerImport($download, $type = 'data')
46
  {
47
  $this->getDataProvider()->setCurlOptions(array(
48
+ CURLOPT_CONNECTTIMEOUT => $this->getDataProvider()->getConfig()->getImportConnectTimeout(),
49
+ CURLOPT_TIMEOUT => $this->getDataProvider()->getConfig()->getImportTimeout()
50
  ));
51
 
52
  $this->getDataProvider()->setParam('download', $download ? 'true' : 'false');
lib/FACTFinder/Xml65/SearchAdapter.php CHANGED
@@ -105,7 +105,7 @@ class FACTFinder_Xml65_SearchAdapter extends FACTFinder_Abstract_SearchAdapter
105
  }
106
 
107
  /**
108
- * returns true if the search-process was aborted because of an timeout
109
  *
110
  * @return boolean true if search timed out
111
  **/
@@ -221,13 +221,18 @@ class FACTFinder_Xml65_SearchAdapter extends FACTFinder_Abstract_SearchAdapter
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
@@ -477,4 +482,19 @@ class FACTFinder_Xml65_SearchAdapter extends FACTFinder_Abstract_SearchAdapter
477
  }
478
  return $error;
479
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  }
105
  }
106
 
107
  /**
108
+ * returns true if the search-process was aborted because of a timeout
109
  *
110
  * @return boolean true if search timed out
111
  **/
221
  if (isset($xmlGroup->attributes()->unit)) {
222
  $groupUnit = strval($xmlGroup->attributes()->unit);
223
  }
224
+
225
+ $groupStyle = 'DEFAULT';
226
+ if (isset($xmlGroup->attributes()->style)) {
227
+ $groupStyle = strval($xmlGroup->attributes()->style);
228
+ }
229
 
230
  $group = FF::getInstance('asnGroup',
231
  array(),
232
  $encodingHandler->encodeServerContentForPage((string)$xmlGroup->attributes()->name),
233
  $encodingHandler->encodeServerContentForPage((string)$xmlGroup->attributes()->detailedLinks),
234
  $groupUnit,
235
+ $groupStyle
236
  );
237
 
238
  //get filters of the current group
482
  }
483
  return $error;
484
  }
485
+
486
+ /**
487
+ * get stacktrace if there is one
488
+ *
489
+ * @return string if stacktrace exists, else null
490
+ */
491
+ public function getStackTrace()
492
+ {
493
+ $stackTrace = null;
494
+ $xmlResult = $this->getData();
495
+ if (!empty($xmlResult->stacktrace)) {
496
+ $stackTrace = trim(strval($xmlResult->stacktrace));
497
+ }
498
+ return $stackTrace;
499
+ }
500
  }
lib/FACTFinder/Xml65/SuggestAdapter.php CHANGED
@@ -44,7 +44,7 @@ class FACTFinder_Xml65_SuggestAdapter extends FACTFinder_Http_SuggestAdapter
44
  */
45
  protected function createSuggestions()
46
  {
47
- $xmlResult = $this->getData();
48
  $encodingHandler = $this->getEncodingHandler();
49
  $paramsParser = $this->getParamsParser();
50
  $suggest = array();
44
  */
45
  protected function createSuggestions()
46
  {
47
+ $xmlResult = parent::createSuggestions();
48
  $encodingHandler = $this->getEncodingHandler();
49
  $paramsParser = $this->getParamsParser();
50
  $suggest = array();
lib/FACTFinder/Xml65/TagCloudAdapter.php CHANGED
@@ -24,6 +24,7 @@ class FACTFinder_Xml65_TagCloudAdapter extends FACTFinder_Abstract_TagCloudAdapt
24
  $this->log->info("Initializing new tag cloud adapter.");
25
  $this->getDataProvider()->setType('WhatsHot.ff');
26
  $this->getDataProvider()->setParam('do', 'getTagCloud');
 
27
  }
28
 
29
  /**
24
  $this->log->info("Initializing new tag cloud adapter.");
25
  $this->getDataProvider()->setType('WhatsHot.ff');
26
  $this->getDataProvider()->setParam('do', 'getTagCloud');
27
+ $this->getDataProvider()->setParam('format', 'xml');
28
  }
29
 
30
  /**
lib/FACTFinder/Xml67/SearchAdapter.php CHANGED
@@ -15,7 +15,7 @@
15
  * @package FACTFinder\Xml67
16
  */
17
  class FACTFinder_Xml67_SearchAdapter extends FACTFinder_Xml66_SearchAdapter
18
- {
19
  /**
20
  * @return array of FACTFinder_Campaign objects
21
  */
15
  * @package FACTFinder\Xml67
16
  */
17
  class FACTFinder_Xml67_SearchAdapter extends FACTFinder_Xml66_SearchAdapter
18
+ {
19
  /**
20
  * @return array of FACTFinder_Campaign objects
21
  */
lib/FACTFinder/Xml68/CompareAdapter.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FACT-Finder PHP Framework
4
+ *
5
+ * @category Library
6
+ * @package FACTFinder\Xml67
7
+ * @copyright Copyright (c) 2012 Omikron Data Quality GmbH (www.omikron.net)
8
+ */
9
+
10
+ /**
11
+ * product comparison adapter using the xml interface
12
+ *
13
+ * @author Rudolf Batt <rb@omikron.net>
14
+ * @version $Id: CompareAdapter.php 25893 2010-06-29 08:19:43Z rb $
15
+ * @package FACTFinder\Xml68
16
+ */
17
+ class FACTFinder_Xml68_CompareAdapter extends FACTFinder_Xml67_CompareAdapter
18
+ {
19
+ }
lib/FACTFinder/Xml68/ImportAdapter.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FACT-Finder PHP Framework
4
+ *
5
+ * @category Library
6
+ * @package FACTFinder\Xml67
7
+ * @copyright Copyright (c) 2012 Omikron Data Quality GmbH (www.omikron.net)
8
+ */
9
+
10
+ /**
11
+ * import adapter using the xml interface
12
+ *
13
+ * @author Rudolf Batt <rb@omikron.net>
14
+ * @version $Id: ImportAdapter.php 25893 2010-06-29 08:19:43Z rb $
15
+ * @package FACTFinder\Xml68
16
+ */
17
+ class FACTFinder_Xml68_ImportAdapter extends FACTFinder_Xml67_ImportAdapter
18
+ {
19
+ }
lib/FACTFinder/Xml68/ProductCampaignAdapter.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FACT-Finder PHP Framework
4
+ *
5
+ * @category Library
6
+ * @package FACTFinder\Xml67
7
+ * @copyright Copyright (c) 2012 Omikron Data Quality GmbH (www.omikron.net)
8
+ */
9
+
10
+ /**
11
+ * product campaign adapter using the xml interface
12
+ *
13
+ * @author Rudolf Batt <rb@omikron.net>, Martin Buettner <martin.buettner@omikron.net>
14
+ * @version $Id: ProductCampaignAdapter.php 43440 2012-02-08 12:42:13Z martin.buettner $
15
+ * @package FACTFinder\Xml68
16
+ */
17
+ class FACTFinder_Xml68_ProductCampaignAdapter extends FACTFinder_Xml67_ProductCampaignAdapter
18
+ {
19
+ }
20
+
lib/FACTFinder/Xml68/RecommendationAdapter.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FACT-Finder PHP Framework
4
+ *
5
+ * @category Library
6
+ * @package FACTFinder\Xml67
7
+ * @copyright Copyright (c) 2012 Omikron Data Quality GmbH (www.omikron.net)
8
+ */
9
+
10
+ /**
11
+ * adapter for the factfinder recommendation engine, working with the XML interface of FF6.7
12
+ *
13
+ * @author Rudolf Batt <rb@omikron.net>
14
+ * @version $Id$
15
+ * @package FACTFinder\Xml68
16
+ */
17
+ class FACTFinder_Xml68_RecommendationAdapter extends FACTFinder_Xml67_RecommendationAdapter
18
+ {
19
+ }
lib/FACTFinder/Xml68/SearchAdapter.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FACT-Finder PHP Framework
4
+ *
5
+ * @category Library
6
+ * @package FACTFinder\Xml67
7
+ * @copyright Copyright (c) 2012 Omikron Data Quality GmbH (www.omikron.net)
8
+ */
9
+
10
+ /**
11
+ * search adapter using the xml interface. expects a xml formated string from the dataprovider
12
+ *
13
+ * @author Rudolf Batt <rb@omikron.net>
14
+ * @version $Id: SearchAdapter.php 25985 2010-06-30 15:31:53Z rb $
15
+ * @package FACTFinder\Xml68
16
+ */
17
+ class FACTFinder_Xml68_SearchAdapter extends FACTFinder_Xml67_SearchAdapter
18
+ {
19
+ }
lib/FACTFinder/Xml68/SimilarRecordsAdapter.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FACT-Finder PHP Framework
4
+ *
5
+ * @category Library
6
+ * @package FACTFinder\Xml67
7
+ * @copyright Copyright (c) 2012 Omikron Data Quality GmbH (www.omikron.net)
8
+ */
9
+
10
+ /**
11
+ * similar records adapter using the xml interface
12
+ *
13
+ * @author Rudolf Batt <rb@omikron.net>
14
+ * @version $Id: SimilarRecordsAdapter.php 25893 2010-06-29 08:19:43Z rb $
15
+ * @package FACTFinder\Xml68
16
+ */
17
+ class FACTFinder_Xml68_SimilarRecordsAdapter extends FACTFinder_Xml67_SimilarRecordsAdapter
18
+ {
19
+ }
lib/FACTFinder/Xml68/SuggestAdapter.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FACT-Finder PHP Framework
4
+ *
5
+ * @category Library
6
+ * @package FACTFinder\Xml67
7
+ * @copyright Copyright (c) 2012 Omikron Data Quality GmbH (www.omikron.net)
8
+ */
9
+
10
+ /**
11
+ * suggest adapter using the xml interface. expects a xml formated string from the dataprovider
12
+ *
13
+ * @author Rudolf Batt <rb@omikron.net>
14
+ * @version $Id: SuggestAdapter.php 25893 2010-06-29 08:19:43Z rb $
15
+ * @package FACTFinder\Xml68
16
+ */
17
+ class FACTFinder_Xml68_SuggestAdapter extends FACTFinder_Xml67_SuggestAdapter
18
+ {
19
+ //TODO: support new Suggest features
20
+ }
lib/FACTFinder/Xml68/TagCloudAdapter.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FACT-Finder PHP Framework
4
+ *
5
+ * @category Library
6
+ * @package FACTFinder\Xml67
7
+ * @copyright Copyright (c) 2012 Omikron Data Quality GmbH (www.omikron.net)
8
+ */
9
+
10
+ /**
11
+ * tag cloud adapter using the xml interface
12
+ *
13
+ * @author Rudolf Batt <rb@omikron.net>
14
+ * @version $Id: TagCloudAdapter.php 25893 2010-06-29 08:19:43Z rb $
15
+ * @package FACTFinder\Xml68
16
+ */
17
+ class FACTFinder_Xml68_TagCloudAdapter extends FACTFinder_Xml67_TagCloudAdapter
18
+ {
19
+ }
lib/FACTFinderCustom/Configuration.php CHANGED
@@ -11,24 +11,26 @@ class FACTFinderCustom_Configuration implements FACTFinder_Abstract_Configuratio
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
  private $storeId = null;
 
 
 
 
25
 
26
  public function __construct($config = null)
27
  {
28
  $this->config = new Varien_Object($config);
29
  if(is_array($config)){
30
  $this->config->setData($config);
31
- }
 
 
32
  }
33
 
34
  /**
@@ -53,7 +55,7 @@ class FACTFinderCustom_Configuration implements FACTFinder_Abstract_Configuratio
53
  {
54
  if(!$this->config->hasData($name)){
55
  try{
56
- $this->config->setData($name, Mage::getStoreConfig(self::XML_CONFIG_PATH.$name, $this->storeId));
57
  }catch (Exception $e){
58
  $this->config->setData($name, null);
59
  }
@@ -113,6 +115,13 @@ class FACTFinderCustom_Configuration implements FACTFinder_Abstract_Configuratio
113
  public function getContext() {
114
  return $this->getCustomValue('context');
115
  }
 
 
 
 
 
 
 
116
 
117
  /**
118
  * @return string
@@ -120,6 +129,18 @@ class FACTFinderCustom_Configuration implements FACTFinder_Abstract_Configuratio
120
  public function getChannel() {
121
  return $this->getCustomValue('channel');
122
  }
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
  /**
125
  * @return string
@@ -248,6 +269,86 @@ class FACTFinderCustom_Configuration implements FACTFinder_Abstract_Configuratio
248
  function getRequiredServerParams(){
249
  return array();
250
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
 
252
 
253
  /**
@@ -294,4 +395,41 @@ class FACTFinderCustom_Configuration implements FACTFinder_Abstract_Configuratio
294
 
295
  return $this;
296
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  }
11
  const HTTP_AUTH = 'http';
12
  const SIMPLE_AUTH = 'simple';
13
  const ADVANCED_AUTH = 'advanced';
14
+ const XML_CONFIG_PATH = 'factfinder/search';
15
+ const DEFAULT_SEMAPHORE_TIMEOUT = 7200; // 60 seconds = 2 hours
16
 
17
  private $config;
18
  private $authType;
19
+ private $secondaryChannels;
 
 
 
 
 
20
  private $storeId = null;
21
+ private $semaphoreTimeout = self::DEFAULT_SEMAPHORE_TIMEOUT;
22
+
23
+ // Should the search adapters retrieve only product ids? (otherwise, full records will be requested)
24
+ private $idsOnly = true;
25
 
26
  public function __construct($config = null)
27
  {
28
  $this->config = new Varien_Object($config);
29
  if(is_array($config)){
30
  $this->config->setData($config);
31
+ } else {
32
+ $this->config->setData(Mage::getStoreConfig(self::XML_CONFIG_PATH));
33
+ }
34
  }
35
 
36
  /**
55
  {
56
  if(!$this->config->hasData($name)){
57
  try{
58
+ $this->config->setData($name, Mage::getStoreConfig(self::XML_CONFIG_PATH.'/'.$name, $this->storeId));
59
  }catch (Exception $e){
60
  $this->config->setData($name, null);
61
  }
115
  public function getContext() {
116
  return $this->getCustomValue('context');
117
  }
118
+
119
+ /**
120
+ * @return string
121
+ **/
122
+ public function getFactFinderVersion() {
123
+ return $this->getCustomValue('ffversion');
124
+ }
125
 
126
  /**
127
  * @return string
129
  public function getChannel() {
130
  return $this->getCustomValue('channel');
131
  }
132
+
133
+ /**
134
+ * @return array of strings
135
+ **/
136
+ public function getSecondaryChannels() {
137
+ if($this->secondaryChannels == null)
138
+ {
139
+ // array_filter() is used to remove empty channel names
140
+ $this->secondaryChannels = array_filter(explode(';', $this->getCustomValue('secondary_channels')));
141
+ }
142
+ return $this->secondaryChannels;
143
+ }
144
 
145
  /**
146
  * @return string
269
  function getRequiredServerParams(){
270
  return array();
271
  }
272
+
273
+ /**
274
+ * {@inheritdoc}
275
+ *
276
+ * @return string
277
+ **/
278
+
279
+ function getDefaultConnectTimeout() {
280
+ return 2;
281
+ }
282
+
283
+ /**
284
+ * {@inheritdoc}
285
+ *
286
+ * @return string
287
+ **/
288
+
289
+ function getDefaultTimeout() {
290
+ return 4;
291
+ }
292
+
293
+ /**
294
+ * {@inheritdoc}
295
+ *
296
+ * @return string
297
+ **/
298
+
299
+ function getSuggestConnectTimeout() {
300
+ return 1;
301
+ }
302
+
303
+ /**
304
+ * {@inheritdoc}
305
+ *
306
+ * @return string
307
+ **/
308
+
309
+ function getSuggestTimeout() {
310
+ return 2;
311
+ }
312
+
313
+ /**
314
+ * {@inheritdoc}
315
+ *
316
+ * @return string
317
+ **/
318
+
319
+ function getScicConnectTimeout() {
320
+ return 1;
321
+ }
322
+
323
+ /**
324
+ * {@inheritdoc}
325
+ *
326
+ * @return string
327
+ **/
328
+
329
+ function getScicTimeout() {
330
+ return 1;
331
+ }
332
+
333
+ /**
334
+ * {@inheritdoc}
335
+ *
336
+ * @return string
337
+ **/
338
+
339
+ function getImportConnectTimeout() {
340
+ return 10;
341
+ }
342
+
343
+ /**
344
+ * {@inheritdoc}
345
+ *
346
+ * @return string
347
+ **/
348
+
349
+ function getImportTimeout() {
350
+ return 360;
351
+ }
352
 
353
 
354
  /**
395
 
396
  return $this;
397
  }
398
+
399
+ /**
400
+ * Sets the idsOnly flag, which determines whether product ids or full records should be requested by the search adapters.
401
+ * Request only products ids if true, full records otherwise
402
+ *
403
+ * @param bool value
404
+ **/
405
+ public function setIdsOnly($value) {
406
+ $this->idsOnly = $value;
407
+ }
408
+
409
+ /**
410
+ * Gets the idsOnly flag, which determines whether product ids or full records should be requested by the search adapters
411
+ *
412
+ * @return bool
413
+ **/
414
+ public function getIdsOnly() {
415
+ return $this->idsOnly;
416
+ }
417
+
418
+ /**
419
+ * Sets the time span in seconds after which semaphores expire
420
+ *
421
+ * @param int value in seconds
422
+ **/
423
+ public function setSemaphoreTimeout($valueInSeconds) {
424
+ $this->semaphoreTimeout = $valueInSeconds;
425
+ }
426
+
427
+ /**
428
+ * Gets the time span in seconds after which semaphores expire
429
+ *
430
+ * @return int
431
+ **/
432
+ public function getSemaphoreTimeout() {
433
+ return $this->semaphoreTimeout;
434
+ }
435
  }
lib/SAI/Curl.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Implements the cURL interface by simply delegating calls to the built-in cURL functions..
4
+ * See http://www.php.net/manual/en/book.curl.php
5
+ **/
6
+
7
+ class SAI_Curl
8
+ implements SAI_CurlInterface
9
+ {
10
+
11
+ public function curl_close($ch)
12
+ {
13
+ curl_close($ch);
14
+ }
15
+
16
+ public function curl_copy_handle($ch)
17
+ {
18
+ return curl_copy_handle($ch);
19
+ }
20
+
21
+ public function curl_errno($ch)
22
+ {
23
+ return curl_errno($ch);
24
+ }
25
+
26
+ public function curl_error($ch)
27
+ {
28
+ return curl_error($ch);
29
+ }
30
+
31
+ public function curl_exec($ch)
32
+ {
33
+ return curl_exec($ch);
34
+ }
35
+
36
+ public function curl_getinfo($ch, $opt = 0)
37
+ {
38
+ return curl_getinfo($ch, $opt);
39
+ }
40
+
41
+ public function curl_init($url = null)
42
+ {
43
+ return curl_init($url);
44
+ }
45
+
46
+ public function curl_multi_add_handle($mh, $ch)
47
+ {
48
+ return curl_multi_add_handle($mh, $ch);
49
+ }
50
+
51
+ public function curl_multi_close($mh)
52
+ {
53
+ curl_multi_close($mh);
54
+ }
55
+
56
+ public function curl_multi_exec($mh, &$still_running)
57
+ {
58
+ return curl_multi_exec($mh, $still_running);
59
+ }
60
+
61
+ public function curl_multi_getcontent($ch)
62
+ {
63
+ return curl_multi_getcontent($ch);
64
+ }
65
+
66
+ public function curl_multi_info_read($mh, &$msgs_in_queue = null)
67
+ {
68
+ return curl_multi_info_read($mh, $msgs_in_queue);
69
+ }
70
+
71
+ public function curl_multi_init()
72
+ {
73
+ return curl_multi_init();
74
+ }
75
+
76
+ public function curl_multi_remove_handle($mh, $ch)
77
+ {
78
+ return curl_multi_remove_handle($mh, $ch);
79
+ }
80
+
81
+ public function curl_multi_select($mh, $timeout = 1.0)
82
+ {
83
+ return curl_multi_select($mh, $timeout);
84
+ }
85
+
86
+ public function curl_setopt_array($ch, $options)
87
+ {
88
+ return curl_setopt_array($ch, $options);
89
+ }
90
+
91
+ public function curl_setopt($ch, $option, $value)
92
+ {
93
+ return curl_setopt($ch, $option, $value);
94
+ }
95
+
96
+ public function curl_version($age = CURLVERSION_NOW)
97
+ {
98
+ return curl_version($age);
99
+ }
100
+ }
lib/SAI/Curl/Handle.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Struct-like class that represents all data associated with one curl handle
4
+ **/
5
+ class SAI_Curl_Handle
6
+ {
7
+ public $options;
8
+ }
lib/SAI/CurlInterface.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Interface for PHP cURL functions.
4
+ **/
5
+ interface SAI_CurlInterface
6
+ {
7
+ public function curl_close($ch);
8
+ public function curl_copy_handle($ch);
9
+ public function curl_errno($ch);
10
+ public function curl_error($ch);
11
+ public function curl_exec($ch);
12
+ public function curl_getinfo($ch, $opt = 0);
13
+ public function curl_init($url = null);
14
+ public function curl_multi_add_handle($mh, $ch);
15
+ public function curl_multi_close($mh);
16
+ public function curl_multi_exec($mh, &$still_running);
17
+ public function curl_multi_getcontent($ch);
18
+ public function curl_multi_info_read($mh, &$msgs_in_queue = null);
19
+ public function curl_multi_init();
20
+ public function curl_multi_remove_handle($mh, $ch);
21
+ public function curl_multi_select($mh, $timeout = 1.0);
22
+ public function curl_setopt_array($ch, $options);
23
+ public function curl_setopt($ch, $option, $value);
24
+ public function curl_version($age = CURLVERSION_NOW);
25
+ }
lib/SAI/CurlStub.php ADDED
@@ -0,0 +1,382 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stubs the cURL interface without issuing any PHP requests.
4
+ **/
5
+
6
+ require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'CurlInterface.php';
7
+ require_once 'Curl/Handle.php';
8
+
9
+ class SAI_CurlStub
10
+ implements SAI_CurlInterface
11
+ {
12
+ private $_lastHandle = -1;
13
+
14
+ private $_mapOptionCounts = array();
15
+ private $_mapOptions = array();
16
+ private $_mapResponses = array();
17
+ private $_mapErrorCodes = array();
18
+ private $_mapInfo = array();
19
+
20
+ /**
21
+ * @var array of SAI_Curl_Handle
22
+ */
23
+ private $_handles = array();
24
+
25
+ public function curl_close($ch)
26
+ {
27
+ unset($this->_handles[$ch]);
28
+ }
29
+
30
+ public function curl_copy_handle($ch)
31
+ {
32
+ $newCh = ++$this->_lastHandle;
33
+
34
+ $handle = clone $this->_handles[$ch];
35
+
36
+ $this->_handles[$newCh] = $handle;
37
+
38
+ return $newCh;
39
+ }
40
+
41
+ public function curl_errno($ch)
42
+ {
43
+ if(!isset($this->_handles[$ch]))
44
+ return 0;
45
+
46
+ return $this->_getErrorCode($this->_handles[$ch]);
47
+ }
48
+
49
+ public function curl_error($ch)
50
+ {
51
+ $errno = $this->curl_errno($ch);
52
+ return SAI_CurlStub::$errorLookup[$errno];
53
+ }
54
+
55
+ public function curl_exec($ch)
56
+ {
57
+ if(!isset($this->_handles[$ch]))
58
+ return false;
59
+
60
+ /**
61
+ * @var $handle SAI_Curl_Handle
62
+ */
63
+ $handle = $this->_handles[$ch];
64
+
65
+ $response = $this->_getResponse($handle);
66
+
67
+ if($response === null)
68
+ return false;
69
+
70
+ if($handle->options[CURLOPT_RETURNTRANSFER])
71
+ return $response;
72
+
73
+ echo $response;
74
+ return true;
75
+ }
76
+
77
+ public function curl_getinfo($ch, $opt = 0)
78
+ {
79
+ // TODO: Include logic to build CURLINFO_EFFECTIVE_URL?
80
+ if(!isset($this->_handles[$ch]))
81
+ trigger_error(__FUNCTION__.'(): '.$ch.' is not a valid cURL handle resource', E_USER_WARNING);
82
+
83
+ if($opt == 0)
84
+ return $this->_getInfoArray($this->_handles[$ch]);
85
+
86
+ return $this->_getInfo($this->_handles[$ch], $opt);
87
+ }
88
+
89
+ public function curl_init($url = null)
90
+ {
91
+ $ch = ++$this->_lastHandle;
92
+
93
+ $handle = new SAI_Curl_Handle();
94
+
95
+ $handle->options = array(
96
+ CURLOPT_RETURNTRANSFER => false
97
+ );
98
+
99
+ $this->_handles[$ch] = $handle;
100
+
101
+ if($url !== null)
102
+ $this->curl_setopt($ch, CURLOPT_URL, $url);
103
+
104
+ return $ch;
105
+ }
106
+
107
+ public function curl_multi_add_handle($mh, $ch)
108
+ {
109
+ throw new Exception("Not yet implemented.");
110
+ }
111
+
112
+ public function curl_multi_close($mh)
113
+ {
114
+ throw new Exception("Not yet implemented.");
115
+ }
116
+
117
+ public function curl_multi_exec($mh, &$still_running)
118
+ {
119
+ throw new Exception("Not yet implemented.");
120
+ }
121
+
122
+ public function curl_multi_getcontent($ch)
123
+ {
124
+ throw new Exception("Not yet implemented.");
125
+ }
126
+
127
+ public function curl_multi_info_read($mh, &$msgs_in_queue = null)
128
+ {
129
+ throw new Exception("Not yet implemented.");
130
+ }
131
+
132
+ public function curl_multi_init()
133
+ {
134
+ throw new Exception("Not yet implemented.");
135
+ }
136
+
137
+ public function curl_multi_remove_handle($mh, $ch)
138
+ {
139
+ throw new Exception("Not yet implemented.");
140
+ }
141
+
142
+ public function curl_multi_select($mh, $timeout = 1.0)
143
+ {
144
+ throw new Exception("Not yet implemented.");
145
+ }
146
+
147
+ public function curl_setopt_array($ch, $options)
148
+ {
149
+ foreach($options as $option => $value)
150
+ {
151
+ if(!$this->curl_setopt($ch, $option, $value))
152
+ return false;
153
+ }
154
+ return true;
155
+ }
156
+
157
+ public function curl_setopt($ch, $option, $value)
158
+ {
159
+ if(!isset($this->_handles[$ch]))
160
+ return false;
161
+
162
+ $this->_handles[$ch]->options[$option] = $value;
163
+
164
+ return true;
165
+ }
166
+
167
+ public function curl_version($age = CURLVERSION_NOW)
168
+ {
169
+ return curl_version($age);
170
+ }
171
+
172
+ public function setResponse($expectedResponse, $requiredOptions = array())
173
+ {
174
+ $hash = $this->_getHashAndSetOptionMaps($requiredOptions);
175
+ $this->_mapResponses[$hash] = $expectedResponse;
176
+ }
177
+
178
+ public function setErrorCode($expectedErrorCode, $requiredOptions = array())
179
+ {
180
+ $hash = $this->_getHashAndSetOptionMaps($requiredOptions);
181
+ $this->_mapErrorCodes[$hash] = $expectedErrorCode;
182
+ }
183
+
184
+ public function setInfo($expectedInfo, $requiredOptions = array())
185
+ {
186
+ $hash = $this->_getHashAndSetOptionMaps($requiredOptions);
187
+ $this->_mapInfo[$hash] = $expectedInfo;
188
+ }
189
+
190
+ private function _getHashAndSetOptionMaps($requiredOptions)
191
+ {
192
+ $hash = md5(http_build_query($requiredOptions));
193
+
194
+ $this->_mapOptionCounts[$hash] = count($requiredOptions);
195
+ arsort($this->_mapOptionCounts);
196
+ $this->_mapOptions[$hash] = $requiredOptions;
197
+ return $hash;
198
+ }
199
+
200
+ private function _getResponse($handle)
201
+ {
202
+ $response = false;
203
+
204
+ $key = $this->_determineKey($handle);
205
+
206
+ if($key !== null && isset($this->_mapResponses[$key]))
207
+ $response = $this->_mapResponses[$key];
208
+
209
+ return $response;
210
+ }
211
+
212
+ private function _getErrorCode($handle)
213
+ {
214
+ $errorCode = 0;
215
+
216
+ $key = $this->_determineKey($handle);
217
+
218
+ if($key !== null && isset($this->_mapErrorCodes[$key]))
219
+ $errorCode = $this->_mapErrorCodes[$key];
220
+
221
+ return $errorCode;
222
+ }
223
+
224
+ private function _getInfo($handle, $opt)
225
+ {
226
+ $info = '';
227
+
228
+ $key = $this->_determineKey($handle);
229
+
230
+ if($key !== null && isset($this->_mapInfo[$key][$opt]))
231
+ $info = $this->_mapInfo[$key][$opt];
232
+
233
+ return $info;
234
+ }
235
+
236
+ private function _getInfoArray($handle)
237
+ {
238
+ $infoArray = array();
239
+
240
+ foreach(self::$infoLookup as $strKey)
241
+ {
242
+ $infoArray[$strKey] = '';
243
+ }
244
+
245
+ $handleKey = $this->_determineKey($handle);
246
+
247
+ if($handleKey !== null && isset($this->_mapInfo[$handleKey]))
248
+ {
249
+ foreach($this->_mapInfo[$handleKey] as $intKey => $value)
250
+ {
251
+ $strKey = self::$infoLookup[$intKey];
252
+ $infoArray[$strKey] = $value;
253
+ }
254
+ }
255
+
256
+ return $infoArray;
257
+ }
258
+
259
+ private function _determineKey($handle)
260
+ {
261
+ // TODO: Treat URL separately, so that order of parameters does not matter
262
+ $returnValue = null;
263
+ $options = $handle->options;
264
+ foreach($this->_mapOptionCounts as $hash => $optionCount)
265
+ {
266
+ foreach($this->_mapOptions[$hash] as $option => $value)
267
+ {
268
+ if(!isset($options[$option]) || $options[$option] != $value)
269
+ continue 2;
270
+ }
271
+
272
+ $returnValue = $hash;
273
+
274
+ break;
275
+ }
276
+ return $returnValue;
277
+ }
278
+
279
+ private static $errorLookup = array(
280
+ 0 => 'CURLE_OK',
281
+ 1 => 'CURLE_UNSUPPORTED_PROTOCOL',
282
+ 2 => 'CURLE_FAILED_INIT',
283
+ 3 => 'CURLE_URL_MALFORMAT',
284
+ 4 => 'CURLE_URL_MALFORMAT_USER',
285
+ 5 => 'CURLE_COULDNT_RESOLVE_PROXY',
286
+ 6 => 'CURLE_COULDNT_RESOLVE_HOST',
287
+ 7 => 'CURLE_COULDNT_CONNECT',
288
+ 8 => 'CURLE_FTP_WEIRD_SERVER_REPLY',
289
+ 9 => 'CURLE_REMOTE_ACCESS_DENIED',
290
+ 11 => 'CURLE_FTP_WEIRD_PASS_REPLY',
291
+ 13 => 'CURLE_FTP_WEIRD_PASV_REPLY',
292
+ 14 => 'CURLE_FTP_WEIRD_227_FORMAT',
293
+ 15 => 'CURLE_FTP_CANT_GET_HOST',
294
+ 17 => 'CURLE_FTP_COULDNT_SET_TYPE',
295
+ 18 => 'CURLE_PARTIAL_FILE',
296
+ 19 => 'CURLE_FTP_COULDNT_RETR_FILE',
297
+ 21 => 'CURLE_QUOTE_ERROR',
298
+ 22 => 'CURLE_HTTP_RETURNED_ERROR',
299
+ 23 => 'CURLE_WRITE_ERROR',
300
+ 25 => 'CURLE_UPLOAD_FAILED',
301
+ 26 => 'CURLE_READ_ERROR',
302
+ 27 => 'CURLE_OUT_OF_MEMORY',
303
+ 28 => 'CURLE_OPERATION_TIMEOUTED', // in the original cURL lib this is called 'CURLE_OPERATION_TIMEOUTED' instead
304
+ 30 => 'CURLE_FTP_PORT_FAILED',
305
+ 31 => 'CURLE_FTP_COULDNT_USE_REST',
306
+ 33 => 'CURLE_RANGE_ERROR',
307
+ 34 => 'CURLE_HTTP_POST_ERROR',
308
+ 35 => 'CURLE_SSL_CONNECT_ERROR',
309
+ 36 => 'CURLE_BAD_DOWNLOAD_RESUME',
310
+ 37 => 'CURLE_FILE_COULDNT_READ_FILE',
311
+ 38 => 'CURLE_LDAP_CANNOT_BIND',
312
+ 39 => 'CURLE_LDAP_SEARCH_FAILED',
313
+ 41 => 'CURLE_FUNCTION_NOT_FOUND',
314
+ 42 => 'CURLE_ABORTED_BY_CALLBACK',
315
+ 43 => 'CURLE_BAD_FUNCTION_ARGUMENT',
316
+ 45 => 'CURLE_INTERFACE_FAILED',
317
+ 47 => 'CURLE_TOO_MANY_REDIRECTS',
318
+ 48 => 'CURLE_UNKNOWN_TELNET_OPTION',
319
+ 49 => 'CURLE_TELNET_OPTION_SYNTAX',
320
+ 51 => 'CURLE_PEER_FAILED_VERIFICATION',
321
+ 52 => 'CURLE_GOT_NOTHING',
322
+ 53 => 'CURLE_SSL_ENGINE_NOTFOUND',
323
+ 54 => 'CURLE_SSL_ENGINE_SETFAILED',
324
+ 55 => 'CURLE_SEND_ERROR',
325
+ 56 => 'CURLE_RECV_ERROR',
326
+ 58 => 'CURLE_SSL_CERTPROBLEM',
327
+ 59 => 'CURLE_SSL_CIPHER',
328
+ 60 => 'CURLE_SSL_CACERT',
329
+ 61 => 'CURLE_BAD_CONTENT_ENCODING',
330
+ 62 => 'CURLE_LDAP_INVALID_URL',
331
+ 63 => 'CURLE_FILESIZE_EXCEEDED',
332
+ 64 => 'CURLE_USE_SSL_FAILED',
333
+ 65 => 'CURLE_SEND_FAIL_REWIND',
334
+ 66 => 'CURLE_SSL_ENGINE_INITFAILED',
335
+ 67 => 'CURLE_LOGIN_DENIED',
336
+ 68 => 'CURLE_TFTP_NOTFOUND',
337
+ 69 => 'CURLE_TFTP_PERM',
338
+ 70 => 'CURLE_REMOTE_DISK_FULL',
339
+ 71 => 'CURLE_TFTP_ILLEGAL',
340
+ 72 => 'CURLE_TFTP_UNKNOWNID',
341
+ 73 => 'CURLE_REMOTE_FILE_EXISTS',
342
+ 74 => 'CURLE_TFTP_NOSUCHUSER',
343
+ 75 => 'CURLE_CONV_FAILED',
344
+ 76 => 'CURLE_CONV_REQD',
345
+ 77 => 'CURLE_SSL_CACERT_BADFILE',
346
+ 78 => 'CURLE_REMOTE_FILE_NOT_FOUND',
347
+ 79 => 'CURLE_SSH',
348
+ 80 => 'CURLE_SSL_SHUTDOWN_FAILED',
349
+ 81 => 'CURLE_AGAIN',
350
+ 82 => 'CURLE_SSL_CRL_BADFILE',
351
+ 83 => 'CURLE_SSL_ISSUER_ERROR',
352
+ 84 => 'CURL E_FTP_PRET_FAILED',
353
+ 85 => 'CURLE_RTSP_CSEQ_ERROR',
354
+ 86 => 'CURLE_RTSP_SESSION_ERROR',
355
+ 87 => 'CURLE_FTP_BAD_FILE_LIST',
356
+ 88 => 'CURLE_CHUNK_FAILED'
357
+ );
358
+
359
+ public static $infoLookup = array(
360
+ CURLINFO_EFFECTIVE_URL => 'url',
361
+ CURLINFO_HTTP_CODE => 'http_code',
362
+ CURLINFO_FILETIME => 'filetime',
363
+ CURLINFO_TOTAL_TIME => 'total_time',
364
+ CURLINFO_NAMELOOKUP_TIME => 'namelookup_time',
365
+ CURLINFO_CONNECT_TIME => 'connect_time',
366
+ CURLINFO_PRETRANSFER_TIME => 'pretransfer_time',
367
+ CURLINFO_STARTTRANSFER_TIME => 'starttransfer_time',
368
+ CURLINFO_REDIRECT_COUNT => 'redirect_count',
369
+ CURLINFO_REDIRECT_TIME => 'redirect_time',
370
+ CURLINFO_SIZE_UPLOAD => 'size_upload',
371
+ CURLINFO_SIZE_DOWNLOAD => 'size_download',
372
+ CURLINFO_SPEED_DOWNLOAD => 'speed_download',
373
+ CURLINFO_SPEED_UPLOAD => 'speed_upload',
374
+ CURLINFO_HEADER_SIZE => 'header_size',
375
+ CURLINFO_HEADER_OUT => 'request_header',
376
+ CURLINFO_REQUEST_SIZE => 'request_size',
377
+ CURLINFO_SSL_VERIFYRESULT => 'ssl_verify_result',
378
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD => 'download_content_length',
379
+ CURLINFO_CONTENT_LENGTH_UPLOAD => 'upload_content_length',
380
+ CURLINFO_CONTENT_TYPE => 'content_type'
381
+ );
382
+ }
package.xml CHANGED
@@ -1,18 +1,37 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Flagbit_Factfinder</name>
4
- <version>3.3.12</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>bugfix: Removing HTML tags from export will no longer cause separate words to be merged.</notes>
12
- <authors><author><name>Rudolf Batt</name><user>rbatt</user><email>rb@omikron.net</email></author></authors>
13
- <date>2012-09-18</date>
14
- <time>13:43:27</time>
15
- <contents><target name="magecommunity"><dir name="Flagbit"><dir name="FactFinder"><dir name="Block"><dir name="Adminhtml"><file name="Cockpit.php" hash="7f5f3e8521f002c8c7b5a2d5f72cf5e1"/><file name="Exportlink.php" hash="f83a083279cec4d1e3fece4bbb94263e"/><dir name="Form"><dir name="Field"><file name="Attribute.php" hash="2e60d7473163fa523f10b2d0c441fe24"/><file name="Attributes.php" hash="cbaf317aa5ce4417cfcd02a6c4f36486"/></dir></dir></dir><dir name="Campaign"><file name="Advisory.php" hash="9eb34869abbc7e4ba4fe3825835793eb"/><dir name="Cart"><file name="Advisory.php" hash="9861e5ff8bb10fdec38d17bc9f61090a"/><file name="Feedback.php" hash="aa9239e92f528ff6b216942194f36776"/></dir><file name="Feedback.php" hash="ffb877d1e9cb5e7fb7b9d5731a8ace56"/><dir name="Product"><file name="Advisory.php" hash="d4736ab3436e7966c37b393a339110ca"/><file name="Feedback.php" hash="7843ed6669b7e6bdd92934b3aeb2fd41"/></dir></dir><dir name="Cart"><file name="Crosssell.php" hash="73e43a5c9048a1d139910dc7a2199952"/></dir><dir name="Filter"><file name="Slider.php" hash="159d3e1b403625dbbb970e5e7ada4ec7"/></dir><dir name="Layer"><file name="Abstract.php" hash="f53a3e2d6ce0da4afee58b4ea806a342"/></dir><file name="Layer.php" hash="fc9ae3f5197a73be5951a420d4b27124"/><dir name="Product"><dir name="List"><file name="Crosssell.php" hash="8b6936aa661cd77a1866da3bc2a40939"/><file name="Upsell.php" hash="8320612f3ae64c74939676b075e77144"/></dir></dir><file name="Scic.php" hash="9ba6aa43204d0aae206d9f24f09aecfc"/><file name="Secondaryresult.php" hash="c2647dd1db7fdd0b77b3f7124e08ce63"/><file name="TagCloud.php" hash="664c18eceaa82779a60b6eb1694cdfca"/><dir name="XmlConnect"><dir name="Catalog"><dir name="Product"><file name="List.php" hash="79103c53bbaa03f02ed8a78554dcc791"/></dir><dir name="Search"><file name="Suggest.php" hash="5c7ef36939885a14ee0644cbb91a945d"/></dir><file name="Search.php" hash="662f7b0df8d21626bf6193906aed5162"/></dir></dir></dir><dir name="Helper"><file name="Backend.php" hash="57771ad274e7e0ea63b9a934b3757f04"/><file name="Data.php" hash="afede9edaf2bcfbc93a4049eee5be89e"/><file name="Debug.php" hash="24b939b03efb2cd5f7815562f896576f"/><file name="Search.php" hash="edc5498b06f5e865cc7f34dce60dc96b"/></dir><dir name="Model"><file name="Adapter.php" hash="b5fc3e4a64610006fd8a5f38e25285c9"/><dir name="Export"><file name="Price.php" hash="5561605bf639385c211f339f0c752a0f"/><file name="Product.php" hash="457e5446b77e80240595f0ed2d48db64"/><file name="Stock.php" hash="28e819f8f317957a70a7d4d318e04791"/></dir><dir name="Layer"><file name="Abstract.php" hash="0a0505e719ca55320da35c7510b82d3a"/><dir name="Filter"><dir name="Attribute"><file name="Abstract.php" hash="2ad710352f1803d15ba056cd93d519f1"/><file name="Catalog.php" hash="f6dce5ea64da9dfb3458ae9ff4b58a7b"/><file name="Catalogsearch.php" hash="75536576aaaa0186f166550ee746ae04"/></dir><file name="Item.php" hash="28e42624d764342dae6cb09a1b29b7b8"/></dir></dir><file name="Layer.php" hash="9da16c44259b4a31d73f63d87787ff11"/><dir name="Mysql4"><dir name="Campaign"><dir name="Pushedproducts"><file name="Collection.php" hash="c966a40c7569b70cef93e47781b95190"/></dir></dir><dir name="Product"><dir name="Attribute"><file name="Collection.php" hash="d9000f3e9c709fa63313b15f34803d74"/></dir><dir name="Recommendation"><file name="Collection.php" hash="fdb6f35fa1cca09aa405bc5cd0c68601"/></dir></dir><dir name="Scic"><dir name="Queue"><file name="Collection.php" hash="5f6b0b6a50838929065ebd941cedce42"/></dir><file name="Queue.php" hash="a1521000a1a10df8e6b580f33d06cf23"/></dir><dir name="Search"><file name="Collection.php" hash="12356224ac22113428b38120a1a002a6"/><file name="Engine.php" hash="88a56eb3b4587d87bb1152476b64036e"/></dir></dir><file name="Observer.php" hash="5478ee05a85d5c502211c66eab3f6190"/><file name="Processor.php" hash="1a48223d1208215013f314a5439b3028"/><dir name="Scic"><file name="Queue.php" hash="828d391339a22c15ad74ae1a2e784b41"/></dir><dir name="System"><dir name="Config"><dir name="Backend"><file name="Attributes.php" hash="8259883090dc4bca9b858d047983e736"/><file name="Enabled.php" hash="3b4d1f4b37d7ddba9768a7da6e3fc778"/></dir><dir name="Source"><file name="Authtype.php" hash="5bc0b1c745782cc51d44d56299059bcb"/><file name="Ffversion.php" hash="41ef9c853705c0777d9a2b7d2f3624ad"/><file name="Identifier.php" hash="cec45238f0e28a1bf66d10dee513c2ca"/></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Factfinder"><file name="CockpitController.php" hash="4c8665feaf14c38e6ba2384db496c95a"/></dir></dir><file name="ExportController.php" hash="01a45ff00a9b5a95ae397fd555507592"/><file name="ProxyController.php" hash="587f159bad384600c724568a61546b66"/></dir><dir name="documentation"><file name="Installation_FACT-Finder_Magento_de.pdf" hash="b4711171c625caaa8996a6a09e0eaaae"/><file name="Installation_FACT-Finder_Magento_en.pdf" hash="d4bef19418ee33a223fbda2d45cca686"/></dir><dir name="etc"><file name="adminhtml.xml" hash="1165a0fecfaa31f2aa4a882d1d8bc033"/><file name="config.xml" hash="09182f5c81fe5fa733dcbbe3a2b66f60"/><file name="system.xml" hash="168f70622dd8d3f5622720f7c6871f08"/></dir><dir name="sql"><dir name="factfinder_setup"><file name="mysql4-install-3.2.0.php" hash="1342320595048cd96659c454381cfbb4"/><file name="mysql4-upgrade-3.2.0-3.2.1.php" hash="3d5276dfe971a6bd48aa8e2a085de004"/><file name="mysql4-upgrade-3.2.1-3.3.0.php" hash="71954ea0cf400950d23b020ff095a9ee"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="factfinder.xml" hash="5e5cb94967917aa2784d19434d02b2d4"/></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="factfinder.xml" hash="b376920761be268df8ad702f93b4e346"/></dir><dir name="template"><dir name="factfinder"><dir name="campaign"><file name="advisory.phtml" hash="d0ef29b97aa4c3bdfa2b94596beb5b21"/><dir name="cart"><file name="advisory.phtml" hash="bb994272a6daaaba298a38023f6db212"/><file name="feedback.phtml" hash="01fa6a9cd024a2a8edaea7013b00fc89"/></dir><file name="feedback.phtml" hash="a44c2521e961cfb62b4b89ad0cb71b15"/><dir name="product"><file name="advisory.phtml" hash="d0ef29b97aa4c3bdfa2b94596beb5b21"/><file name="feedback.phtml" hash="40e944aa8dd3cb993cd0190a518f4ac8"/></dir></dir><dir name="filter"><file name="slider.phtml" hash="80e4e9e1c81437fe41b6a52d98e73549"/></dir><file name="form.mini.phtml" hash="54045a15eb78bea151f518303773ed0e"/><file name="logo.phtml" hash="7a40d67bf648e65345f69b2cf9d3c6b6"/><file name="scic.phtml" hash="3553a9f0f3c66015610f4c7f1d770a51"/><file name="secondaryresult.phtml" hash="a4cdff409ccedb16d4fe9a038a4dd9e8"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="."><file name="factfinder.xml" hash="ca4dac634339217dd2ee6e8dc477d694"/></dir><dir name="modules"><file name="Flagbit_FactFinder.xml" hash="99c6b4e5981ac7592830a9fb3f5e5a0e"/></dir></target><target name="magelocale"><dir name="de_DE"><file name="Flagbit_FactFinder.csv" hash="e1b1aa6179c7aac9cd8dc294e136a7f5"/></dir></target><target name="mageweb"><dir name="js"><dir name="factfinder"><file name="jXHR.js" hash="0473a3ea88f08797737814c7ffbeba18"/><file name="scic.js" hash="10f509fb3f468a8557ca17205a361d52"/><file name="suggest.js" hash="c39230ada8f44c3d3a8c7540c0b4a8c9"/></dir></dir></target><target name="magelib"><dir name="FACTFinder"><dir name="Abstract"><file name="Adapter.php" hash="f0059219a3f00180007b99fb493e0d72"/><file name="CompareAdapter.php" hash="d26dec2f3dc98269dcb43f10bcfcdfe9"/><file name="Configuration.php" hash="5e421f8569742aa949c201249cb46581"/><file name="DataProvider.php" hash="5ba56f8daab07d86139cdcc67d73e270"/><file name="ImportAdapter.php" hash="8427bb6b4b33c37bfe9090d7c16e0238"/><file name="Logger.php" hash="c5b1ace6158035e80b3d4a79a942a381"/><file name="ProductCampaignAdapter.php" hash="daa4f28109edf685b33f31fce8573ced"/><file name="RecommendationAdapter.php" hash="655e55d17ba0eb790d3b2146299404d1"/><file name="ScicAdapter.php" hash="0ca4747a30249ed0b944e2f330390171"/><file name="SearchAdapter.php" hash="c03d9bea34da5cc0e0b5885bd2c89c74"/><file name="SimilarRecordsAdapter.php" hash="2cef8bdabc112c2c78fb95e75ef748bd"/><file name="SuggestAdapter.php" hash="ef13ace0995fa2f57b87f38cc2fb701a"/><file name="TagCloudAdapter.php" hash="ac5465a5dde73dde3ead1f6f08eced08"/></dir><file name="AdvisorAnswer.php" hash="b6dfbe2d43660b1624ce7788bef7356a"/><file name="AdvisorQuestion.php" hash="7f3d039dc86c5baebb4702f8a66ca6d4"/><file name="Asn.php" hash="8a3753feea0901c7ace25e011be38e56"/><file name="AsnFilterItem.php" hash="cdd0bb237873b54877b4b52744250018"/><file name="AsnGroup.php" hash="fd6834f2857c8dc15e79f46eeb977186"/><file name="AsnSliderFilter.php" hash="da4eb96cdb47553793b278aca2d0ec19"/><file name="BreadCrumbItem.php" hash="115ffb2f30e346b29f93ce2d84be724e"/><file name="Campaign.php" hash="138f990ff2180d369bd0b441998b9cb4"/><file name="CampaignIterator.php" hash="d58f054580f0057e8471dbd8334157f1"/><file name="Configuration.php" hash="6a514853077250ac0271f9dc4858fcf6"/><file name="EncodingHandler.php" hash="4f0b616bca9158bfb7eddcfcba192dc6"/><dir name="Http"><file name="DataProvider.php" hash="01d3616caf13b17183799cce4e7609c6"/><file name="DummyProvider.php" hash="30d61ea2ce373f5b501bb64d8ed19393"/><file name="ParallelDataProvider.php" hash="a513931b400bc940a8fe9e78bf489490"/><file name="ScicAdapter.php" hash="a1979f92c3c8d0bc7239ad63ef55dbaa"/><file name="SuggestAdapter.php" hash="c454126b2e5b18edc7e753973cc7b791"/></dir><file name="Item.php" hash="431843e9e2847e8a6c966a185c39f5e9"/><file name="Loader.php" hash="e76d471f86c6c68ef3228c0b98aaed6e"/><file name="Log4PhpLogger.php" hash="ecfb1f084b8d0bd2d51bf417fa0b0b3c"/><file name="NullLogger.php" hash="be8782000070665f0e9fcc011ae4fe77"/><file name="Paging.php" hash="a07db7cb4b02893792e6e29018a36858"/><file name="Parameters.php" hash="612c4a9b98cb8a17d0f2d30cf2641936"/><file name="ParametersParser.php" hash="187527e3d7f233ca60d89748be8c2896"/><file name="ProductsPerPageOptions.php" hash="1929e3d0c7ce95372b04e8925f7c17c7"/><file name="Record.php" hash="4bc036a2d47cd1b76d09af6290f49044"/><file name="Result.php" hash="6b4e959df31a73b9fe25de7a76551970"/><file name="SingleWordSearchItem.php" hash="8f0feac780e68a8b0eab6d44dd6c6813"/><file name="SuggestQuery.php" hash="cf3cf51839e06475bdcf62bb49ee96c5"/><file name="TagQuery.php" hash="ece1fda66af2c6053507941f35423c5f"/><file name="Util.php" hash="4ac8b8eb630e83c65a065fd4e01ab11f"/><dir name="Xml64"><file name="SearchAdapter.php" hash="58a49882c741216cf278c4556ea7d224"/></dir><dir name="Xml65"><file name="ImportAdapter.php" hash="329fcaf405969b30ea6cbd3ae4a783f2"/><file name="RecommendationAdapter.php" hash="14a126d5a9c14da3e754186f81bfeacb"/><file name="SearchAdapter.php" hash="5c2056713238ae017b4af8912e27f6b0"/><file name="SuggestAdapter.php" hash="878a1f04fdce6956b644cdff227d50c2"/><file name="TagCloudAdapter.php" hash="feacc3e6c13d3c49f748b4a85418d994"/></dir><dir name="Xml66"><file name="CompareAdapter.php" hash="a6f500504086c842e8e50772305b98df"/><file name="ImportAdapter.php" hash="5ea0d06cc2ddc7a1b7c880203c38fe40"/><file name="RecommendationAdapter.php" hash="9490ea2b17fded94d087046065596b1b"/><file name="SearchAdapter.php" hash="82214090045d963b15ccc7073d73d7ea"/><file name="SimilarRecordsAdapter.php" hash="532cbc18947dad44fdb296bc82ea3fa0"/><file name="SuggestAdapter.php" hash="813bfb64ac9d2dc45443cc7c33e854a7"/><file name="TagCloudAdapter.php" hash="a44dd623910bbb6766a0b0c25584212c"/></dir><dir name="Xml67"><file name="CompareAdapter.php" hash="37980ec507fd7f13e81ece413915da2d"/><file name="ImportAdapter.php" hash="dc0d334439aa59f3e0a4226bbf1456d2"/><file name="ProductCampaignAdapter.php" hash="64faea05ff05c3031da6f30b3a169980"/><file name="RecommendationAdapter.php" hash="b991b5e2570c28530164b3cacfffa6e1"/><file name="SearchAdapter.php" hash="f69bf92b5a42c2e46a777435e15adf2d"/><file name="SimilarRecordsAdapter.php" hash="b60a974a22d3e473538524dc57d1e91d"/><file name="SuggestAdapter.php" hash="7290503daae4ae9e595cc5b1480ce8a1"/><file name="TagCloudAdapter.php" hash="d3efa6616331286cb221f8ca79021324"/></dir></dir><dir name="FACTFinderCustom"><file name="Configuration.php" hash="96b16f73d80f74ee0a24d39bc81ac321"/></dir></target></contents>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  <compatible/>
17
- <dependencies><required><php><min>5.2.6</min><max>6.0.0</max></php></required></dependencies>
18
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Flagbit_Factfinder</name>
4
+ <version>3.4.0</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>new features:
12
+ * added support for FACT-Finder 6.8
13
+ * new Suggest template system
14
+ * including two new alternative suggest templates
15
+ * Suggest image size is configurable in backend
16
+ * Alternative slider template that uses script.aculo.us instead of Omikron's OneTouchSlider
17
+ * Secondary Channels (searching one or more additional database(s) - for example "content", "community" etc.)
18
+ * Use of parallel requests between Magento and FACT-Finder
19
+ * Parallel data exports are now prevented; this is relevant for large shops whose exports might take hours (and could be requested more frequently)
20
+ * Optional fallback to Magento in case of FACT-Finder server problems
21
+ * Added support for shopping cart campaigns
22
+ * extended error reporting at the installation process, for a better usability at the integration process
23
+ * FACT-Finder Configuration displays export link
24
+ * FACT-Finder version is configurable
25
+
26
+ bugfixes since last release:
27
+ * Explicit export attributes work now even if they are not searchable or filterable
28
+ * Click tracking for product details works now with automatic redirect for single result searches
29
+ * Click tracking for product details works now even if detail page is loaded very quickly
30
+ * HTML tags in export data will not result in unseparated words any more</notes>
31
+ <authors><author><name>Flagbit GmbH Co. KG</name><user>auto-converted</user><email>magento@flagbit.de</email></author></authors>
32
+ <date>2012-09-28</date>
33
+ <time>15:39:52</time>
34
+ <contents><target name="mageetc"><dir><dir><file name="factfinder.xml" hash="ca4dac634339217dd2ee6e8dc477d694"/></dir><dir name="modules"><file name="Flagbit_FactFinder.xml" hash="99c6b4e5981ac7592830a9fb3f5e5a0e"/></dir></dir></target><target name="magedesign"><dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="factfinder.xml" hash="5e5cb94967917aa2784d19434d02b2d4"/></dir><dir name="template"><dir name="factfinder"><file name="cockpit.phtml" hash="db2b5c21f817f1abdab3dabce26c699f"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="factfinder.xml" hash="8afd0a0ae73978191ab07431360b3bef"/></dir><dir name="template"><dir name="factfinder"><file name="form.advancedsuggest.phtml" hash="bb848ea2403c737dbf46acbe5b8af6e2"/><file name="form.advancedsuggest68.phtml" hash="2910c0f39c52e6e02eead79688f682af"/><file name="form.mini.phtml" hash="eb49c2fb57594e2ebeed1ffb01c2606d"/><file name="logo.phtml" hash="7a40d67bf648e65345f69b2cf9d3c6b6"/><file name="scic.phtml" hash="4d4f8d2318837122973049496feafea5"/><file name="secondaryresult.phtml" hash="a4cdff409ccedb16d4fe9a038a4dd9e8"/><dir name="campaign"><file name="advisory.phtml" hash="d0ef29b97aa4c3bdfa2b94596beb5b21"/><file name="feedback.phtml" hash="a44c2521e961cfb62b4b89ad0cb71b15"/><dir name="cart"><file name="advisory.phtml" hash="bb994272a6daaaba298a38023f6db212"/><file name="feedback.phtml" hash="01fa6a9cd024a2a8edaea7013b00fc89"/></dir></dir><dir name="filter"><file name="scriptaculousSlider.phtml" hash="e3ee4dbb6bc6e0546b4374078a9d88bc"/><file name="slider.phtml" hash="80e4e9e1c81437fe41b6a52d98e73549"/></dir></dir></dir></dir></dir></dir></dir></target><target name="magelocale"><dir><dir name="de_DE"><file name="Flagbit_FactFinder.csv" hash="4df4f128de560a402243cd7718f7be2a"/></dir></dir></target><target name="magelib"><dir><dir name="FACTFinder"><file name="AdvisorAnswer.php" hash="b6dfbe2d43660b1624ce7788bef7356a"/><file name="AdvisorQuestion.php" hash="7f3d039dc86c5baebb4702f8a66ca6d4"/><file name="Asn.php" hash="8a3753feea0901c7ace25e011be38e56"/><file name="AsnFilterItem.php" hash="cdd0bb237873b54877b4b52744250018"/><file name="AsnGroup.php" hash="51aa9c3dfad5ec727cade5962cd7ad2f"/><file name="AsnSliderFilter.php" hash="da4eb96cdb47553793b278aca2d0ec19"/><file name="BreadCrumbItem.php" hash="115ffb2f30e346b29f93ce2d84be724e"/><file name="Campaign.php" hash="138f990ff2180d369bd0b441998b9cb4"/><file name="CampaignIterator.php" hash="d58f054580f0057e8471dbd8334157f1"/><file name="Configuration.php" hash="972367363e6c84fe80f2c73a1528b8aa"/><file name="EncodingHandler.php" hash="4f0b616bca9158bfb7eddcfcba192dc6"/><file name="Item.php" hash="431843e9e2847e8a6c966a185c39f5e9"/><file name="Loader.php" hash="e76d471f86c6c68ef3228c0b98aaed6e"/><file name="Log4PhpLogger.php" hash="ecfb1f084b8d0bd2d51bf417fa0b0b3c"/><file name="NullLogger.php" hash="be8782000070665f0e9fcc011ae4fe77"/><file name="Paging.php" hash="a07db7cb4b02893792e6e29018a36858"/><file name="Parameters.php" hash="612c4a9b98cb8a17d0f2d30cf2641936"/><file name="ParametersParser.php" hash="187527e3d7f233ca60d89748be8c2896"/><file name="ProductsPerPageOptions.php" hash="1e69121e89109f31b0929706ea3dcabc"/><file name="Record.php" hash="4bc036a2d47cd1b76d09af6290f49044"/><file name="Result.php" hash="6b4e959df31a73b9fe25de7a76551970"/><file name="SingleWordSearchItem.php" hash="8f0feac780e68a8b0eab6d44dd6c6813"/><file name="SuggestQuery.php" hash="cf3cf51839e06475bdcf62bb49ee96c5"/><file name="TagQuery.php" hash="ece1fda66af2c6053507941f35423c5f"/><file name="Util.php" hash="4ac8b8eb630e83c65a065fd4e01ab11f"/><dir name="Abstract"><file name="Adapter.php" hash="dea9f000509f94599e3b4d38ee14d66f"/><file name="CompareAdapter.php" hash="d26dec2f3dc98269dcb43f10bcfcdfe9"/><file name="Configuration.php" hash="233565de45f56ba7bdcd604817dd7fc6"/><file name="DataProvider.php" hash="8b1dfc68d335aa006f7af9f2a60e519d"/><file name="ImportAdapter.php" hash="8427bb6b4b33c37bfe9090d7c16e0238"/><file name="Logger.php" hash="c5b1ace6158035e80b3d4a79a942a381"/><file name="ProductCampaignAdapter.php" hash="daa4f28109edf685b33f31fce8573ced"/><file name="RecommendationAdapter.php" hash="0c11f59134083f1377f1d0c38a6fdefb"/><file name="ScicAdapter.php" hash="e1a0b64f7555e32a78109bbbaaf3c939"/><file name="SearchAdapter.php" hash="c03d9bea34da5cc0e0b5885bd2c89c74"/><file name="SimilarRecordsAdapter.php" hash="2cef8bdabc112c2c78fb95e75ef748bd"/><file name="SuggestAdapter.php" hash="ef13ace0995fa2f57b87f38cc2fb701a"/><file name="TagCloudAdapter.php" hash="ac5465a5dde73dde3ead1f6f08eced08"/></dir><dir name="Http"><file name="DataProvider.php" hash="301e78f2d7b9c56d344b4a5989ef6b43"/><file name="DummyProvider.php" hash="30d61ea2ce373f5b501bb64d8ed19393"/><file name="ParallelDataProvider.php" hash="78f6039e0b6ec92b9e066e315fed77de"/><file name="ScicAdapter.php" hash="821294ba5ab1fbce8b8208d89e2162dc"/><file name="StatusHelper.php" hash="e4760fadae33a5574f9445bbc73c1283"/><file name="SuggestAdapter.php" hash="9ddfe5fdd6b373e9f7126867ed1f0b06"/><file name="UrlBuilder.php" hash="99efad6cb8243ee93a5d4b61c93d8303"/></dir><dir name="Xml64"><file name="SearchAdapter.php" hash="58a49882c741216cf278c4556ea7d224"/></dir><dir name="Xml65"><file name="ImportAdapter.php" hash="e372e9eaa322a1b2d9ace33679c80815"/><file name="RecommendationAdapter.php" hash="14a126d5a9c14da3e754186f81bfeacb"/><file name="SearchAdapter.php" hash="255e5ae9cd8fe3ff2588222c5a086376"/><file name="SuggestAdapter.php" hash="e5381502b74dd62be1a7aa833cbb03e2"/><file name="TagCloudAdapter.php" hash="711e1aabd4d2895f66fdc329ee2b82b8"/></dir><dir name="Xml66"><file name="CompareAdapter.php" hash="a6f500504086c842e8e50772305b98df"/><file name="ImportAdapter.php" hash="5ea0d06cc2ddc7a1b7c880203c38fe40"/><file name="RecommendationAdapter.php" hash="9490ea2b17fded94d087046065596b1b"/><file name="SearchAdapter.php" hash="82214090045d963b15ccc7073d73d7ea"/><file name="SimilarRecordsAdapter.php" hash="532cbc18947dad44fdb296bc82ea3fa0"/><file name="SuggestAdapter.php" hash="813bfb64ac9d2dc45443cc7c33e854a7"/><file name="TagCloudAdapter.php" hash="a44dd623910bbb6766a0b0c25584212c"/></dir><dir name="Xml67"><file name="CompareAdapter.php" hash="37980ec507fd7f13e81ece413915da2d"/><file name="ImportAdapter.php" hash="dc0d334439aa59f3e0a4226bbf1456d2"/><file name="ProductCampaignAdapter.php" hash="64faea05ff05c3031da6f30b3a169980"/><file name="RecommendationAdapter.php" hash="b991b5e2570c28530164b3cacfffa6e1"/><file name="SearchAdapter.php" hash="bda78e482ab612bc8902aee11260afb9"/><file name="SimilarRecordsAdapter.php" hash="b60a974a22d3e473538524dc57d1e91d"/><file name="SuggestAdapter.php" hash="7290503daae4ae9e595cc5b1480ce8a1"/><file name="TagCloudAdapter.php" hash="d3efa6616331286cb221f8ca79021324"/></dir><dir name="Xml68"><file name="CompareAdapter.php" hash="0a8ebc48d90e7aaf131b66180d10ba11"/><file name="ImportAdapter.php" hash="bf483742e13d647da407f7da85828b98"/><file name="ProductCampaignAdapter.php" hash="db981749b20f69eca65d5ac1e622bafe"/><file name="RecommendationAdapter.php" hash="69e031adc81be7a88a0cffbe1b96c317"/><file name="SearchAdapter.php" hash="de47913e1c064b171aea892443885e8f"/><file name="SimilarRecordsAdapter.php" hash="b9c70b5c7d6d803bb1c7f1255be55285"/><file name="SuggestAdapter.php" hash="5cf5b95340983823c9e7a3fd0dc20a0b"/><file name="TagCloudAdapter.php" hash="3bfa1e877269be17ee08c403254925bf"/></dir></dir><dir name="FACTFinderCustom"><file name="Configuration.php" hash="2451df5afb1c64460c07b4caa228fabf"/></dir><dir name="SAI"><file name="Curl.php" hash="1fb18096257151b5b47bc2964dd9fe39"/><file name="CurlInterface.php" hash="714fa045dd4546d0c92cd022efb09422"/><file name="CurlStub.php" hash="2521763ee414683aced1afd1ec12511d"/><dir name="Curl"><file name="Handle.php" hash="0fc7132737da7cee7df6b974447864ac"/></dir></dir></dir></target><target name="magecommunity"><dir><dir name="Flagbit"><dir name="FactFinder"><dir name="Block"><file name="Layer.php" hash="b87e7abe04f1601f0298cc1bb33001ce"/><file name="Scic.php" hash="9ba6aa43204d0aae206d9f24f09aecfc"/><file name="Secondaryresult.php" hash="3b40908d8089ce30a1ab815e618800d3"/><file name="TagCloud.php" hash="bedca1b6a0a5b40bef6b4c263172a83f"/><dir name="Adminhtml"><file name="Cockpit.php" hash="e12c45f55d5fd31d164187bd9d16a0bd"/><file name="Exportlink.php" hash="29044f67c1ebb0e6950da286a24a1db7"/><dir name="Form"><dir name="Field"><file name="Attribute.php" hash="2e60d7473163fa523f10b2d0c441fe24"/><file name="Attributes.php" hash="cbaf317aa5ce4417cfcd02a6c4f36486"/></dir></dir></dir><dir name="Campaign"><file name="Advisory.php" hash="0dab72c7edeb28479ef82c8c4f85c871"/><file name="Feedback.php" hash="c30b7a27bbf05df9cafc259562cdc50b"/><dir name="Cart"><file name="Advisory.php" hash="73d79fc1a899e2c94cd0301a3901c171"/><file name="Feedback.php" hash="86818ceff0cbe0fea694448037d8c0a9"/></dir><dir name="Product"><file name="Advisory.php" hash="bd1f468d56b6bc1fa3541406796c133a"/><file name="Feedback.php" hash="576bd4801d14f08bc1c62688ffab2e04"/></dir></dir><dir name="Cart"><file name="Crosssell.php" hash="aad1e79b0d9ef61b27e5f94d1a3fe2fe"/></dir><dir name="Filter"><file name="Slider.php" hash="159d3e1b403625dbbb970e5e7ada4ec7"/></dir><dir name="Layer"><file name="Abstract.php" hash="f53a3e2d6ce0da4afee58b4ea806a342"/></dir><dir name="Product"><dir name="List"><file name="Crosssell.php" hash="80ac0ab275f3e903c3df80961d6afa35"/><file name="Upsell.php" hash="5141fb89f0c27970e9540dbbc27c1b25"/></dir></dir><dir name="XmlConnect"><dir name="Catalog"><file name="Search.php" hash="662f7b0df8d21626bf6193906aed5162"/><dir name="Product"><file name="List.php" hash="79103c53bbaa03f02ed8a78554dcc791"/></dir><dir name="Search"><file name="Suggest.php" hash="a0fed06b80840e63f9983909847d7e58"/></dir></dir></dir></dir><dir name="controllers"><file name="ExportController.php" hash="d130083fd8ef132cc48aa4b3746e3c2c"/><file name="ProxyController.php" hash="9cac55f10a4fd33a8396bc460ee3f272"/><dir name="Adminhtml"><dir name="Factfinder"><file name="CockpitController.php" hash="4c8665feaf14c38e6ba2384db496c95a"/></dir></dir></dir><dir name="documentation"><file name="Installation_FACT-Finder_Magento_de.pdf" hash="b4711171c625caaa8996a6a09e0eaaae"/><file name="Installation_FACT-Finder_Magento_en.pdf" hash="d4bef19418ee33a223fbda2d45cca686"/></dir><dir name="etc"><file name="adminhtml.xml" hash="1165a0fecfaa31f2aa4a882d1d8bc033"/><file name="config.xml" hash="58aef2514e99f4f2e281cbf6fe972129"/><file name="system.xml" hash="d3721503a1b346f60633e2f0a8e361a1"/></dir><dir name="Helper"><file name="Backend.php" hash="87b662c7c7242ef349f4606ad2ab5279"/><file name="Data.php" hash="afede9edaf2bcfbc93a4049eee5be89e"/><file name="Debug.php" hash="24b939b03efb2cd5f7815562f896576f"/><file name="Search.php" hash="40618065534d57a4db33f18ab4186989"/></dir><dir name="Model"><file name="Facade.php" hash="340a0a5cd9a7f7dd99508fc88c13dcc9"/><file name="Layer.php" hash="9da16c44259b4a31d73f63d87787ff11"/><file name="Observer.php" hash="eae5f421c3cd8e39cbfc6eef5f96d304"/><file name="Processor.php" hash="5e76103096faccd5b26b2d036bdc7c5e"/><dir name="Export"><file name="Price.php" hash="5561605bf639385c211f339f0c752a0f"/><file name="Product.php" hash="2cc9fb277e4d598fb40f4a2b6858d9f2"/><file name="Stock.php" hash="28e819f8f317957a70a7d4d318e04791"/></dir><dir name="Handler"><file name="Abstract.php" hash="f5724a1c82becbc4d76a6f46dc591977"/><file name="CheckStatus.php" hash="8d595ae034bb373cca899dfe4f40aebb"/><file name="ProductCampaign.php" hash="831d8d3ff2cd29e090cff10c3a9c8844"/><file name="ProductDetailCampaign.php" hash="c714d9b43772f1665d64daea8d16594d"/><file name="Recommendations.php" hash="47b12e1f2f1e1d83ecaba77fdb20b63b"/><file name="Search.php" hash="4d0438b67c59034e74e37ca66ace6967"/><file name="SecondarySearch.php" hash="de4ced818f7865a491438a4d103b431a"/><file name="ShoppingCartCampaign.php" hash="202fc9ab4018247dfb8e8bcefd417465"/><file name="Suggest.php" hash="3b286cbda3cad188b10f7fac06e0ca32"/><file name="TagCloud.php" hash="e60bd2a5d314cfe3bad445ba88740878"/></dir><dir name="Layer"><file name="Abstract.php" hash="0a0505e719ca55320da35c7510b82d3a"/><dir name="Filter"><file name="Item.php" hash="28e42624d764342dae6cb09a1b29b7b8"/><dir name="Attribute"><file name="Abstract.php" hash="2ad710352f1803d15ba056cd93d519f1"/><file name="Catalog.php" hash="f6dce5ea64da9dfb3458ae9ff4b58a7b"/><file name="Catalogsearch.php" hash="75536576aaaa0186f166550ee746ae04"/></dir></dir></dir><dir name="Mysql4"><dir name="Campaign"><dir name="Pushedproducts"><file name="Collection.php" hash="c657b421e0137bf842ec78c26718363f"/></dir></dir><dir name="Product"><dir name="Attribute"><file name="Collection.php" hash="a5b47ca867be314d2d0edf1621608d8b"/></dir><dir name="Recommendation"><file name="Collection.php" hash="fdb6f35fa1cca09aa405bc5cd0c68601"/></dir></dir><dir name="Scic"><file name="Queue.php" hash="a1521000a1a10df8e6b580f33d06cf23"/><dir name="Queue"><file name="Collection.php" hash="5f6b0b6a50838929065ebd941cedce42"/></dir></dir><dir name="Search"><file name="Collection.php" hash="2a0c4ff355e035d11209115f054dc3dd"/><file name="Engine.php" hash="88a56eb3b4587d87bb1152476b64036e"/></dir></dir><dir name="Scic"><file name="Queue.php" hash="828d391339a22c15ad74ae1a2e784b41"/></dir><dir name="System"><dir name="Config"><dir name="Backend"><file name="Attributes.php" hash="8259883090dc4bca9b858d047983e736"/><file name="Enabled.php" hash="3b4d1f4b37d7ddba9768a7da6e3fc778"/></dir><dir name="Source"><file name="Authtype.php" hash="5bc0b1c745782cc51d44d56299059bcb"/><file name="Ffversion.php" hash="0270fbefb18c180abc98f2e02e37532c"/><file name="Identifier.php" hash="cec45238f0e28a1bf66d10dee513c2ca"/></dir></dir></dir></dir><dir name="sql"><dir name="factfinder_setup"><file name="mysql4-install-3.2.0.php" hash="1342320595048cd96659c454381cfbb4"/><file name="mysql4-upgrade-3.2.0-3.2.1.php" hash="3d5276dfe971a6bd48aa8e2a085de004"/><file name="mysql4-upgrade-3.2.1-3.3.0.php" hash="71954ea0cf400950d23b020ff095a9ee"/></dir></dir></dir></dir></dir></target><target name="mageskin"><dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><file name="factfinder.css" hash="16766d07b20544e11184ee21f95b2692"/></dir></dir></dir></dir></dir></target><target name="mage"><dir><dir name="js"><dir name="factfinder"><file name="jXHR.js" hash="0473a3ea88f08797737814c7ffbeba18"/><file name="scic.js" hash="e942f1386b29f6868f3ebe20c52e2782"/><file name="suggest.js" hash="c60da60ac082a4bca9d9c04be47e3138"/></dir></dir></dir></target></contents>
35
  <compatible/>
36
+ <dependencies/>
37
  </package>
skin/frontend/base/default/css/factfinder.css ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .header .form-search .search-autocomplete.advanced-suggest li.delimiter {
2
+ cursor: default;
3
+ padding-left: 4px;
4
+ font-weight: bold;
5
+ font-size: 10px;
6
+ background-color: #4F4F4F;
7
+ color: #F4EEE7;
8
+ }
9
+
10
+ .header .form-search .search-autocomplete.advanced-suggest li.category {
11
+ background-color: #E4DED7;
12
+ }
13
+
14
+ .header .form-search .search-autocomplete.advanced-suggest li.category.selected {
15
+ background-color: #E4D6CF;
16
+ }
17
+
18
+ .header .form-search .search-autocomplete.advanced-suggest img.thumbnail {
19
+ float:left;
20
+ margin-top: 2px;
21
+ margin-bottom: 3px;
22
+ margin-right: 5px;
23
+ width: 31px;
24
+ height: 31px;
25
+ }