Files
wyczarujprezent.pl/modules/doofinder/lib/DoofinderResults.php
2024-10-28 22:14:22 +01:00

260 lines
9.3 KiB
PHP

<?php
/**
* @author JoeZ99 <jzarate@gmail.com>
* @copyright Doofinder
* @license GPLv3
*
* DoofinderResults
*
* Very thin wrapper of the results obtained from the doofinder server
* it holds to accessor:
* - getProperty : get single property of the search results (rpp, page, etc....)
* - getResults: get an array with the results
*/
class DoofinderResults
{
// doofinder status
const SUCCESS = 'success'; // everything ok
const NOTFOUND = 'notfound'; // no account with the provided hashid found
const EXHAUSTED = 'exhausted'; // the account has reached its query limit
private $properties = null;
private $results = null;
private $facets = null;
private $filter = null;
private $banner = null;
public $status = null;
/**
* Constructor
*
* @param string $jsonString stringified json returned by doofinder search serverphp cs
*/
public function __construct($jsonString)
{
$rawResults = json_decode($jsonString, true);
foreach ($rawResults as $kkey => $vall) {
if (!is_array($vall)) {
$this->properties[$kkey] = $vall;
}
}
// doofinder status
$this->status = isset($this->properties['doofinder_status']) ?
$this->properties['doofinder_status'] : self::SUCCESS;
// results
$this->results = array();
if (isset($rawResults['results']) && is_array($rawResults['results'])) {
$this->results = $rawResults['results'];
}
if (isset($rawResults['banner']) && is_array($rawResults['banner'])) {
$this->banner = $rawResults['banner'];
}
// build a friendly filter array
$this->filter = array();
// reorder filter, before assigning it to $this
if (isset($rawResults['filter'])) {
foreach ($rawResults['filter'] as $filterType => $filters) {
foreach ($filters as $filterName => $filterProperties) {
$this->filter[$filterName] = $filterProperties;
}
}
}
// facets
$this->facets = array();
if (isset($rawResults['facets'])) {
$this->facets = $rawResults['facets'];
// mark "selected" true or false according to filters presence
foreach ($this->facets as $facetName => $facetProperties) {
if (!isset($facetProperties['_type'])) {
$facetProperties['_type'] = null;
//$facetProperties['_type'] = (array_key_exists('terms',$facetProperties)?'terms':((array_key_exists('range',$facetProperties))?'range':null));
}
switch ($facetProperties['_type']) {
case 'terms':
foreach ($facetProperties['terms'] as $pos => $term) {
if (isset($this->filter[$facetName])
&& in_array($term['term'], $this->filter[$facetName])) {
$this->facets[$facetName]['terms'][$pos]['selected'] = true;
} else {
$this->facets[$facetName]['terms'][$pos]['selected'] = false;
}
}
break;
case 'range':
foreach ($facetProperties['ranges'] as $pos => $range) {
$this->facets[$facetName]['ranges'][$pos]['selected_from'] = false;
$this->facets[$facetName]['ranges'][$pos]['selected_to'] = false;
if (isset($this->filter[$facetName]) && isset($this->filter[$facetName]['gte'])) {
$this->facets[$facetName]['ranges'][$pos]['selected_from'] =
$this->filter[$facetName]['gte'];
}
if (isset($this->filter[$facetName]) && isset($this->filter[$facetName]['lte'])) {
$this->facets[$facetName]['ranges'][$pos]['selected_to'] =
$this->filter[$facetName]['lte'];
}
}
break;
}
}
}
}
/**
* getProperty
*
* get single property from the results
* @param string @propertyName: 'results_per_page', 'query', 'max_score', 'page', 'total', 'hashid'
* @return mixed the value of the property
*/
public function getProperty($propertyName)
{
return array_key_exists($propertyName, $this->properties) ?
$this->properties[$propertyName] : null;
}
/**
* getResults
*
* @return array search results. at the moment, only the 'cooked' version.
* Each result is of the form:
* array('header'=>...,
* 'body' => ..,
* 'price' => ..,
* 'href' => ...,
* 'image' => ...,
* 'type' => ...,
* 'id' => ..)
*/
public function getResults()
{
return $this->results;
}
/**
*
* getFacetsNames
*
* @return array facets names.
*/
public function getFacetsNames()
{
return array_keys($this->facets);
}
/**
* getFacet
*
* @param string name the facet name whose results are wanted
*
* @return array facet search data
* - for terms facets
* array(
* '_type'=> 'terms', // type of facet 'terms' or 'range'
* 'missing'=> 3, // # of elements with no value for this facet
* 'others'=> 2, // # of terms not present in the search response
* 'total'=> 6, // # number of possible terms for this facet
* 'terms'=> array(
* array('count'=>6, 'term'=>'Blue', 'selected'=>false),
* // in the response, there are 6 'blue' terms
* array('count'=>3, 'term': 'Red', 'selected'=>true),
* // if 'selected'=>true, that term has been selected as filter
* ...
* )
* )
* - for range facets
* array(
* '_type'=> 'range',
* 'ranges'=> array(
* array(
* 'count'=>6, // in the response, 6 elements within that range.
* 'from':0,
* 'min': 30
* 'max': 90,
* 'mean'=>33.2,
* 'total'=>432,
* 'total_count'=>6,
* 'selected_from'=> 34.3
* // if present. this value has been used as filter. false otherwise
* 'selected_to'=> 99.3
* // if present. this value has been used as filter. false otherwise
* ),
* ...
* )
* )
*
*
*/
public function getFacet($facetName)
{
return $this->facets[$facetName];
}
/**
* getFacets
*
* get the whole facets associative array:
* array('color'=>array(...), 'brand'=>array(...))
* each array is defined as in getFacet() docstring
*
* @return array facets assoc. array
*/
public function getFacets()
{
return $this->facets;
}
/**
* getAppliedFilters
*
* get the filters the query has defined
* array('categories' => array( // filter name . same as facet name
* 'Sillas de paseo', // if simple array, it's a terms facet
* 'Sacos sillas de paseo'
* ),
* 'color' => array(
* 'red',
* 'blue'
* ),
* 'price' => array(
* 'include_upper'=>true, // if 'from' , 'to' keys, it's a range facet
* 'from'=>35.19,
* 'to'=>9999
* )
* )
* MEANING OF THE EXAMPLE FILTER:
* "FROM the query results, filter only results that have
* ('Sillas de paseo' OR 'Sacos sillas de paseo') categories
* AND ('red' OR 'blue') color AND price is BETWEEN 34.3 and 99.3"
*/
public function getAppliedFilters()
{
return $this->filter;
}
/**
* isOk
*
* checks if all went well
* @return boolean true if the status is 'success'.
* false if the status is not.
*/
public function isOk()
{
return $this->status == self::SUCCESS;
}
public function getBanner()
{
return $this->banner;
}
}