diff --git a/Classes/Flowpack/SearchPlugin/Controller/SuggestController.php b/Classes/Flowpack/SearchPlugin/Controller/SuggestController.php new file mode 100644 index 0000000..92d6bee --- /dev/null +++ b/Classes/Flowpack/SearchPlugin/Controller/SuggestController.php @@ -0,0 +1,84 @@ + + * @package Flowpack\SearchPlugin\Controller + */ +class SuggestController extends ActionController { + + /** + * @Flow\Inject + * @var \Flowpack\ElasticSearch\ContentRepositoryAdaptor\ElasticSearchClient + */ + protected $elasticSearchClient; + + /** + * The node inside which searching should happen + * + * @var NodeInterface + */ + protected $contextNode; + + /** + * @Flow\Inject + * @var \Flowpack\ElasticSearch\ContentRepositoryAdaptor\LoggerInterface + */ + protected $logger; + + /** + * @var boolean + */ + protected $logThisQuery = FALSE; + + /** + * @var string + */ + protected $logMessage; + + /** + * @var array + */ + protected $viewFormatToObjectNameMap = array( + 'json' => 'TYPO3\Flow\Mvc\View\JsonView' + ); + + /** + * @param NodeInterface $node + * @param string $term + */ + public function indexAction(NodeInterface $node, $term) { + $request = array( + 'suggests' => array( + 'text' => $term, + 'term' => array( + 'field' => '_all' + ) + ) + ); + + $response = $this->elasticSearchClient->getIndex()->request('GET', '/_suggest', array(), json_encode($request))->getTreatedContent(); + $suggestions = array_map(function($option) { + return $option['text']; + }, $response['suggests'][0]['options']); + + $this->view->assign('value', $suggestions); + } + +} \ No newline at end of file diff --git a/Classes/Flowpack/SearchPlugin/EelHelper/SearchArrayHelper.php b/Classes/Flowpack/SearchPlugin/EelHelper/SearchArrayHelper.php new file mode 100644 index 0000000..55c07d3 --- /dev/null +++ b/Classes/Flowpack/SearchPlugin/EelHelper/SearchArrayHelper.php @@ -0,0 +1,47 @@ +indexAction()) + +roles: + 'TYPO3.Flow:Everybody': + privileges: + - + privilegeTarget: Flowpack_SearchPlugin_Controller_SuggestController + permission: GRANT \ No newline at end of file diff --git a/Configuration/Routes.yaml b/Configuration/Routes.yaml new file mode 100644 index 0000000..ccadb24 --- /dev/null +++ b/Configuration/Routes.yaml @@ -0,0 +1,11 @@ +# DataSourceController routes +- + name: 'flowpack/searchplugin - SuggestController->index' + uriPattern: 'flowpack/searchplugin' + defaults: + '@package': 'Flowpack.SearchPlugin' + '@controller': 'Suggest' + '@action': 'index' + '@format': 'json' + appendExceedingArguments: TRUE + httpMethods: ['GET'] \ No newline at end of file diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index d07b68d..d6c5e71 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -2,4 +2,8 @@ TYPO3: Neos: typoScript: autoInclude: - 'Flowpack.SearchPlugin': TRUE \ No newline at end of file + 'Flowpack.SearchPlugin': TRUE + + TypoScript: + defaultContext: + Flowpack.SearchPlugin.Array: 'Flowpack\SearchPlugin\EelHelper\SearchArrayHelper' diff --git a/Resources/Private/Templates/NodeTypes/Search.Form.html b/Resources/Private/Templates/NodeTypes/Search.Form.html index 1bffd5a..6a28db3 100644 --- a/Resources/Private/Templates/NodeTypes/Search.Form.html +++ b/Resources/Private/Templates/NodeTypes/Search.Form.html @@ -1,4 +1,4 @@ -
- - + + +
\ No newline at end of file diff --git a/Resources/Private/Templates/NodeTypes/Search.html b/Resources/Private/Templates/NodeTypes/Search.html index e15e0ac..20190cf 100644 --- a/Resources/Private/Templates/NodeTypes/Search.html +++ b/Resources/Private/Templates/NodeTypes/Search.html @@ -1,8 +1,13 @@ {namespace neos=TYPO3\Neos\ViewHelpers} {namespace ts=TYPO3\TypoScript\ViewHelpers} +{namespace search=TYPO3\TYPO3CR\Search\ViewHelpers} + f:format.raw()}> + {searchForm -> f:format.raw()} -{searchForm -> f:format.raw()} - -Showing {searchResults -> f:count()} of {totalSearchResults} results - -{searchResultRenderer -> f:format.raw()} + + + Showing {results.accessibleCount} of {totalSearchResults} results + + + + \ No newline at end of file diff --git a/Resources/Private/Templates/SearchResult/DocumentSearchResult.html b/Resources/Private/Templates/SearchResult/DocumentSearchResult.html index 0edacfc..11a7854 100644 --- a/Resources/Private/Templates/SearchResult/DocumentSearchResult.html +++ b/Resources/Private/Templates/SearchResult/DocumentSearchResult.html @@ -1,9 +1,18 @@ {namespace neos=TYPO3\Neos\ViewHelpers} +{title} - - {title} -
+ +

