<?php
/*
* Free IT Foundation
* Free Technology Serving Knowledge
* http://www.free-it-foundation.org
*
* This file is part of Knowledge Box.
*
* Knowledge Box is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Knowledge Box is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Knowledge Box. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* class
* KBModuleSearch
*/
class KBModuleSearch
{
/*
* constructor
*/
function KBModuleSearch ()
{
// void
}
/*
* getLastEntries ()
*/
function getLastEntries ($base_id, $limit = KB_CONFIG_DEFAULT_LASTENTRIES, $contributor = false)
{
if ($contributor)
return KBModuleEntry::getEntriesByBase ($base_id, $limit);
else
return KBModuleEntry::getVisibleEntriesByBase ($base_id, $limit);
}
/*
* getResults ()
*/
function getResults ($base_id, $keywords, $text = '', $field_id = -1, $contributor = false)
{
$results = array ();
$relationsPerKeywords = array ();
$entries = array ();
$real_entries = array ();
if (empty ($keywords))
$real_entries = KBModuleSearch::getLastEntries ($base_id, -1, $contributor);
else
{
// iterate over keywords
foreach ($keywords as $keyword_id)
{
// relations
$relations = KBModuleRelation::getRelationsByKeyword ($keyword_id);
// init
$relationsPerKeywords [$keyword_id] = array ();
// iterate over relations
foreach ($relations as $relation)
$relationsPerKeywords [$keyword_id][$relation->getEntryId ()] = $keyword_id . '-' . $relation->getEntryId ();
}
// sort
sort ($relationsPerKeywords);
// intersect relations per keywords
for ($i = 0; $i < count ($relationsPerKeywords); $i++)
{
$relations = $relationsPerKeywords [$i];
if ($i == 0)
$entries = $relations;
else {
// interset keys
//php5: $entries = array_intersect_key ($entries, $relations);
foreach ($entries as $key => $v) {
if (!array_key_exists ($key, $relations))
unset ($entries [$key]);
}
}
}
// by default, sort entries by key in reverse order
krsort ($entries);
// load entries
foreach ($entries as $key => $void)
{
$entry = new KBModuleEntry ();
$entry->load ($key);
// is visible
if ($contributor || (!$contributor && $entry->isVisible ()))
$real_entries [] = $entry;
}
}
// iterate
foreach ($real_entries as $entry)
{
// if there's something to search and we don't find
// it in the entry name, search in the substances for it
if (strlen ($text) > 0)
{
// check in name
$found = $field_id > 0 ? false : stripos ($entry->getName (), $text) !== false;
// if we must only search in name stop here
if ($field_id == 0 && !$found)
continue;
if ($field_id != -1 || !$found)
{
// search in the other fields
$substances = KBModuleSubstance::getSubstancesByEntry ($entry->getId ());
foreach ($substances as $substance)
{
$field = new KBModuleField ();
$field->load ($substance->getFieldId ());
if ($field_id != -1 && $field->getId () != $field_id)
continue;
switch ($field->getType ())
{
case KB_FIELD_TEXT:
case KB_FIELD_HTML:
case KB_FIELD_EMAIL:
{
if (stripos ($substance->getTextValue (), $text) !== false)
$found = true;
break;
}
case KB_FIELD_LINK:
{
if (stripos ($substance->getTextValue (), $text) !== false || stripos ($substance->getInformation (), $text) !== false)
$found = true;
break;
}
case KB_FIELD_FILE:
{
if (stripos ($substance->getInformation (), $text) !== false)
$found = true;
break;
}
case KB_FIELD_DATE:
{
// config
$configDateFormat = KBModuleConfig::getConfig ($entry->getBaseId (), KB_CONFIG_PROPERTY_DATEFORMAT);
$configDateSeparator = KBModuleConfig::getConfig ($entry->getBaseId (), KB_CONFIG_PROPERTY_DATESEPARATOR);
// search a range?
if (stripos ($text, ' to ') > 0)
{
// split dates
$dates = explode (' to ', $text);
// two dates
if (count ($dates) != 2)
break;
// clean input
$from = trim ($dates [0]);
$to = trim ($dates [1]);
// unformatted
$dateFrom = unformatDateAsInConfig ($from, $configDateFormat, $configDateSeparator);
$dateTo = unformatDateAsInConfig ($to, $configDateFormat, $configDateSeparator);
// check
if ((int) $substance->getTextValue () >= $dateFrom && (int) $substance->getTextValue () <= $dateTo)
$found = true;
break;
// specific date
} else {
// unformatted
$date = unformatDateAsInConfig (trim ($text), $configDateFormat, $configDateSeparator);
// parts
if (stripos ($substance->getTextValue (), $date) !== false)
$found = true;
break;
}
}
}
// found it, don't check in the other substances
if ($found)
break;
}
}
// not found, skip keyword
if (!$found)
continue;
}
$results [] = $entry;
}
// return
return $results;
}
/*
* getPaginatedResults ()
*/
function getPaginatedResults ($entries, $index = 0, $pagination = KB_CONFIG_DEFAULT_RESULTS)
{
// prepare
$paginated = array ();
// pagination
if ($pagination > 0)
{
for ($i = $index * $pagination; $i < ($index+1) * $pagination; $i++)
{
$entry = $entries [$i];
if (is_object ($entry))
$paginated [] = $entry;
}
// return paginated
return $paginated;
}
// return results
return $entries;
}
/*
* getTotalPages ()
*/
function getTotalPages ($entries, $pagination = KB_CONFIG_DEFAULT_RESULTS)
{
if ($pagination < 1)
return 1;
// count entries
$elements = count ($entries);
// get pages
$pages = (int) ($elements / $pagination);
// crumbs
$crumbs = $elements % $pagination;
return $crumbs > 0 ? $pages + 1 : $pages;
}
/*
* makeSortUrl ()
*/
function makeSortUrl ($element_id, $direction)
{
// get current url
$url = urldecode ($_SERVER ['REQUEST_URI']);
// cleanup what was used
$url = preg_replace ('/[?&](sort|dir|inx)=[^&]*/', '', $url);
// rebuild url
$url .= (strpos ($url, '?') === false) ? '?' : '&';
$url .= 'sort=' . $element_id;
$url .= '&dir=' . $direction;
$url .= '&inx=0';
return $url;
}
/*
* getElements ()
*/
function getElements ($base_id)
{
return KBModuleElement::getElementsByBase ($base_id);
}
}
// end of class
/*
* stripos ()
* class helper method
*/
if (!function_exists ("stripos"))
{
function stripos($str, $needle, $offset = 0)
{
return strpos(strtolower($str), strtolower($needle), $offset);
}
}
/*
* sortEntries ()
* class helper method
*/
function sortEntries ($a, $b)
{
$element_id = $_SESSION [KB_SEARCH_SORT_FIELD];
$direction = $_SESSION [KB_SEARCH_SORT_DIR];
$element = new KBModuleElement ();
$element->load ($element_id);
$entry_a = ($direction == 'asc') ? $a : $b;
$entry_b = ($direction == 'asc') ? $b : $a;
// switch on element type
switch ($element->getType ())
{
case KB_ELEMENT_ENTRY:
{
return strcasecmp ($entry_a->getName (), $entry_b->getName ());
break;
}
case KB_ELEMENT_FIELD:
{
// get field
$field = new KBModuleField ();
$field->load ($element->getResourceId ());
// get substance
$substance_a = KBModuleSubstance::getSubstance ($entry_a->getId (), $field->getId ());
$substance_b = KBModuleSubstance::getSubstance ($entry_b->getId (), $field->getId ());
// switch field type
switch ($field->getType ())
{
case KB_FIELD_TEXT:
case KB_FIELD_EMAIL:
case KB_FIELD_DATE:
{
return strcasecmp ($substance_a->getTextValue (), $substance_b->getTextValue ());
break;
}
case KB_FIELD_FILE:
case KB_FIELD_LINK:
{
return strcasecmp ($substance_a->getInformation (), $substance_b->getInformation ());
break;
}
}
}
case KB_ELEMENT_KEYWORDS:
{
// get relations
$relations_a = KBModuleRelation::getRelationsByEntry ($entry_a->getId ());
$relations_b = KBModuleRelation::getRelationsByEntry ($entry_b->getId ());
// get group
$group = new KBModuleGroup ();
$group->load ($element->getResourceId ());
// get keywords
$keywords = KBModuleKeyword::getKeywordsByGroup ($group->getId ());
// init
$key_a = '';
$key_b = '';
// keywords
foreach ($keywords as $keyword)
{
// relations entry a
foreach ($relations_a as $relation) {
if ($keyword->getId () == $relation->getKeywordId ())
$key_a .= $keyword->getName () . ' ; ';
}
// relations entry b
foreach ($relations_b as $relation) {
if ($keyword->getId () == $relation->getKeywordId ())
$key_b .= $keyword->getName () . ' ; ';
}
}
return strcasecmp ($key_a, $key_b);
}
case KB_ELEMENT_AGGREGATION:
{
// get relations
$relations_a = KBModuleRelation::getRelationsByEntry ($entry_a->getId ());
$relations_b = KBModuleRelation::getRelationsByEntry ($entry_b->getId ());
// groups
$groups = KBModuleGroup::getGroupsByBase ($element->getBaseId ());
// init
$key_a = '';
$key_b = '';
// iterate groups
foreach ($groups as $group)
{
// get keywords
$keywords = KBModuleKeyword::getKeywordsByGroup ($group->getId ());
// keywords
foreach ($keywords as $keyword)
{
// relations entry a
foreach ($relations_a as $relation) {
if ($keyword->getId () == $relation->getKeywordId ())
$key_a .= $keyword->getName () . ' ; ';
}
// relations entry b
foreach ($relations_b as $relation) {
if ($keyword->getId () == $relation->getKeywordId ())
$key_b .= $keyword->getName () . ' ; ';
}
}
}
return strcasecmp ($key_a, $key_b);
}
}
return 0;
}
?>