diff --git a/search2.php b/search2.php
index a2e90fc..63b5378 100644
--- a/search2.php
+++ b/search2.php
@@ -35,15 +35,20 @@
* Contributor( s): ______________________________________
*/
+// TODO: do we have to serialise/unserialise the results. this is not optimal!!!
+
session_start();
require_once("config/dmsDefaults.php");
+require_once(KT_DIR . '/search2/indexing/indexerCore.inc.php');
+
require_once(KT_LIB_DIR . "/unitmanagement/Unit.inc");
require_once(KT_LIB_DIR . "/templating/templating.inc.php");
require_once(KT_LIB_DIR . "/dispatcher.inc.php");
require_once(KT_LIB_DIR . "/widgets/forms.inc.php");
require_once(KT_LIB_DIR . "/actions/bulkaction.php");
-require_once(KT_DIR . '/search2/search/search.inc.php');
+
+require_once(KT_LIB_DIR . '/browse/DocumentCollection.inc.php');
require_once(KT_LIB_DIR . '/documentmanagement/Document.inc');
require_once(KT_LIB_DIR . '/browse/PartialQuery.inc.php');
@@ -117,7 +122,6 @@ function search2QuerySort($sSortColumn, $sSortOrder)
return;
}
-
$results = unserialize($_SESSION['search2_results']);
usort($results, 'search2queryCompare');
@@ -132,38 +136,70 @@ function search2QuerySort($sSortColumn, $sSortOrder)
*/
class Search2Query extends PartialQuery
{
- function getFolderCount() { return 0; }
+ function _count($type)
+ {
+ $count = 0;
+ $results = unserialize($_SESSION['search2_results']);
+
+ switch ($type)
+ {
+ case 'Document':
+ return count($results['docs']) + count($results['shortdocs']);
+ case 'Folder':
+ return count($results['folders']) + count($results['shortfolders']);
+ default:
+ return 0;
+ }
+ }
+
+ function getFolderCount()
+ {
+ return $this->_count('Folder');
+ }
function getDocumentCount()
{
- $results = $_SESSION['search2_results'];
- if(isset($results) && !empty($results)){
- return count(unserialize($results));
+ return $this->_count('Document');
+ }
+
+ function getItems($type, $iStart, $iSize, $sSortColumn, $sSortOrder)
+ {
+ // TODO: quick hack. do this more optimally!!!!
+ $results = unserialize($_SESSION['search2_results']);
+
+ switch ($type)
+ {
+ case 'Document':
+ $type = 'docs';
+ break;
+ case 'Folder':
+ $type = 'folders';
+ break;
}
- return 0;
+
+ $resultArray = $results[$type];
+ foreach($results['short' . $type] as $rec)
+ {
+ $resultArray[] = $rec;
+ }
+
+ $resultArray = array_slice($resultArray, $iStart, $iSize);
+ $results = array();
+ foreach($resultArray as $rec)
+ {
+ $results[] = array('id'=>$rec->Id);
+ }
+
+ return $results;
}
function getFolders($iBatchSize, $iBatchStart, $sSortColumn, $sSortOrder, $sJoinClause = null, $aJoinParams = null)
{
- return array();
+ return $this->getItems('Folder', $iBatchStart, $iBatchSize, $sSortColumn, $sSortOrder);
}
function getDocuments($iBatchSize, $iBatchStart, $sSortColumn, $sSortOrder, $sJoinClause = null, $aJoinParams = null)
{
- search2QuerySort($_GET['sort_on'], $_GET['sort_order']);
- $results = unserialize($_SESSION['search2_results']);
-
- $batch = array();
-
- $no_results = count($results);
- for($i=0;$i<$no_results;$i++)
- {
- if ($i < $iBatchStart) continue;
- if ($i > $iBatchStart + $iBatchSize) continue;
-
- $batch[] = array('id'=>$results[$i]->DocumentID);
- }
-
- return $batch;
+ return $this->getItems('Document', $iBatchStart, $iBatchSize, $sSortColumn, $sSortOrder);
}
}
@@ -208,10 +244,12 @@ class SearchDispatcher extends KTStandardDispatcher {
{
$expr = parseExpression($query);
- $result = $expr->evaluate();
- usort($result, 'rank_compare');
+ $results = $expr->evaluate();
+ $results = resolveSearchShortcuts($results);
- $_SESSION['search2_results'] = serialize($result);
+ usort($result['docs'], 'rank_compare');
+
+ $_SESSION['search2_results'] = serialize($results);
$_SESSION['search2_query'] = $query;
$_SESSION['search2_sort'] = 'rank';
@@ -410,6 +448,15 @@ class SearchDispatcher extends KTStandardDispatcher {
$results = unserialize($_SESSION['search2_results']);
+ // NOTE: sorting results (when it is implemented) might have to be done per section, as it is done with the browse view
+
+ $resultArray = $results['docs'];
+ foreach($results['folders'] as $f) $resultArray[] = $f;
+ foreach($results['shortdocs'] as $d) $resultArray[] = $d;
+ foreach($results['shortfolders'] as $f) $resultArray[] = $f;
+
+ $results = $resultArray;
+
if (!is_array($results) || count($results) == 0)
{
$results=array();
diff --git a/search2/indexing/indexerCore.inc.php b/search2/indexing/indexerCore.inc.php
index 84c9527..bcf91aa 100755
--- a/search2/indexing/indexerCore.inc.php
+++ b/search2/indexing/indexerCore.inc.php
@@ -41,17 +41,142 @@ define('SEARCH2_INDEXER_DIR',realpath(dirname(__FILE__)) . '/');
require_once('indexing/extractorCore.inc.php');
require_once(KT_DIR . '/plugins/ktcore/scheduler/schedulerUtil.php');
-
class IndexerInconsistencyException extends Exception {};
+// TODO: Query Result Items code should be moved into the Search section. It has less to do with indexing...
+
class QueryResultItem
{
- protected $document_id;
+ protected $id;
protected $title;
protected $rank;
protected $text;
- protected $filesize;
protected $fullpath;
+
+ public function __construct($id, $title, $rank, $text, $fullpath)
+ {
+ $this->id = $id;
+ $this->title = $title;
+ $this->rank = $rank;
+ $this->text = $text;
+ $this->fullpath = $fullpath;
+ }
+
+ public function getId() { return $this->id; }
+
+ public function getIsProxy() { return $this instanceof ProxyResultItem; }
+ public function getIsFolder() { return substr(get_class($this), 0, 6) == 'Folder' ; }
+ public function getIsDocument() { return substr(get_class($this), 0, 8) == 'Document' ; }
+
+ public function setRank($value)
+ {
+ $this->rank = number_format($value,2,'.',',');
+ }
+
+ public function getIsLive()
+ {
+ return true;
+ }
+
+ public function setTitle($value)
+ {
+ $this->title = $value;
+ }
+
+ public function setText($value)
+ {
+ $this->text = $value;
+ }
+
+ public function getRelevance() { return (float) $this->rank; }
+ public function getRank() { return $this->getRelevance(); }
+ public function getText() { return (string) $this->text; }
+ public function getTitle() { return (string) $this->title; }
+ public function getFullPath() { return (string) $this->fullpath; }
+
+ protected function __get($property)
+ {
+ if (empty($property))
+ {
+ return '';
+ }
+
+ $method = 'get' . $property;
+ if (method_exists($this, $method))
+ {
+ return $this->$method();
+ }
+ return $this->getUnknown();
+ }
+
+ protected function getUnknown()
+ {
+ return _kt('n/a');
+ }
+
+ protected function __set($property, $value)
+ {
+ if (empty($property))
+ {
+ return '';
+ }
+
+ $method = 'set' . $property;
+ if (method_exists($this, $method))
+ {
+ return $this->$method($value);
+ }
+ throw new Exception("Unknown property '$property' to set on QueryResultItem");
+ }
+}
+
+class ProxyResultItem extends QueryResultItem
+{
+ protected $proxy;
+ protected $proxyId;
+
+ public function __construct($proxyId, $proxy)
+ {
+ parent::__construct($proxyId, $proxy->getTitle, $proxy->getRank(), $proxy->getText(), $proxy->getFullPath());
+ $this->proxyId = $proxyId;
+ $this->proxy = $proxy;
+ }
+
+ public function getId() { return $this->proxyId; }
+ public function getTitle() { return $this->proxy->getTitle(); }
+ public function getRealId() { return $this->proxy->getId(); }
+
+ protected function __get($property)
+ {
+ $method = 'get' . $property;
+
+ if (method_exists($this, $method))
+ {
+ return $this->$method();
+ }
+ else
+ {
+ return $this->proxy->$method();
+ }
+ }
+
+ protected function __set($property, $value)
+ {
+ $method = 'set' . $property;
+ if (method_exists($this, $method))
+ {
+ return $this->$method($value);
+ }
+ else
+ {
+ return $this->proxy->$method($value);
+ }
+ }
+}
+
+class DocumentResultItem extends QueryResultItem
+{
+ protected $filesize;
protected $live;
protected $version;
protected $mimeType;
@@ -78,17 +203,14 @@ class QueryResultItem
protected $mimeDisplay;
protected $oemDocumentNo;
- public function __construct($document_id, $rank=null, $title=null, $text=null)
+ public function __construct($document_id, $rank=null, $title=null, $text=null, $fullpath = null)
{
- $this->document_id=(int) $document_id;
- $this->rank= $rank;
- $this->title=$title;
- $this->text = $text;
+ parent::__construct($document_id, $title, $rank, $text, $fullpath);
$this->live = true;
$this->loadDocumentInfo();
}
- protected function __isset($property)
+ /*protected function __isset($property)
{
switch($property)
{
@@ -101,8 +223,9 @@ class QueryResultItem
throw new Exception("Unknown property '$property' to get on QueryResultItem");
}
return true; // should not be reached
- }
+ }*/
+ // TODO: this is bad. must refactor to do the query on the group of documents.
public function loadDocumentInfo()
{
global $default;
@@ -127,7 +250,7 @@ class QueryResultItem
LEFT JOIN users cbu ON d.creator_id=cbu.id
LEFT JOIN users ou ON d.owner_id=ou.id
WHERE
- d.id=$this->document_id";
+ d.id=$this->id";
$result = DBUtil::getOneResult($sql);
@@ -186,107 +309,116 @@ class QueryResultItem
$this->mimeType = $result['mimetype'];
$this->mimeIconPath = $result['mime_icon_path'];
+ if (empty($this->mimeIconPath))
+ {
+ $this->mimeIconPath = 'unspecified_type';
+ }
$this->mimeDisplay = $result['mime_display'];
$this->storagePath = $result['storage_path'];
$this->status = Document::getStatusString($result['status_id']);
}
- protected function __get($property)
- {
- switch($property)
- {
- case null: return '';
- case 'DocumentID': return (int) $this->document_id;
- case 'Relevance':
- case 'Rank': return (float) $this->rank;
- case 'Text': return (string) $this->text;
- case 'Title': return (string) $this->title;
- case 'FullPath': return (string) $this->fullpath;
- case 'IsLive': return (bool) $this->live;
- case 'Filesize': return $this->filesize;
- case 'Version': return (string) $this->version;
- case 'Filename': return (string)$this->filename;
- case 'FolderId': return (int)$this->folderId;
- case 'OemDocumentNo': return (string) $this->oemDocumentNo;
- case 'Document':
- if (is_null($this->document))
+ public function getDocumentID() { return $this->getId(); }
+ public function getIsLive() { return (bool) $this->live; }
+ public function getFilesize() { return $this->filesize; }
+ public function getVersion() { return (string) $this->version; }
+ public function getFilename() { return (string)$this->filename; }
+ public function getFolderId() { return (int)$this->folderId; }
+ public function getOemDocumentNo() { return (string) $this->oemDocumentNo; }
+ public function getDocument() { if (is_null($this->document))
{
- $this->document = Document::get($this->document_id);
+ $this->document = Document::get($this->id);
}
- return $this->document;
- case 'IsAvailable':
- return $this->Document->isLive();
- case 'CheckedOutUser':
- case 'CheckedOutBy':
- return (string) $this->checkedOutUser;
- case 'WorkflowOnly':
- case 'Workflow':
- return (string)$this->workflow;
- case 'WorkflowStateOnly':
- case 'WorkflowState':
- return (string)$this->workflowState;
- case 'WorkflowAndState':
- if (is_null($this->workflow))
+ return $this->document; }
+ public function getIsAvailable() { return $this->Document->isLive(); }
+ public function getCheckedOutUser() { return (string) $this->checkedOutUser; }
+ public function getCheckedOutByr() { return $this->getCheckedOutUser(); }
+ public function getWorkflowOnly() { return (string)$this->workflow; }
+ public function getWorkflow() { return $this->getWorkflow(); }
+ public function getWorkflowStateOnly() { return (string)$this->workflowState; }
+ public function getWorkflowState() { return $this->getWorkflowStateOnly(); }
+ public function getWorkflowAndState() { if (is_null($this->workflow))
{
return '';
}
- return "$this->workflow - $this->workflowState";
- case 'MimeType':
- return (string) $this->mimeType;
- case 'MimeIconPath':
- return (string) $this->mimeIconPath;
- case 'MimeDisplay':
- return (string) $this->mimeDisplay;
- case 'DateCheckedOut':
- return (string) $this->dateCheckedout;
- case 'ModifiedBy':
- return (string) $this->modifiedBy;
- case 'DateModified':
- return (string) $this->dateModified;
- case 'CreatedBy':
- return (string) $this->createdBy;
- case 'DateCreated':
- return (string) $this->dateCreated;
- case 'Owner':
- case 'OwnedBy':
- return (string) $this->owner;
- case 'IsImmutable':
- case 'Immutable':
- return (bool) $this->immutable;
- case 'Status':
- return $this->status;
- case 'StoragePath':
- return $this->storagePath;
- case 'DocumentType':
- return $this->documentType;
- case 'Permissions':
- return 'not available';
- case 'CanBeReadByUser':
- if (!$this->live)
+ return "$this->workflow - $this->workflowState"; }
+ public function getMimeType() { return (string) $this->mimeType; }
+ public function getMimeIconPath() { return (string) $this->mimeIconPath; }
+ public function getMimeDisplay() { return (string) $this->mimeDisplay; }
+ public function getDateCheckedOut() { return (string) $this->dateCheckedout; }
+ public function getModifiedBy() { return (string) $this->modifiedBy; }
+ public function getDateModified() { return (string) $this->dateModified; }
+ public function getCreatedBy() { return (string) $this->createdBy; }
+ public function getDateCreated() { return (string) $this->dateCreated; }
+ public function getOwner() { return (string) $this->owner; }
+ public function getOwnedBy() { return $this->getOwner(); }
+ public function getIsImmutable() { return (bool) $this->immutable; }
+ public function getImmutable() { return $this->getIsImmutable(); }
+ public function getStatus() { return $this->status; }
+ public function getStoragePath() { return $this->storagePath; }
+ public function getDocumentType() { return $this->documentType; }
+ public function getPermissions() { return 'not available'; }
+ public function getCanBeReadByUser() { if (!$this->live)
return false;
if (Permission::userHasDocumentReadPermission($this->Document))
return true;
if (Permission::adminIsInAdminMode())
return true;
- return false;
- default:
- throw new Exception("Unknown property '$property' to get on QueryResultItem");
- }
- return ''; // Should not be reached
+ return false; }
+
+
+}
+
+class FolderResultItem extends QueryResultItem
+{
+ protected $folder;
+ protected $createdBy;
+ protected $parentId;
+
+ public function __construct($folder_id, $rank=null, $title=null, $text=null, $fullpath = null)
+ {
+ parent::__construct($folder_id, $title, $rank, $text, $fullpath);
+ $this->loadDocumentInfo();
}
- protected function __set($property, $value)
+ public function getFolderID() { return $this->getId(); }
+ public function getParentID() { return $this->parentId; }
+ public function getCreatedBy() { return $this->createdBy; }
+ public function getMimeIconPath() { return 'folder'; }
+ public function getFolder() {
+ return $this->folder; }
+
+ public function loadDocumentInfo()
{
- switch($property)
+ global $default;
+ $this->folder = $folder = Folder::get($this->getFolderID());
+ if (PEAR::isError($folder))
{
- case 'Rank': $this->rank = number_format($value,2,'.',','); break;
- case 'Title': $this->title = $value; break;
- case 'Text': $this->text = $value; break;
- default:
- throw new Exception("Unknown property '$property' to set on QueryResultItem");
+ throw new Exception('Database exception! There appears to be an error in the system: ' .$result->getMessage());
}
+ $this->title = $folder->getName();
+ $this->fullpath = '/' . $folder->getFullPath();
+ $this->parentId = $folder->getParentId();
+
+ $user = User::get($folder->getCreatorID());
+ $this->createdBy = (PEAR::isError($user))?_kt('Unknown'):$user->getName();
}
+
+}
+
+class DocumentShortcutResultItem extends ProxyResultItem
+{
+ public function getDocumentID() { return $this->getId(); }
+ public function getMimeIconPath() { return $this->proxy->getMimeIconPath() . '_shortcut'; }
+
+}
+
+class FolderShortcutResultItem extends ProxyResultItem
+{
+ public function getFolderID() { return $this->getId(); }
+ public function getMimeIconPath() { return 'folder_shortcut'; }
+
}
function MatchResultCompare($a, $b)
diff --git a/search2/indexing/indexers/JavaXMLRPCLuceneIndexer.inc.php b/search2/indexing/indexers/JavaXMLRPCLuceneIndexer.inc.php
index d95a5cb..f724630 100755
--- a/search2/indexing/indexers/JavaXMLRPCLuceneIndexer.inc.php
+++ b/search2/indexing/indexers/JavaXMLRPCLuceneIndexer.inc.php
@@ -187,14 +187,11 @@ class JavaXMLRPCLuceneIndexer extends Indexer
{
try
{
- $item = new QueryResultItem($document_id);
- $item->Title = $hit->Title;
- $item->Text = $hit->Content;
- $item->Rank = $hit->Rank;
+ $item = new DocumentResultItem($document_id, $hit->Rank, $hit->Title, $hit->Content);
if ($item->CanBeReadByUser)
{
- $results[$document_id] = $item;
+ $results['docs'][$document_id] = $item;
}
}
catch(IndexerInconsistencyException $ex)
diff --git a/search2/search/expr.inc.php b/search2/search/expr.inc.php
index 6f7a293..18c8fc2 100755
--- a/search2/search/expr.inc.php
+++ b/search2/search/expr.inc.php
@@ -43,6 +43,8 @@
*
*/
+// TODO: search expression evaluation needs some optimisation
+
require_once('indexing/indexerCore.inc.php');
require_once('search/fieldRegistry.inc.php');
require_once('search/exprConstants.inc.php');
@@ -157,11 +159,28 @@ class Expr
protected $expr_id;
+ protected $context;
+
public function __construct()
{
$this->expr_id = Expr::$node_id++;
}
+ public function appliesToContext()
+ {
+ return ExprContext::DOCUMENT;
+ }
+
+ public function setContext($context)
+ {
+ $this->context = $context;
+ }
+
+ public function getContext()
+ {
+ return $this->context;
+ }
+
public function getExprId()
{
return $this->expr_id;
@@ -406,6 +425,14 @@ class FieldExpr extends Expr
}
}
+class ExprContext
+{
+ const DOCUMENT = 1;
+ const FOLDER = 2;
+ const DOCUMENT_AND_FOLDER = 3;
+}
+
+
class DBFieldExpr extends FieldExpr
{
/**
@@ -966,24 +993,43 @@ class SQLQueryBuilder implements QueryBuilder
private $sql;
private $db;
private $metadata;
+ private $context;
- public function __construct()
+ public function __construct($context)
{
- $this->used_tables = array(
- 'documents'=>1,
- 'document_metadata_version'=>1,
- 'document_content_version'=>0,
- 'tag_words'=>0,
- 'document_fields_link'=>0
- );
-
- $this->aliases = array(
- 'documents'=>'d',
- 'document_metadata_version'=>'dmv',
- 'document_content_version'=>'dcv',
- 'tag_words'=>'tw',
- 'document_fields_link'=>'pdfl'
- );
+ $this->context = $context;
+
+ switch ($context)
+ {
+ case ExprContext::DOCUMENT:
+ $this->used_tables = array(
+ 'documents'=>1,
+ 'document_metadata_version'=>1,
+ 'document_content_version'=>0,
+ 'tag_words'=>0,
+ 'document_fields_link'=>0
+ );
+
+ $this->aliases = array(
+ 'documents'=>'d',
+ 'document_metadata_version'=>'dmv',
+ 'document_content_version'=>'dcv',
+ 'tag_words'=>'tw',
+ 'document_fields_link'=>'pdfl'
+ );
+ break;
+ case ExprContext::FOLDER:
+ $this->used_tables = array(
+ 'folders'=>1,
+ );
+
+ $this->aliases = array(
+ 'folders'=>'f',
+ );
+ break;
+ default:
+ throw new Exception('This was not expected - Context = ' . $context);
+ }
$this->sql = '';
$this->db = array();
@@ -1013,8 +1059,15 @@ class SQLQueryBuilder implements QueryBuilder
}
elseif ($expr->isDBExpr())
{
- $this->db[] = & $parent;
- $this->used_tables[$expr->getTable()]++;
+ if (($this->context & $expr->appliesToContext()) == $this->context)
+ {
+ $this->db[] = & $parent;
+ $tablename = $expr->getTable();
+ if (array_key_exists($tablename, $this->used_tables))
+ {
+ $this->used_tables[$tablename]++;
+ }
+ }
}
elseif ($expr->isOpExpr())
{
@@ -1042,12 +1095,16 @@ class SQLQueryBuilder implements QueryBuilder
if ($field->isMetadataField())
{
- $this->metadata[] = $expr->getParent();
+ $this->metadata[] = $expr->getParent();
}
elseif ($field->isDBExpr())
{
- $this->db[] = $expr->getParent();
- $this->used_tables[$field->getTable()]++;
+ $this->db[] = $expr->getParent();
+ $tablename = $field->getTable();
+ if (array_key_exists($tablename, $this->used_tables))
+ {
+ $this->used_tables[$tablename]++;
+ }
}
}
}
@@ -1076,29 +1133,40 @@ class SQLQueryBuilder implements QueryBuilder
$left = $expr->left();
$right = $expr->right();
$isNot = $expr->not();
- if ($left->isMetadataField())
+ if ($left->isMetadataField() )
{
- $offset = $this->resolveMetadataOffset($expr) + 1;
-
- $fieldset = $left->getField();
- $query = '(';
-
- if ($isNot)
- {
- $query .= "df$offset.name IS NULL OR ";
- }
-
- $query .= '(' . "df$offset.name='$fieldset' AND " . $right->getSQL($left, "dfl$offset.value", $expr->op(), $isNot) . ')';
-
-
- $query .= ')';
-
+ if ($this->context == ExprContext::DOCUMENT)
+ {
+ $offset = $this->resolveMetadataOffset($expr) + 1;
+
+ $fieldset = $left->getField();
+ $query = '(';
+
+ if ($isNot)
+ {
+ $query .= "df$offset.name IS NULL OR ";
+ }
+
+ $query .= '(' . "df$offset.name='$fieldset' AND " . $right->getSQL($left, "dfl$offset.value", $expr->op(), $isNot) . ')';
+
+ $query .= ')';
+ }
+ else
+ {
+ $query = 'false';
+ }
}
else
{
- $fieldname = $this->getFieldnameFromExpr($expr);
-
- $query = $right->getSQL($left, $left->modifyName($fieldname), $expr->op(), $isNot);
+ if ($this->context == ExprContext::FOLDER && $left->getContext() != ExprContext::FOLDER)
+ {
+ $query = 'false';
+ }
+ else
+ {
+ $fieldname = $this->getFieldnameFromExpr($expr);
+ $query = $right->getSQL($left, $left->modifyName($fieldname), $expr->op(), $isNot);
+ }
}
return $query;
}
@@ -1107,17 +1175,30 @@ class SQLQueryBuilder implements QueryBuilder
{
if (count($this->metadata) + count($this->db) == 0)
{
- throw new Exception('nothing to do');
+ // return empty result set
+ return 'select 1 from documents where false';
}
- // we are doing this because content table is dependant on metadata table
- if ($this->used_tables['document_content_version'] > 0) $this->used_tables['document_metadata_version']++;
-
$sql =
'SELECT ' . "\n";
- $sql .=
+ if ($this->context == ExprContext::DOCUMENT)
+ {
+ // we are doing this because content table is dependant on metadata table
+ if ($this->used_tables['document_content_version'] > 0)
+ {
+ $this->used_tables['document_metadata_version']++;
+ }
+
+ $sql .=
' DISTINCT d.id, dmv.name as title';
+ }
+ else
+ {
+ $sql .=
+ ' DISTINCT f.id, f.name as title';
+ }
+
$offset=0;
foreach($this->db as $expr)
@@ -1133,26 +1214,36 @@ class SQLQueryBuilder implements QueryBuilder
}
$sql .=
- "\n" . 'FROM ' ."\n" .
- ' documents d ' ."\n";
+ "\n" . 'FROM ' ."\n";
- if ($this->used_tables['document_metadata_version'] > 0)
- {
- $sql .= ' INNER JOIN document_metadata_version dmv ON d.metadata_version_id=dmv.id' . "\n";
- }
- if ($this->used_tables['document_content_version'] > 0)
- {
- $sql .= ' INNER JOIN document_content_version dcv ON dmv.content_version_id=dcv.id ' . "\n";
- }
- if ($this->used_tables['document_fields_link'] > 0)
+ if ($this->context == ExprContext::DOCUMENT)
{
- $sql .= ' LEFT JOIN document_fields_link pdfl ON dmv.id=pdfl.metadata_version_id ' . "\n";
- }
+ $primaryAlias = 'd';
+ $sql .= ' documents d ' ."\n";
- if ($this->used_tables['tag_words'] > 0)
+ if ($this->used_tables['document_metadata_version'] > 0)
+ {
+ $sql .= ' INNER JOIN document_metadata_version dmv ON d.metadata_version_id=dmv.id' . "\n";
+ }
+ if ($this->used_tables['document_content_version'] > 0)
+ {
+ $sql .= ' INNER JOIN document_content_version dcv ON dmv.content_version_id=dcv.id ' . "\n";
+ }
+ if ($this->used_tables['document_fields_link'] > 0)
+ {
+ $sql .= ' LEFT JOIN document_fields_link pdfl ON dmv.id=pdfl.metadata_version_id ' . "\n";
+ }
+
+ if ($this->used_tables['tag_words'] > 0)
+ {
+ $sql .= ' LEFT OUTER JOIN document_tags dt ON dt.document_id=d.id ' . "\n" .
+ ' LEFT OUTER JOIN tag_words tw ON dt.tag_id = tw.id ' . "\n";
+ }
+ }
+ else
{
- $sql .= ' LEFT OUTER JOIN document_tags dt ON dt.document_id=d.id ' . "\n" .
- ' LEFT OUTER JOIN tag_words tw ON dt.tag_id = tw.id ' . "\n";
+ $primaryAlias = 'f';
+ $sql .= ' folders f ' ."\n";
}
$offset = 0;
@@ -1171,17 +1262,18 @@ class SQLQueryBuilder implements QueryBuilder
$offset++;
}
-
-
- $offset=0;
- foreach($this->metadata as $expr)
+ if ($this->context == ExprContext::DOCUMENT)
{
- $offset++;
- $field = $expr->left();
+ $offset=0;
+ foreach($this->metadata as $expr)
+ {
+ $offset++;
+ $field = $expr->left();
- $fieldid = $field->getFieldId();
- $sql .= " LEFT JOIN document_fields_link dfl$offset ON dfl$offset.metadata_version_id=d.metadata_version_id AND dfl$offset.document_field_id=$fieldid" . "\n";
- $sql .= " LEFT JOIN document_fields df$offset ON df$offset.id=dfl$offset.document_field_id" . "\n";
+ $fieldid = $field->getFieldId();
+ $sql .= " LEFT JOIN document_fields_link dfl$offset ON dfl$offset.metadata_version_id=d.metadata_version_id AND dfl$offset.document_field_id=$fieldid" . "\n";
+ $sql .= " LEFT JOIN document_fields df$offset ON df$offset.id=dfl$offset.document_field_id" . "\n";
+ }
}
// Add permissions sql for read access
@@ -1189,15 +1281,16 @@ class SQLQueryBuilder implements QueryBuilder
$permId = $oPermission->getID();
$oUser = User::get($_SESSION['userID']);
$aPermissionDescriptors = KTPermissionUtil::getPermissionDescriptorsForUser($oUser);
- $sPermissionDescriptors = (!empty($aPermissionDescriptors)) ? implode(',', $aPermissionDescriptors) : '';
+ $sPermissionDescriptors = empty($aPermissionDescriptors)? -1: implode(',', $aPermissionDescriptors);
- $sql .= 'LEFT JOIN folders f ON d.folder_id = f.id '. "\n";
-
- $sql .= 'INNER JOIN permission_lookups AS PL ON f.permission_lookup_id = PL.id '. "\n";
+ $sql .= "INNER JOIN permission_lookups AS PL ON $primaryAlias.permission_lookup_id = PL.id\n";
$sql .= 'INNER JOIN permission_lookup_assignments AS PLA ON PL.id = PLA.permission_lookup_id AND PLA.permission_id = '.$permId. " \n";
+ $sql .= "WHERE PLA.permission_descriptor_id IN ($sPermissionDescriptors) AND ";
- $sql .= "WHERE PLA.permission_descriptor_id IN ($sPermissionDescriptors) AND dmv.status_id=1 AND d.status_id=1 AND \n ";
-
+ if ($this->context == ExprContext::DOCUMENT)
+ {
+ $sql .= "dmv.status_id=1 AND d.status_id=1 AND \n ";
+ }
return $sql;
}
@@ -1222,8 +1315,6 @@ class SQLQueryBuilder implements QueryBuilder
private function resolveJoinOffset($expr)
{
-
-
$offset=0;
foreach($this->db as $item)
{
@@ -1242,11 +1333,18 @@ class SQLQueryBuilder implements QueryBuilder
$right = $expr->right();
if (DefaultOpCollection::isBoolean($expr))
{
- $query = '(' . $this->buildCoreSQLExpr($left) . ' ' . $expr->op() . ' ' . $this->buildCoreSQLExpr($right) . ')';
+ $query = '(' . $this->buildCoreSQLExpr($left) . ' ' . $expr->op() . ' ' . $this->buildCoreSQLExpr($right) . ')';
}
else
{
- $query = $this->getSQLEvalExpr($expr);
+ if (($this->context & $expr->appliesToContext()) == $this->context)
+ {
+ $query = $this->getSQLEvalExpr($expr);
+ }
+ else
+ {
+ $query = 'false';
+ }
}
return $query;
@@ -1259,7 +1357,11 @@ class SQLQueryBuilder implements QueryBuilder
$sql = $this->buildCoreSQL();
- $sql .= $this->buildCoreSQLExpr($expr);
+ $expr = $this->buildCoreSQLExpr($expr);
+ if ($expr != 'false')
+ {
+ $sql .= $expr;
+ }
return $sql;
}
@@ -1299,19 +1401,22 @@ class SQLQueryBuilder implements QueryBuilder
$sql .= $value->getSQL($field, $left->modifyName($fieldname), $expr->op(), $expr->not());
}
- $moffset=0;
- foreach($this->metadata as $expr)
+ if ($this->context == ExprContext::DOCUMENT)
{
- $moffset++;
- if ($offset++)
+ $moffset=0;
+ foreach($this->metadata as $expr)
{
- $sql .= " $op\n " ;
- }
+ $moffset++;
+ if ($offset++)
+ {
+ $sql .= " $op\n " ;
+ }
- $field = $expr->left();
- $value = $expr->right();
+ $field = $expr->left();
+ $value = $expr->right();
- $sql .= $value->getSQL($field, "dfl$moffset.value", $expr->getOp());
+ $sql .= $value->getSQL($field, "dfl$moffset.value", $expr->getOp());
+ }
}
return $sql;
@@ -1331,7 +1436,6 @@ class SQLQueryBuilder implements QueryBuilder
if (substr($col, 0, 4) == 'expr' && is_numeric(substr($col, 4)))
{
-
$exprno = substr($col, 4);
if ($exprno <= count($this->db))
{
@@ -1379,8 +1483,6 @@ class SQLQueryBuilder implements QueryBuilder
}
return '(' . implode(') AND (', $text) . ')';
}
-
-
}
@@ -1444,6 +1546,13 @@ class OpExpr extends Expr
$this->has_text=$value;
}
+ public function setContext($context)
+ {
+ parent::setContext($context);
+ $this->left()->setContext($context);
+ $this->right()->setContext($context);
+ }
+
public function getHasDb()
{
return $this->has_db;
@@ -1619,7 +1728,6 @@ class OpExpr extends Expr
$point = null;
-
if ($left_op_match && $right_op_match) { $point = 'point'; }
$left_op_match_flex = $left_op_match || ($left->isOpExpr());
@@ -1682,6 +1790,11 @@ class OpExpr extends Expr
return $this->getHasDb() && $this->getHasText();
}
+ public function appliesToContext()
+ {
+ return $this->left()->appliesToContext() | $this->right()->appliesToContext();
+ }
+
/**
* Enter description here...
*
@@ -1805,7 +1918,7 @@ class OpExpr extends Expr
* @param array $rightres
* @return array
*/
- protected static function intersect($leftres, $rightres)
+ protected static function _intersect($leftres, $rightres)
{
if (empty($leftres) || empty($rightres))
{
@@ -1814,7 +1927,7 @@ class OpExpr extends Expr
$result = array();
foreach($leftres as $item)
{
- $document_id = $item->DocumentID;
+ $document_id = $item->Id;
if (!$item->IsLive)
{
@@ -1831,6 +1944,22 @@ class OpExpr extends Expr
return $result;
}
+ protected static function intersect($leftres, $rightres)
+ {
+ return array(
+ 'docs'=>self::_intersect($leftres['docs'],$rightres['docs']),
+ 'folders'=>self::_intersect($leftres['folders'],$rightres['folders'])
+ );
+ }
+
+ protected static function union($leftres, $rightres)
+ {
+ return array(
+ 'docs'=>self::_union($leftres['docs'],$rightres['docs']),
+ 'folders'=>self::_union($leftres['folders'],$rightres['folders'])
+ );
+ }
+
/**
* The objective of this function is to merge the results so that there is a union of the results,
* but there should be no duplicates.
@@ -1839,7 +1968,7 @@ class OpExpr extends Expr
* @param array $rightres
* @return array
*/
- protected static function union($leftres, $rightres)
+ protected static function _union($leftres, $rightres)
{
if (empty($leftres))
{
@@ -1855,15 +1984,15 @@ class OpExpr extends Expr
{
if ($item->IsLive)
{
- $result[$item->DocumentID] = $item;
+ $result[$item->Id] = $item;
}
}
foreach($rightres as $item)
{
- if (!array_key_exists($item->DocumentID, $result) || $item->Rank > $result[$item->DocumentID]->Rank)
+ if (!array_key_exists($item->Id, $result) || $item->Rank > $result[$item->Id]->Rank)
{
- $result[$item->DocumentID] = $item;
+ $result[$item->Id] = $item;
}
}
return $result;
@@ -1996,7 +2125,7 @@ class OpExpr extends Expr
{
if (empty($group)) { return array(); }
- $exprbuilder = new SQLQueryBuilder();
+ $exprbuilder = new SQLQueryBuilder($this->getContext());
if (count($group) == 1)
{
@@ -2020,11 +2149,18 @@ class OpExpr extends Expr
foreach($rs as $item)
{
- $document_id = $item['id'];
+ $id = $item['id'];
$rank = $exprbuilder->getRanking($item);
- if (!array_key_exists($document_id, $results) || $rank > $results[$document_id]->Rank)
+ if (!array_key_exists($id, $results) || $rank > $results[$id]->Rank)
{
- $results[$document_id] = new QueryResultItem($document_id, $rank, $item['title'], $exprbuilder->getResultText($item));
+ if ($this->context == ExprContext::DOCUMENT)
+ {
+ $results[$id] = new DocumentResultItem($id, $rank, $item['title'], $exprbuilder->getResultText($item));
+ }
+ else
+ {
+ $results[$id] = new FolderResultItem($id, $rank, $item['title'], $exprbuilder->getResultText($item));
+ }
}
}
@@ -2034,7 +2170,10 @@ class OpExpr extends Expr
private function exec_text_query($op, $group)
{
- if (empty($group)) { return array(); }
+ if (($this->getContext() != ExprContext::DOCUMENT) || empty($group))
+ {
+ return array();
+ }
$exprbuilder = new TextQueryBuilder();
@@ -2060,12 +2199,21 @@ class OpExpr extends Expr
}
return $results;
-
-
}
- public function evaluate()
+ public function evaluate($context = ExprContext::DOCUMENT_AND_FOLDER)
{
+ if ($context == ExprContext::DOCUMENT_AND_FOLDER)
+ {
+ $docs = $this->evaluate(ExprContext::DOCUMENT);
+ $folders = $this->evaluate(ExprContext::FOLDER);
+
+ return array(
+ 'docs' => $docs['docs'],
+ 'folders' => $folders['folders']);
+ }
+ $this->setContext($context);
+
$left = $this->left();
$right = $this->right();
$op = $this->op();
@@ -2075,12 +2223,12 @@ class OpExpr extends Expr
{
$point = 'point';
}
+ $resultContext = ($this->getContext() == ExprContext::DOCUMENT)?'docs':'folders';
if ($point == 'merge')
{
-
- $leftres = $left->evaluate();
- $rightres = $right->evaluate();
+ $leftres = $left->evaluate($context);
+ $rightres = $right->evaluate($context);
switch ($op)
{
case ExprOp::OP_AND:
@@ -2099,31 +2247,33 @@ class OpExpr extends Expr
{
if ($this->isDBonly())
{
- $result = $this->exec_db_query($op, array($this));
+ $result[$resultContext] = $this->exec_db_query($op, array($this));
}
elseif ($this->isTextOnly())
{
- $result = $this->exec_text_query($op, array($this));
+ $result[$resultContext] = $this->exec_text_query($op, array($this));
}
elseif (in_array($op, array(ExprOp::OP_OR, ExprOp::OP_AND)))
{
+ // do we get to this???
+ // TODO: remove me please.... the simpleQuery stuff should go???
$db_group = array();
$text_group = array();
$this->explore($left, $right, $db_group, 'db');
$this->explore($left, $right, $text_group, 'text');
- $db_result = $this->exec_db_query($op, $db_group);
- $text_result = $this->exec_text_query($op, $text_group);
+ $db_result[$resultContext] = $this->exec_db_query($op, $db_group);
+ $text_result[$resultContext] = $this->exec_text_query($op, $text_group);
switch ($op)
{
case ExprOp::OP_AND:
if ($this->debug) print "\n\npoint: intersect\n\n";
- $result = OpExpr::intersect($db_result, $text_result);
+ $result[$resultContext] = OpExpr::intersect($db_result, $text_result);
break;
case ExprOp::OP_OR:
if ($this->debug) print "\n\nmerge: union\n\n";
- $result = OpExpr::union($db_result, $text_result);
+ $result[$resultContext] = OpExpr::union($db_result, $text_result);
break;
default:
throw new Exception('how did this happen??');
@@ -2141,9 +2291,9 @@ class OpExpr extends Expr
}
$permResults = array();
- foreach($result as $idx=>$item)
+ foreach($result[$resultContext] as $idx=>$item)
{
- $permResults[$idx] = $item;
+ $permResults[$resultContext][$idx] = $item;
}
return $permResults;
diff --git a/search2/search/fields/CreatedByField.inc.php b/search2/search/fields/CreatedByField.inc.php
index 3d872c5..ab930a3 100755
--- a/search2/search/fields/CreatedByField.inc.php
+++ b/search2/search/fields/CreatedByField.inc.php
@@ -7,31 +7,31 @@
* Document Management Made Simple
* Copyright (C) 2008 KnowledgeTree Inc.
* Portions copyright The Jam Warehouse Software (Pty) Limited
- *
+ *
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 3 as published by the
* Free Software Foundation.
- *
+ *
* This program 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 this program. If not, see
-
+
{/if}
- {if !$document->IsAvailable}
+ {if !$hit->IsAvailable}
* {i18n}NOT AVAILABLE{/i18n} *
{/if}
+ {else}
+ {$hit->Title|truncate:80}
+
+ {/if}
+
| - {i18n}Document ID:{/i18n} {$document->DocumentID} - - {i18n}Version:{/i18n} {$document->Version} | + {if $hit->IsDocument} + {i18n}Document ID:{/i18n} {$hit->Id} + + {i18n}Version:{/i18n} {$hit->Version} + {else} + {i18n}Folder ID:{/i18n} {$hit->Id} + {/if}
| {$document->Text} | |
| {$document->FullPath|truncate:40}/{$document->Title|truncate:40} - {$document->Filesize} - + | |
| {$hit->Text} | |
| + {if $hit->IsDocument} + {$hit->FullPath|truncate:40}/{$hit->Title|truncate:40} - {$hit->Filesize} + {else} + {$hit->FullPath|truncate:40} + {/if} | |
| {if $workflow != ''} - {i18n}Workflow:{/i18n} $document->Workflow} + {i18n}Workflow:{/i18n} $hit->Workflow} {/if} | |