+ + {fragment -> f:format.raw()}{f:if(condition: fragmentIterator.isLast, else: '...')} + +

- - {description} + \ No newline at end of file diff --git a/Resources/Private/TypoScript/ResultRendering.ts2 b/Resources/Private/TypoScript/ResultRendering.ts2 index 05407ae..c2da059 100644 --- a/Resources/Private/TypoScript/ResultRendering.ts2 +++ b/Resources/Private/TypoScript/ResultRendering.ts2 @@ -15,14 +15,11 @@ prototype(Flowpack.SearchPlugin:SingleResult) < prototype(TYPO3.TypoScript:Case) prototype(TYPO3.Neos:DocumentSearchResult) < prototype(TYPO3.TypoScript:Template) { templatePath = 'resource://Flowpack.SearchPlugin/Private/Templates/SearchResult/DocumentSearchResult.html' node = ${node} + highlight = ${Flowpack.SearchPlugin.Array.flatten(searchHit.highlight)} title = ${q(node).property('title')} description = '' + parents = ${Array.reverse(q(node).parents('[instanceof TYPO3.Neos:Document]').get())} } -prototype(TYPO3.Neos.NodeTypes:PageSearchResult) < prototype(TYPO3.Neos:DocumentSearchResult) - - -prototype(TYPO3.NeosDemoTypo3Org:ChapterSearchResult) < prototype(TYPO3.Neos:DocumentSearchResult) { - description = ${q(node).property('chapterDescription')} -} \ No newline at end of file +prototype(TYPO3.Neos.NodeTypes:PageSearchResult) < prototype(TYPO3.Neos:DocumentSearchResult) \ No newline at end of file diff --git a/Resources/Private/TypoScript/SearchPlugin.ts2 b/Resources/Private/TypoScript/SearchPlugin.ts2 index b8051d6..f7cfd25 100644 --- a/Resources/Private/TypoScript/SearchPlugin.ts2 +++ b/Resources/Private/TypoScript/SearchPlugin.ts2 @@ -1,24 +1,22 @@ - prototype(Flowpack.SearchPlugin:Search) { - // we store the search results in the TypoScript context, so that they bubble through the nested elements like the searchResultRenderer - @override.searchResults = ${this.searchQuery.execute()} - - - searchQuery = ${Search.query(site).fulltext(request.arguments.search || '')} + searchTerm = ${request.arguments.search} + searchQuery = ${this.searchTerm ? Search.query(site).fulltext(this.searchTerm) : null} totalSearchResults = ${this.searchQuery.count()} - searchResults = ${searchResults} searchForm = Flowpack.SearchPlugin:Search.Form searchResultRenderer = TYPO3.TypoScript:Collection { + // the "searchResults" are filled from the ViewHelper. collection = ${searchResults} itemRenderer = Flowpack.SearchPlugin:SingleResult itemName = 'node' + // we also make the full ElasticSearch hit available to nested rendering, if possible + itemRenderer.@override.searchHit = ${searchResults.searchHitForNode(node)} } - searchResultRenderer.@process.wrap = ${'
    ' + value + '
'} + searchResultRenderer.@process.wrap = ${'
    ' + value + '
'} prototype(Flowpack.SearchPlugin:SingleResult).@process.wrap = ${'
  • ' + value + '
  • '} @cache { @@ -32,7 +30,7 @@ prototype(Flowpack.SearchPlugin:Search) { prototype(Flowpack.SearchPlugin:Search.Form) < prototype(TYPO3.TypoScript:Template) { - templatePath = 'resource://Flowpack.SearchPlugin/Private/Templates/NodeTypes/Search.Form.Html' + node = ${site} + templatePath = 'resource://Flowpack.SearchPlugin/Private/Templates/NodeTypes/Search.Form.html' searchWord = ${request.arguments.search} -} - +} \ No newline at end of file