Bitbull_Tooso - Version 1.0.0

Version Notes

This is the first release version.

Download this release

Release Info

Developer Tooso Inc.
Extension Bitbull_Tooso
Version 1.0.0
Comparing to
See all releases


Version 1.0.0

Files changed (29) hide show
  1. app/code/community/Bitbull/Tooso/Block/CatalogSearch/Autocomplete.php +38 -0
  2. app/code/community/Bitbull/Tooso/Block/CatalogSearch/Result.php +41 -0
  3. app/code/community/Bitbull/Tooso/Block/Rebuild.php +29 -0
  4. app/code/community/Bitbull/Tooso/Helper/CatalogSearch/Data.php +33 -0
  5. app/code/community/Bitbull/Tooso/Helper/Data.php +109 -0
  6. app/code/community/Bitbull/Tooso/Helper/Log.php +46 -0
  7. app/code/community/Bitbull/Tooso/Helper/Log/Send.php +71 -0
  8. app/code/community/Bitbull/Tooso/Model/CatalogSearch/Resource/Fulltext.php +134 -0
  9. app/code/community/Bitbull/Tooso/Model/Document.php +9 -0
  10. app/code/community/Bitbull/Tooso/Model/Export/Adapter/Csv.php +22 -0
  11. app/code/community/Bitbull/Tooso/Model/Indexer.php +73 -0
  12. app/code/community/Bitbull/Tooso/Model/Observer.php +37 -0
  13. app/code/community/Bitbull/Tooso/Model/Resource/CatalogSearch/Fulltext/Collection.php +47 -0
  14. app/code/community/Bitbull/Tooso/Model/Resource/CatalogSearch/Query.php +44 -0
  15. app/code/community/Bitbull/Tooso/Model/Search.php +210 -0
  16. app/code/community/Bitbull/Tooso/Model/Suggest.php +90 -0
  17. app/code/community/Bitbull/Tooso/controllers/Adminhtml/ToosoController.php +25 -0
  18. app/code/community/Bitbull/Tooso/etc/adminhtml.xml +28 -0
  19. app/code/community/Bitbull/Tooso/etc/config.xml +112 -0
  20. app/code/community/Bitbull/Tooso/etc/system.xml +126 -0
  21. app/etc/modules/Bitbull_Tooso.xml +13 -0
  22. app/locale/en_US/template/email/tooso_alert.html +26 -0
  23. lib/Bitbull/Tooso/Client.php +284 -0
  24. lib/Bitbull/Tooso/Exception.php +23 -0
  25. lib/Bitbull/Tooso/Index/Result.php +22 -0
  26. lib/Bitbull/Tooso/Log/SendInterface.php +20 -0
  27. lib/Bitbull/Tooso/Search/Result.php +57 -0
  28. lib/Bitbull/Tooso/Suggest/Result.php +27 -0
  29. package.xml +27 -0
