birzha/plugins/offline/sitesearch/classes/Result.php

273 lines
5.5 KiB
PHP

<?php
namespace OFFLINE\SiteSearch\Classes;
use Config;
use Html;
use October\Rain\Database\Model;
use OFFLINE\SiteSearch\Models\Settings;
use Str;
use System\Models\File;
use URL;
/**
* Object to store a result's data.
*
* @package OFFLINE\SiteSearch\Classes
*/
class Result
{
/**
* @var string
*/
public $excerpt;
/**
* @var float
*/
public $relevance;
/**
* @var string
*/
public $provider;
/**
* @var string
*/
public $identifier;
/**
* @var string
*/
public $query;
/**
* @var mixed
*/
public $meta;
/**
* @var Model
*/
public $model;
/**
* Result constructor.
*
* @param $query
* @param int $relevance
* @param string $provider
*/
public function __construct($query, $relevance = 1, $provider = '')
{
$this->setQuery($query);
$this->setRelevance($relevance);
$this->setProvider($provider);
}
/**
* Set a property on the Result.
*
* Since only public properties can be accessed via Twig and it
* does not support __get, we need to make all properties public.
* This method tries to ensure that only valid properties
* are set and all values are passed through the respective
* setter method.
*
* @param $property
* @param $value
*
* @throws \InvalidArgumentException
*/
public function __set($property, $value)
{
$method = 'set' . ucfirst($property);
if ( ! method_exists($this, $method)) {
throw new \InvalidArgumentException(sprintf('"%s" is not a valid property to set.', $property));
}
call_user_func([$this, $method], $value);
}
/**
* @param $query
*
* @return Result
*/
public function setQuery($query)
{
$this->query = $query;
return $this;
}
/**
* @param $meta
*
* @return Result
*/
public function setMeta($meta)
{
$this->meta = $meta;
return $this;
}
/**
* @param float $relevance
*
* @return $this
*/
public function setRelevance($relevance)
{
$this->relevance = (float)$relevance;
return $this;
}
/**
* @param string $provider
*
* @return $this
*/
public function setProvider($provider)
{
$this->provider = $provider;
return $this;
}
/**
* @param string $title
*
* @return Result
*/
public function setTitle($title)
{
$this->title = $this->markQuery($this->prepare($title));
return $this;
}
/**
* Sets the text property and creates
* a separate excerpt to display in the results
* listing.
*
* @param string $text
*
* @return Result
*/
public function setText($text)
{
$this->text = $this->prepare($text);
$this->excerpt = $this->createExcerpt($this->text);
return $this;
}
/**
* @param string $url
*
* @return Result
*/
public function setUrl($url)
{
// If a provider returns the absolute URL to a result
// remove the base url to make sure every result can
// be linked by using the "app" filter in Twig.
$baseUrl = URL::to('/');
if (starts_with($url, $baseUrl)) {
$url = str_replace($baseUrl, '', $url);
}
$this->url = $url;
return $this;
}
/**
* @param File $thumb
*
* @return Result
*/
public function setThumb(File $thumb = null)
{
$this->thumb = $thumb;
return $this;
}
/**
* @param Model $model
*
* @return Result
*/
public function setModel($model = null)
{
$this->model = $model;
return $this;
}
/**
* Surrounds all instances of the query
* in $text with <mark> tags.
*
* @param $text
*
* @return string
*/
public function markQuery($text)
{
// Only mark the query if this feature is enabled
if ( ! Settings::get('mark_results', true)) {
return $text;
}
return (string)preg_replace('/(' . preg_quote($this->query, '/') . ')/iu', '<mark>$0</mark>', $text);
}
/**
* Shortens a string and removes all HTML.
*
* @param string $string
*
* @return string
*/
protected function prepare($string)
{
// Add a space before each tag to prevent
// paragraphs from sticking together after
// removing the html.
$string = str_replace('<', ' <', $string);
return Html::strip($string);
}
/**
* Creates an excerpt of the query-relevant parts of $text
* to display below a search result.
*
* @param $text
*
* @return string
*/
protected function createExcerpt($text)
{
$length = Settings::get('excerpt_length', 250);
$loweredText = mb_strtolower($text);
$loweredQuery = mb_strtolower($this->query);
$position = mb_strpos($loweredText, $loweredQuery);
$start = (int)$position - ($length / 2);
if ($start < 0) {
$excerpt = Str::limit($text, $length);
} else {
// The relevant part is in the middle of the string,
// so surround it with "..."
$excerpt = '...' . trim(mb_substr($text, $start, $length)) . '...';
}
return $this->markQuery($excerpt);
}
}