Last active
April 26, 2019 17:49
-
-
Save htuscher/3bd1fbdd8c43f7b2b412 to your computer and use it in GitHub Desktop.
TYPO3 Solr Autosuggest and Autocomplete using Extbase and TypeNum Ajax
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
if (!defined('TYPO3_MODE')) { | |
die('Access denied.'); | |
} | |
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( | |
'Vendor.' . $_EXTKEY, | |
'Suggest', | |
array( | |
'Suggest' => 'suggest', | |
), | |
// non-cacheable actions | |
array( | |
'Suggest' => 'suggest', | |
) | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
plugin.tx_myext { | |
view { | |
templateRootPath = {$plugin.tx_myext.view.templateRootPath} | |
partialRootPath = {$plugin.tx_myext.view.partialRootPath} | |
layoutRootPath = {$plugin.tx_myext.view.layoutRootPath} | |
} | |
settings { | |
suggest { | |
resultsPerPage = 3 | |
autocompleteLimit = 10 | |
autocompleteField = spell | |
returnFieldsQuery = * | |
} | |
} | |
} | |
suggest_type = PAGE | |
suggest_type { | |
typeNum = 1337 | |
config { | |
disableAllHeaderCode = 1 | |
xhtml_cleaning = 0 | |
admPanel = 0 | |
additionalHeaders = Content-type: text/html | |
} | |
10 = USER_INT | |
10 { | |
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run | |
extensionName = MyExt | |
pluginName = Suggest | |
vendorName = Vendor | |
controller = Suggest | |
action = suggest | |
switchableControllerActions { | |
Suggest { | |
1 = suggest | |
} | |
} | |
} | |
} | |
page.includeJSFooterlibs.autosuggest = typo3conf/ext/my_ext/Resources/Public/JavaScripts/suggest.js | |
page.includeCSS.autosuggest = typo3conf/ext/my_ext/Resources/Public/Css/suggest.css |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<f:layout name="Default" /> | |
<f:section name="Main"> | |
<button type="button" class="close"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> | |
<div class="row"> | |
<div class="col-md-9"> | |
<div class="row"> | |
<f:for each="{suggest}" as="sug"> | |
<div class="col-sm-6 col-md-4"> | |
<div class="thumbnail"> | |
<a class="figure" href="{sug.url}" title="{sug.title}"> | |
<img src="{sug.thumbnail_stringS}" width="180" height="100" alt="{sug.title}"> | |
</a> | |
<div class="caption"> | |
<h3 class="shorttitle">{sug.title}</h3> | |
<p> | |
<f:format.crop maxCharacters="100" append=" ...">{sug.content}</f:format.crop> | |
</p> | |
</div> | |
</div> | |
</div> | |
</f:for> | |
</div> | |
</div> | |
<div class="col-md-3"> | |
<ul class="list-unstyled"> | |
<f:for each="{autocomplete}" as="keywordCount" key="keyword"> | |
<li> | |
<f:link.page pageUid="{settings.searchPageUid}" additionalParams="{q : '{keyword}'}"> | |
{keyword} ({keywordCount}) | |
</f:link.page> | |
</li> | |
</f:for> | |
</ul> | |
</div> | |
</div> | |
</f:section> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Suggest | |
*/ | |
(function($){ | |
$(document).ready(function(){ | |
var suggestRequest = null; | |
var inputField = '#inputText' | |
var flyoutContainer = '#suggest-container'; | |
$(inputField).on('input', function() { | |
if($(this).val().length >= 3){ | |
suggestRequest = $.ajax({ | |
type: "GET", | |
url: '/', | |
data: { | |
type: '1337', | |
q : $(this).val() | |
}, | |
dataType : 'html' | |
}); | |
suggestRequest.done(function(result) { | |
$(flyoutContainer).html(result); | |
if($(flyoutContainer).not(':visible') && $(flyoutContainer + ' .thumbnail').length > 0) { | |
$(flyoutContainer).fadeIn(); | |
} else if($(flyoutContainer).is(':visible') && $(flyoutContainer + ' .thumbnail').length == 0) { | |
$(flyoutContainer).fadeOut(); | |
} | |
}); | |
} else { | |
if($(flyoutContainer).is(':visible')){ | |
$(flyoutContainer).fadeOut(); | |
} | |
} | |
}); | |
$(document).on('click', flyoutContainer + ' button.close', function(){ | |
if($(flyoutContainer).is(':visible')){ | |
$(flyoutContainer).fadeOut(); | |
} | |
}); | |
$(window).resize(function() { | |
if($(flyoutContainer).is(':visible')) { | |
$(flyoutContainer).hide(); | |
} | |
}); | |
}); | |
})(jQuery); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Vendor\MyExt\Controller; | |
use TYPO3\CMS\Core\Error\Http\ServiceUnavailableException; | |
use TYPO3\CMS\Core\Utility\GeneralUtility; | |
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; | |
use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException; | |
class SuggestController extends ActionController { | |
/** | |
* Initialize Query object with configured parameters | |
* | |
* @param string $q | |
* | |
* @return \Tx_Solr_Query | |
*/ | |
protected function initQuery($q) { | |
$suggestConf = $this->settings['suggest']; | |
$solrConfiguration = \Tx_Solr_Util::getSolrConfigurationFromPageId($GLOBALS['TSFE']->id, FALSE, $GLOBALS['TSFE']->sys_language_uid); | |
/** @var \Tx_Solr_Query $query */ | |
$query = GeneralUtility::makeInstance('Tx_Solr_Query', $q . '* OR ' . $q); | |
/* | |
* Add configured filters | |
*/ | |
if (is_array($suggestConf['filter']) && !empty($suggestConf['filter'])) { | |
foreach ($suggestConf['filter'] as $filter) { | |
$query->addFilter($filter); | |
} | |
} | |
/* | |
* Add default parameters | |
*/ | |
$query->setUserAccessGroups(explode(',', $GLOBALS['TSFE']->gr_list)); | |
$site = \Tx_Solr_Site::getSiteByPageId($GLOBALS['TSFE']->id); | |
$query->setSiteHashFilter($site->getDomain()); | |
$query->setSpellchecking(TRUE); | |
$query->setFieldList($suggestConf['returnFieldsQuery']); | |
$query->setHighlighting(TRUE); | |
/* | |
* Add Boost Queries | |
*/ | |
if (!empty($solrConfiguration['search.']['query.']['boostFunction'])) { | |
$query->setBoostFunction($solrConfiguration['search.']['query.']['boostFunction']); | |
} | |
if (!empty($solrConfiguration['search.']['query.']['boostQuery'])) { | |
$query->setBoostQuery($solrConfiguration['search.']['query.']['boostQuery']); | |
} | |
if (!empty($solrConfiguration['search.']['query.']['boostQuery.'])) { | |
$boostQueries = array(); | |
$boostConfiguration = $solrConfiguration['search.']['query.']['boostQuery.']; | |
foreach ($boostConfiguration as $boostQuery) { | |
$boostQueries[] = $boostQuery; | |
} | |
$query->setBoostQuery($boostQueries); | |
} | |
return $query; | |
} | |
/** | |
* action suggest | |
* | |
* @return string | |
*/ | |
public function suggestAction() { | |
/** @var \Tx_Solr_ConnectionManager $solrConnection */ | |
$solrConnection = GeneralUtility::makeInstance('Tx_Solr_ConnectionManager')-> | |
getConnectionByPageId($GLOBALS['TSFE']->id, $GLOBALS['TSFE']->sys_language_uid); | |
/** @var \Tx_Solr_Search $search */ | |
$search = GeneralUtility::makeInstance('Tx_Solr_Search', $solrConnection); | |
try { | |
$q = strtolower(trim(GeneralUtility::_GP('q'))); | |
// Empty paramter is not allowed | |
if (empty($q)) { | |
throw new NoSuchArgumentException('Empty query provided, please check your query parameter'); | |
} | |
//Check for availability | |
if (!$search->ping()) { | |
throw new ServiceUnavailableException('Search server not available'); | |
} | |
$query = $this->initQuery($q); | |
$this->view->assign('q', $q); | |
$flyoutResults = json_decode($search->search($query, 0 , $this->settings['suggest']['resultsPerPage'])->getRawResponse()); | |
$this->view->assign('status', 'ok'); | |
$this->view->assign('suggest', $flyoutResults->response->docs); | |
$query->setQueryString('*:*'); | |
$query->addQueryParameter('facet.prefix',$q); | |
$query->setFaceting(TRUE); | |
$query->addFacetField($this->settings['suggest']['autocompleteField']); | |
$query->addQueryParameter('facet.limit', $this->settings['suggest']['autocompleteLimit']); | |
$autocompleteResults = json_decode($search->search($query, 0 , $this->settings['suggest']['resultsPerPage'])->getRawResponse()); | |
$this->view->assign('autocomplete', get_object_vars($autocompleteResults->facet_counts->facet_fields->{$this->settings['suggest']['autocompleteField']})); | |
} catch (NoSuchArgumentException $e) { | |
$this->view->assign('status', 'error'); | |
$this->view->assign('errorMsg', $e->getMessage()); | |
} catch (ServiceUnavailableException $e) { | |
$this->view->assign('status', 'error'); | |
$this->view->assign('errorMsg', $e->getMessage()); | |
} | |
} | |
} |
Where should the 'suggest' plugin will be called on page ? Any instructions doc you have ?
Is there a solr v 9.0 compatible version of this code?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Where should the 'suggest' plugin will be called on page ? Any instructions doc you have ?