app/code/community/Bitbull/Tooso/Block/CatalogSearch/Autocomplete.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Block_CatalogSearch_Autocomplete extends Mage_CatalogSearch_Block_Autocomplete
8
+ {
9
+ public function getSuggestData()
10
+ {
11
+ if (!Mage::getStoreConfigFlag(Bitbull_Tooso_Helper_Data::XML_PATH_ENABLE_SEARCH)) {
12
+ return parent::getSuggestData();
13
+ }
14
+
15
+ if (!$this->_suggestData) {
16
+ $query = $this->helper('catalogsearch')->getQueryText();
17
+ $suggest = Mage::getModel('tooso/suggest')->suggest($query);
18
+ $counter = 0;
19
+ $data = array();
20
+ foreach ($suggest->getSuggestions() as $item) {
21
+ $_data = array(
22
+ 'title' => $item->getQueryText(),
23
+ 'row_class' => (++$counter)%2?'odd':'even',
24
+ 'num_of_results' => $item->getNumResults()
25
+ );
26
+
27
+ if ($item->getQueryText() == $query) {
28
+ array_unshift($data, $_data);
29
+ }
30
+ else {
31
+ $data[] = $_data;
32
+ }
33
+ }
34
+ $this->_suggestData = $data;
35
+ }
36
+ return $this->_suggestData;
37
+ }
38
+ }
app/code/community/Bitbull/Tooso/Block/CatalogSearch/Result.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Block_CatalogSearch_Result extends Mage_CatalogSearch_Block_Result
8
+ {
9
+ /**
10
+ * Prepare layout
11
+ *
12
+ * @return Mage_CatalogSearch_Block_Result
13
+ */
14
+ protected function _prepareLayout()
15
+ {
16
+ $fixedSearchString = Mage::helper('tooso')->getFixedSearchString();
17
+
18
+ // add Home breadcrumb
19
+ $breadcrumbs = $this->getLayout()->getBlock('breadcrumbs');
20
+ if ($breadcrumbs) {
21
+ $title = $this->__("Search results for: '%s'", $fixedSearchString ? $fixedSearchString : $this->helper('catalogsearch')->getQueryText());
22
+
23
+ $breadcrumbs->addCrumb('home', array(
24
+ 'label' => $this->__('Home'),
25
+ 'title' => $this->__('Go to Home Page'),
26
+ 'link' => Mage::getBaseUrl()
27
+ ))->addCrumb('search', array(
28
+ 'label' => $title,
29
+ 'title' => $title
30
+ ));
31
+ }
32
+
33
+ // modify page title
34
+ $title = $this->__("Search results for: '%s'", $fixedSearchString ? $fixedSearchString : $this->helper('catalogsearch')->getEscapedQueryText());
35
+ $this->getLayout()->getBlock('head')->setTitle($title);
36
+
37
+ $this->setHeaderText($title);
38
+
39
+ return Mage_Core_Block_Template::_prepareLayout();
40
+ }
41
+ }
app/code/community/Bitbull/Tooso/Block/Rebuild.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Bitbull_Tooso
4
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
5
+ */
6
+
7
+ class Bitbull_Tooso_Block_Rebuild extends Mage_Adminhtml_Block_System_Config_Form_Field
8
+ {
9
+ /**
10
+ * Return element html
11
+ *
12
+ * @param Varien_Data_Form_Element_Abstract $element
13
+ * @return string
14
+ */
15
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
16
+ {
17
+ $this->setElement($element);
18
+ $url = $this->getUrl('*/tooso/rebuild');
19
+
20
+ $html = $this->getLayout()->createBlock('adminhtml/widget_button')
21
+ ->setType('button')
22
+ ->setClass('rebuild')
23
+ ->setLabel('Rebuild index')
24
+ ->setOnClick("setLocation('".$url."')")
25
+ ->toHtml();
26
+
27
+ return $html;
28
+ }
29
+ }
app/code/community/Bitbull/Tooso/Helper/CatalogSearch/Data.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Helper_CatalogSearch_Data extends Mage_CatalogSearch_Helper_Data
8
+ {
9
+ /**
10
+ * Retrieve query model object
11
+ *
12
+ * @return Mage_CatalogSearch_Model_Query
13
+ */
14
+ public function getQuery()
15
+ {
16
+ if (!$this->_query) {
17
+ if (Mage::helper('tooso')->isTypoCorrectedSearch()) {
18
+ $this->_query = Mage::getModel('catalogsearch/query')
19
+ ->loadByQuery($this->getQueryText());
20
+ } else {
21
+ $this->_query = Mage::getModel('catalogsearch/query')
22
+ ->loadByQueryText($this->getQueryText());
23
+ }
24
+
25
+ if (!$this->_query->getId()) {
26
+ $this->_query->setQueryText($this->getQueryText());
27
+ }
28
+ }
29
+ return $this->_query;
30
+ }
31
+
32
+
33
+ }
app/code/community/Bitbull/Tooso/Helper/Data.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Bitbull_Tooso
4
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
5
+ */
6
+
7
+ class Bitbull_Tooso_Helper_Data extends Mage_Core_Helper_Abstract
8
+ {
9
+ const XML_PATH_ENABLE_SEARCH = 'tooso/active/frontend';
10
+
11
+ const XML_PATH_ENABLE_INDEX = 'tooso/active/index';
12
+
13
+ protected $_fixedSearchString = null;
14
+
15
+ protected $_searchId = null;
16
+
17
+ protected $_products = null;
18
+
19
+ /**
20
+ * @return array
21
+ */
22
+ public function getProducts()
23
+ {
24
+ return $this->_products;
25
+ }
26
+
27
+ /**
28
+ * @param array $products
29
+ */
30
+ public function setProducts($products)
31
+ {
32
+ $this->_products = $products;
33
+ }
34
+
35
+ /**
36
+ * @param string $fixedSearchString
37
+ */
38
+ public function setFixedSearchString($fixedSearchString)
39
+ {
40
+ $this->_fixedSearchString = $fixedSearchString;
41
+ }
42
+
43
+ /**
44
+ * @return string
45
+ */
46
+ public function getFixedSearchString()
47
+ {
48
+ return $this->_fixedSearchString;
49
+ }
50
+
51
+ /**
52
+ * @param string $searchId
53
+ */
54
+ public function setSearchId($searchId)
55
+ {
56
+ $this->_searchId = $searchId;
57
+ }
58
+
59
+ /**
60
+ * @return string
61
+ */
62
+ public function getSearchId()
63
+ {
64
+ return $this->_searchId;
65
+ }
66
+
67
+ public function isTypoCorrectedSearch()
68
+ {
69
+ return Mage::app()->getRequest()->getParam('typoCorrection', 'true') == 'true';
70
+ }
71
+
72
+ /**
73
+ * Create and configure a Tooso API Client instance
74
+ *
75
+ * @return Bitbull_Tooso_Client
76
+ */
77
+ public function getClient()
78
+ {
79
+ $apiKey = Mage::getStoreConfig('tooso/server/api_key');
80
+ $language = Mage::app()->getLocale()->getLocaleCode();
81
+ $storeCode = Mage::app()->getStore()->getCode();
82
+
83
+ $client = new Bitbull_Tooso_Client($apiKey, $language, $storeCode);
84
+
85
+ $client->setReportSender(Mage::helper('tooso/log_send'));
86
+
87
+ return $client;
88
+ }
89
+
90
+ /**
91
+ * @return array
92
+ */
93
+ public function getProfilingParams()
94
+ {
95
+ $customerSession = Mage::getSingleton('customer/session');
96
+ $sessionId = Mage::getSingleton('core/session')->getSessionId();
97
+
98
+ if ($customerSession->isLoggedIn()) {
99
+ $userId = $customerSession->getCustomerId();
100
+ } else {
101
+ $userId = $sessionId;
102
+ }
103
+
104
+ return array(
105
+ 'userId' => $userId,
106
+ 'sessionId' => $sessionId,
107
+ );
108
+ }
109
+ }
app/code/community/Bitbull/Tooso/Helper/Log.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Helper_Log extends Mage_Core_Helper_Abstract
8
+ {
9
+ const LOG_FILENAME = 'tooso_search.log';
10
+
11
+ const XML_PATH_FORCE_LOG = 'tooso/server/force_log';
12
+
13
+ /**
14
+ * Retrieve Tooso Log File
15
+ *
16
+ * @return string
17
+ */
18
+ public function getLogFile()
19
+ {
20
+ return self::LOG_FILENAME;
21
+ }
22
+
23
+ /**
24
+ * Logging facility
25
+ *
26
+ * @param string $message
27
+ * @param string $level
28
+ */
29
+ public function log($message, $level = null)
30
+ {
31
+ $forceLog = Mage::getStoreConfigFlag(self::XML_PATH_FORCE_LOG);
32
+
33
+ Mage::log($message, $level, $this->getLogFile(), $forceLog);
34
+ }
35
+
36
+ public function logException(Exception $e)
37
+ {
38
+ if ($e instanceof Bitbull_Tooso_Exception) {
39
+ $message = $e->getMessage() . ' - ERROR CODE = ' . $e->getCode() . ($e->getDebugInfo() ? ' - DEBUG INFO = ' . $e->getDebugInfo() : '');
40
+
41
+ $this->log($message, Zend_Log::ERR);
42
+ }
43
+
44
+ Mage::logException($e);
45
+ }
46
+ }
app/code/community/Bitbull/Tooso/Helper/Log/Send.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Helper_Log_Send extends Mage_Core_Helper_Abstract implements Bitbull_Tooso_Log_SendInterface
8
+ {
9
+ const DEBUG_EMAIL_ADDRESS = 'alert@tooso.ai';
10
+
11
+ const DEBUG_EMAIL_ADDRESS_CC = 'gennaro.vietri@bitbull.it';
12
+
13
+ const XML_PATH_SEND_REPORT = 'tooso/server/send_report';
14
+
15
+ const EMAIL_TEMPLATE = 'tooso_alert_email_template';
16
+
17
+ /**
18
+ * Send report via email
19
+ *
20
+ * @param string $url
21
+ * @param string $httpMethod
22
+ * @param string $apiKey
23
+ * @param string $language
24
+ * @param string $storeCode
25
+ * @param string $message
26
+ */
27
+ public function sendReport($url, $httpMethod, $apiKey, $language, $storeCode, $message)
28
+ {
29
+ $sendReport = Mage::getStoreConfigFlag(self::XML_PATH_SEND_REPORT);
30
+
31
+ if ($sendReport) {
32
+
33
+ $data = array(
34
+ 'currentDate' => Mage::getModel('core/date')->date('Y-m-d H:i:s'),
35
+ 'storeName' => Mage::app()->getStore()->getFrontendName(),
36
+ 'currentUrl' => Mage::helper('core/url')->getCurrentUrl(),
37
+ 'language' => $language,
38
+ 'storeCode' => $storeCode,
39
+ 'apiKey' => $apiKey,
40
+ 'url' => $url,
41
+ 'message' => $message,
42
+ 'httpMethod' => $httpMethod,
43
+ );
44
+
45
+ $dataObject = new Varien_Object();
46
+ $dataObject->setData($data);
47
+
48
+ /* @var $mailTemplate Mage_Core_Model_Email_Template */
49
+ $mailTemplate = Mage::getModel('core/email_template');
50
+
51
+ try {
52
+ $mailTemplate
53
+ ->setDesignConfig(array('area' => 'admin'))
54
+ ->sendTransactional(
55
+ self::EMAIL_TEMPLATE,
56
+ array(
57
+ 'name' => 'Tooso report',
58
+ 'email' => self::DEBUG_EMAIL_ADDRESS,
59
+ ),
60
+ array(
61
+ self::DEBUG_EMAIL_ADDRESS,
62
+ self::DEBUG_EMAIL_ADDRESS_CC
63
+ ),
64
+ null,
65
+ array('data' => $dataObject)
66
+ );
67
+ }
68
+ catch(Exception $error) {}
69
+ }
70
+ }
71
+ }
app/code/community/Bitbull/Tooso/Model/CatalogSearch/Resource/Fulltext.php ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Bitbull_Tooso
4
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
5
+ */
6
+
7
+ class Bitbull_Tooso_Model_CatalogSearch_Resource_Fulltext extends Mage_CatalogSearch_Model_Resource_Fulltext
8
+ {
9
+ /**
10
+ * @var Bitbull_Tooso_Helper_Log
11
+ */
12
+ protected $_logger = null;
13
+
14
+ public function _construct()
15
+ {
16
+ parent::_construct();
17
+
18
+ $this->_logger = Mage::helper('tooso/log');
19
+ }
20
+
21
+ /**
22
+ * Prepare results for query.
23
+ * Replaces the built-in fulltext search with a Tooso search (if active).
24
+ *
25
+ * @param Mage_CatalogSearch_Model_Fulltext $object
26
+ * @param string $queryText
27
+ * @param Mage_CatalogSearch_Model_Query $query
28
+ * @return Bitbull_Tooso_Model_CatalogSearch_Resource_Fulltext
29
+ */
30
+ public function prepareResult($object, $queryText, $query)
31
+ {
32
+ if (!Mage::getStoreConfigFlag(Bitbull_Tooso_Helper_Data::XML_PATH_ENABLE_SEARCH)) {
33
+ return parent::prepareResult($object, $queryText, $query);
34
+ }
35
+
36
+ $search = null;
37
+
38
+ if (null == Mage::helper('tooso')->getProducts()) {
39
+
40
+ try {
41
+ $search = Mage::getModel('tooso/search')->search($queryText, Mage::helper('tooso')->isTypoCorrectedSearch());
42
+
43
+ // It's true if no errors was given by API call
44
+ if ($search->isSearchAvailable()) {
45
+
46
+ $products = array();
47
+ foreach ($search->getProducts() as $product) {
48
+ $products[] = $product['product_id'];
49
+ }
50
+
51
+ // Store products ids for later use them to build database query
52
+ Mage::helper('tooso')->setProducts($products);
53
+
54
+ // If this query was automatically typo-corrected, save in request scope the searchId for link
55
+ // this query (the parent) with the following one forced as not typo-correct
56
+ if (Mage::helper('tooso')->isTypoCorrectedSearch()) {
57
+ Mage::helper('tooso')->setSearchId($search->getSearchId());
58
+ }
59
+
60
+ } else {
61
+ return parent::prepareResult($object, $queryText, $query);
62
+ }
63
+
64
+ } catch (Exception $e) {
65
+ $this->_logger->logException($e);
66
+
67
+ return parent::prepareResult($object, $queryText, $query);
68
+ }
69
+ }
70
+
71
+ // If this query was typo-corrected, build the link to the same query but with typo-correction disabled
72
+ // and build the message that will be shown to the user
73
+ if ($search
74
+ && $search->getFixedSearchString()
75
+ && Mage::helper('catalogsearch')->getQueryText() == $search->getOriginalSearchString()) {
76
+
77
+ $queryString = array(
78
+ 'q' => $search->getOriginalSearchString(),
79
+ 'typoCorrection' => 'false',
80
+ Bitbull_Tooso_Model_Search::SEARCH_PARAM_PARENT_SEARCH_ID => Mage::helper('tooso')->getSearchId()
81
+ );
82
+
83
+ $message = sprintf(
84
+ 'Search instead for "<a href="%s">%s</a>"',
85
+ Mage::getUrl('catalogsearch/result', array('_query' => $queryString)),
86
+ $search->getOriginalSearchString()
87
+ );
88
+ Mage::helper('catalogsearch')->addNoteMessage($message);
89
+ Mage::helper('tooso')->setFixedSearchString($search->getFixedSearchString());
90
+ }
91
+
92
+ return $this;
93
+ }
94
+
95
+ // Following methods can't be implemented so far, because reindex
96
+ // is ever performed async with a cronjob, and can be forced only
97
+ // with the button in the config admin panel
98
+
99
+ // /**
100
+ // * Regenerate search index for store(s)
101
+ // *
102
+ // * @param int|null $storeId
103
+ // * @param int|array|null $productIds
104
+ // * @return Bitbull_Tooso_Model_CatalogSearch_Resource_Fulltext
105
+ // */
106
+ // public function rebuildIndex($storeId = null, $productIds = null)
107
+ // {
108
+ // if (Mage::getStoreConfigFlag('tooso/active/admin')) {
109
+ // Mage::getModel('tooso/indexer')->rebuildIndex();
110
+ // }
111
+ //
112
+ // parent::rebuildIndex($storeId, $productIds);
113
+ //
114
+ // return $this;
115
+ // }
116
+ //
117
+ // /**
118
+ // * Clean index for store(s)
119
+ // *
120
+ // * @param int $storeId Store View Id
121
+ // * @param int|array|null $productIds Product Entity Id
122
+ // * @return Mage_CatalogSearch_Model_Resource_Fulltext
123
+ // */
124
+ // public function cleanIndex($storeId = null, $productIds = null)
125
+ // {
126
+ // parent::cleanIndex($storeId, $productIds);
127
+ //
128
+ // if (Mage::getStoreConfigFlag('tooso/active/admin')) {
129
+ // Mage::getModel('tooso/indexer')->cleanIndex();
130
+ // }
131
+ //
132
+ // return $this;
133
+ // }
134
+ }
app/code/community/Bitbull/Tooso/Model/Document.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Bitbull_Tooso
4
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
5
+ */
6
+ class Bitbull_Tooso_Model_Document
7
+ {
8
+
9
+ }
app/code/community/Bitbull/Tooso/Model/Export/Adapter/Csv.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Bitbull_Tooso
4
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
5
+ */
6
+ class Bitbull_Tooso_Model_Export_Adapter_Csv extends Mage_ImportExport_Model_Export_Adapter_Csv
7
+ {
8
+ /**
9
+ * Close file handler on shutdown
10
+ * and delete the temporary file
11
+ */
12
+ public function destruct()
13
+ {
14
+ if (is_resource($this->_fileHandler)) {
15
+ fclose($this->_fileHandler);
16
+ }
17
+
18
+ if (file_exists($this->_destination)) {
19
+ unlink($this->_destination);
20
+ }
21
+ }
22
+ }
app/code/community/Bitbull/Tooso/Model/Indexer.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Bitbull_Tooso
4
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
5
+ */
6
+
7
+ class Bitbull_Tooso_Model_Indexer
8
+ {
9
+ /**
10
+ * Client for API comunication
11
+ *
12
+ * @var Bitbull_Tooso_Client
13
+ */
14
+ protected $_client;
15
+
16
+ /**
17
+ * @var Bitbull_Tooso_Helper_Log
18
+ */
19
+ protected $_logger = null;
20
+
21
+ public function __construct()
22
+ {
23
+ $this->_client = Mage::helper('tooso')->getClient();
24
+
25
+ $this->_logger = Mage::helper('tooso/log');
26
+ }
27
+
28
+ /**
29
+ * Rebuild Tooso Index
30
+ *
31
+ * @return boolean
32
+ */
33
+ public function rebuildIndex()
34
+ {
35
+ try {
36
+ $this->_client->index($this->_getCsvContent());
37
+ } catch (Exception $e) {
38
+ $this->_logger->logException($e);
39
+
40
+ return false;
41
+ }
42
+
43
+ return true;
44
+ }
45
+
46
+ /**
47
+ * Clean Tooso Index
48
+ *
49
+ * @todo Should be implemented, but so far Tooso don't support index cleaning
50
+ *
51
+ * @return boolean
52
+ */
53
+ public function cleanIndex()
54
+ {
55
+ return true;
56
+ }
57
+
58
+ /**
59
+ * return string
60
+ */
61
+ protected function _getCsvContent()
62
+ {
63
+ /** @var $model Mage_ImportExport_Model_Export */
64
+ $model = Mage::getModel('importexport/export');
65
+ $model->setData(array(
66
+ 'entity' => 'catalog_product',
67
+ 'file_format' => 'tooso_csv',
68
+ 'export_filter' => array(),
69
+ ));
70
+
71
+ return $model->export();
72
+ }
73
+ }
app/code/community/Bitbull/Tooso/Model/Observer.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Model_Observer
8
+ {
9
+ /**
10
+ * @var Bitbull_Tooso_Helper_Log
11
+ */
12
+ protected $_logger = null;
13
+
14
+ public function __construct()
15
+ {
16
+ $this->_logger = Mage::helper('tooso/log');
17
+ }
18
+
19
+ /**
20
+ * Regenerate search index
21
+ *
22
+ * @param Mage_Cron_Model_Schedule $schedule
23
+ * @return Bitbull_Tooso_Model_Observer
24
+ */
25
+ public function rebuildIndex(Mage_Cron_Model_Schedule $schedule)
26
+ {
27
+ if (Mage::getStoreConfigFlag(Bitbull_Tooso_Helper_Data::XML_PATH_ENABLE_INDEX)) {
28
+ $this->_logger->log('Start scheduled reindex', Zend_Log::DEBUG);
29
+
30
+ Mage::getModel('tooso/indexer')->rebuildIndex();
31
+
32
+ $this->_logger->log('End scheduled reindex', Zend_Log::DEBUG);
33
+ }
34
+
35
+ return $this;
36
+ }
37
+ }
app/code/community/Bitbull/Tooso/Model/Resource/CatalogSearch/Fulltext/Collection.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Model_Resource_CatalogSearch_Fulltext_Collection extends Mage_CatalogSearch_Model_Resource_Fulltext_Collection
8
+ {
9
+ /**
10
+ * Filter database query using the products ids
11
+ * retrieved from API call.
12
+ *
13
+ * @param string $query
14
+ * @return Mage_CatalogSearch_Model_Resource_Fulltext_Collection
15
+ */
16
+ public function addSearchFilter($query)
17
+ {
18
+ Mage::getSingleton('catalogsearch/fulltext')->prepareResult();
19
+
20
+ $products = Mage::helper('tooso')->getProducts();
21
+ $this->addFieldToFilter('entity_id', array('in' => (sizeof($products) > 0) ? $products : array(0)));
22
+
23
+ return $this;
24
+ }
25
+
26
+ /**
27
+ * Set Order field
28
+ *
29
+ * @param string $attribute
30
+ * @param string $dir
31
+ * @return Mage_CatalogSearch_Model_Resource_Fulltext_Collection
32
+ */
33
+ public function setOrder($attribute, $dir = 'desc')
34
+ {
35
+ if ($attribute == 'relevance') {
36
+ $products = Mage::helper('tooso')->getProducts();
37
+
38
+ // If the order criteria is the relevance, we need to respect the order of products ids given by API call
39
+ if (sizeof($products) > 0) {
40
+ $this->getSelect()->order(new Zend_Db_Expr('FIELD(e.entity_id, ' . implode(',', $products) . ')'));
41
+ }
42
+ } else {
43
+ parent::setOrder($attribute, $dir);
44
+ }
45
+ return $this;
46
+ }
47
+ }
app/code/community/Bitbull/Tooso/Model/Resource/CatalogSearch/Query.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Model_Resource_CatalogSearch_Query extends Mage_CatalogSearch_Model_Resource_Query
8
+ {
9
+ /**
10
+ * Custom load model by search query string.
11
+ * Extended to alter sort direction for synonym_for
12
+ *
13
+ * @param Mage_Core_Model_Abstract $object
14
+ * @param string $value
15
+ * @return Mage_CatalogSearch_Model_Resource_Query
16
+ */
17
+ public function loadByQuery(Mage_Core_Model_Abstract $object, $value)
18
+ {
19
+ $readAdapter = $this->_getReadAdapter();
20
+ $select = $readAdapter->select();
21
+
22
+ $synonymSelect = clone $select;
23
+ $synonymSelect
24
+ ->from($this->getMainTable())
25
+ ->where('store_id = ?', $object->getStoreId());
26
+
27
+ $querySelect = clone $synonymSelect;
28
+ $querySelect->where('query_text = ?', $value);
29
+
30
+ $synonymSelect->where('synonym_for = ?', $value);
31
+
32
+ $select->union(array($querySelect, "($synonymSelect)"), Zend_Db_Select::SQL_UNION_ALL)
33
+ ->order('synonym_for ' . (Mage::helper('tooso')->isTypoCorrectedSearch() ? 'DESC' : 'ASC'))
34
+ ->limit(1);
35
+
36
+ $data = $readAdapter->fetchRow($select);
37
+ if ($data) {
38
+ $object->setData($data);
39
+ $this->_afterLoad($object);
40
+ }
41
+
42
+ return $this;
43
+ }
44
+ }
app/code/community/Bitbull/Tooso/Model/Search.php ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Bitbull_Tooso
4
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
5
+ */
6
+ class Bitbull_Tooso_Model_Search
7
+ {
8
+ const SEARCH_PARAM_IP_ADDRESS = 'ip';
9
+ const SEARCH_PARAM_PARENT_SEARCH_ID = 'parentSearchId';
10
+
11
+ /**
12
+ * Client for API comunication
13
+ *
14
+ * @var Bitbull_Tooso_Client
15
+ */
16
+ protected $_client;
17
+
18
+ /**
19
+ * Represents a Tooso search result.
20
+ *
21
+ * @var Bitbull_Tooso_Search_Result
22
+ */
23
+ protected $_result;
24
+
25
+ /**
26
+ * Read connection
27
+ *
28
+ * @var Varien_Db_Adapter_Pdo_Mysql
29
+ */
30
+ protected $_readAdapter;
31
+
32
+ /**
33
+ * @var Bitbull_Tooso_Helper_Log
34
+ */
35
+ protected $_logger = null;
36
+
37
+ /**
38
+ * Constructor, retrieve config for connection to Tooso API.
39
+ */
40
+ public function __construct()
41
+ {
42
+ $this->_client = Mage::helper('tooso')->getClient();
43
+
44
+ $this->_logger = Mage::helper('tooso/log');
45
+ }
46
+
47
+ /**
48
+ * Load query and set response
49
+ *
50
+ * @param string $query
51
+ * @param boolean $typoCorrection
52
+ * @param string $parentSearchId
53
+ * @return Bitbull_Tooso_Model_Search
54
+ */
55
+ public function search($query, $typoCorrection = true, $parentSearchId = null)
56
+ {
57
+ $query = urlencode($query);
58
+ if ($query) {
59
+ try {
60
+ $params = Mage::helper('tooso')->getProfilingParams();
61
+ $params[self::SEARCH_PARAM_IP_ADDRESS] = Mage::helper('core/http')->getRemoteAddr();
62
+
63
+ if (!is_null($parentSearchId)) {
64
+ $params[self::SEARCH_PARAM_PARENT_SEARCH_ID] = $parentSearchId;
65
+ }
66
+
67
+ $result = $this->_client->search($query, $typoCorrection, $params);
68
+ $this->setResult($result);
69
+ } catch (Exception $e) {
70
+ $this->_logger->logException($e);
71
+ }
72
+ }
73
+
74
+ return $this;
75
+ }
76
+
77
+ /**
78
+ * Set Tooso response
79
+ *
80
+ * @param Bitbull_Tooso_Search_Result $result
81
+ */
82
+ public function setResult(Bitbull_Tooso_Search_Result $result)
83
+ {
84
+ $this->_result = $result;
85
+ }
86
+
87
+ /**
88
+ * Extract product ids and score from Tooso response
89
+ *
90
+ * @return array
91
+ */
92
+ public function getProducts()
93
+ {
94
+ $products = array();
95
+
96
+ if (!is_null($this->_result)) {
97
+ $skus = $this->_result->getResults();
98
+
99
+ $i = 1;
100
+ $productIds = $this->_getIdsBySkus($skus);
101
+
102
+ foreach ($productIds as $sku => $productId) {
103
+ $products[] = array(
104
+ 'sku' => $sku,
105
+ 'product_id' => $productId,
106
+ 'relevance' => $i
107
+ );
108
+
109
+ $i++;
110
+ }
111
+ }
112
+
113
+ return $products;
114
+ }
115
+
116
+ public function getFixedSearchString()
117
+ {
118
+ return (!is_null($this->_result) ? $this->_result->getFixedSearchString() : null);
119
+ }
120
+
121
+ public function getOriginalSearchString()
122
+ {
123
+ return (!is_null($this->_result) ? $this->_result->getOriginalSearchString() : null);
124
+ }
125
+
126
+ public function getParentSearchId()
127
+ {
128
+ return (!is_null($this->_result) ? $this->_result->getParentSearchId() : null);
129
+ }
130
+
131
+ public function getSearchId()
132
+ {
133
+ return (!is_null($this->_result) ? $this->_result->getSearchId() : null);
134
+ }
135
+
136
+ /**
137
+ * Retreive documents count
138
+ *
139
+ * @return int
140
+ */
141
+ public function count()
142
+ {
143
+ return (!is_null($this->_result) ? $this->_result->getTotalResults() : 0);
144
+ }
145
+
146
+ /**
147
+ * Is search available?
148
+ *
149
+ * @return boolean
150
+ */
151
+ public function isSearchAvailable()
152
+ {
153
+ return !is_null($this->_result);
154
+ }
155
+
156
+ /**
157
+ * Retrieve Store Id
158
+ *
159
+ * @return int
160
+ */
161
+ public function getStoreId()
162
+ {
163
+ return Mage::app()->getStore()->getId();
164
+ }
165
+
166
+ /**
167
+ * Get products identifiers by skus
168
+ *
169
+ * @param array $skus
170
+ * @return array
171
+ */
172
+ protected function _getIdsBySkus($skus)
173
+ {
174
+ $adapter = $this->_getReadAdapter();
175
+
176
+ $skusCount = count($skus);
177
+
178
+ if ($skusCount == 0) return array();
179
+
180
+ $where = 'sku IN (';
181
+ $bind = array();
182
+
183
+ // Build the where clause with all the required placeholder for binding
184
+ for ($i=0; $i<$skusCount; $i++) {
185
+ $bind[':sku' . $i] = $skus[$i];
186
+ }
187
+
188
+ $where .= implode(',', array_keys($bind)) . ')';
189
+
190
+ $select = $adapter->select()
191
+ ->from(Mage::getResourceSingleton('catalog/product')->getEntityTable(), array('sku', 'entity_id'))
192
+ ->where($where);
193
+
194
+ return $adapter->fetchPairs($select, $bind);
195
+ }
196
+
197
+ /**
198
+ * Retrieve connection for read data
199
+ *
200
+ * @return Varien_Db_Adapter_Interface
201
+ */
202
+ protected function _getReadAdapter()
203
+ {
204
+ if (is_null($this->_readAdapter)) {
205
+ $this->_readAdapter = Mage::getSingleton('core/resource')->getConnection('core_read');
206
+ }
207
+
208
+ return $this->_readAdapter;
209
+ }
210
+ }
app/code/community/Bitbull/Tooso/Model/Suggest.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Model_Suggest
8
+ {
9
+ /**
10
+ * Client for API comunication
11
+ *
12
+ * @var Bitbull_Tooso_Client
13
+ */
14
+ protected $_client;
15
+
16
+ /**
17
+ * Represents a Tooso search result.
18
+ *
19
+ * @var Bitbull_Tooso_Suggest_Result
20
+ */
21
+ protected $_result;
22
+
23
+ /**
24
+ * @var Bitbull_Tooso_Helper_Log
25
+ */
26
+ protected $_logger = null;
27
+
28
+ protected $_maxResults = 10;
29
+
30
+ /**
31
+ * Constructor, retrieve config for connection to Tooso API.
32
+ */
33
+ public function __construct()
34
+ {
35
+ $this->_client = Mage::helper('tooso')->getClient();
36
+
37
+ $this->_logger = Mage::helper('tooso/log');
38
+
39
+ $this->_maxResults = (int)Mage::getStoreConfig('tooso/suggest/max_results');
40
+ }
41
+
42
+ /**
43
+ * @param string $query
44
+ * @return Bitbull_Tooso_Model_Suggest
45
+ */
46
+ public function suggest($query)
47
+ {
48
+ $query = urlencode($query);
49
+ if ($query) {
50
+ try {
51
+ $params = Mage::helper('tooso')->getProfilingParams();
52
+
53
+ $result = $this->_client->suggest($query, $this->_maxResults, $params);
54
+ $this->setResult($result);
55
+ } catch (Exception $e) {
56
+ $this->_logger->logException($e);
57
+ }
58
+ }
59
+
60
+ return $this;
61
+ }
62
+
63
+ /**
64
+ * Set Tooso response
65
+ *
66
+ * @param Bitbull_Tooso_Suggest_Result $result
67
+ */
68
+ public function setResult(Bitbull_Tooso_Suggest_Result $result)
69
+ {
70
+ $this->_result = $result;
71
+ }
72
+
73
+ public function getSuggestions()
74
+ {
75
+ $suggestions = array();
76
+
77
+ if (!is_null($this->_result)) {
78
+ $results = $this->_result->getSuggestions();
79
+
80
+ foreach ($results as $suggestedString => $occurrence) {
81
+ $suggestions[] = new Varien_Object(array(
82
+ 'query_text' => $suggestedString,
83
+ 'num_results' => (int)$occurrence
84
+ ));
85
+ }
86
+ }
87
+
88
+ return $suggestions;
89
+ }
90
+ }
app/code/community/Bitbull/Tooso/controllers/Adminhtml/ToosoController.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Bitbull_Tooso
4
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
5
+ */
6
+ class Bitbull_Tooso_Adminhtml_ToosoController extends Mage_Adminhtml_Controller_Action
7
+ {
8
+ /**
9
+ * Rebuild action
10
+ */
11
+ public function rebuildAction()
12
+ {
13
+ $session = Mage::getSingleton('adminhtml/session');
14
+
15
+ if (Mage::getModel('tooso/indexer')->rebuildIndex()) {
16
+ $session->addSuccess(Mage::helper('tooso')->__('Catalog data have been successfully sent to Tooso.'));
17
+ } else {
18
+ $session->addNotice(Mage::helper('tooso')->__('Can not sent data to Tooso, please see log for details.'));
19
+ }
20
+
21
+ $this->_redirect('*/system_config/edit', array('section' => 'tooso'));
22
+
23
+ return;
24
+ }
25
+ }
app/code/community/Bitbull/Tooso/etc/adminhtml.xml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ -->
8
+ <config>
9
+ <acl>
10
+ <resources>
11
+ <admin>
12
+ <children>
13
+ <system>
14
+ <children>
15
+ <config>
16
+ <children>
17
+ <tooso translate="title" module="tooso">
18
+ <title>Tooso Search</title>
19
+ </tooso>
20
+ </children>
21
+ </config>
22
+ </children>
23
+ </system>
24
+ </children>
25
+ </admin>
26
+ </resources>
27
+ </acl>
28
+ </config>
app/code/community/Bitbull/Tooso/etc/config.xml ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ -->
8
+ <config>
9
+ <modules>
10
+ <Bitbull_Tooso>
11
+ <version>1.0.0</version>
12
+ </Bitbull_Tooso>
13
+ </modules>
14
+ <global>
15
+ <models>
16
+ <tooso>
17
+ <class>Bitbull_Tooso_Model</class>
18
+ </tooso>
19
+ <catalogsearch_resource>
20
+ <rewrite>
21
+ <fulltext>Bitbull_Tooso_Model_CatalogSearch_Resource_Fulltext</fulltext>
22
+ <query>Bitbull_Tooso_Model_Resource_CatalogSearch_Query</query>
23
+ <fulltext_collection>Bitbull_Tooso_Model_Resource_CatalogSearch_Fulltext_Collection</fulltext_collection>
24
+ </rewrite>
25
+ </catalogsearch_resource>
26
+ </models>
27
+ <resources>
28
+ <tooso_setup>
29
+ <setup>
30
+ <module>Bitbull_Tooso</module>
31
+ </setup>
32
+ </tooso_setup>
33
+ </resources>
34
+ <helpers>
35
+ <tooso>
36
+ <class>Bitbull_Tooso_Helper</class>
37
+ </tooso>
38
+ <catalogsearch>
39
+ <rewrite>
40
+ <data>Bitbull_Tooso_Helper_CatalogSearch_Data</data>
41
+ </rewrite>
42
+ </catalogsearch>
43
+ </helpers>
44
+ <blocks>
45
+ <tooso>
46
+ <class>Bitbull_Tooso_Block</class>
47
+ </tooso>
48
+ <catalogsearch>
49
+ <rewrite>
50
+ <result>Bitbull_Tooso_Block_CatalogSearch_Result</result>
51
+ <autocomplete>Bitbull_Tooso_Block_CatalogSearch_Autocomplete</autocomplete>
52
+ </rewrite>
53
+ </catalogsearch>
54
+ </blocks>
55
+ <template>
56
+ <email>
57
+ <tooso_alert_email_template translate="label" module="tooso">
58
+ <label>Send report for API error</label>
59
+ <file>tooso_alert.html</file>
60
+ <type>html</type>
61
+ </tooso_alert_email_template>
62
+ </email>
63
+ </template>
64
+ <importexport>
65
+ <export_file_formats>
66
+ <tooso_csv translate="label">
67
+ <model_token>tooso/export_adapter_csv</model_token>
68
+ <label>CSV</label>
69
+ </tooso_csv>
70
+ </export_file_formats>
71
+ </importexport>
72
+ </global>
73
+ <admin>
74
+ <routers>
75
+ <adminhtml>
76
+ <args>
77
+ <modules>
78
+ <Bitbull_Tooso before="Mage_Adminhtml">Bitbull_Tooso_Adminhtml</Bitbull_Tooso>
79
+ </modules>
80
+ </args>
81
+ </adminhtml>
82
+ </routers>
83
+ </admin>
84
+ <default>
85
+ <tooso>
86
+ <active>
87
+ <frontend>0</frontend>
88
+ <index>0</index>
89
+ </active>
90
+ <server>
91
+ <api_key />
92
+ <send_report>1</send_report>
93
+ <force_log>1</force_log>
94
+ </server>
95
+ <suggest>
96
+ <max_results>10</max_results>
97
+ </suggest>
98
+ </tooso>
99
+ </default>
100
+ <crontab>
101
+ <jobs>
102
+ <tooso_reindex>
103
+ <schedule>
104
+ <cron_expr>*/15 * * * *</cron_expr>
105
+ </schedule>
106
+ <run>
107
+ <model>tooso/observer::rebuildIndex</model>
108
+ </run>
109
+ </tooso_reindex>
110
+ </jobs>
111
+ </crontab>
112
+ </config>
app/code/community/Bitbull/Tooso/etc/system.xml ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ -->
8
+ <config>
9
+ <sections>
10
+ <tooso translate="label" module="tooso">
11
+ <label>Tooso Search Engine</label>
12
+ <tab>catalog</tab>
13
+ <sort_order>9000</sort_order>
14
+ <show_in_default>1</show_in_default>
15
+ <show_in_website>1</show_in_website>
16
+ <show_in_store>1</show_in_store>
17
+ <groups>
18
+ <active translate="label">
19
+ <label>Active Tooso</label>
20
+ <frontend_type>text</frontend_type>
21
+ <sort_order>10</sort_order>
22
+ <show_in_default>1</show_in_default>
23
+ <show_in_website>1</show_in_website>
24
+ <show_in_store>1</show_in_store>
25
+ <fields>
26
+ <frontend translate="label">
27
+ <label>Enable Search</label>
28
+ <frontend_type>select</frontend_type>
29
+ <source_model>adminhtml/system_config_source_yesno</source_model>
30
+ <sort_order>1</sort_order>
31
+ <show_in_default>1</show_in_default>
32
+ <show_in_website>1</show_in_website>
33
+ <show_in_store>1</show_in_store>
34
+ <comment><![CDATA[Use Tooso for search on frontend]]></comment>
35
+ </frontend>
36
+ <index translate="label">
37
+ <label>Enable Indexing</label>
38
+ <frontend_type>select</frontend_type>
39
+ <source_model>adminhtml/system_config_source_yesno</source_model>
40
+ <sort_order>2</sort_order>
41
+ <show_in_default>1</show_in_default>
42
+ <show_in_website>1</show_in_website>
43
+ <show_in_store>1</show_in_store>
44
+ <comment><![CDATA[Enable/disable scheduled reindex process]]></comment>
45
+ </index>
46
+ </fields>
47
+ </active>
48
+ <server translate="label">
49
+ <label>API Configuration</label>
50
+ <frontend_type>text</frontend_type>
51
+ <sort_order>20</sort_order>
52
+ <show_in_default>1</show_in_default>
53
+ <show_in_website>1</show_in_website>
54
+ <show_in_store>1</show_in_store>
55
+ <fields>
56
+ <api_key translate="label">
57
+ <label>API key</label>
58
+ <frontend_type>text</frontend_type>
59
+ <sort_order>10</sort_order>
60
+ <show_in_default>1</show_in_default>
61
+ <show_in_website>1</show_in_website>
62
+ <show_in_store>1</show_in_store>
63
+ </api_key>
64
+ <send_report>
65
+ <label>Send report</label>
66
+ <frontend_type>select</frontend_type>
67
+ <source_model>adminhtml/system_config_source_yesno</source_model>
68
+ <sort_order>20</sort_order>
69
+ <show_in_default>1</show_in_default>
70
+ <show_in_website>1</show_in_website>
71
+ <show_in_store>1</show_in_store>
72
+ <comment><![CDATA[Send a report to Tooso when an API error occourred]]></comment>
73
+ </send_report>
74
+ <force_log>
75
+ <label>Force logging</label>
76
+ <frontend_type>select</frontend_type>
77
+ <source_model>adminhtml/system_config_source_yesno</source_model>
78
+ <sort_order>30</sort_order>
79
+ <show_in_default>1</show_in_default>
80
+ <show_in_website>1</show_in_website>
81
+ <show_in_store>1</show_in_store>
82
+ <comment><![CDATA[Force logging to {{base_dir}}/var/log/tooso_search.log even when logging is disabled]]></comment>
83
+ </force_log>
84
+ </fields>
85
+ </server>
86
+ <!--index translate="label">
87
+ <label>Index</label>
88
+ <frontend_type>text</frontend_type>
89
+ <sort_order>30</sort_order>
90
+ <show_in_default>1</show_in_default>
91
+ <show_in_website>1</show_in_website>
92
+ <show_in_store>1</show_in_store>
93
+ <fields>
94
+ <rebuild translate="label">
95
+ <label>Rebuild index</label>
96
+ <frontend_type>button</frontend_type>
97
+ <frontend_model>tooso/rebuild</frontend_model>
98
+ <sort_order>20</sort_order>
99
+ <show_in_default>1</show_in_default>
100
+ <show_in_website>1</show_in_website>
101
+ <show_in_store>1</show_in_store>
102
+ </rebuild>
103
+ </fields>
104
+ </index-->
105
+ <suggest translate="label">
106
+ <label>Suggest</label>
107
+ <frontend_type>text</frontend_type>
108
+ <sort_order>40</sort_order>
109
+ <show_in_default>1</show_in_default>
110
+ <show_in_website>1</show_in_website>
111
+ <show_in_store>1</show_in_store>
112
+ <fields>
113
+ <max_results translate="label">
114
+ <label>Max results to show</label>
115
+ <frontend_type>text</frontend_type>
116
+ <sort_order>1</sort_order>
117
+ <show_in_default>1</show_in_default>
118
+ <show_in_website>1</show_in_website>
119
+ <show_in_store>1</show_in_store>
120
+ </max_results>
121
+ </fields>
122
+ </suggest>
123
+ </groups>
124
+ </tooso>
125
+ </sections>
126
+ </config>
app/etc/modules/Bitbull_Tooso.xml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Bitbull_Tooso>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends>
8
+ <Mage_Catalog/>
9
+ <Mage_CatalogSearch/>
10
+ </depends>
11
+ </Bitbull_Tooso>
12
+ </modules>
13
+ </config>
app/locale/en_US/template/email/tooso_alert.html ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--@subject Magento / Tooso - API Error occurred @-->
2
+ <!--@vars
3
+ {"var data.currentDate":"Current date",
4
+ "var data.storeName":"Store name",
5
+ "var data.storeCode":"Store code",
6
+ "var data.currentUrl":"Current URL",
7
+ "var data.language":"Language",
8
+ "var data.apiKey":"API key",
9
+ "var data.httpMethod":"HTTP method",
10
+ "var data.url":"API URL",
11
+ "var data.message":"Error message"}
12
+ @-->
13
+ <p><strong>An error occurred</strong></p>
14
+ <p>Information for current environment:</p>
15
+ <ul>
16
+ <li>Date: {{var data.currentDate}}</li>
17
+ <li>Store name: {{var data.storeName}}</li>
18
+ <li>Store code: {{var data.storeCode}}</li>
19
+ <li>Current URL: {{var data.currentUrl}}</li>
20
+ <li>API language: {{var data.language}}</li>
21
+ <li>API key: {{var data.apiKey}}</li>
22
+ </ul>
23
+ <p>The following API call was performed (with HTTP method {{var data.httpMethod}}):</p>
24
+ <p>{{var data.url}}</p>
25
+ <p>The result was:</p>
26
+ {{var data.message}}
lib/Bitbull/Tooso/Client.php ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Client
8
+ {
9
+ const HTTP_METHOD_GET = 'GET';
10
+ const HTTP_METHOD_POST = 'POST';
11
+
12
+ /**
13
+ * Base url for API calls
14
+ *
15
+ * @var string
16
+ */
17
+ protected $_baseUrl = 'http://toosopublicapi.cloudapp.net';
18
+
19
+ /**
20
+ * API key
21
+ *
22
+ * @var string
23
+ */
24
+ protected $_apiKey;
25
+
26
+ /**
27
+ * Store language
28
+ *
29
+ * @var string
30
+ */
31
+ protected $_language;
32
+
33
+ /**
34
+ * Store code
35
+ *
36
+ * @var string
37
+ */
38
+ protected $_storeCode;
39
+
40
+ /**
41
+ * Timeout for API connection wait
42
+ * in milliseconds
43
+ *
44
+ * @var int
45
+ */
46
+ protected $_connectTimeout = 2000;
47
+
48
+ /**
49
+ * Timeout for API response wait
50
+ * in milliseconds
51
+ *
52
+ * @var int
53
+ */
54
+ protected $_timeout = 2000;
55
+
56
+ /**
57
+ * @var stdClass
58
+ */
59
+ protected $_response = null;
60
+
61
+ /**
62
+ * @var Bitbull_Tooso_Log_SendInterface
63
+ */
64
+ protected $_reportSender;
65
+
66
+ /**
67
+ * @param string $apiKey
68
+ * @param string $language
69
+ * @param string $storeCode
70
+ */
71
+ public function __construct($apiKey, $language, $storeCode)
72
+ {
73
+ $this->_apiKey = $apiKey;
74
+ $this->_language = $language;
75
+ $this->_storeCode = $storeCode;
76
+ }
77
+
78
+ /**
79
+ * @param Bitbull_Tooso_Log_SendInterface $reportSender
80
+ */
81
+ public function setReportSender(Bitbull_Tooso_Log_SendInterface $reportSender)
82
+ {
83
+ $this->_reportSender = $reportSender;
84
+ }
85
+
86
+ /**
87
+ * Perform a search
88
+ *
89
+ * @param string $query
90
+ * @param boolean $typoCorrection
91
+ * @param array $extraParams
92
+ * @return Bitbull_Tooso_Search_Result
93
+ * @throws Bitbull_Tooso_Exception
94
+ */
95
+ public function search($query, $typoCorrection = true, $extraParams = array())
96
+ {
97
+ $path = '/Search/search';
98
+ $params = array_merge(
99
+ array('query' => $query, 'typoCorrection' => ($typoCorrection ? 'true' : 'false')),
100
+ (array)$extraParams
101
+ );
102
+
103
+ $rawResponse = $this->_doRequest($path, self::HTTP_METHOD_GET, $params);
104
+
105
+ $result = new Bitbull_Tooso_Search_Result();
106
+ $result->setResponse($rawResponse);
107
+
108
+ // In the early adopter phase, even a 0 result query need to be treated as an error
109
+ if ($result->getTotalResults() == 0 && $typoCorrection) {
110
+ $message = 'No result found for query "' . $query . '""';
111
+
112
+ if ($this->_reportSender) {
113
+ $this->_reportSender->sendReport($this->_buildUrl($path, $params), self::HTTP_METHOD_GET, $this->_apiKey, $this->_language, $this->_storeCode, $message);
114
+ }
115
+
116
+ throw new Bitbull_Tooso_Exception($message, 0);
117
+ }
118
+
119
+ return $result;
120
+ }
121
+
122
+ /**
123
+ * Perform a search for suggestions
124
+ *
125
+ * @param string $query
126
+ * @param int $limit
127
+ * @param array $extraParams
128
+ * @return Bitbull_Tooso_Suggest_Result
129
+ */
130
+ public function suggest($query, $limit = 10, $extraParams = array())
131
+ {
132
+ $params = array_merge(
133
+ array('query' => $query, 'limit' => $limit),
134
+ (array)$extraParams
135
+ );
136
+
137
+ $rawResponse = $this->_doRequest('/Search/suggest', self::HTTP_METHOD_GET, $params);
138
+
139
+ $result = new Bitbull_Tooso_Suggest_Result();
140
+ $result->setResponse($rawResponse);
141
+
142
+ return $result;
143
+ }
144
+
145
+ /**
146
+ * Send data to index
147
+ *
148
+ * @param string $csvContent
149
+ * @return Bitbull_Tooso_Index_Result
150
+ * @throws Bitbull_Tooso_Exception
151
+ */
152
+ public function index($csvContent)
153
+ {
154
+ $tmpZipFile = sys_get_temp_dir() . '/tooso_index_' . microtime() . '.zip';
155
+
156
+ $zip = new ZipArchive;
157
+ if ($zip->open($tmpZipFile, ZipArchive::CREATE)) {
158
+ $zip->addFromString('magento_catalog.csv', $csvContent);
159
+ $zip->close();
160
+ } else {
161
+ throw new Bitbull_Tooso_Exception('Error creating zip file for reindex', 0);
162
+ }
163
+
164
+ $rawResponse = $this->_doRequest('/Index/index', self::HTTP_METHOD_POST, array(), $tmpZipFile, 300000);
165
+
166
+ unlink($tmpZipFile);
167
+
168
+ $result = new Bitbull_Tooso_Index_Result();
169
+ $result->setResponse($rawResponse);
170
+
171
+ return $result;
172
+ }
173
+
174
+ /**
175
+ * Build and execute request via CURL.
176
+ *
177
+ * @param string $path
178
+ * @param string $httpMethod
179
+ * @param array $params
180
+ * @param string $attachment
181
+ * @param int $timeout
182
+ * @return stdClass
183
+ * @throws Bitbull_Tooso_Exception
184
+ */
185
+ protected function _doRequest($path, $httpMethod = self::HTTP_METHOD_GET, $params = array(), $attachment = '', $timeout = null)
186
+ {
187
+ $url = $this->_buildUrl($path, $params);
188
+
189
+ $ch = curl_init();
190
+
191
+ if ($httpMethod == self::HTTP_METHOD_POST) {
192
+ curl_setopt($ch, CURLOPT_POST, true);
193
+ }
194
+
195
+ if (strlen($attachment) > 0) {
196
+ curl_setopt($ch, CURLOPT_POSTFIELDS, array(
197
+ 'file' => '@' . realpath($attachment)
198
+ ));
199
+ }
200
+
201
+ curl_setopt($ch, CURLOPT_URL, $url);
202
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
203
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $this->_connectTimeout);
204
+ curl_setopt($ch, CURLOPT_TIMEOUT_MS, !is_null($timeout) ? $timeout : $this->_timeout);
205
+
206
+ $output = curl_exec($ch);
207
+ $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
208
+ $error = curl_error($ch);
209
+ $errorNumber = curl_errno($ch);
210
+
211
+ curl_close($ch);
212
+
213
+ if (false === $output) {
214
+
215
+ if ($this->_reportSender) {
216
+ $message = 'cURL error = ' . $error . ' - Error number = ' . $errorNumber;
217
+
218
+ $this->_reportSender->sendReport($url, $httpMethod, $this->_apiKey, $this->_language, $this->_storeCode, $message);
219
+ }
220
+
221
+ throw new Bitbull_Tooso_Exception('cURL error = ' . $error, $errorNumber);
222
+
223
+ } else if ($httpStatusCode != 200) {
224
+
225
+ if ($this->_reportSender) {
226
+ $message = 'API unavailable, HTTP STATUS CODE = ' . $httpStatusCode;
227
+
228
+ $response = json_decode($output);
229
+ if (isset($response->ToosoError) && isset($response->ToosoError->DebugInfo)) {
230
+ $message .= "\n\nDebugInfo: " . $response->ToosoError->DebugInfo;
231
+ }
232
+
233
+ $this->_reportSender->sendReport($url, $httpMethod, $this->_apiKey, $this->_language, $this->_storeCode, $message);
234
+ }
235
+
236
+ throw new Bitbull_Tooso_Exception('API unavailable, HTTP STATUS CODE = ' . $httpStatusCode, 0);
237
+
238
+ } else {
239
+ $response = json_decode($output);
240
+
241
+ if (isset($response->ToosoError)) {
242
+ $e = new Bitbull_Tooso_Exception($response->ToosoError->Description, $response->Code);
243
+ $e->setDebugInfo($response->ToosoError->DebugInfo);
244
+
245
+ if ($this->_reportSender) {
246
+ $message = 'Error description = ' . $response->ToosoError->Description . "\n"
247
+ . "Error code = " . $response->Code . "\n"
248
+ . "Debug info = " . $response->ToosoError->DebugInfo;
249
+
250
+ $this->_reportSender->sendReport($url, $httpMethod, $this->_apiKey, $this->_language, $this->_storeCode, $message);
251
+ }
252
+
253
+ throw $e;
254
+ } else {
255
+ return $response;
256
+ }
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Build an url for an API call
262
+ *
263
+ * @param string $path
264
+ * @param array $params
265
+ * @return string
266
+ */
267
+ protected function _buildUrl($path, $params)
268
+ {
269
+ $url = $this->_baseUrl . '/' . $this->_apiKey . $path;
270
+
271
+ $queryString = array(
272
+ 'language=' . $this->_language,
273
+ 'storeCode=' . $this->_storeCode,
274
+ );
275
+
276
+ foreach ($params as $key => $value) {
277
+ $queryString[] = $key . '=' . $value;
278
+ }
279
+
280
+ $url .= '?' . implode('&', $queryString);
281
+
282
+ return $url;
283
+ }
284
+ }
lib/Bitbull/Tooso/Exception.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Exception extends Exception
8
+ {
9
+ /**
10
+ * @var string
11
+ */
12
+ protected $_debugInfo = null;
13
+
14
+ public function setDebugInfo($debugInfo)
15
+ {
16
+ $this->_debugInfo = $debugInfo;
17
+ }
18
+
19
+ public function getDebugInfo()
20
+ {
21
+ return $this->_debugInfo;
22
+ }
23
+ }
lib/Bitbull/Tooso/Index/Result.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Index_Result
8
+ {
9
+ protected $_response = null;
10
+
11
+ public function __construct($response = null)
12
+ {
13
+ if ($response) {
14
+ $this->setResponse($response);
15
+ }
16
+ }
17
+
18
+ public function setResponse($response)
19
+ {
20
+ $this->_response = $response;
21
+ }
22
+ }
lib/Bitbull/Tooso/Log/SendInterface.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ interface Bitbull_Tooso_Log_SendInterface
8
+ {
9
+ /**
10
+ * Send report API
11
+ *
12
+ * @param string $url
13
+ * @param string $httpMethod
14
+ * @param string $apiKey
15
+ * @param string $language
16
+ * @param string $storeCode
17
+ * @param string $message
18
+ */
19
+ public function sendReport($url, $httpMethod, $apiKey, $language, $storeCode, $message);
20
+ }
lib/Bitbull/Tooso/Search/Result.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Search_Result
8
+ {
9
+ protected $_response = null;
10
+
11
+ public function __construct($response = null)
12
+ {
13
+ if ($response) {
14
+ $this->setResponse($response);
15
+ }
16
+ }
17
+
18
+ public function setResponse($response)
19
+ {
20
+ $this->_response = $response;
21
+ }
22
+
23
+ public function getResults()
24
+ {
25
+ return $this->_response->Content->Results;
26
+ }
27
+
28
+ public function getTotalTime()
29
+ {
30
+ return $this->_response->Content->TotalTime;
31
+ }
32
+
33
+ public function getSearchId()
34
+ {
35
+ return $this->_response->Content->SearchId;
36
+ }
37
+
38
+ public function getTotalResults()
39
+ {
40
+ return $this->_response->Content->TotalResults;
41
+ }
42
+
43
+ public function getOriginalSearchString()
44
+ {
45
+ return $this->_response->Content->OriginalSearchString;
46
+ }
47
+
48
+ public function getFixedSearchString()
49
+ {
50
+ return $this->_response->Content->FixedSearchString;
51
+ }
52
+
53
+ public function getParentSearchId()
54
+ {
55
+ return $this->_response->Content->ParentSearchId;
56
+ }
57
+ }
lib/Bitbull/Tooso/Suggest/Result.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @category Bitbull
4
+ * @package Bitbull_Tooso
5
+ * @author Gennaro Vietri <gennaro.vietri@bitbull.it>
6
+ */
7
+ class Bitbull_Tooso_Suggest_Result
8
+ {
9
+ protected $_response = null;
10
+
11
+ public function __construct($response = null)
12
+ {
13
+ if ($response) {
14
+ $this->setResponse($response);
15
+ }
16
+ }
17
+
18
+ public function setResponse($response)
19
+ {
20
+ $this->_response = $response;
21
+ }
22
+
23
+ public function getSuggestions()
24
+ {
25
+ return $this->_response->Content->Suggestions;
26
+ }
27
+ }
package.xml ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Bitbull_Tooso</name>
4
+ <version>1.0.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://opensource.org/licenses/osl-3.0.php">OSL</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>This extension replaces the default search of Magento with a typo-tolerant, fast &amp; relevant search experience backed by Tooso.</summary>
10
+ <description>Tooso is a cloud-based, multi-language search tool for e-commerce.&#xD;
11
+ &#xD;
12
+ This extension replaces the default search of Magento with a typo-tolerant, fast &amp; relevant search experience backed by Tooso. &#xD;
13
+ It provide the following features:&#xD;
14
+ &#xD;
15
+ * Fulltext search for catalog products&#xD;
16
+ * Scheduled indexing of catalog products&#xD;
17
+ * Automatic typo correction&#xD;
18
+ * Search keywords suggest&#xD;
19
+ </description>
20
+ <notes>This is the first release version.</notes>
21
+ <authors><author><name>Tooso Inc.</name><user>Tooso</user><email>ciro.greco@tooso.ai</email></author><author><name>Bitbull srl</name><user>bitbullit</user><email>devel@bitbull.it</email></author></authors>
22
+ <date>2016-06-22</date>
23
+ <time>13:01:22</time>
24
+ <contents><target name="magecommunity"><dir name="Bitbull"><dir name="Tooso"><dir name="Block"><dir name="CatalogSearch"><file name="Autocomplete.php" hash="2a00b2f492d507594b1fe6f34e9cad92"/><file name="Result.php" hash="1cd469ae700f6560d08eb9ae57bd0c81"/></dir><file name="Rebuild.php" hash="7e8d9cf37b90712e077caaf6ef9593fb"/></dir><dir name="Helper"><dir name="CatalogSearch"><file name="Data.php" hash="3950404f58dbb6a7b1771d79c105bbf3"/></dir><file name="Data.php" hash="97f29c41bdec723ce1e834f095f24173"/><dir name="Log"><file name="Send.php" hash="5404be47bb61b57de4956b170a2bb0e7"/></dir><file name="Log.php" hash="291d92b98d0f3cd644ea823b2e82af60"/></dir><dir name="Model"><dir name="CatalogSearch"><dir name="Resource"><file name="Fulltext.php" hash="4bd85f7a6252a67214b299e88d474884"/></dir></dir><file name="Document.php" hash="8494db27df0418d82b3dd1d62c3b0024"/><dir name="Export"><dir name="Adapter"><file name="Csv.php" hash="7a7f2b6a65d31e1ca73a704a701d7def"/></dir></dir><file name="Indexer.php" hash="dc87343f576592706763dfc5780b7890"/><file name="Observer.php" hash="1de7e3c576c0cda4a08991b646a187af"/><dir name="Resource"><dir name="CatalogSearch"><dir name="Fulltext"><file name="Collection.php" hash="f02d6ab072708bf4278333be1c1eca9b"/></dir><file name="Query.php" hash="ed4544b31cef91482d83ce972df6df3b"/></dir></dir><file name="Search.php" hash="c422f1e61893fcb6683338c5a0e550b1"/><file name="Suggest.php" hash="5a6945815a577798023bdd124c0b1296"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="ToosoController.php" hash="8ec5ef47c376938cdd8bb0fc1c54ed20"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="83c32bf662abe4862cc020c87c210c77"/><file name="config.xml" hash="83043efd864433e81687568b6be9e576"/><file name="system.xml" hash="c0488ce3db9f16d8b3c14025c87e583b"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Bitbull_Tooso.xml" hash="72e8ab6ad38fa30148022266b5930774"/></dir></target><target name="magelocale"><dir name="en_US"><dir name="template"><dir name="email"><file name="tooso_alert.html" hash="bed763fc02c8f7e4dd77210c21fdd43a"/></dir></dir></dir></target><target name="magelib"><dir name="Bitbull"><dir name="Tooso"><file name="Client.php" hash="73f175735846c21798f5e68d9b30ff7d"/><file name="Exception.php" hash="18a7e7c9a4ed8ff74553d71ec5168f04"/><dir name="Index"><file name="Result.php" hash="51473ad6a03d37f6263e06f4d0068984"/></dir><dir name="Log"><file name="SendInterface.php" hash="4536b2a072bfc0778c3597ebf5e9101f"/></dir><dir name="Search"><file name="Result.php" hash="d94ee5c847144f5c5d0e804715a088ae"/></dir><dir name="Suggest"><file name="Result.php" hash="1cf76eb5eba7b6799baf98286f321389"/></dir></dir></dir></target></contents>
25
+ <compatible/>
26
+ <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
27
+ </package>