📄 indexercore.inc.php
字号:
<?php
/**
* $Id:$
*
* KnowledgeTree Community Edition
* 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 <http://www.gnu.org/licenses/>.
*
* You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
* California 94120-7775, or email info@knowledgetree.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* KnowledgeTree" logo and retain the original copyright notice. If the display of the
* logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
* must display the words "Powered by KnowledgeTree" and retain the original
* copyright notice.
* Contributor( s): ______________________________________
*
*/
define('SEARCH2_INDEXER_DIR',realpath(dirname(__FILE__)) . '/');
require_once('indexing/extractorCore.inc.php');
require_once(KT_DIR . '/plugins/ktcore/scheduler/schedulerUtil.php');
require_once(KT_DIR . '/ktapi/ktapi.inc.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 $id;
protected $title;
protected $rank;
protected $text;
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 getRealId() { 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;
protected $filename;
protected $thumbnail; // TODO: if not null, gui can display a thumbnail
protected $viewer; // TODO: if not null, a viewer can be used to view the document
protected $document;
protected $checkedOutUser;
protected $dateCheckedout;
protected $workflowState;
protected $workflow;
protected $modifiedBy;
protected $dateModified;
protected $createdBy;
protected $dateCreated;
protected $owner;
protected $immutable;
protected $deleted;
protected $status;
protected $folderId;
protected $storagePath;
protected $documentType;
protected $mimeIconPath;
protected $mimeDisplay;
protected $oemDocumentNo;
public function __construct($document_id, $rank=null, $title=null, $text=null, $fullpath = null)
{
parent::__construct($document_id, $title, $rank, $text, $fullpath);
$this->live = true;
$this->loadDocumentInfo();
}
// TODO: this is bad. must refactor to do the query on the group of documents.
public function loadDocumentInfo()
{
global $default;
$sql = "SELECT
d.folder_id, f.full_path, f.name, dcv.size as filesize, dcv.major_version,
dcv.minor_version, dcv.filename, cou.name as checkoutuser, w.human_name as workflow, ws.human_name as workflowstate,
mt.mimetypes as mimetype, md.mime_doc as mimedoc, d.checkedout, mbu.name as modifiedbyuser, d.modified,
cbu.name as createdbyuser, ou.name as owneruser, d.immutable, d.status_id, d.created,dcv.storage_path, dtl.name as document_type,
mt.icon_path as mime_icon_path, mt.friendly_name as mime_display, d.oem_no, dmv.name as title
FROM
documents d
INNER JOIN document_metadata_version dmv ON d.metadata_version_id = dmv.id
INNER JOIN document_content_version dcv ON dmv.content_version_id = dcv.id
INNER JOIN mime_types mt ON dcv.mime_id=mt.id
LEFT JOIN document_types_lookup dtl ON dtl.id=dmv.document_type_id
LEFT JOIN folders f ON f.id=d.folder_id
LEFT JOIN users cou ON d.checked_out_user_id=cou.id
LEFT JOIN workflows w ON dmv.workflow_id=w.id
LEFT JOIN workflow_states ws ON dmv.workflow_state_id = ws.id
LEFT JOIN mime_documents md ON mt.mime_document_id = md.id
LEFT JOIN users mbu ON d.modified_user_id=mbu.id
LEFT JOIN users cbu ON d.creator_id=cbu.id
LEFT JOIN users ou ON d.owner_id=ou.id
WHERE
d.id=$this->id";
$result = DBUtil::getOneResult($sql);
if (PEAR::isError($result) || empty($result))
{
$this->live = false;
if (PEAR::isError($result))
{
throw new Exception('Database exception! There appears to be an error in the system: ' .$result->getMessage());
}
$default->log->error('QueryResultItem: $result is null');
$msg = 'The database did not have a record matching the result from the document indexer. This may occur if there is an inconsistency between the document indexer and the repository. The indexer needs to be repaired.';
$default->log->error('QueryResultItem: ' . $msg);
// TODO: repair process where we scan documents in index, and delete those for which there is nothing in the repository
throw new IndexerInconsistencyException(_kt($msg));
}
// document_id, relevance, text, title
$this->documentType = $result['document_type'];
$this->filename=$result['filename'];
$this->filesize = KTUtil::filesizeToString($result['filesize']);
$this->folderId = $result['folder_id'];
$this->title = $result['title'];
$this->createdBy = $result['createdbyuser'];
$this->dateCreated = $result['created'];
$this->modifiedBy = $result['modifiedbyuser'];
$this->dateModified = $result['modified'];
$this->checkedOutUser = $result['checkoutuser'];
$this->dateCheckedout = $result['checkedout'];
$this->owner = $result['owneruser'];
$this->version = $result['major_version'] . '.' . $result['minor_version'];
$this->immutable = ($result['immutable'] + 0)?_kt('Immutable'):'';
$this->workflow = $result['workflow'];
$this->workflowState = $result['workflowstate'];
$this->oemDocumentNo = $result['oem_no'];
if (empty($this->oemDocumentNo)) $this->oemDocumentNo = 'n/a';
if (is_null($result['name']))
{
$this->fullpath = '(orphaned)';
}
else
{
$this->fullpath = $result['full_path'];
}
$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']);
}
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() { return Document::get($this->id); }
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";
}
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 KTAPI_Document::get_permission_string($this->Document); }
public function getCanBeReadByUser() {
if (!$this->live)
return false;
if (Permission::userHasDocumentReadPermission($this->Document))
return true;
if (Permission::adminIsInAdminMode())
return true;
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->loadFolderInfo();
}
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 Folder::get($this->getFolderID()); }
public function getPermissions() { return KTAPI_Folder::get_permission_string($this->Folder); }
public function loadFolderInfo()
{
global $default;
$folder = $this->getFolder();
if (PEAR::isError($folder))
{
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)
{
if ($a->Rank == $b->Rank) {
return 0;
}
return ($a->Rank < $b->Rank) ? -1 : 1;
}
abstract class Indexer
{
/**
* Cache of extractors
*
* @var array
*/
private $extractorCache;
/**
* Indicates if the indexer will do logging.
*
* @var boolean
*/
private $debug;
/**
* Cache on mime related hooks
*
* @var unknown_type
*/
private $mimeHookCache;
/**
* Cache on general hooks.
*
* @var array
*/
private $generalHookCache;
/**
* This is a path to the extractors.
*
* @var string
*/
private $extractorPath;
/**
* This is a path to the hooks.
*
* @var string
*/
private $hookPath;
private $enabledExtractors;
/**
* Initialise the indexer
*
*/
protected function __construct()
{
$config = KTConfig::getSingleton();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -