/** * @param array $data * @return mixed */ public function results(array $data) { // do the search $results = ShopSearch::inst()->search($data); $request = $this->controller->getRequest(); $baseLink = $request->getURL(false); // if there was only one category filter, remember it for the category dropdown to retain it's value if (!ShopSearchForm::config()->disable_category_dropdown) { $qs_filters = (string) Config::inst()->get('ShopSearch', 'qs_filters'); $categoryKey = (string) ShopSearchForm::config()->category_field; if (preg_match('/\\[(.+)\\]/', $categoryKey, $matches)) { // get right of the f[] around the actual key if present $categoryKey = $matches[1]; } if (!empty($data[$qs_filters][$categoryKey])) { $categoryID = $data[$qs_filters][$categoryKey]; if (is_numeric($categoryID)) { // If it's set in the dropdown it will just be a number // If it's set from the checkboxes it will be something like LIST~1,2,3,4 // We only want to remember the value in the former case Session::set('LastSearchCatID', $categoryID); } } else { // If they unchecked every value, then clear the dropdown as well Session::clear('LastSearchCatID'); } } // add links for any facets if ($results->Facets && $results->Facets->count()) { $qs_ps = (string) Config::inst()->get('ShopSearch', 'qs_parent_search'); $baseParams = array_merge($data, array($qs_ps => $results->SearchLogID)); unset($baseParams['url']); $results->Facets = FacetHelper::inst()->insertFacetLinks($results->Facets, $baseParams, $baseLink); } // add a dropdown for sorting $qs_sort = (string) Config::inst()->get('ShopSearch', 'qs_sort'); $options = Config::inst()->get('ShopSearch', 'sort_options'); $sortParams = array_merge($data, array($qs_sort => 'NEWSORTVALUE')); unset($sortParams['url']); $results->SortControl = DropdownField::create($qs_sort, ShopSearch::config()->sort_label, $options, $results->Sort)->setAttribute('data-url', $baseLink . '?' . http_build_query($sortParams)); // a little more output management $results->Title = "Search Results"; $results->Results = $results->Matches; // this makes us compatible with the default search template // Give a hook for the parent controller to format the results, for example, // interpreting filters in a specific way to affect the title or content // when no results are returned. Since this is domain-specific we just leave // it up to the host app. if ($this->controller->hasMethod('onBeforeSearchDisplay')) { $this->controller->onBeforeSearchDisplay($results); } // give a hook for processing ajax requests through a different template (i.e. for returning only fragments) $tpl = Config::inst()->get('ShopSearch', 'ajax_results_template'); if (!empty($tpl) && Director::is_ajax()) { return $this->controller->customise($results)->renderWith($tpl); } // Give a hook for modifying the search responses $this->controller->extend('updateSearchResultsResponse', $request, $response, $results, $data); return $response ?: $this->controller->customise($results)->renderWith(array('ShopSearch_results', 'Page_results', 'Page')); }
/** * @param SS_HTTPRequest $req * @return string */ public function search_suggest(SS_HTTPRequest $req) { /** @var SS_HTTPResponse $response */ $response = $this->owner->getResponse(); $callback = $req->requestVar('callback'); // convert the search results into usable json for search-as-you-type if (ShopSearch::config()->search_as_you_type_enabled) { $searchVars = $req->requestVars(); $searchVars[ShopSearch::config()->qs_query] = $searchVars['term']; unset($searchVars['term']); $results = ShopSearch::inst()->suggestWithResults($searchVars); } else { $results = array('suggestions' => ShopSearch::inst()->suggest($req->requestVar('term'))); } if ($callback) { $response->addHeader('Content-type', 'application/javascript'); $response->setBody($callback . '(' . json_encode($results) . ');'); } else { $response->addHeader('Content-type', 'application/json'); $response->setBody(json_encode($results)); } return $response; }
public function testFilters() { VirtualFieldIndex::build('Product'); // one filter $r = ShopSearch::inst()->search(array('f' => array('Model' => 'ABC'))); $this->assertEquals(2, $r->TotalMatches, 'Should contain 2 products'); $this->assertEquals('ABC', $r->Matches->first()->Model, 'Should actually match'); // two filters $r = ShopSearch::inst()->search(array('f' => array('Model' => 'ABC', 'Price' => 10.5))); $this->assertEquals(1, $r->TotalMatches, 'Should contain 1 product'); $this->assertEquals('ABC', $r->Matches->first()->Model, 'Should actually match'); $this->assertEquals(10.5, $r->Matches->first()->sellingPrice(), 'Should actually match'); // filter on category $r = ShopSearch::inst()->search(array('f' => array('Category' => $this->idFromFixture('ProductCategory', 'c3')))); $this->assertEquals(3, $r->TotalMatches, 'Should contain 3 products'); // filter on multiple categories $r = ShopSearch::inst()->search(array('f' => array('Category' => array($this->idFromFixture('ProductCategory', 'c1'), $this->idFromFixture('ProductCategory', 'c3'))))); $this->assertEquals(4, $r->TotalMatches, 'Should contain all products'); // filter on multiple categories with comma separation $r = ShopSearch::inst()->search(array('f' => array('Category' => 'LIST~' . implode(',', array($this->idFromFixture('ProductCategory', 'c1'), $this->idFromFixture('ProductCategory', 'c3')))))); $this->assertEquals(4, $r->TotalMatches, 'Should contain all products'); // filter on price range $r = ShopSearch::inst()->search(array('f' => array('Price' => 'RANGE~8~12'))); $this->assertEquals(1, $r->TotalMatches, 'Should contain only 1 product'); $this->assertEquals($this->idFromFixture('Product', 'p2'), $r->Matches->first()->ID, 'Match should be p2'); $r = ShopSearch::inst()->search(array('f' => array('Price' => 'RANGE~-3~4'))); $this->assertEquals(0, $r->TotalMatches, 'Empty matches work on the low end'); $r = ShopSearch::inst()->search(array('f' => array('Price' => 'RANGE~5555~10000'))); $this->assertEquals(0, $r->TotalMatches, 'Empty matches work on the high end'); $r = ShopSearch::inst()->search(array('f' => array('Price' => 'RANGE~12~8'))); $this->assertEquals(0, $r->TotalMatches, 'A flipped range does not cause error'); }