Source of file SearchPageController.php
Size: 12,086 Bytes - Last Modified: 2021-12-23T10:38:36+00:00
/var/www/docs.ssmods.com/process/src/src/Page/SearchPageController.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 | <?php declare(strict_types = 1); namespace Suilven\FreeTextSearch\Page; use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\PaginatedList; use SilverStripe\View\ArrayData; use Suilven\FreeTextSearch\Container\SearchResults; use Suilven\FreeTextSearch\Factory\SearcherFactory; use Suilven\FreeTextSearch\Helper\FacetLinkHelper; use Suilven\FreeTextSearch\Indexes; // @phpcs:disable SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification /** * Class SearchPageController * * @package Suilven\FreeTextSearch\Page * @property int $ID Page ID * @property int $PageSize the number of results to show on each page */ class SearchPageController extends \PageController { /** @var array<string,string|float|int|bool> */ protected static $selected = []; /** @var array<string,int> */ // * @phpstan-ignore-next-line private $tagCloud = []; /** @var array<string> */ // * @phpstan-ignore-next-line private static $allowed_actions = ['index', 'similar']; public function similar(): \SilverStripe\View\ViewableData_Customised { /** @var \Suilven\FreeTextSearch\Page\SearchPage $model */ $model = SearchPage::get_by_id(SearchPage::class, $this->ID); $indexes = new Indexes(); $index = $indexes->getIndex($model->IndexToSearch); /** @var string $clazz */ $clazz = $index->getClass(); $dataObjectID = $this->getRequest()->param('ID'); $dataObjectID = \intval($dataObjectID); $objectInContext = DataObject::get_by_id($clazz, $dataObjectID); $factory = new SearcherFactory(); $searcher = $factory->getSearcher(); $searcher->setIndexName($index->getName()); $this->paginateSearcher($searcher); $results = $searcher->searchForSimilar($objectInContext); // tweak results set for rendering purposes, we do not want all the OR constructs $results->setQuery(''); $results->setSimilarTo($objectInContext); return $this->renderSearchResults($model, $results); } public function index(): \SilverStripe\View\ViewableData_Customised { // @todo search indexes addition $q = $this->getRequest()->getVar('q'); $this->selected = $this->getRequest()->getVars(); /** @var \Suilven\FreeTextSearch\Page\SearchPage $model */ $model = SearchPage::get_by_id(SearchPage::class, $this->ID); $results = new SearchResults(); if (isset($q) || $model->PageLandingMode !== 'DoNothing' || isset($this->selected['q'])) { $results = $this->performSearchIncludingFacets($model, $q); if ($model->PageLandingMode === 'TagCloud') { $this->buildTagCloud(); } } unset($this->selected['q']); unset($this->selected['start']); unset($this->selected['flush']); return $this->renderSearchResults($model, $results); } public function performSearchIncludingFacets(SearchPage $searchPage, ?string $q): SearchResults { $factory = new SearcherFactory(); /** @var \Suilven\FreeTextSearch\Interfaces\Searcher $searcher */ $searcher = $factory->getSearcher(); $searcher->setFilters($this->selected); $searcher->setIndexName($searchPage->IndexToSearch); $facets = $searchPage->getFacetFields(); $hasManyFields = $searchPage->getHasManyFields(); // @todo ShutterSpeed breaks, no idea why $searcher->setFacettedTokens($facets); $searcher->setHasManyTokens($hasManyFields); $this->paginateSearcher($searcher); return $searcher->search($q); } private function buildTagCloud(): void { /* $facetted = isset($results['AllFacets']); $targetFacet = new ArrayList(); if (isset($model->ShowTagCloudFor)) { // get the tag cloud from calculated facets, but if not calculated, ie the arrive on the page case, // calculate them if ($facetted) { $facets = $results['AllFacets']; } else { $proxyResults = $this->performSearchIncludingFacets($selected, $model, $q); $facets = $proxyResults['AllFacets']; } foreach ($facets as $facet) { $name = $facet->getField('Name'); if ($name === $model->ShowTagCloudFor) { $targetFacet = $facet->getField('Facets'); break; } } $facetArray = $targetFacet->toArray(); $minSize = 10; $maxSize = 40; $maxCount = 0; foreach ($facetArray as $tag) { $count = $tag['Count']; $maxCount = $count > $maxCount ? $count : $maxCount; } $tagCloud = new ArrayList(); foreach ($facetArray as $tag) { $size = $minSize + ($maxSize - $minSize) * $tag['Count'] / $maxCount; $size = \round($size); $row = new ArrayData([ 'Name' => $tag['Value'], 'Size' => $size, 'Params' => $tag['Params'], ]); $tagCloud->push($row); } $results['TagCloud'] = $tagCloud; } //for($i = 3; $i < 40; $i++) { // echo "li.tag{$i} { font-size: {$i}px;};\n"; //} */ } /** @throws \Exception */ private function renderSearchResults( SearchPage $model, SearchResults $results ): \SilverStripe\View\ViewableData_Customised { $indexes = new Indexes(); $index = $indexes->getIndex($model->IndexToSearch); $hasManyFieldsDetails = $index->getHasManyFields(); $hasManyFieldsNames = \array_keys($hasManyFieldsDetails); /** @var string $clazz */ $clazz = $index->getClass(); $templateName = 'Suilven/FreeTextSearch/' . \str_replace('\\', '/', $clazz); $splits = \explode('/', $templateName); $last = \array_pop($splits); $templateName = \implode('/', $splits) . '/Includes/' . $last; $records = $results->getRecords(); $newRecords = new ArrayList(); foreach ($records as $record) { $highsList = new ArrayList(); $highlightsArray = $record->Highlights; if (isset($highlightsArray['Title'])) { $record->ResultTitle = $highlightsArray['Title'][0]; unset($highlightsArray['Title']); } $record->HighlightedLink = $record->Link; if (isset($highlightsArray['Link']) && \count($highlightsArray['Link']) > 0) { $record->HighlightedLink = $highlightsArray['Link'][0]; unset($highlightsArray['Link']); } // this simply repeats the title most times unset($highlightsArray['MenuTitle']); $keys = \is_null($highlightsArray) ? [] : \array_keys($highlightsArray); foreach ($keys as $highlightedField) { foreach ($highlightsArray[$highlightedField] as $highlightsForField) { $do = new DataObject(); // @phpstan-ignore-next-line $do->Snippet = '...' . $highlightsForField . '...'; $highsList->push($do); } } $record->Highlights = $highsList; $html = $this->renderWith( [ $templateName, 'Suilven/FreeTextSearch/SilverStripe/CMS/Model/Includes/SiteTree', ], [ 'Record' => $record, 'SimilarLink' => $this->Link('similar') . '/' . $record->ID, ] ); $record->HTML = $html; $newRecords->push($record); } $paginatedList = new PaginatedList($records); $paginatedList->setLimitItems(false); $paginatedList->setPageLength($results->getPageSize()); $paginatedList->setTotalItems($results->getTotaNumberOfResults()); $paginatedList->setCurrentPage($results->getPage()); $facets = $results->getFacets(); $selectedFacetNames = \array_keys($this->selected); $displayFacets = new ArrayList(); $helper = new FacetLinkHelper(); /** @var \Suilven\FreeTextSearch\Container\Facet $facet */ foreach ($facets as $facet) { $displayFacet = new DataObject(); $facetName= $facet->getName(); /** @phpstan-ignore-next-line */ $displayFacet->Name = $facetName; $helper->setFacetInContext($facetName); $isHasManyFacet = \in_array($facetName, $hasManyFieldsNames, true); $isSelectedFacet = \in_array($facetName, $selectedFacetNames, true); $counts = new ArrayList(); /** @var \Suilven\FreeTextSearch\Container\FacetCount $facetCount */ foreach ($facet->getFacetCounts() as $facetCount) { // @todo Make this an object $count = new DataObject(); $key = $facetCount->getKey(); /** @phpstan-ignore-next-line */ $count->Key = $key; /** @phpstan-ignore-next-line */ $count->Count = $facetCount->getCount(); $link = $helper->isSelectedFacet($key) ? null: $helper->getDrillDownFacetLink( $model->Link(), $count->Key ); $clearFacetLink = $helper->isSelectedFacet($key) ? $helper->getClearFacetLink($model->Link(), $facet->getName()) : null; // @phpstan-ignore-next-line $count->Link = $link; // @phpstan-ignore-next-line $count->ClearFacetLink = $clearFacetLink; // @phpstan-ignore-next-line $count->IsSelected = $isSelectedFacet; // @phpstan-ignore-next-line $count->KeySelected = $helper->isSelectedFacet($key); // decide whether or not to show this facet count if ($isHasManyFacet) { if ($isSelectedFacet && !\is_null($count->ClearFacetLink)) { $counts->push($count); } elseif (!$isSelectedFacet && \is_null($count->ClearFacetLink)) { $counts->push($count); } } else { // token facets $counts->push($count); } } // @phpstan-ignore-next-line $displayFacet->FacetCounts = $counts; $displayFacets->push($displayFacet); } return $this->customise(new ArrayData([ 'NumberOfResults' => $results->getTotaNumberOfResults(), 'Query' => $results->getQuery(), 'Records' => $newRecords, 'Page' => $results->getPage(), 'PageSize' => $results->getPageSize(), 'Pages' => $results->getTotalPages(), 'Suggestions' => new ArrayList($results->getSuggestions()), 'Time' => $results->getTime(), 'Pagination' => $paginatedList, 'SimilarTo' => $results->getSimilarTo(), 'Facets' => $displayFacets, ])); } private function paginateSearcher(\Suilven\FreeTextSearch\Interfaces\Searcher &$searcher): void { $searcher->setPageSize($this->PageSize); $start = $this->getRequest()->getVar('start'); // page 1 is the first page $page = isset($start) ? \ceil($start / $this->PageSize) + 1 : 1; $page = \intval($page); $searcher->setPage($page); } } |