ACC SHELL
<?php
class SearchComponent extends Object {
var $ft_min = 4;
var $ft_max = 20;
var $controller = true; // To give access to the controller
var $dbConn;
var $types = array(
'article', 'product', 'static'
);
var $term, $term_db, $term_no;
/**
*
*/
function init()
{
$this->dbConn =& ConnectionManager::getDataSource('default');
}
/**
*
*/
function search($term)
{
$this->words = $tmp = array();
foreach (preg_split('/\s+/', $term) as $word) {
$this->words[strtolower(__latin2ascii($word))] = 1;
if (strlen($word) < $this->ft_min || strlen($word) > $this->ft_max) {
continue;
}
$tmp[] = $word;
}
if (! $tmp) {
return array();
}
$this->term = join(' ', $tmp);
$this->term_db = $this->dbConn->value(__latin2ascii($this->term));
$this->term_no = count($tmp);
$found = array();
foreach ($this->dbConn->query(sprintf('
SELECT id, type, url, content, title FROM search
WHERE MATCH(content_ascii) AGAINST (%s) >= %d
ORDER BY MATCH(content_ascii) AGAINST (%s) DESC
LIMIT 35
', $this->term_db, $this->term_no, $this->term_db)) as $row) {
$found[] = $this->getContext($row);
}
return $found;
}
/**
*
*/
function getContext($row)
{
$content = $row['search']['content'];
$content_a = preg_split('/\s+/', $row['search']['content']);
$positions = array();
$i = 0;
foreach (preg_split('/\s+/', strtolower(__latin2ascii($content))) as $word) {
if (isset($this->words[$word])) {
$positions[$i] = 1;
}
$i++;
}
$context = array();
$clen = 8;
foreach (array_keys($positions) as $p) {
if ($p < $clen) {
$n = $clen + $p;
$p = 0;
}
else {
$n = 2 * $clen;
$p -= $clen;
}
$context = array_merge($context, array_keys(array_fill($p, $n, 1)));
}
sort($context);
$context = array_unique($context);
$context_txt = array();
$last = NULL;
foreach ($context as $pos) {
if (isset($positions[$pos])) {
$text = '<span class="hilite">' . $content_a[$pos] . '</span>';
}
else if (isset($content_a[$pos])) {
$text = $content_a[$pos];
}
else {
$text = NULL;
}
if ($last === NULL && $pos) {
$text = '...' . $text;
}
else if ($last && $last != ($pos - 1)) {
$text .= '...';
}
$last = $pos;
if ($text !== NULL) {
$context_txt[] = $text;
}
}
if ($context_txt && $pos != (count($content_a) - 1)) {
$context_txt[count($context_txt) - 1] .= '...';
}
if (! $context_txt) {
$context_txt = array_slice($content_a, 0, 2 * $clen);
$context_txt[count($context_txt) - 1] .= '...';
}
$row['search']['url'] = $this->_lookupURL($row['search']['id'],
$row['search']['type'], $row['search']['url']);
return array(
'title' => $row['search']['title'],
'type' => $row['search']['type'],
'id' => $row['search']['id'],
'url' => $row['search']['url'],
'context' => join(' ', $context_txt),
);
}
/**
*
*/
function reindex()
{
$this->dbConn->query('TRUNCATE search');
foreach ($this->dbConn->query('
SELECT id, title, perex, content FROM articles WHERE published = 1
AND (publish_from <= NOW() OR publish_from IS NULL)
AND (publish_to >= NOW() OR publish_to IS NULL)
') as $row) {
$text = join(' ', array(
$row['articles']['title'],
$row['articles']['title'],
$row['articles']['perex'],
$row['articles']['content']
));
$this->_addText($row['articles']['id'], 0, $row['articles']['title'], $text);
}
foreach ($this->dbConn->query('
SELECT products.id, products.name, products.descr,
GROUP_CONCAT(prod_parameters.par_text) as params FROM products
LEFT JOIN prod_parameters ON (products.id = prod_parameters.product)
GROUP BY products.id, products.name, products.descr
') as $row) {
$text = join(' ', array(
$row['products']['name'],
$row['products']['name'],
$row['products']['descr'],
$row[0]['params']
));
$this->_addText($row['products']['id'], 1, $row['products']['name'], $text);
}
$i = 1;
foreach (array(
'calibration.thtml' => '/kalibrace',
'repairs.thtml' => '/opravy',
'measuration.thtml' => '/mereni-a-zkouseni',
) as $page => $url) {
$text = file_get_contents(ROOT . '/' . APP_DIR . '/views/pages/' . $page);
preg_match(',<h1>(.*?)</h1>,', $text, $m);
$this->_addText($i++, 2, strip_tags($m[1]), $text, $url);
}
}
/**
*
*/
function _lookupURL($id, $type, $url)
{
if ($url) {
return $url;
}
/*
* article_type: 2 - publikace-inzerce 1 vystavy-konference-seminare 0 /novinky
*/
if (! $type) {
$row = $this->dbConn->query('SELECT article_type, title_idx FROM articles WHERE id = ' . (int) $id);
if ($row[0]['articles']['article_type'] == 1) {
$url = '/vystavy-konference-seminare/';
}
else if ($row[0]['articles']['article_type'] == 2) {
$url = '/publikace-inzerce/';
}
else {
$url = '/novinky/';
}
$url .= substr($row[0]['articles']['title_idx'], 0, 6);
$url .= '/' . substr($row[0]['articles']['title_idx'], 7);
return $url;
}
$row = $this->dbConn->query('SELECT name_idx FROM products WHERE id = ' . (int) $id);
$url = '/produkty/' . $row[0]['products']['name_idx'];
return $url;
}
/**
*
*/
function _addText($id, $type, $title, $text, $url = '')
{
$this->_cleanUp($text);
$ascii = __latin2ascii($text);
$this->dbConn->query(sprintf(
'insert into search (id, type, content, content_ascii, title, url)
values (%d, %d, %s, %s, %s, %s)',
$id, $type, $this->dbConn->value(trim(str_replace($title, '', $text))),
$this->dbConn->value(trim($ascii)),
$this->dbConn->value(trim($title)),
$this->dbConn->value(trim($url))
));
}
/**
*
*/
function _cleanUp(&$text)
{
static $lat1ent = 'áéíóúýÁÉÍÓÚÝ';
static $trtbl;
if (! $trtbl) {
$tmp = __latin2ascii($lat1ent);
for ($i = 0; $i < strlen($tmp); $i++) {
$trtbl['&' . $tmp[$i] . 'acute;'] = $lat1ent[$i];
}
$trtbl['š'] = '¹';
$trtbl['Š'] = '©';
$trtbl[' '] = ' ';
$trtbl["\xa0"] = ' ';
}
$text = str_replace(array_keys($trtbl), $trtbl, $text);
$text = preg_replace('/&(#\d+|[a-z]+);/i', ' ', $text);
$text = str_replace('<', ' <', $text);
$text = str_replace('>', '> ', $text);
$text = strip_tags($text);
$text = preg_replace('/[\\t\\r\\n ]+/', ' ', $text);
}
}
?>
ACC SHELL 2018