Big global search update for 1.9. Will resolve major bug points in Global Search component section.
This commit is contained in:
@@ -36,7 +36,7 @@
|
||||
global $CFG;
|
||||
|
||||
if (empty($CFG->enableglobalsearch)) {
|
||||
return '';
|
||||
return get_string('disabledsearch', 'search');
|
||||
}
|
||||
|
||||
//cache block contents
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Requires and includes
|
||||
*/
|
||||
include_once $CFG->dirroot."/search/lib.php";
|
||||
|
||||
$defaultfiletypes = "PDF,TXT,HTML,PPT,XML,DOC,HTM";
|
||||
|
||||
if (!isset($CFG->block_search_utf8dir)){
|
||||
$CFG->block_search_utf8dir = 0;
|
||||
}
|
||||
if (!isset($CFG->block_search_softlock)){
|
||||
$CFG->block_search_softlock = 0;
|
||||
}
|
||||
|
||||
?>
|
||||
<div style="text-align:center;">
|
||||
<table cellspacing="5">
|
||||
<table cellspacing="5" width="90%">
|
||||
<tr>
|
||||
<td valign="top" align="right">
|
||||
<b><?php print_string('configsearchtext', 'block_search') ?>:</b>
|
||||
@@ -26,6 +43,26 @@
|
||||
} ?>"/><br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" align="right">
|
||||
<b><?php print_string('configutf8transcoding', 'block_search') ?>:</b>
|
||||
</td>
|
||||
<td valign="top" align="left">
|
||||
<input type="radio" name="block_search_utf8dir" value="0" <?php if (!$CFG->block_search_utf8dir) echo "checked=\"checked\"" ?> /> <?php print_string('enabled', 'block_search') ?>
|
||||
<input type="radio" name="block_search_utf8dir" value="1" <?php if ($CFG->block_search_utf8dir) echo "checked=\"checked\"" ?> /> <?php print_string('disabled', 'block_search') ?>
|
||||
<br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" align="right">
|
||||
<b><?php print_string('configusingsoftlock', 'block_search') ?>:</b>
|
||||
</td>
|
||||
<td valign="top" align="left">
|
||||
<input type="radio" name="block_search_softlock" value="0" <?php if (!$CFG->block_search_softlock) echo "checked=\"checked\"" ?> /> <?php print_string('disabled', 'block_search') ?>
|
||||
<input type="radio" name="block_search_softlock" value="1" <?php if ($CFG->block_search_softlock) echo "checked=\"checked\"" ?> /> <?php print_string('enabled', 'block_search') ?>
|
||||
<br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" align="right">
|
||||
<b><?php print_string('configenablefileindexing', 'block_search') ?>:</b>
|
||||
@@ -48,11 +85,12 @@
|
||||
</td>
|
||||
<td valign="top" align="left">
|
||||
<input id="block_search_filetypes" type="text" name="block_search_filetypes" value="<?php
|
||||
if(isset($CFG->block_search_filetypes)) {
|
||||
p($CFG->block_search_filetypes);
|
||||
} else {
|
||||
p("PDF,TXT,HTML,PPT,XML,DOC,HTM");
|
||||
} ?>"/><br/><br/>
|
||||
if(!isset($CFG->block_search_filetypes)) {
|
||||
$CFG->block_search_filetypes = $defaultfiletypes;
|
||||
}
|
||||
p($CFG->block_search_filetypes);
|
||||
?>" />
|
||||
<br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -69,6 +107,24 @@
|
||||
<br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" align="right">
|
||||
<b><?php print_string('configlimitindexbody', 'block_search') ?>:</b>
|
||||
</td>
|
||||
<td valign="top" align="left">
|
||||
<input id="block_search_limit_index_body" type="text" size="8" name="block_search_limit_index_body" value="<?php
|
||||
if(isset($CFG->block_search_limit_index_body)) {
|
||||
p($CFG->block_search_limit_index_body);
|
||||
} else {
|
||||
p('');
|
||||
} ?>"/> <?php print_string('bytes', 'block_search') ?><br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<fieldset name="">
|
||||
<legend align="top"><?php print_string('pdfhandling', 'block_search') ?></legend>
|
||||
<table cellspacing="5" width="90%">
|
||||
<tr>
|
||||
<td valign="top" align="right">
|
||||
<b><?php print_string('configpdftotextcmd', 'block_search') ?>:</b>
|
||||
@@ -88,6 +144,12 @@
|
||||
} ?>"/><br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="">
|
||||
<legend align="top"><?php print_string('wordhandling', 'block_search') ?></legend>
|
||||
<table cellspacing="5" width="90%">
|
||||
<tr>
|
||||
<td valign="top" align="right">
|
||||
<b><?php print_string('configwordtotextcmd', 'block_search') ?>:</b>
|
||||
@@ -124,19 +186,140 @@
|
||||
} ?>"/><br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<?php
|
||||
$types = split(',', $CFG->block_search_filetypes);
|
||||
if (!empty($types)){
|
||||
foreach($types as $type) {
|
||||
$utype = strtoupper($type);
|
||||
$type = strtolower($type);
|
||||
$type = trim($type);
|
||||
if (preg_match("/\\b$type\\b/i", $defaultfiletypes)) continue;
|
||||
?>
|
||||
<fieldset name="">
|
||||
<legend align="top"><?php echo get_string('handlingfor', 'block_search').' '.$utype ?></legend>
|
||||
<table cellspacing="5" width="90%">
|
||||
<tr>
|
||||
<td valign="top" align="right">
|
||||
<b><?php print_string('configlimitindexbody', 'block_search') ?>:</b>
|
||||
<b><?php print_string('configtypetotxtcmd', 'block_search') ?>:</b>
|
||||
</td>
|
||||
<td valign="top" align="left">
|
||||
<input id="block_search_limit_index_body" type="text" size="8" name="block_search_limit_index_body" value="<?php
|
||||
if(isset($CFG->block_search_limit_index_body)) {
|
||||
p($CFG->block_search_limit_index_body);
|
||||
} else {
|
||||
p('');
|
||||
} ?>"/> <?php print_string('bytes', 'block_search') ?><br/><br/>
|
||||
<input id="block_search_<?php p($type) ?>_to_text_cmd" type="text" size="60" name="block_search_<?php p($type) ?>_to_text_cmd" value="<?php
|
||||
$propname = "block_search_{$type}_to_text_cmd";
|
||||
if(isset($CFG->$propname)) {
|
||||
p($CFG->$propname);
|
||||
}
|
||||
?>"/>
|
||||
<br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" align="right">
|
||||
<b><?php print_string('configtypetotxtenv', 'block_search') ?>:</b>
|
||||
</td>
|
||||
<td valign="top" align="left">
|
||||
<input id="block_search_<?php p($type) ?>_to_text_env" type="text" size="60" name="block_search_<?php p($type) ?>_to_text_env" value="<?php
|
||||
$propname = "block_search_{$type}_to_text_env";
|
||||
if(isset($CFG->$propname)) {
|
||||
echo stripslashes($CFG->$propname);
|
||||
} ?>"/><br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<fieldset name="">
|
||||
<legend align="top"><?php echo get_string('searchdiscovery', 'block_search') ?></legend>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<pre>
|
||||
<?php
|
||||
$searchnames = search_collect_searchables(true);
|
||||
$searchable_list = implode("','", $searchnames);
|
||||
?>
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="">
|
||||
<legend align="top"><?php echo get_string('modulessearchswitches', 'block_search') ?></legend>
|
||||
<table cellspacing="5" width="90%">
|
||||
<tr valign="top">
|
||||
<td align="left">
|
||||
<?php
|
||||
$i = 0;
|
||||
$found_searchable_modules = 0;
|
||||
if ($modules = get_records_select('modules', " name IN ('{$searchable_list}') ", 'name', 'id,name')){
|
||||
foreach($modules as $module){
|
||||
$i++;
|
||||
$keyname = "search_in_{$module->name}";
|
||||
$checkedup = (!isset($CFG->$keyname) || $CFG->$keyname) ? 'checked="checked"' : '' ;
|
||||
$checkeddown = !(!isset($CFG->$keyname) || $CFG->$keyname) ? 'checked="checked"' : '' ;
|
||||
echo "<input type=\"radio\" name=\"search_in_{$module->name}\" value=\"0\" {$checkeddown} /> " . get_string('no');
|
||||
echo " - <input type=\"radio\" name=\"search_in_{$module->name}\" value=\"1\" {$checkedup} /> " . get_string('yes');
|
||||
echo " - ".get_string('modulename', $module->name).'<br/>';
|
||||
if ($i % 20 == 0){
|
||||
echo "</td><td align=\"left\">";
|
||||
}
|
||||
$found_searchable_modules = 1;
|
||||
}
|
||||
}
|
||||
if (!$found_searchable_modules) {
|
||||
print_string('nosearchablemodules', 'block_search');
|
||||
}
|
||||
?>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="">
|
||||
<legend align="top"><?php echo get_string('blockssearchswitches', 'block_search') ?></legend>
|
||||
<table cellspacing="5" width="90%">
|
||||
<tr valign="top">
|
||||
<td align="left">
|
||||
<?php
|
||||
$i = 0;
|
||||
$found_searchable_blocks = 0;
|
||||
if ($blocks = get_records_select('block', " name IN ('{$searchable_list}') ", 'name', 'id,name')){
|
||||
foreach($blocks as $block){
|
||||
$i++;
|
||||
$keyname = "search_in_{$block->name}";
|
||||
$checked = (!isset($CFG->$keyname) || $CFG->$keyname) ? 'checked="checked"' : '' ;
|
||||
echo "<input type=\"checkbox\" name=\"search_in_{$block->name}\" value=\"1\" {$checked} />";
|
||||
|
||||
// multiple fallback strategy to get the name of the block
|
||||
$blocklabel = get_string('blockname', 'block_'.$block->name);
|
||||
if ($blocklabel == '[[blockname]]') $blocklabel = get_string($block->name, 'block_'.$block->name);
|
||||
if ($blocklabel == "[[{$block->name}]]") $blocklabel = "<span class=\"dimmed_text\">$block->name</span>";
|
||||
echo " - ".$blocklabel.'<br/>';
|
||||
if ($i % 20 == 0){
|
||||
echo "</td><td align=\"left\">";
|
||||
}
|
||||
$found_searchable_blocks = 1;
|
||||
}
|
||||
}
|
||||
if (!$found_searchable_blocks) {
|
||||
print_string('nosearchableblocks', 'block_search');
|
||||
}
|
||||
?>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<table cellspacing="5" width="90%">
|
||||
<tr>
|
||||
<td valign="top" align="right" colspan="2">
|
||||
<input type="submit" value="<?php print_string('savechanges'); ?>" />
|
||||
|
||||
@@ -1,15 +1,34 @@
|
||||
<?php
|
||||
$string['asynchronous'] = 'Asynchronous (Ajax)';
|
||||
$string['blockname'] = 'Global Search';
|
||||
$string['blockssearchswitches'] = 'Indexer activation for blocks';
|
||||
$string['blockssearchmnetfeatures'] = 'Moodle Network Search';
|
||||
$string['bytes'] = ' bytes (0 stands for no limits)';
|
||||
$string['configbuttonlabel'] = 'Button label';
|
||||
$string['configenablefileindexing'] = 'Enable file indexing';
|
||||
$string['configfiletypes'] = 'File types handled';
|
||||
$string['configlimitindexbody'] = 'Indexed body size limitation';
|
||||
$string['configpdftotextcmd'] = 'Path to command pdftotext';
|
||||
$string['configsearchtext'] = 'Search text';
|
||||
$string['configtypetotxtcmd'] = 'Converter\'s command line';
|
||||
$string['configtypetotxtenv'] = 'Environment define for converter';
|
||||
$string['configusingsoftlock'] = 'Software interlocking (for NFS mounted clusters)';
|
||||
$string['configutf8transcoding'] = 'UTF8 transcoding direction of results';
|
||||
$string['configwordtotextcmd'] = 'Path to command doctotext';
|
||||
$string['configwordtotextenv'] = 'Environment setting for the MSWord converter';
|
||||
$string['configsearchtext'] = 'Search text';
|
||||
$string['disabled'] = 'Disabled';
|
||||
$string['disabledsearch'] = 'The global search engine is off. Inform your administrator.';
|
||||
$string['enabled'] = 'Enabled';
|
||||
$string['go'] = 'Go!';
|
||||
$string['bytes'] = ' bytes (0 stands for no limits)';
|
||||
$string['handlingfor'] = 'Extra handling for';
|
||||
$string['modulessearchswitches'] = 'Indexer activation for modules';
|
||||
$string['nosearchableblocks'] = 'No searchable blocks';
|
||||
$string['nosearchablemodules'] = 'No searchable modules';
|
||||
$string['pdfhandling'] = 'Acrobat PDF handling';
|
||||
$string['search'] = 'Search';
|
||||
$string['searchdiscovery'] = 'Searchable items discovery';
|
||||
$string['searchmoodle'] = 'Search Moodle';
|
||||
$string['synchronous'] = 'Synchronous';
|
||||
$string['usemoodleroot'] = 'Use moodle root for external converters';
|
||||
$string['wordhandling'] = 'Microsoft Word handling';
|
||||
?>
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
/**
|
||||
* Framework base exception
|
||||
*/
|
||||
require_once $CFG->dirroot.'/search/Zend/Exception.php';
|
||||
require_once "Zend/Exception.php";
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Exception extends Zend_Exception
|
||||
|
||||
+426
-77
@@ -14,65 +14,72 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once "Zend/Search/Lucene/Exception.php";
|
||||
|
||||
/** Zend_Search_Lucene_Document */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Document.php';
|
||||
require_once "Zend/Search/Lucene/Document.php";
|
||||
|
||||
/** Zend_Search_Lucene_Document_Html */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Document/Html.php';
|
||||
require_once "Zend/Search/Lucene/Document/Html.php";
|
||||
|
||||
/** Zend_Search_Lucene_Storage_Directory */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Storage/Directory/Filesystem.php';
|
||||
/** Zend_Search_Lucene_Storage_Directory_Filesystem */
|
||||
require_once "Zend/Search/Lucene/Storage/Directory/Filesystem.php";
|
||||
|
||||
/** Zend_Search_Lucene_Storage_File_Memory */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Storage/File/Memory.php';
|
||||
require_once "Zend/Search/Lucene/Storage/File/Memory.php";
|
||||
|
||||
/** Zend_Search_Lucene_Index_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/Term.php';
|
||||
require_once "Zend/Search/Lucene/Index/Term.php";
|
||||
|
||||
/** Zend_Search_Lucene_Index_TermInfo */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/TermInfo.php';
|
||||
require_once "Zend/Search/Lucene/Index/TermInfo.php";
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentInfo */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentInfo.php';
|
||||
require_once "Zend/Search/Lucene/Index/SegmentInfo.php";
|
||||
|
||||
/** Zend_Search_Lucene_Index_FieldInfo */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/FieldInfo.php';
|
||||
require_once "Zend/Search/Lucene/Index/FieldInfo.php";
|
||||
|
||||
/** Zend_Search_Lucene_Index_Writer */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/Writer.php';
|
||||
require_once "Zend/Search/Lucene/Index/Writer.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParser */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParser.php';
|
||||
require_once "Zend/Search/Lucene/Search/QueryParser.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryHit */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryHit.php';
|
||||
require_once "Zend/Search/Lucene/Search/QueryHit.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Similarity */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Similarity.php';
|
||||
require_once "Zend/Search/Lucene/Search/Similarity.php";
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentInfoPriorityQueue */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentInfoPriorityQueue.php';
|
||||
require_once "Zend/Search/Lucene/Index/SegmentInfoPriorityQueue.php";
|
||||
|
||||
/** Zend_Search_Lucene_LockManager */
|
||||
if (@$CFG->block_search_softlock){
|
||||
require_once "Zend/Search/Lucene/SoftLockManager.php";
|
||||
} else {
|
||||
require_once "Zend/Search/Lucene/LockManager.php";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Interface */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Interface.php';
|
||||
require_once "Zend/Search/Lucene/Interface.php";
|
||||
|
||||
/** Zend_Search_Lucene_Proxy */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Proxy.php';
|
||||
require_once "Zend/Search/Lucene/Proxy.php";
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
@@ -86,6 +93,15 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
*/
|
||||
private static $_defaultSearchField = null;
|
||||
|
||||
/**
|
||||
* Result set limit
|
||||
*
|
||||
* 0 means no limit
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private static $_resultSetLimit = 0;
|
||||
|
||||
/**
|
||||
* File system adapter.
|
||||
*
|
||||
@@ -129,13 +145,6 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
private $_hasChanges = false;
|
||||
|
||||
|
||||
/**
|
||||
* Index lock object
|
||||
*
|
||||
* @var Zend_Search_Lucene_Storage_File
|
||||
*/
|
||||
private $_lock;
|
||||
|
||||
/**
|
||||
* Signal, that index is already closed, changes are fixed and resources are cleaned up
|
||||
*
|
||||
@@ -150,7 +159,14 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
*/
|
||||
private $_refCount = 0;
|
||||
|
||||
/**
|
||||
* Current segment generation
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_generation;
|
||||
|
||||
|
||||
/**
|
||||
* Create index
|
||||
*
|
||||
@@ -173,56 +189,101 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
return new Zend_Search_Lucene_Proxy(new Zend_Search_Lucene($directory, false));
|
||||
}
|
||||
|
||||
/** Generation retrieving counter */
|
||||
const GENERATION_RETRIEVE_COUNT = 10;
|
||||
|
||||
/** Pause between generation retrieving attempts in milliseconds */
|
||||
const GENERATION_RETRIEVE_PAUSE = 50;
|
||||
|
||||
/**
|
||||
* Opens the index.
|
||||
* Get current generation number
|
||||
*
|
||||
* IndexReader constructor needs Directory as a parameter. It should be
|
||||
* a string with a path to the index folder or a Directory object.
|
||||
* Returns generation number
|
||||
* 0 means pre-2.1 index format
|
||||
* -1 means there are no segments files.
|
||||
*
|
||||
* @param mixed $directory
|
||||
* @param Zend_Search_Lucene_Storage_Directory $directory
|
||||
* @return integer
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
public function __construct($directory = null, $create = false)
|
||||
public static function getActualGeneration(Zend_Search_Lucene_Storage_Directory $directory)
|
||||
{
|
||||
if ($directory === null) {
|
||||
throw new Zend_Search_Exception('No index directory specified');
|
||||
}
|
||||
/**
|
||||
* Zend_Search_Lucene uses segments.gen file to retrieve current generation number
|
||||
*
|
||||
* Apache Lucene index format documentation mentions this method only as a fallback method
|
||||
*
|
||||
* Nevertheless we use it according to the performance considerations
|
||||
*
|
||||
* @todo check if we can use some modification of Apache Lucene generation determination algorithm
|
||||
* without performance problems
|
||||
*/
|
||||
|
||||
if ($directory instanceof Zend_Search_Lucene_Storage_Directory_Filesystem) {
|
||||
$this->_directory = $directory;
|
||||
$this->_closeDirOnExit = false;
|
||||
} else {
|
||||
$this->_directory = new Zend_Search_Lucene_Storage_Directory_Filesystem($directory);
|
||||
$this->_closeDirOnExit = true;
|
||||
}
|
||||
try {
|
||||
for ($count = 0; $count < self::GENERATION_RETRIEVE_COUNT; $count++) {
|
||||
// Try to get generation file
|
||||
$genFile = $directory->getFileObject('segments.gen', false);
|
||||
|
||||
$format = $genFile->readInt();
|
||||
if ($format != (int)0xFFFFFFFE) {
|
||||
throw new Zend_Search_Lucene_Exception('Wrong segments.gen file format');
|
||||
}
|
||||
|
||||
// Get a shared lock to the index
|
||||
$this->_lock = $this->_directory->createFile('index.lock');
|
||||
$gen1 = $genFile->readLong();
|
||||
$gen2 = $genFile->readLong();
|
||||
|
||||
$this->_segmentInfos = array();
|
||||
if ($gen1 == $gen2) {
|
||||
return $gen1;
|
||||
}
|
||||
|
||||
if ($create) {
|
||||
// Throw an exception if index is under processing now
|
||||
if (!$this->_lock->lock(LOCK_EX, true)) {
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t create index. It\'s under processing now');
|
||||
usleep(self::GENERATION_RETRIEVE_PAUSE * 1000);
|
||||
}
|
||||
|
||||
// Writer will create segments file for empty segments list
|
||||
$this->_writer = new Zend_Search_Lucene_Index_Writer($this->_directory, $this->_segmentInfos, true);
|
||||
// All passes are failed
|
||||
throw new Zend_Search_Lucene_Exception('Index is under processing now');
|
||||
} catch (Zend_Search_Lucene_Exception $e) {
|
||||
if (strpos($e->getMessage(), 'is not readable') !== false) {
|
||||
try {
|
||||
// Try to open old style segments file
|
||||
$segmentsFile = $directory->getFileObject('segments', false);
|
||||
|
||||
if (!$this->_lock->lock(LOCK_SH)) {
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t reduce lock level from Exclusive to Shared');
|
||||
// It's pre-2.1 index
|
||||
return 0;
|
||||
} catch (Zend_Search_Lucene_Exception $e) {
|
||||
if (strpos($e->getMessage(), 'is not readable') !== false) {
|
||||
return -1;
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
} else {
|
||||
// Wait if index is under switching from one set of segments to another (Index_Writer::_updateSegments())
|
||||
if (!$this->_lock->lock(LOCK_SH)) {
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t obtain shared index lock');
|
||||
}
|
||||
$this->_writer = null;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get segments file name
|
||||
*
|
||||
* @param integer $generation
|
||||
* @return string
|
||||
*/
|
||||
public static function getSegmentFileName($generation)
|
||||
{
|
||||
if ($generation == 0) {
|
||||
return 'segments';
|
||||
}
|
||||
|
||||
return 'segments_' . base_convert($generation, 10, 36);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read segments file for pre-2.1 Lucene index format
|
||||
*/
|
||||
private function _readPre21SegmentsFile()
|
||||
{
|
||||
$segmentsFile = $this->_directory->getFileObject('segments');
|
||||
|
||||
$format = $segmentsFile->readInt();
|
||||
@@ -248,13 +309,156 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
$segSize = $segmentsFile->readInt();
|
||||
$this->_docCount += $segSize;
|
||||
|
||||
$this->_segmentInfos[] =
|
||||
new Zend_Search_Lucene_Index_SegmentInfo($segName,
|
||||
$segSize,
|
||||
$this->_directory);
|
||||
$this->_segmentInfos[$segName] =
|
||||
new Zend_Search_Lucene_Index_SegmentInfo($this->_directory,
|
||||
$segName,
|
||||
$segSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read segments file
|
||||
*
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
private function _readSegmentsFile()
|
||||
{
|
||||
$segmentsFile = $this->_directory->getFileObject(self::getSegmentFileName($this->_generation));
|
||||
|
||||
$format = $segmentsFile->readInt();
|
||||
|
||||
if ($format != (int)0xFFFFFFFD) {
|
||||
throw new Zend_Search_Lucene_Exception('Wrong segments file format');
|
||||
}
|
||||
|
||||
// read version
|
||||
// $segmentsFile->readLong();
|
||||
$segmentsFile->readInt(); $segmentsFile->readInt();
|
||||
|
||||
// read segment name counter
|
||||
$segmentsFile->readInt();
|
||||
|
||||
$segments = $segmentsFile->readInt();
|
||||
|
||||
$this->_docCount = 0;
|
||||
|
||||
// read segmentInfos
|
||||
for ($count = 0; $count < $segments; $count++) {
|
||||
$segName = $segmentsFile->readString();
|
||||
$segSize = $segmentsFile->readInt();
|
||||
|
||||
// 2.1+ specific properties
|
||||
//$delGen = $segmentsFile->readLong();
|
||||
$delGenHigh = $segmentsFile->readInt();
|
||||
$delGenLow = $segmentsFile->readInt();
|
||||
if ($delGenHigh == (int)0xFFFFFFFF && $delGenLow == (int)0xFFFFFFFF) {
|
||||
$delGen = -1; // There are no deletes
|
||||
} else {
|
||||
$delGen = ($delGenHigh << 32) | $delGenLow;
|
||||
}
|
||||
|
||||
$hasSingleNormFile = $segmentsFile->readByte();
|
||||
$numField = $segmentsFile->readInt();
|
||||
|
||||
$normGens = array();
|
||||
if ($numField != (int)0xFFFFFFFF) {
|
||||
for ($count1 = 0; $count1 < $numField; $count1++) {
|
||||
$normGens[] = $segmentsFile->readLong();
|
||||
}
|
||||
|
||||
throw new Zend_Search_Lucene_Exception('Separate norm files are not supported. Optimize index to use it with Zend_Search_Lucene.');
|
||||
}
|
||||
|
||||
$isCompound = $segmentsFile->readByte();
|
||||
|
||||
|
||||
$this->_docCount += $segSize;
|
||||
|
||||
$this->_segmentInfos[$segName] =
|
||||
new Zend_Search_Lucene_Index_SegmentInfo($this->_directory,
|
||||
$segName,
|
||||
$segSize,
|
||||
$delGen,
|
||||
$hasSingleNormFile,
|
||||
$isCompound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the index.
|
||||
*
|
||||
* IndexReader constructor needs Directory as a parameter. It should be
|
||||
* a string with a path to the index folder or a Directory object.
|
||||
*
|
||||
* @param mixed $directory
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
public function __construct($directory = null, $create = false)
|
||||
{
|
||||
if ($directory === null) {
|
||||
throw new Zend_Search_Exception('No index directory specified');
|
||||
}
|
||||
|
||||
if ($directory instanceof Zend_Search_Lucene_Storage_Directory_Filesystem) {
|
||||
$this->_directory = $directory;
|
||||
$this->_closeDirOnExit = false;
|
||||
} else {
|
||||
$this->_directory = new Zend_Search_Lucene_Storage_Directory_Filesystem($directory);
|
||||
$this->_closeDirOnExit = true;
|
||||
}
|
||||
|
||||
$this->_segmentInfos = array();
|
||||
|
||||
// Mark index as "under processing" to prevent other processes from premature index cleaning
|
||||
Zend_Search_Lucene_LockManager::obtainReadLock($this->_directory);
|
||||
|
||||
// Escalate read lock to prevent current generation index files to be deleted while opening process is not done
|
||||
Zend_Search_Lucene_LockManager::escalateReadLock($this->_directory);
|
||||
|
||||
|
||||
$this->_generation = self::getActualGeneration($this->_directory);
|
||||
|
||||
if ($create) {
|
||||
try {
|
||||
Zend_Search_Lucene_LockManager::obtainWriteLock($this->_directory);
|
||||
} catch (Zend_Search_Lucene_Exception $e) {
|
||||
if (strpos($e->getMessage(), 'Can\'t obtain exclusive index lock') === false) {
|
||||
throw $e;
|
||||
} else {
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t create index. It\'s under processing now');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->_generation == -1) {
|
||||
// Directory doesn't contain existing index, start from 1
|
||||
$this->_generation = 1;
|
||||
$nameCounter = 0;
|
||||
} else {
|
||||
// Directory contains existing index
|
||||
$segmentsFile = $this->_directory->getFileObject(self::getSegmentFileName($this->_generation));
|
||||
$segmentsFile->seek(12); // 12 = 4 (int, file format marker) + 8 (long, index version)
|
||||
|
||||
$nameCounter = $segmentsFile->readInt();
|
||||
$this->_generation++;
|
||||
}
|
||||
|
||||
Zend_Search_Lucene_Index_Writer::createIndex($this->_directory, $this->_generation, $nameCounter);
|
||||
|
||||
Zend_Search_Lucene_LockManager::releaseWriteLock($this->_directory);
|
||||
}
|
||||
|
||||
if ($this->_generation == -1) {
|
||||
throw new Zend_Search_Lucene_Exception('Index doesn\'t exists in the specified directory.');
|
||||
} else if ($this->_generation == 0) {
|
||||
$this->_readPre21SegmentsFile();
|
||||
} else {
|
||||
$this->_readSegmentsFile();
|
||||
}
|
||||
|
||||
// De-escalate read lock to prevent current generation index files to be deleted while opening process is not done
|
||||
Zend_Search_Lucene_LockManager::deEscalateReadLock($this->_directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close current index and free resources
|
||||
*/
|
||||
@@ -267,9 +471,9 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
|
||||
$this->commit();
|
||||
|
||||
// Free shared lock
|
||||
$this->_lock->unlock();
|
||||
|
||||
// Release "under processing" flag
|
||||
Zend_Search_Lucene_LockManager::releaseReadLock($this->_directory);
|
||||
|
||||
if ($this->_closeDirOnExit) {
|
||||
$this->_directory->close();
|
||||
}
|
||||
@@ -431,6 +635,30 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
return self::$_defaultSearchField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set result set limit.
|
||||
*
|
||||
* 0 (default) means no limit
|
||||
*
|
||||
* @param integer $limit
|
||||
*/
|
||||
public static function setResultSetLimit($limit)
|
||||
{
|
||||
self::$_resultSetLimit = $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set result set limit.
|
||||
*
|
||||
* 0 means no limit
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public static function getResultSetLimit()
|
||||
{
|
||||
return self::$_resultSetLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve index maxBufferedDocs option
|
||||
*
|
||||
@@ -585,11 +813,15 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
$topScore = $docScore;
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$_resultSetLimit != 0 && count($hits) >= self::$_resultSetLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($hits) == 0) {
|
||||
// skip sorting, which may cause a error on empty index
|
||||
return array();
|
||||
return array();
|
||||
}
|
||||
|
||||
if ($topScore > 1) {
|
||||
@@ -977,6 +1209,8 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
{
|
||||
$this->getIndexWriter()->addDocument($document);
|
||||
$this->_docCount++;
|
||||
|
||||
$this->_hasChanges = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1002,14 +1236,12 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
foreach ($this->_segmentInfos as $segInfo) {
|
||||
$segInfo->writeChanges();
|
||||
}
|
||||
|
||||
$this->_hasChanges = false;
|
||||
}
|
||||
|
||||
if ($this->_writer !== null) {
|
||||
$this->_writer->commit();
|
||||
|
||||
|
||||
$this->getIndexWriter()->commit();
|
||||
|
||||
$this->_updateDocCount();
|
||||
|
||||
$this->_hasChanges = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1059,9 +1291,7 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
$result[] = $segmentInfo->currentTerm();
|
||||
}
|
||||
|
||||
$segmentInfo->nextTerm();
|
||||
// check, if segment dictionary is finished
|
||||
if ($segmentInfo->currentTerm() !== null) {
|
||||
if ($segmentInfo->nextTerm() !== null) {
|
||||
// Put segment back into the priority queue
|
||||
$segmentInfoQueue->put($segmentInfo);
|
||||
}
|
||||
@@ -1071,6 +1301,125 @@ class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Terms stream queue
|
||||
*
|
||||
* @var Zend_Search_Lucene_Index_SegmentInfoPriorityQueue
|
||||
*/
|
||||
private $_termsStreamQueue = null;
|
||||
|
||||
/**
|
||||
* Last Term in a terms stream
|
||||
*
|
||||
* @var Zend_Search_Lucene_Index_Term
|
||||
*/
|
||||
private $_lastTerm = null;
|
||||
|
||||
/**
|
||||
* Reset terms stream.
|
||||
*/
|
||||
public function resetTermsStream()
|
||||
{
|
||||
$this->_termsStreamQueue = new Zend_Search_Lucene_Index_SegmentInfoPriorityQueue();
|
||||
|
||||
foreach ($this->_segmentInfos as $segmentInfo) {
|
||||
$segmentInfo->reset();
|
||||
|
||||
// Skip "empty" segments
|
||||
if ($segmentInfo->currentTerm() !== null) {
|
||||
$this->_termsStreamQueue->put($segmentInfo);
|
||||
}
|
||||
}
|
||||
|
||||
$this->nextTerm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip terms stream up to specified term preffix.
|
||||
*
|
||||
* Prefix contains fully specified field info and portion of searched term
|
||||
*
|
||||
* @param Zend_Search_Lucene_Index_Term $prefix
|
||||
*/
|
||||
public function skipTo(Zend_Search_Lucene_Index_Term $prefix)
|
||||
{
|
||||
$segments = array();
|
||||
|
||||
while (($segmentInfo = $this->_termsStreamQueue->pop()) !== null) {
|
||||
$segments[] = $segmentInfo;
|
||||
}
|
||||
|
||||
foreach ($segments as $segmentInfo) {
|
||||
$segmentInfo->skipTo($prefix);
|
||||
|
||||
if ($segmentInfo->currentTerm() !== null) {
|
||||
$this->_termsStreamQueue->put($segmentInfo);
|
||||
}
|
||||
}
|
||||
|
||||
$this->nextTerm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans terms dictionary and returns next term
|
||||
*
|
||||
* @return Zend_Search_Lucene_Index_Term|null
|
||||
*/
|
||||
public function nextTerm()
|
||||
{
|
||||
while (($segmentInfo = $this->_termsStreamQueue->pop()) !== null) {
|
||||
if ($this->_termsStreamQueue->top() === null ||
|
||||
$this->_termsStreamQueue->top()->currentTerm()->key() !=
|
||||
$segmentInfo->currentTerm()->key()) {
|
||||
// We got new term
|
||||
$this->_lastTerm = $segmentInfo->currentTerm();
|
||||
|
||||
if ($segmentInfo->nextTerm() !== null) {
|
||||
// Put segment back into the priority queue
|
||||
$this->_termsStreamQueue->put($segmentInfo);
|
||||
}
|
||||
|
||||
return $this->_lastTerm;
|
||||
}
|
||||
|
||||
if ($segmentInfo->nextTerm() !== null) {
|
||||
// Put segment back into the priority queue
|
||||
$this->_termsStreamQueue->put($segmentInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// End of stream
|
||||
$this->_lastTerm = null;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns term in current position
|
||||
*
|
||||
* @return Zend_Search_Lucene_Index_Term|null
|
||||
*/
|
||||
public function currentTerm()
|
||||
{
|
||||
return $this->_lastTerm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close terms stream
|
||||
*
|
||||
* Should be used for resources clean up if stream is not read up to the end
|
||||
*/
|
||||
public function closeTermsStream()
|
||||
{
|
||||
while (($segmentInfo = $this->_termsStreamQueue->pop()) !== null) {
|
||||
$segmentInfo->closeTermsStream();
|
||||
}
|
||||
|
||||
$this->_termsStreamQueue = null;
|
||||
$this->_lastTerm = null;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
@todo UNIMPLEMENTED
|
||||
*************************************************************************/
|
||||
|
||||
@@ -15,37 +15,43 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Token */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Token.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/Token.php";
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8 */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Utf8.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Utf8.php";
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive */
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Utf8/CaseInsensitive.php";
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Utf8Num.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Utf8Num.php";
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive */
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Utf8Num/CaseInsensitive.php";
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common_Text */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Text.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Text.php";
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Text/CaseInsensitive.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Text/CaseInsensitive.php";
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common/TextNum.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/Analyzer/Common/TextNum.php";
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common/TextNum/CaseInsensitive.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/Analyzer/Common/TextNum/CaseInsensitive.php";
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_TokenFilter_StopWords */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/TokenFilter/StopWords.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/TokenFilter/StopWords.php';
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_TokenFilter_ShortWords */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/TokenFilter/ShortWords.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/TokenFilter/ShortWords.php";
|
||||
|
||||
|
||||
/**
|
||||
@@ -61,7 +67,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/TokenFilter/Shor
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -97,9 +103,10 @@ abstract class Zend_Search_Lucene_Analysis_Analyzer
|
||||
* @param string $data
|
||||
* @return array
|
||||
*/
|
||||
public function tokenize($data, $encoding = 'UTF-8')
|
||||
public function tokenize($data, $encoding = '')
|
||||
{
|
||||
$this->setInput($data, $encoding);
|
||||
|
||||
$tokenList = array();
|
||||
while (($nextToken = $this->nextToken()) !== null) {
|
||||
$tokenList[] = $nextToken;
|
||||
@@ -160,7 +167,7 @@ abstract class Zend_Search_Lucene_Analysis_Analyzer
|
||||
public static function getDefault()
|
||||
{
|
||||
if (!self::$_defaultImpl instanceof Zend_Search_Lucene_Analysis_Analyzer) {
|
||||
self::$_defaultImpl = new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8();
|
||||
self::$_defaultImpl = new Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive();
|
||||
}
|
||||
|
||||
return self::$_defaultImpl;
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -34,7 +34,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Search_Lucene_Analysis_Analyzer_Common extends Zend_Search_Lucene_Analysis_Analyzer
|
||||
@@ -68,7 +68,7 @@ abstract class Zend_Search_Lucene_Analysis_Analyzer_Common extends Zend_Search_L
|
||||
foreach ($this->_filters as $filter) {
|
||||
$token = $filter->normalize($token);
|
||||
|
||||
// resulting token can be null if the filter removed it
|
||||
// resulting token can be null if the filter removes it
|
||||
if (is_null($token)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Analyzer/Common.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -53,7 +53,9 @@ class Zend_Search_Lucene_Analysis_Analyzer_Common_Text extends Zend_Search_Lucen
|
||||
}
|
||||
|
||||
// convert input into ascii
|
||||
$this->_input = iconv($this->_encoding, 'ASCII//TRANSLIT', $this->_input);
|
||||
//$this->_input = iconv($this->_encoding, 'ASCII//TRANSLIT', $this->_input);
|
||||
$this->_input = mb_convert_encoding($this->_input, 'ASCII', 'auto');
|
||||
|
||||
$this->_encoding = 'ASCII';
|
||||
}
|
||||
|
||||
@@ -75,7 +77,7 @@ class Zend_Search_Lucene_Analysis_Analyzer_Common_Text extends Zend_Search_Lucen
|
||||
if (! preg_match('/[a-zA-Z]+/', $this->_input, $match, PREG_OFFSET_CAPTURE, $this->_position)) {
|
||||
// It covers both cases a) there are no matches (preg_match(...) === 0)
|
||||
// b) error occured (preg_match(...) === FALSE)
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
$str = $match[0][0];
|
||||
|
||||
@@ -15,23 +15,23 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common_Text */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common/Text.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Analyzer/Common/Text.php';
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_TokenFilter_LowerCase */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/TokenFilter/LowerCase.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/TokenFilter/LowerCase.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Analyzer/Common.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -74,7 +74,7 @@ class Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum extends Zend_Search_Lu
|
||||
if (! preg_match('/[a-zA-Z0-9]+/', $this->_input, $match, PREG_OFFSET_CAPTURE, $this->_position)) {
|
||||
// It covers both cases a) there are no matches (preg_match(...) === 0)
|
||||
// b) error occured (preg_match(...) === FALSE)
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
$str = $match[0][0];
|
||||
|
||||
@@ -15,23 +15,23 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common/TextNum.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Analyzer/Common/TextNum.php';
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_TokenFilter_LowerCase */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/TokenFilter/LowerCase.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/TokenFilter/LowerCase.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Analyzer/Common.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -47,13 +47,20 @@ class Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8 extends Zend_Search_Lucen
|
||||
* @var integer
|
||||
*/
|
||||
private $_bytePosition;
|
||||
|
||||
|
||||
/**
|
||||
* Stream length
|
||||
* Object constructor
|
||||
*
|
||||
* @var integer
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
private $_streamLength;
|
||||
public function __construct()
|
||||
{
|
||||
if (@preg_match('/\pL/u', 'a') != 1) {
|
||||
// PCRE unicode support is turned off
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
throw new Zend_Search_Lucene_Exception('Utf8 analyzer needs PCRE unicode support to be enabled.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset token stream
|
||||
@@ -66,56 +73,9 @@ class Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8 extends Zend_Search_Lucen
|
||||
// convert input into UTF-8
|
||||
if (strcasecmp($this->_encoding, 'utf8' ) != 0 &&
|
||||
strcasecmp($this->_encoding, 'utf-8') != 0 ) {
|
||||
$this->_input = iconv($this->_encoding, 'UTF-8', $this->_input);
|
||||
$this->_input = @iconv($this->_encoding, 'UTF-8', $this->_input);
|
||||
$this->_encoding = 'UTF-8';
|
||||
}
|
||||
|
||||
// Get UTF-8 string length.
|
||||
// It also checks if it's a correct utf-8 string
|
||||
$this->_streamLength = iconv_strlen($this->_input, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check, that character is a letter
|
||||
*
|
||||
* @param string $char
|
||||
* @return boolean
|
||||
*/
|
||||
private static function _isAlpha($char)
|
||||
{
|
||||
if (strlen($char) > 1) {
|
||||
// It's an UTF-8 character
|
||||
return true;
|
||||
}
|
||||
|
||||
return ctype_alpha($char);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next UTF-8 char
|
||||
*
|
||||
* @param string $char
|
||||
* @return boolean
|
||||
*/
|
||||
private function _nextChar()
|
||||
{
|
||||
$char = $this->_input[$this->_bytePosition++];
|
||||
|
||||
if (( ord($char) & 0xC0 ) == 0xC0) {
|
||||
$addBytes = 1;
|
||||
if (ord($char) & 0x20 ) {
|
||||
$addBytes++;
|
||||
if (ord($char) & 0x10 ) {
|
||||
$addBytes++;
|
||||
}
|
||||
}
|
||||
$char .= substr($this->_input, $this->_bytePosition, $addBytes);
|
||||
$this->_bytePosition += $addBytes;
|
||||
}
|
||||
|
||||
$this->_position++;
|
||||
|
||||
return $char;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,39 +91,35 @@ class Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8 extends Zend_Search_Lucen
|
||||
return null;
|
||||
}
|
||||
|
||||
while ($this->_position < $this->_streamLength) {
|
||||
// skip white space
|
||||
while ($this->_position < $this->_streamLength &&
|
||||
!self::_isAlpha($char = $this->_nextChar())) {
|
||||
$char = '';
|
||||
}
|
||||
|
||||
$termStartPosition = $this->_position - 1;
|
||||
$termText = $char;
|
||||
|
||||
// read token
|
||||
while ($this->_position < $this->_streamLength &&
|
||||
self::_isAlpha($char = $this->_nextChar())) {
|
||||
$termText .= $char;
|
||||
}
|
||||
|
||||
// Empty token, end of stream.
|
||||
if ($termText == '') {
|
||||
do {
|
||||
if (! preg_match('/[\p{L}]+/u', $this->_input, $match, PREG_OFFSET_CAPTURE, $this->_bytePosition)) {
|
||||
// It covers both cases a) there are no matches (preg_match(...) === 0)
|
||||
// b) error occured (preg_match(...) === FALSE)
|
||||
return null;
|
||||
}
|
||||
|
||||
$token = new Zend_Search_Lucene_Analysis_Token(
|
||||
$termText,
|
||||
$termStartPosition,
|
||||
$this->_position - 1);
|
||||
$token = $this->normalize($token);
|
||||
if ($token !== null) {
|
||||
return $token;
|
||||
}
|
||||
// Continue if token is skipped
|
||||
}
|
||||
// matched string
|
||||
$matchedWord = $match[0][0];
|
||||
|
||||
// binary position of the matched word in the input stream
|
||||
$binStartPos = $match[0][1];
|
||||
|
||||
// character position of the matched word in the input stream
|
||||
$startPos = $this->_position +
|
||||
iconv_strlen(substr($this->_input,
|
||||
$this->_bytePosition,
|
||||
$binStartPos - $this->_bytePosition),
|
||||
'UTF-8');
|
||||
// character postion of the end of matched word in the input stream
|
||||
$endPos = $startPos + iconv_strlen($matchedWord, 'UTF-8');
|
||||
|
||||
return null;
|
||||
$this->_bytePosition = $binStartPos + strlen($matchedWord);
|
||||
$this->_position = $endPos;
|
||||
|
||||
$token = $this->normalize(new Zend_Search_Lucene_Analysis_Token($matchedWord, $startPos, $endPos));
|
||||
} while ($token === null); // try again if token is skipped
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer_Common */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer/Common.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Analyzer/Common.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -49,11 +49,18 @@ class Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num extends Zend_Search_Lu
|
||||
private $_bytePosition;
|
||||
|
||||
/**
|
||||
* Stream length
|
||||
* Object constructor
|
||||
*
|
||||
* @var integer
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
private $_streamLength;
|
||||
public function __construct()
|
||||
{
|
||||
if (@preg_match('/\pL/u', 'a') != 1) {
|
||||
// PCRE unicode support is turned off
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
throw new Zend_Search_Lucene_Exception('Utf8Num analyzer needs PCRE unicode support to be enabled.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset token stream
|
||||
@@ -69,53 +76,6 @@ class Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num extends Zend_Search_Lu
|
||||
$this->_input = iconv($this->_encoding, 'UTF-8', $this->_input);
|
||||
$this->_encoding = 'UTF-8';
|
||||
}
|
||||
|
||||
// Get UTF-8 string length.
|
||||
// It also checks if it's a correct utf-8 string
|
||||
$this->_streamLength = iconv_strlen($this->_input, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check, that character is a letter
|
||||
*
|
||||
* @param string $char
|
||||
* @return boolean
|
||||
*/
|
||||
private static function _isAlNum($char)
|
||||
{
|
||||
if (strlen($char) > 1) {
|
||||
// It's an UTF-8 character
|
||||
return true;
|
||||
}
|
||||
|
||||
return ctype_alnum($char);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next UTF-8 char
|
||||
*
|
||||
* @param string $char
|
||||
* @return boolean
|
||||
*/
|
||||
private function _nextChar()
|
||||
{
|
||||
$char = $this->_input[$this->_bytePosition++];
|
||||
|
||||
if (( ord($char) & 0xC0 ) == 0xC0) {
|
||||
$addBytes = 1;
|
||||
if (ord($char) & 0x20 ) {
|
||||
$addBytes++;
|
||||
if (ord($char) & 0x10 ) {
|
||||
$addBytes++;
|
||||
}
|
||||
}
|
||||
$char .= substr($this->_input, $this->_bytePosition, $addBytes);
|
||||
$this->_bytePosition += $addBytes;
|
||||
}
|
||||
|
||||
$this->_position++;
|
||||
|
||||
return $char;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,39 +91,35 @@ class Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num extends Zend_Search_Lu
|
||||
return null;
|
||||
}
|
||||
|
||||
while ($this->_position < $this->_streamLength) {
|
||||
// skip white space
|
||||
while ($this->_position < $this->_streamLength &&
|
||||
!self::_isAlNum($char = $this->_nextChar())) {
|
||||
$char = '';
|
||||
}
|
||||
|
||||
$termStartPosition = $this->_position - 1;
|
||||
$termText = $char;
|
||||
|
||||
// read token
|
||||
while ($this->_position < $this->_streamLength &&
|
||||
self::_isAlNum($char = $this->_nextChar())) {
|
||||
$termText .= $char;
|
||||
}
|
||||
|
||||
// Empty token, end of stream.
|
||||
if ($termText == '') {
|
||||
do {
|
||||
if (! preg_match('/[\p{L}\p{N}]+/u', $this->_input, $match, PREG_OFFSET_CAPTURE, $this->_bytePosition)) {
|
||||
// It covers both cases a) there are no matches (preg_match(...) === 0)
|
||||
// b) error occured (preg_match(...) === FALSE)
|
||||
return null;
|
||||
}
|
||||
|
||||
$token = new Zend_Search_Lucene_Analysis_Token(
|
||||
$termText,
|
||||
$termStartPosition,
|
||||
$this->_position - 1);
|
||||
$token = $this->normalize($token);
|
||||
if ($token !== null) {
|
||||
return $token;
|
||||
}
|
||||
// Continue if token is skipped
|
||||
}
|
||||
// matched string
|
||||
$matchedWord = $match[0][0];
|
||||
|
||||
// binary position of the matched word in the input stream
|
||||
$binStartPos = $match[0][1];
|
||||
|
||||
// character position of the matched word in the input stream
|
||||
$startPos = $this->_position +
|
||||
iconv_strlen(substr($this->_input,
|
||||
$this->_bytePosition,
|
||||
$binStartPos - $this->_bytePosition),
|
||||
'UTF-8');
|
||||
// character postion of the end of matched word in the input stream
|
||||
$endPos = $startPos + iconv_strlen($matchedWord, 'UTF-8');
|
||||
|
||||
return null;
|
||||
$this->_bytePosition = $binStartPos + strlen($matchedWord);
|
||||
$this->_position = $endPos;
|
||||
|
||||
$token = $this->normalize(new Zend_Search_Lucene_Analysis_Token($matchedWord, $startPos, $endPos));
|
||||
} while ($token === null); // try again if token is skipped
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Analysis_Token
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Token */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Token.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Token.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Token.php';
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_TokenFilter */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/TokenFilter.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/TokenFilter.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/TokenFilter.php'
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_TokenFilter */
|
||||
require_once 'Zend/Search/Lucene/Analysis/TokenFilter.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Analysis/TokenFilter.php";
|
||||
|
||||
|
||||
/**
|
||||
@@ -41,9 +41,10 @@ class Zend_Search_Lucene_Analysis_TokenFilter_LowerCaseUtf8 extends Zend_Search_
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
global $CFG;
|
||||
if (!function_exists('mb_strtolower')) {
|
||||
// mbstring extension is disabled
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Exception.php";
|
||||
throw new Zend_Search_Lucene_Exception('Utf8 compatible lower case filter needs mbstring extension to be enabled.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_TokenFilter */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/TokenFilter.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/TokenFilter.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/TokenFilter.php'
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_TokenFilter */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/TokenFilter.php';
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/TokenFilter.php';
|
||||
require_once 'Zend/Search/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -34,14 +34,14 @@ require_once $CFG->dirroot.'/search/Zend/Search/Exception.php';
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Analysis
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
class Zend_Search_Lucene_Analysis_TokenFilter_StopWords extends Zend_Search_Lucene_Analysis_TokenFilter
|
||||
{
|
||||
/**
|
||||
* Minimum allowed term length
|
||||
* Stop Words
|
||||
* @var array
|
||||
*/
|
||||
private $_stopSet;
|
||||
@@ -63,7 +63,6 @@ class Zend_Search_Lucene_Analysis_TokenFilter_StopWords extends Zend_Search_Luce
|
||||
*/
|
||||
public function normalize(Zend_Search_Lucene_Analysis_Token $srcToken) {
|
||||
if (array_key_exists($srcToken->getTermText(), $this->_stopSet)) {
|
||||
$t = $srcToken->getTermText();
|
||||
return null;
|
||||
} else {
|
||||
return $srcToken;
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Document
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Field */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Field.php';
|
||||
require_once "Zend/Search/Lucene/Field.php";
|
||||
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Field.php';
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Document
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Document
|
||||
@@ -54,10 +54,10 @@ class Zend_Search_Lucene_Document
|
||||
* @param $offset
|
||||
* @return string
|
||||
*/
|
||||
public function __get($offset)
|
||||
{
|
||||
return $this->getFieldValue($offset);
|
||||
}
|
||||
public function __get($offset)
|
||||
{
|
||||
return $this->getFieldValue($offset);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -78,7 +78,7 @@ class Zend_Search_Lucene_Document
|
||||
*/
|
||||
public function getFieldNames()
|
||||
{
|
||||
return array_keys($this->_fields);
|
||||
return array_keys($this->_fields);
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ class Zend_Search_Lucene_Document
|
||||
*/
|
||||
public function getFieldValue($fieldName)
|
||||
{
|
||||
return $this->getField($fieldName)->value;
|
||||
return $this->getField($fieldName)->value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,6 +116,6 @@ class Zend_Search_Lucene_Document
|
||||
*/
|
||||
public function getFieldUtf8Value($fieldName)
|
||||
{
|
||||
return $this->getField($fieldName)->getUtf8Value();
|
||||
return $this->getField($fieldName)->getUtf8Value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Document
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Document */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Document.php';
|
||||
require_once 'Zend/Search/Lucene/Document.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Document.php';
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Document
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Document_Html extends Zend_Search_Lucene_Document
|
||||
@@ -290,7 +290,7 @@ class Zend_Search_Lucene_Document_Html extends Zend_Search_Lucene_Document
|
||||
|
||||
$xpath = new DOMXPath($this->_doc);
|
||||
|
||||
$matchedNodes = $xpath->query("/html/body/*");
|
||||
$matchedNodes = $xpath->query("/html/body");
|
||||
foreach ($matchedNodes as $matchedNode) {
|
||||
$this->_highlightNode($matchedNode, $wordsToHighlightFlipped, $color);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
/**
|
||||
* Framework base exception
|
||||
*/
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Exception.php';
|
||||
require_once "Zend/Search/Exception.php";
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Exception extends Zend_Search_Exception
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_FSMAction */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/FSMAction.php';
|
||||
require_once 'Zend/Search/Lucene/FSMAction.php';
|
||||
|
||||
/** Zend_Search_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Exception.php';
|
||||
require_once 'Zend/Search/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -37,7 +37,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Exception.php';
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Search_Lucene_FSM
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_FSMAction
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Document
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Document
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Field
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -35,7 +35,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Index_DictionaryLoader
|
||||
@@ -61,11 +61,12 @@ class Zend_Search_Lucene_Index_DictionaryLoader
|
||||
// $tiVersion = $tiiFile->readInt();
|
||||
$tiVersion = ord($data[0]) << 24 | ord($data[1]) << 16 | ord($data[2]) << 8 | ord($data[3]);
|
||||
$pos += 4;
|
||||
if ($tiVersion != (int)0xFFFFFFFE) {
|
||||
if ($tiVersion != (int)0xFFFFFFFE /* pre-2.1 format */ &&
|
||||
$tiVersion != (int)0xFFFFFFFD /* 2.1+ format */) {
|
||||
throw new Zend_Search_Lucene_Exception('Wrong TermInfoIndexFile file format');
|
||||
}
|
||||
|
||||
// $indexTermCount = = $tiiFile->readLong();
|
||||
// $indexTermCount = $tiiFile->readLong();
|
||||
if (PHP_INT_SIZE > 4) {
|
||||
$indexTermCount = ord($data[$pos]) << 56 |
|
||||
ord($data[$pos+1]) << 48 |
|
||||
@@ -101,6 +102,11 @@ class Zend_Search_Lucene_Index_DictionaryLoader
|
||||
throw new Zend_Search_Lucene_Exception('Wrong number of terms in a term dictionary index');
|
||||
}
|
||||
|
||||
if ($tiVersion == (int)0xFFFFFFFD /* 2.1+ format */) {
|
||||
/* Skip MaxSkipLevels value */
|
||||
$pos += 4;
|
||||
}
|
||||
|
||||
$prevTerm = '';
|
||||
$freqPointer = 0;
|
||||
$proxPointer = 0;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Index_FieldInfo
|
||||
|
||||
@@ -15,23 +15,30 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
/** Zend_Search_Lucene_Index_DictionaryLoader */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/DictionaryLoader.php';
|
||||
require_once 'Zend/Search/Lucene/Index/DictionaryLoader.php';
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_LockManager */
|
||||
if (@$CFG->block_search_softlock){
|
||||
require_once "Zend/Search/Lucene/SoftLockManager.php";
|
||||
} else {
|
||||
require_once "Zend/Search/Lucene/LockManager.php";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Index_SegmentInfo
|
||||
@@ -110,6 +117,35 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
*/
|
||||
private $_segFileSizes;
|
||||
|
||||
/**
|
||||
* Delete file generation number
|
||||
*
|
||||
* -1 means 'there is no delete file'
|
||||
* 0 means pre-2.1 format delete file
|
||||
* X specifies used delete file
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_delGen;
|
||||
|
||||
/**
|
||||
* Segment has single norms file
|
||||
*
|
||||
* If true then one .nrm file is used for all fields
|
||||
* Otherwise .fN files are used
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $_hasSingleNormFile;
|
||||
|
||||
/**
|
||||
* Use compound segment file (*.cfs) to collect all other segment files
|
||||
* (excluding .del files)
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $_isCompound;
|
||||
|
||||
|
||||
/**
|
||||
* File system adapter.
|
||||
@@ -136,7 +172,7 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
private $_deleted;
|
||||
private $_deleted = null;
|
||||
|
||||
/**
|
||||
* $this->_deleted update flag
|
||||
@@ -147,22 +183,45 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
|
||||
|
||||
/**
|
||||
* Zend_Search_Lucene_Index_SegmentInfo constructor needs Segmentname,
|
||||
* Documents count and Directory as a parameter.
|
||||
* Zend_Search_Lucene_Index_SegmentInfo constructor
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $directory
|
||||
* @param string $name
|
||||
* @param integer $docCount
|
||||
* @param Zend_Search_Lucene_Storage_Directory $directory
|
||||
* @param integer $delGen
|
||||
* @param boolean $isCompound
|
||||
*/
|
||||
public function __construct($name, $docCount, $directory)
|
||||
public function __construct(Zend_Search_Lucene_Storage_Directory $directory, $name, $docCount, $delGen = 0, $hasSingleNormFile = false, $isCompound = null)
|
||||
{
|
||||
$this->_name = $name;
|
||||
$this->_docCount = $docCount;
|
||||
$this->_directory = $directory;
|
||||
$this->_termDictionary = null;
|
||||
$this->_name = $name;
|
||||
$this->_docCount = $docCount;
|
||||
$this->_hasSingleNormFile = $hasSingleNormFile;
|
||||
$this->_delGen = $delGen;
|
||||
$this->_termDictionary = null;
|
||||
|
||||
if (!is_null($isCompound)) {
|
||||
$this->_isCompound = $isCompound;
|
||||
} else {
|
||||
// It's a pre-2.1 segment
|
||||
// detect if it uses compond file
|
||||
$this->_isCompound = true;
|
||||
|
||||
try {
|
||||
// Try to open compound file
|
||||
$this->_directory->getFileObject($name . '.cfs');
|
||||
} catch (Zend_Search_Lucene_Exception $e) {
|
||||
if (strpos($e->getMessage(), 'is not readable') !== false) {
|
||||
// Compound file is not found or is not readable
|
||||
$this->_isCompound = false;
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->_segFiles = array();
|
||||
if ($this->_directory->fileExists($name . '.cfs')) {
|
||||
if ($this->_isCompound) {
|
||||
$cfsFile = $this->_directory->getFileObject($name . '.cfs');
|
||||
$segFilesCount = $cfsFile->readVInt();
|
||||
|
||||
@@ -202,37 +261,83 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
array_multisort($fieldNames, SORT_ASC, SORT_REGULAR, $fieldNums);
|
||||
$this->_fieldsDicPositions = array_flip($fieldNums);
|
||||
|
||||
try {
|
||||
$delFile = $this->openCompoundFile('.del');
|
||||
if ($this->_delGen == -1) {
|
||||
// There is no delete file for this segment
|
||||
// Do nothing
|
||||
} else if ($this->_delGen == 0) {
|
||||
// It's a segment with pre-2.1 format delete file
|
||||
// Try to find delete file
|
||||
try {
|
||||
// '.del' files always stored in a separate file
|
||||
// Segment compound is not used
|
||||
$delFile = $this->_directory->getFileObject($this->_name . '.del');
|
||||
|
||||
$byteCount = $delFile->readInt();
|
||||
$byteCount = ceil($byteCount/8);
|
||||
$bitCount = $delFile->readInt();
|
||||
$byteCount = $delFile->readInt();
|
||||
$byteCount = ceil($byteCount/8);
|
||||
$bitCount = $delFile->readInt();
|
||||
|
||||
if ($bitCount == 0) {
|
||||
$delBytes = '';
|
||||
} else {
|
||||
$delBytes = $delFile->readBytes($byteCount);
|
||||
}
|
||||
if ($bitCount == 0) {
|
||||
$delBytes = '';
|
||||
} else {
|
||||
$delBytes = $delFile->readBytes($byteCount);
|
||||
}
|
||||
|
||||
if (extension_loaded('bitset')) {
|
||||
$this->_deleted = $delBytes;
|
||||
} else {
|
||||
$this->_deleted = array();
|
||||
for ($count = 0; $count < $byteCount; $count++) {
|
||||
$byte = ord($delBytes{$count});
|
||||
for ($bit = 0; $bit < 8; $bit++) {
|
||||
if ($byte & (1<<$bit)) {
|
||||
$this->_deleted[$count*8 + $bit] = 1;
|
||||
if (extension_loaded('bitset')) {
|
||||
$this->_deleted = $delBytes;
|
||||
} else {
|
||||
$this->_deleted = array();
|
||||
for ($count = 0; $count < $byteCount; $count++) {
|
||||
$byte = ord($delBytes{$count});
|
||||
for ($bit = 0; $bit < 8; $bit++) {
|
||||
if ($byte & (1<<$bit)) {
|
||||
$this->_deleted[$count*8 + $bit] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Zend_Search_Exception $e) {
|
||||
if (strpos($e->getMessage(), 'is not readable') === false ) {
|
||||
throw $e;
|
||||
}
|
||||
// There is no delete file
|
||||
// Do nothing
|
||||
}
|
||||
} catch(Zend_Search_Exception $e) {
|
||||
if (strpos($e->getMessage(), 'compound file doesn\'t contain') !== false ) {
|
||||
$this->_deleted = null;
|
||||
} else {
|
||||
// It's 2.1+ format delete file
|
||||
$delFile = $this->_directory->getFileObject($this->_name . '_' . base_convert($this->_delGen, 10, 36) . '.del');
|
||||
|
||||
$format = $delFile->readInt();
|
||||
|
||||
if ($format == (int)0xFFFFFFFF) {
|
||||
/**
|
||||
* @todo Implement support of DGaps delete file format.
|
||||
* See Lucene file format for details - http://lucene.apache.org/java/docs/fileformats.html#Deleted%20Documents
|
||||
*/
|
||||
throw new Zend_Search_Lucene_Exception('DGaps delete file format is not supported. Optimize index to use it with Zend_Search_Lucene');
|
||||
} else {
|
||||
throw $e;
|
||||
// $format is actually byte count
|
||||
$byteCount = ceil($format/8);
|
||||
$bitCount = $delFile->readInt();
|
||||
|
||||
if ($bitCount == 0) {
|
||||
$delBytes = '';
|
||||
} else {
|
||||
$delBytes = $delFile->readBytes($byteCount);
|
||||
}
|
||||
|
||||
if (extension_loaded('bitset')) {
|
||||
$this->_deleted = $delBytes;
|
||||
} else {
|
||||
$this->_deleted = array();
|
||||
for ($count = 0; $count < $byteCount; $count++) {
|
||||
$byte = ord($delBytes{$count});
|
||||
for ($bit = 0; $bit < 8; $bit++) {
|
||||
if ($byte & (1<<$bit)) {
|
||||
$this->_deleted[$count*8 + $bit] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,13 +354,12 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
{
|
||||
$filename = $this->_name . $extension;
|
||||
|
||||
// Try to open common file first
|
||||
if ($this->_directory->fileExists($filename)) {
|
||||
if (!$this->_isCompound) {
|
||||
return $this->_directory->getFileObject($filename, $shareHandler);
|
||||
}
|
||||
|
||||
if( !isset($this->_segFiles[$filename]) ) {
|
||||
throw new Zend_Search_Lucene_Exception('Index compound file doesn\'t contain '
|
||||
throw new Zend_Search_Lucene_Exception('Segment compound file doesn\'t contain '
|
||||
. $filename . ' file.' );
|
||||
}
|
||||
|
||||
@@ -343,6 +447,16 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
return $this->_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns actual deletions file generation number.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getDelGen()
|
||||
{
|
||||
return $this->_delGen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of documents in this segment (including deleted documents).
|
||||
*
|
||||
@@ -431,6 +545,41 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load terms dictionary index
|
||||
*
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
private function _loadDictionaryIndex()
|
||||
{
|
||||
// Check, if index is already serialized
|
||||
if ($this->_directory->fileExists($this->_name . '.sti')) {
|
||||
// Load serialized dictionary index data
|
||||
$stiFile = $this->_directory->getFileObject($this->_name . '.sti');
|
||||
$stiFileData = $stiFile->readBytes($this->_directory->fileLength($this->_name . '.sti'));
|
||||
|
||||
// Load dictionary index data
|
||||
if (($unserializedData = @unserialize($stiFileData)) !== false) {
|
||||
list($this->_termDictionary, $this->_termDictionaryInfos) = $unserializedData;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Load data from .tii file and generate .sti file
|
||||
|
||||
// Prefetch dictionary index data
|
||||
$tiiFile = $this->openCompoundFile('.tii');
|
||||
$tiiFileData = $tiiFile->readBytes($this->compoundFileLength('.tii'));
|
||||
|
||||
// Load dictionary index data
|
||||
list($this->_termDictionary, $this->_termDictionaryInfos) =
|
||||
Zend_Search_Lucene_Index_DictionaryLoader::load($tiiFileData);
|
||||
|
||||
$stiFileData = serialize(array($this->_termDictionary, $this->_termDictionaryInfos));
|
||||
$stiFile = $this->_directory->createFile($this->_name . '.sti');
|
||||
$stiFile->writeBytes($stiFileData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans terms dictionary and returns term info
|
||||
*
|
||||
@@ -452,32 +601,9 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
|
||||
|
||||
if ($this->_termDictionary === null) {
|
||||
// Check, if index is already serialized
|
||||
if ($this->_directory->fileExists($this->_name . '.sti')) {
|
||||
// Prefetch dictionary index data
|
||||
$stiFile = $this->_directory->getFileObject($this->_name . '.sti');
|
||||
$stiFileData = $stiFile->readBytes($this->_directory->fileLength($this->_name . '.sti'));
|
||||
|
||||
// Load dictionary index data
|
||||
list($this->_termDictionary, $this->_termDictionaryInfos) = unserialize($stiFileData);
|
||||
} else {
|
||||
// Prefetch dictionary index data
|
||||
$tiiFile = $this->openCompoundFile('.tii');
|
||||
$tiiFileData = $tiiFile->readBytes($this->compoundFileLength('.tii'));
|
||||
|
||||
// Load dictionary index data
|
||||
list($this->_termDictionary, $this->_termDictionaryInfos) =
|
||||
Zend_Search_Lucene_Index_DictionaryLoader::load($tiiFileData);
|
||||
|
||||
$stiFileData = serialize(array($this->_termDictionary, $this->_termDictionaryInfos));
|
||||
$stiFile = $this->_directory->createFile($this->_name . '.sti');
|
||||
$stiFile->writeBytes($stiFileData);
|
||||
}
|
||||
|
||||
$this->_loadDictionaryIndex();
|
||||
}
|
||||
|
||||
|
||||
|
||||
$searchField = $this->getFieldNum($term->field);
|
||||
|
||||
if ($searchField == -1) {
|
||||
@@ -526,15 +652,19 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
|
||||
$tisFile = $this->openCompoundFile('.tis');
|
||||
$tiVersion = $tisFile->readInt();
|
||||
if ($tiVersion != (int)0xFFFFFFFE) {
|
||||
if ($tiVersion != (int)0xFFFFFFFE /* pre-2.1 format */ &&
|
||||
$tiVersion != (int)0xFFFFFFFD /* 2.1+ format */) {
|
||||
throw new Zend_Search_Lucene_Exception('Wrong TermInfoFile file format');
|
||||
}
|
||||
|
||||
$termCount = $tisFile->readLong();
|
||||
$indexInterval = $tisFile->readInt();
|
||||
$skipInterval = $tisFile->readInt();
|
||||
if ($tiVersion == (int)0xFFFFFFFD /* 2.1+ format */) {
|
||||
$maxSkipLevels = $tisFile->readInt();
|
||||
}
|
||||
|
||||
$tisFile->seek($prevTermInfo[4] /* indexPointer */ - 20 /* header size*/, SEEK_CUR);
|
||||
$tisFile->seek($prevTermInfo[4] /* indexPointer */ - (($tiVersion == (int)0xFFFFFFFD)? 24 : 20) /* header size*/, SEEK_CUR);
|
||||
|
||||
$termValue = $prevTerm[1] /* text */;
|
||||
$termFieldNum = $prevTerm[0] /* field */;
|
||||
@@ -666,11 +796,29 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
* Load normalizatin factors from an index file
|
||||
*
|
||||
* @param integer $fieldNum
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
private function _loadNorm($fieldNum)
|
||||
{
|
||||
$fFile = $this->openCompoundFile('.f' . $fieldNum);
|
||||
$this->_norms[$fieldNum] = $fFile->readBytes($this->_docCount);
|
||||
if ($this->_hasSingleNormFile) {
|
||||
$normfFile = $this->openCompoundFile('.nrm');
|
||||
|
||||
$header = $normfFile->readBytes(3);
|
||||
$headerFormatVersion = $normfFile->readByte();
|
||||
|
||||
if ($header != 'NRM' || $headerFormatVersion != (int)0xFF) {
|
||||
throw new Zend_Search_Lucene_Exception('Wrong norms file format.');
|
||||
}
|
||||
|
||||
foreach ($this->_fields as $fieldNum => $fieldInfo) {
|
||||
if ($fieldInfo->isIndexed) {
|
||||
$this->_norms[$fieldNum] = $normfFile->readBytes($this->_docCount);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$fFile = $this->openCompoundFile('.f' . $fieldNum);
|
||||
$this->_norms[$fieldNum] = $fFile->readBytes($this->_docCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -731,6 +879,26 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if segment has single norms file.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasSingleNormFile()
|
||||
{
|
||||
return $this->_hasSingleNormFile ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if segment is stored using compound segment file.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isCompound()
|
||||
{
|
||||
return $this->_isCompound ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a document from the index segment.
|
||||
* $id is an internal document id
|
||||
@@ -803,7 +971,35 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
}
|
||||
|
||||
|
||||
$delFile = $this->_directory->createFile($this->_name . '.del');
|
||||
// Get new generation number
|
||||
Zend_Search_Lucene_LockManager::obtainWriteLock($this->_directory);
|
||||
|
||||
$delFileList = array();
|
||||
foreach ($this->_directory->fileList() as $file) {
|
||||
if ($file == $this->_name . '.del') {
|
||||
// Matches <segment_name>.del file name
|
||||
$delFileList[] = 0;
|
||||
} else if (preg_match('/^' . $this->_name . '_([a-zA-Z0-9]+)\.del$/i', $file, $matches)) {
|
||||
// Matches <segment_name>_NNN.del file names
|
||||
$delFileList[] = (int)base_convert($matches[1], 36, 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($delFileList) == 0) {
|
||||
// There is no deletions file for current segment in the directory
|
||||
// Set detetions file generation number to 1
|
||||
$this->_delGen = 1;
|
||||
} else {
|
||||
// There are some deletions files for current segment in the directory
|
||||
// Set detetions file generation number to the highest + 1
|
||||
$this->_delGen = max($delFileList) + 1;
|
||||
}
|
||||
|
||||
$delFile = $this->_directory->createFile($this->_name . '_' . base_convert($this->_delGen, 10, 36) . '.del');
|
||||
|
||||
Zend_Search_Lucene_LockManager::releaseWriteLock($this->_directory);
|
||||
|
||||
|
||||
$delFile->writeInt($this->_docCount);
|
||||
$delFile->writeInt($bitCount);
|
||||
$delFile->writeBytes($delBytes);
|
||||
@@ -820,6 +1016,13 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
*/
|
||||
private $_tisFile = null;
|
||||
|
||||
/**
|
||||
* Actual offset of the .tis file data
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_tisFileOffset;
|
||||
|
||||
/**
|
||||
* Frequencies File object for stream like terms reading
|
||||
*
|
||||
@@ -828,7 +1031,7 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
private $_frqFile = null;
|
||||
|
||||
/**
|
||||
* Offset of the .frq file in the compound file
|
||||
* Actual offset of the .frq file data
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
@@ -842,7 +1045,7 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
private $_prxFile = null;
|
||||
|
||||
/**
|
||||
* Offset of the .prx file in the compound file
|
||||
* Actual offset of the .prx file in the compound file
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
@@ -850,12 +1053,26 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
|
||||
|
||||
/**
|
||||
* Number of terms in term stream
|
||||
* Actual number of terms in term stream
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_termCount = 0;
|
||||
|
||||
/**
|
||||
* Overall number of terms in term stream
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_termNum = 0;
|
||||
|
||||
/**
|
||||
* Segment index interval
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_indexInterval;
|
||||
|
||||
/**
|
||||
* Segment skip interval
|
||||
*
|
||||
@@ -891,10 +1108,32 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
* An array of all term positions in the documents.
|
||||
* Array structure: array( docId => array( pos1, pos2, ...), ...)
|
||||
*
|
||||
* @var array
|
||||
* Is set to null if term positions loading has to be skipped
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
private $_lastTermPositions;
|
||||
|
||||
|
||||
/**
|
||||
* Terms scan mode
|
||||
*
|
||||
* Values:
|
||||
*
|
||||
* self::SM_TERMS_ONLY - terms are scanned, no additional info is retrieved
|
||||
* self::SM_MERGE_INFO - terms are scanned, frequency and position info is retrieved
|
||||
* document numbers are compacted (shifted if segment has deleted documents)
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_termsScanMode;
|
||||
|
||||
/** Scan modes */
|
||||
const SM_TERMS_ONLY = 0; // terms are scanned, no additional info is retrieved
|
||||
const SM_FULL_INFO = 1; // terms are scanned, frequency and position info is retrieved
|
||||
const SM_MERGE_INFO = 2; // terms are scanned, frequency and position info is retrieved
|
||||
// document numbers are compacted (shifted if segment contains deleted documents)
|
||||
|
||||
/**
|
||||
* Reset terms stream
|
||||
*
|
||||
@@ -904,50 +1143,223 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
* Returns start document id for the next segment
|
||||
*
|
||||
* @param integer $startId
|
||||
* @param boolean $compact
|
||||
* @param integer $mode
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
* @return integer
|
||||
*/
|
||||
public function reset($startId = 0, $compact = false)
|
||||
public function reset($startId = 0, $mode = self::SM_TERMS_ONLY)
|
||||
{
|
||||
if ($this->_tisFile !== null) {
|
||||
$this->_tisFile = null;
|
||||
}
|
||||
|
||||
$this->_tisFile = $this->openCompoundFile('.tis', false);
|
||||
$this->_tisFileOffset = $this->_tisFile->tell();
|
||||
|
||||
$tiVersion = $this->_tisFile->readInt();
|
||||
if ($tiVersion != (int)0xFFFFFFFE) {
|
||||
if ($tiVersion != (int)0xFFFFFFFE /* pre-2.1 format */ &&
|
||||
$tiVersion != (int)0xFFFFFFFD /* 2.1+ format */) {
|
||||
throw new Zend_Search_Lucene_Exception('Wrong TermInfoFile file format');
|
||||
}
|
||||
|
||||
$this->_termCount = $this->_tisFile->readLong();
|
||||
$this->_tisFile->readInt(); // Read Index interval
|
||||
$this->_skipInterval = $this->_tisFile->readInt(); // Read skip interval
|
||||
$this->_termCount =
|
||||
$this->_termNum = $this->_tisFile->readLong(); // Read terms count
|
||||
$this->_indexInterval = $this->_tisFile->readInt(); // Read Index interval
|
||||
$this->_skipInterval = $this->_tisFile->readInt(); // Read skip interval
|
||||
if ($tiVersion == (int)0xFFFFFFFD /* 2.1+ format */) {
|
||||
$maxSkipLevels = $this->_tisFile->readInt();
|
||||
}
|
||||
|
||||
if ($this->_frqFile !== null) {
|
||||
$this->_frqFile = null;
|
||||
}
|
||||
$this->_frqFile = $this->openCompoundFile('.frq', false);
|
||||
$this->_frqFileOffset = $this->_frqFile->tell();
|
||||
|
||||
if ($this->_prxFile !== null) {
|
||||
$this->_prxFile = null;
|
||||
}
|
||||
$this->_prxFile = $this->openCompoundFile('.prx', false);
|
||||
$this->_prxFileOffset = $this->_prxFile->tell();
|
||||
|
||||
$this->_lastTerm = new Zend_Search_Lucene_Index_Term('', -1);
|
||||
$this->_lastTermInfo = new Zend_Search_Lucene_Index_TermInfo(0, 0, 0, 0);
|
||||
|
||||
$this->_docMap = array();
|
||||
for ($count = 0; $count < $this->_docCount; $count++) {
|
||||
if (!$this->isDeleted($count)) {
|
||||
$this->_docMap[$count] = $startId + ($compact ? count($this->_docMap) : $count);
|
||||
|
||||
$this->_lastTerm = new Zend_Search_Lucene_Index_Term('', -1);
|
||||
$this->_lastTermInfo = new Zend_Search_Lucene_Index_TermInfo(0, 0, 0, 0);
|
||||
$this->_lastTermPositions = null;
|
||||
|
||||
$this->_termsScanMode = $mode;
|
||||
|
||||
switch ($mode) {
|
||||
case self::SM_TERMS_ONLY:
|
||||
// Do nothing
|
||||
break;
|
||||
|
||||
case self::SM_FULL_INFO:
|
||||
// break intentionally omitted
|
||||
case self::SM_MERGE_INFO:
|
||||
$this->_frqFile = $this->openCompoundFile('.frq', false);
|
||||
$this->_frqFileOffset = $this->_frqFile->tell();
|
||||
|
||||
$this->_prxFile = $this->openCompoundFile('.prx', false);
|
||||
$this->_prxFileOffset = $this->_prxFile->tell();
|
||||
|
||||
for ($count = 0; $count < $this->_docCount; $count++) {
|
||||
if (!$this->isDeleted($count)) {
|
||||
$this->_docMap[$count] = $startId + (($mode == self::SM_MERGE_INFO) ? count($this->_docMap) : $count);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Zend_Search_Lucene_Exception('Wrong terms scaning mode specified.');
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$this->nextTerm();
|
||||
return $startId + (($mode == self::SM_MERGE_INFO) ? count($this->_docMap) : $this->_docCount);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Skip terms stream up to specified term preffix.
|
||||
*
|
||||
* Prefix contains fully specified field info and portion of searched term
|
||||
*
|
||||
* @param Zend_Search_Lucene_Index_Term $prefix
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
public function skipTo(Zend_Search_Lucene_Index_Term $prefix)
|
||||
{
|
||||
if ($this->_termDictionary === null) {
|
||||
$this->_loadDictionaryIndex();
|
||||
}
|
||||
|
||||
$searchField = $this->getFieldNum($prefix->field);
|
||||
|
||||
if ($searchField == -1) {
|
||||
/**
|
||||
* Field is not presented in this segment
|
||||
* Go to the end of dictionary
|
||||
*/
|
||||
$this->_tisFile = null;
|
||||
$this->_frqFile = null;
|
||||
$this->_prxFile = null;
|
||||
|
||||
$this->_lastTerm = null;
|
||||
$this->_lastTermInfo = null;
|
||||
$this->_lastTermPositions = null;
|
||||
|
||||
return;
|
||||
}
|
||||
$searchDicField = $this->_getFieldPosition($searchField);
|
||||
|
||||
// search for appropriate value in dictionary
|
||||
$lowIndex = 0;
|
||||
$highIndex = count($this->_termDictionary)-1;
|
||||
while ($highIndex >= $lowIndex) {
|
||||
// $mid = ($highIndex - $lowIndex)/2;
|
||||
$mid = ($highIndex + $lowIndex) >> 1;
|
||||
$midTerm = $this->_termDictionary[$mid];
|
||||
|
||||
$fieldNum = $this->_getFieldPosition($midTerm[0] /* field */);
|
||||
$delta = $searchDicField - $fieldNum;
|
||||
if ($delta == 0) {
|
||||
$delta = strcmp($prefix->text, $midTerm[1] /* text */);
|
||||
}
|
||||
|
||||
if ($delta < 0) {
|
||||
$highIndex = $mid-1;
|
||||
} elseif ($delta > 0) {
|
||||
$lowIndex = $mid+1;
|
||||
} else {
|
||||
// We have reached term we are looking for
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->nextTerm();
|
||||
return $startId + ($compact ? count($this->_docMap) : $this->_docCount);
|
||||
if ($highIndex == -1) {
|
||||
// Term is out of the dictionary range
|
||||
$this->_tisFile = null;
|
||||
$this->_frqFile = null;
|
||||
$this->_prxFile = null;
|
||||
|
||||
$this->_lastTerm = null;
|
||||
$this->_lastTermInfo = null;
|
||||
$this->_lastTermPositions = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$prevPosition = $highIndex;
|
||||
$prevTerm = $this->_termDictionary[$prevPosition];
|
||||
$prevTermInfo = $this->_termDictionaryInfos[$prevPosition];
|
||||
|
||||
if ($this->_tisFile === null) {
|
||||
// The end of terms stream is reached and terms dictionary file is closed
|
||||
// Perform mini-reset operation
|
||||
$this->_tisFile = $this->openCompoundFile('.tis', false);
|
||||
|
||||
if ($this->_termsScanMode == self::SM_FULL_INFO || $this->_termsScanMode == self::SM_MERGE_INFO) {
|
||||
$this->_frqFile = $this->openCompoundFile('.frq', false);
|
||||
$this->_prxFile = $this->openCompoundFile('.prx', false);
|
||||
}
|
||||
}
|
||||
$this->_tisFile->seek($this->_tisFileOffset + $prevTermInfo[4], SEEK_SET);
|
||||
|
||||
$this->_lastTerm = new Zend_Search_Lucene_Index_Term($prevTerm[1] /* text */,
|
||||
($prevTerm[0] == -1) ? '' : $this->_fields[$prevTerm[0] /* field */]->name);
|
||||
$this->_lastTermInfo = new Zend_Search_Lucene_Index_TermInfo($prevTermInfo[0] /* docFreq */,
|
||||
$prevTermInfo[1] /* freqPointer */,
|
||||
$prevTermInfo[2] /* proxPointer */,
|
||||
$prevTermInfo[3] /* skipOffset */);
|
||||
$this->_termCount = $this->_termNum - $prevPosition*$this->_indexInterval;
|
||||
|
||||
if ($highIndex == 0) {
|
||||
// skip start entry
|
||||
$this->nextTerm();
|
||||
} else if ($prefix->field == $this->_lastTerm->field && $prefix->text == $this->_lastTerm->text) {
|
||||
// We got exact match in the dictionary index
|
||||
|
||||
if ($this->_termsScanMode == self::SM_FULL_INFO || $this->_termsScanMode == self::SM_MERGE_INFO) {
|
||||
$this->_lastTermPositions = array();
|
||||
|
||||
$this->_frqFile->seek($this->_lastTermInfo->freqPointer + $this->_frqFileOffset, SEEK_SET);
|
||||
$freqs = array(); $docId = 0;
|
||||
for( $count = 0; $count < $this->_lastTermInfo->docFreq; $count++ ) {
|
||||
$docDelta = $this->_frqFile->readVInt();
|
||||
if( $docDelta % 2 == 1 ) {
|
||||
$docId += ($docDelta-1)/2;
|
||||
$freqs[ $docId ] = 1;
|
||||
} else {
|
||||
$docId += $docDelta/2;
|
||||
$freqs[ $docId ] = $this->_frqFile->readVInt();
|
||||
}
|
||||
}
|
||||
|
||||
$this->_prxFile->seek($this->_lastTermInfo->proxPointer + $this->_prxFileOffset, SEEK_SET);
|
||||
foreach ($freqs as $docId => $freq) {
|
||||
$termPosition = 0; $positions = array();
|
||||
|
||||
for ($count = 0; $count < $freq; $count++ ) {
|
||||
$termPosition += $this->_prxFile->readVInt();
|
||||
$positions[] = $termPosition;
|
||||
}
|
||||
|
||||
if (isset($this->_docMap[$docId])) {
|
||||
$this->_lastTermPositions[$this->_docMap[$docId]] = $positions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Search term matching specified prefix
|
||||
while ($this->_lastTerm !== null) {
|
||||
if ( strcmp($this->_lastTerm->field, $prefix->field) > 0 ||
|
||||
($prefix->field == $this->_lastTerm->field && strcmp($this->_lastTerm->text, $prefix->text) >= 0) ) {
|
||||
// Current term matches or greate than the pattern
|
||||
return;
|
||||
}
|
||||
|
||||
$this->nextTerm();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -959,8 +1371,10 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
public function nextTerm()
|
||||
{
|
||||
if ($this->_tisFile === null || $this->_termCount == 0) {
|
||||
$this->_lastTerm = null;
|
||||
$this->_lastTermInfo = null;
|
||||
$this->_lastTerm = null;
|
||||
$this->_lastTermInfo = null;
|
||||
$this->_lastTermPositions = null;
|
||||
$this->_docMap = null;
|
||||
|
||||
// may be necessary for "empty" segment
|
||||
$this->_tisFile = null;
|
||||
@@ -989,36 +1403,37 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
$this->_lastTermInfo = new Zend_Search_Lucene_Index_TermInfo($docFreq, $freqPointer, $proxPointer, $skipOffset);
|
||||
|
||||
|
||||
$this->_lastTermPositions = array();
|
||||
if ($this->_termsScanMode == self::SM_FULL_INFO || $this->_termsScanMode == self::SM_MERGE_INFO) {
|
||||
$this->_lastTermPositions = array();
|
||||
|
||||
$this->_frqFile->seek($this->_lastTermInfo->freqPointer + $this->_frqFileOffset, SEEK_SET);
|
||||
$freqs = array(); $docId = 0;
|
||||
for( $count = 0; $count < $this->_lastTermInfo->docFreq; $count++ ) {
|
||||
$docDelta = $this->_frqFile->readVInt();
|
||||
if( $docDelta % 2 == 1 ) {
|
||||
$docId += ($docDelta-1)/2;
|
||||
$freqs[ $docId ] = 1;
|
||||
} else {
|
||||
$docId += $docDelta/2;
|
||||
$freqs[ $docId ] = $this->_frqFile->readVInt();
|
||||
$this->_frqFile->seek($this->_lastTermInfo->freqPointer + $this->_frqFileOffset, SEEK_SET);
|
||||
$freqs = array(); $docId = 0;
|
||||
for( $count = 0; $count < $this->_lastTermInfo->docFreq; $count++ ) {
|
||||
$docDelta = $this->_frqFile->readVInt();
|
||||
if( $docDelta % 2 == 1 ) {
|
||||
$docId += ($docDelta-1)/2;
|
||||
$freqs[ $docId ] = 1;
|
||||
} else {
|
||||
$docId += $docDelta/2;
|
||||
$freqs[ $docId ] = $this->_frqFile->readVInt();
|
||||
}
|
||||
}
|
||||
|
||||
$this->_prxFile->seek($this->_lastTermInfo->proxPointer + $this->_prxFileOffset, SEEK_SET);
|
||||
foreach ($freqs as $docId => $freq) {
|
||||
$termPosition = 0; $positions = array();
|
||||
|
||||
for ($count = 0; $count < $freq; $count++ ) {
|
||||
$termPosition += $this->_prxFile->readVInt();
|
||||
$positions[] = $termPosition;
|
||||
}
|
||||
|
||||
if (isset($this->_docMap[$docId])) {
|
||||
$this->_lastTermPositions[$this->_docMap[$docId]] = $positions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->_prxFile->seek($this->_lastTermInfo->proxPointer + $this->_prxFileOffset, SEEK_SET);
|
||||
foreach ($freqs as $docId => $freq) {
|
||||
$termPosition = 0; $positions = array();
|
||||
|
||||
for ($count = 0; $count < $freq; $count++ ) {
|
||||
$termPosition += $this->_prxFile->readVInt();
|
||||
$positions[] = $termPosition;
|
||||
}
|
||||
|
||||
if (isset($this->_docMap[$docId])) {
|
||||
$this->_lastTermPositions[$this->_docMap[$docId]] = $positions;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->_termCount--;
|
||||
if ($this->_termCount == 0) {
|
||||
$this->_tisFile = null;
|
||||
@@ -1029,11 +1444,28 @@ class Zend_Search_Lucene_Index_SegmentInfo
|
||||
return $this->_lastTerm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close terms stream
|
||||
*
|
||||
* Should be used for resources clean up if stream is not read up to the end
|
||||
*/
|
||||
public function closeTermsStream()
|
||||
{
|
||||
$this->_tisFile = null;
|
||||
$this->_frqFile = null;
|
||||
$this->_prxFile = null;
|
||||
|
||||
$this->_lastTerm = null;
|
||||
$this->_lastTermInfo = null;
|
||||
$this->_lastTermPositions = null;
|
||||
|
||||
$this->_docMap = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns term in current position
|
||||
*
|
||||
* @param Zend_Search_Lucene_Index_Term $term
|
||||
* @return Zend_Search_Lucene_Index_Term|null
|
||||
*/
|
||||
public function currentTerm()
|
||||
|
||||
@@ -15,23 +15,23 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/PriorityQueue.php';
|
||||
require_once 'Zend/Search/Lucene/PriorityQueue.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Index_SegmentInfoPriorityQueue extends Zend_Search_Lucene_PriorityQueue
|
||||
|
||||
@@ -15,29 +15,29 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentInfo */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentInfo.php';
|
||||
require_once 'Zend/Search/Lucene/Index/SegmentInfo.php';
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentWriter_StreamWriter */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentWriter/StreamWriter.php';
|
||||
require_once 'Zend/Search/Lucene/Index/SegmentWriter/StreamWriter.php';
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentInfoPriorityQueue */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentInfoPriorityQueue.php';
|
||||
require_once 'Zend/Search/Lucene/Index/SegmentInfoPriorityQueue.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Index_SegmentMerger
|
||||
@@ -232,7 +232,7 @@ class Zend_Search_Lucene_Index_SegmentMerger
|
||||
|
||||
$segmentStartId = 0;
|
||||
foreach ($this->_segmentInfos as $segName => $segmentInfo) {
|
||||
$segmentStartId = $segmentInfo->reset($segmentStartId, true);
|
||||
$segmentStartId = $segmentInfo->reset($segmentStartId, Zend_Search_Lucene_Index_SegmentInfo::SM_MERGE_INFO);
|
||||
|
||||
// Skip "empty" segments
|
||||
if ($segmentInfo->currentTerm() !== null) {
|
||||
|
||||
@@ -15,23 +15,23 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentInfo */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentInfo.php';
|
||||
require_once 'Zend/Search/Lucene/Index/SegmentInfo.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Search_Lucene_Index_SegmentWriter
|
||||
@@ -47,19 +47,33 @@ abstract class Zend_Search_Lucene_Index_SegmentWriter
|
||||
*/
|
||||
public static $indexInterval = 128;
|
||||
|
||||
/** Expert: The fraction of TermDocs entries stored in skip tables.
|
||||
/**
|
||||
* Expert: The fraction of TermDocs entries stored in skip tables.
|
||||
* Larger values result in smaller indexes, greater acceleration, but fewer
|
||||
* accelerable cases, while smaller values result in bigger indexes,
|
||||
* less acceleration and more
|
||||
* accelerable cases. More detailed experiments would be useful here.
|
||||
*
|
||||
* 0x0x7FFFFFFF indicates that we don't use skip data
|
||||
* Default value is 16
|
||||
* 0x7FFFFFFF indicates that we don't use skip data
|
||||
*
|
||||
* Note: not used in current implementation
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public static $skipInterval = 0x7FFFFFFF;
|
||||
|
||||
/**
|
||||
* Expert: The maximum number of skip levels. Smaller values result in
|
||||
* slightly smaller indexes, but slower skipping in big posting lists.
|
||||
*
|
||||
* 0 indicates that we don't use skip data
|
||||
*
|
||||
* Note: not used in current implementation
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public static $maxSkipLevels = 0;
|
||||
|
||||
/**
|
||||
* Number of docs in a segment
|
||||
*
|
||||
@@ -245,6 +259,16 @@ abstract class Zend_Search_Lucene_Index_SegmentWriter
|
||||
return $this->_docCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return segment name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump Field Info (.fnm) segment file
|
||||
*/
|
||||
@@ -253,6 +277,12 @@ abstract class Zend_Search_Lucene_Index_SegmentWriter
|
||||
$fnmFile = $this->_directory->createFile($this->_name . '.fnm');
|
||||
$fnmFile->writeVInt(count($this->_fields));
|
||||
|
||||
$nrmFile = $this->_directory->createFile($this->_name . '.nrm');
|
||||
// Write header
|
||||
$nrmFile->writeBytes('NRM');
|
||||
// Write format specifier
|
||||
$nrmFile->writeByte((int)0xFF);
|
||||
|
||||
foreach ($this->_fields as $field) {
|
||||
$fnmFile->writeString($field->name);
|
||||
$fnmFile->writeByte(($field->isIndexed ? 0x01 : 0x00) |
|
||||
@@ -262,14 +292,18 @@ abstract class Zend_Search_Lucene_Index_SegmentWriter
|
||||
);
|
||||
|
||||
if ($field->isIndexed) {
|
||||
$normFileName = $this->_name . '.f' . $field->number;
|
||||
$fFile = $this->_directory->createFile($normFileName);
|
||||
$fFile->writeBytes($this->_norms[$field->name]);
|
||||
$this->_files[] = $normFileName;
|
||||
// pre-2.1 index mode (not used now)
|
||||
// $normFileName = $this->_name . '.f' . $field->number;
|
||||
// $fFile = $this->_directory->createFile($normFileName);
|
||||
// $fFile->writeBytes($this->_norms[$field->name]);
|
||||
// $this->_files[] = $normFileName;
|
||||
|
||||
$nrmFile->writeBytes($this->_norms[$field->name]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->_files[] = $this->_name . '.fnm';
|
||||
$this->_files[] = $this->_name . '.nrm';
|
||||
}
|
||||
|
||||
|
||||
@@ -351,16 +385,18 @@ abstract class Zend_Search_Lucene_Index_SegmentWriter
|
||||
public function initializeDictionaryFiles()
|
||||
{
|
||||
$this->_tisFile = $this->_directory->createFile($this->_name . '.tis');
|
||||
$this->_tisFile->writeInt((int)0xFFFFFFFE);
|
||||
$this->_tisFile->writeInt((int)0xFFFFFFFD);
|
||||
$this->_tisFile->writeLong(0 /* dummy data for terms count */);
|
||||
$this->_tisFile->writeInt(self::$indexInterval);
|
||||
$this->_tisFile->writeInt(self::$skipInterval);
|
||||
$this->_tisFile->writeInt(self::$maxSkipLevels);
|
||||
|
||||
$this->_tiiFile = $this->_directory->createFile($this->_name . '.tii');
|
||||
$this->_tiiFile->writeInt((int)0xFFFFFFFE);
|
||||
$this->_tiiFile->writeInt((int)0xFFFFFFFD);
|
||||
$this->_tiiFile->writeLong(0 /* dummy data for terms count */);
|
||||
$this->_tiiFile->writeInt(self::$indexInterval);
|
||||
$this->_tiiFile->writeInt(self::$skipInterval);
|
||||
$this->_tiiFile->writeInt(self::$maxSkipLevels);
|
||||
|
||||
/** Dump dictionary header */
|
||||
$this->_tiiFile->writeVInt(0); // preffix length
|
||||
@@ -370,7 +406,7 @@ abstract class Zend_Search_Lucene_Index_SegmentWriter
|
||||
$this->_tiiFile->writeVInt(0); // DocFreq
|
||||
$this->_tiiFile->writeVInt(0); // FreqDelta
|
||||
$this->_tiiFile->writeVInt(0); // ProxDelta
|
||||
$this->_tiiFile->writeVInt(20); // IndexDelta
|
||||
$this->_tiiFile->writeVInt(24); // IndexDelta
|
||||
|
||||
$this->_frqFile = $this->_directory->createFile($this->_name . '.frq');
|
||||
$this->_prxFile = $this->_directory->createFile($this->_name . '.prx');
|
||||
@@ -384,7 +420,7 @@ abstract class Zend_Search_Lucene_Index_SegmentWriter
|
||||
$this->_prevTermInfo = null;
|
||||
$this->_prevIndexTerm = null;
|
||||
$this->_prevIndexTermInfo = null;
|
||||
$this->_lastIndexPosition = 20;
|
||||
$this->_lastIndexPosition = 24;
|
||||
$this->_termCount = 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -15,26 +15,26 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentWriter */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentWriter.php';
|
||||
require_once 'Zend/Search/Lucene/Index/SegmentWriter.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Index_SegmentWriter_DocumentWriter extends Zend_Search_Lucene_Index_SegmentWriter
|
||||
@@ -204,9 +204,12 @@ class Zend_Search_Lucene_Index_SegmentWriter_DocumentWriter extends Zend_Search_
|
||||
|
||||
$this->_generateCFS();
|
||||
|
||||
return new Zend_Search_Lucene_Index_SegmentInfo($this->_name,
|
||||
return new Zend_Search_Lucene_Index_SegmentInfo($this->_directory,
|
||||
$this->_name,
|
||||
$this->_docCount,
|
||||
$this->_directory);
|
||||
-1,
|
||||
true,
|
||||
true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,26 +15,26 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentInfo */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentInfo.php';
|
||||
require_once 'Zend/Search/Lucene/Index/SegmentInfo.php';
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentWriter */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentWriter.php';
|
||||
require_once 'Zend/Search/Lucene/Index/SegmentWriter.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Index_SegmentWriter_StreamWriter extends Zend_Search_Lucene_Index_SegmentWriter
|
||||
@@ -86,9 +86,12 @@ class Zend_Search_Lucene_Index_SegmentWriter_StreamWriter extends Zend_Search_Lu
|
||||
$this->_dumpFNM();
|
||||
$this->_generateCFS();
|
||||
|
||||
return new Zend_Search_Lucene_Index_SegmentInfo($this->_name,
|
||||
return new Zend_Search_Lucene_Index_SegmentInfo($this->_directory,
|
||||
$this->_name,
|
||||
$this->_docCount,
|
||||
$this->_directory);
|
||||
-1,
|
||||
true,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Index_Term
|
||||
@@ -74,6 +74,7 @@ class Zend_Search_Lucene_Index_Term
|
||||
/**
|
||||
* Get term prefix
|
||||
*
|
||||
* @param string $str
|
||||
* @param integer $length
|
||||
* @return string
|
||||
*/
|
||||
@@ -104,5 +105,39 @@ class Zend_Search_Lucene_Index_Term
|
||||
|
||||
return substr($str, 0, $prefixBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get UTF-8 string length
|
||||
*
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
public static function getLength($str)
|
||||
{
|
||||
$bytes = 0;
|
||||
$chars = 0;
|
||||
while ($bytes < strlen($str)) {
|
||||
$charBytes = 1;
|
||||
if ((ord($str[$bytes]) & 0xC0) == 0xC0) {
|
||||
$charBytes++;
|
||||
if (ord($str[$bytes]) & 0x20 ) {
|
||||
$charBytes++;
|
||||
if (ord($str[$bytes]) & 0x10 ) {
|
||||
$charBytes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($bytes + $charBytes > strlen($str)) {
|
||||
// wrong character
|
||||
break;
|
||||
}
|
||||
|
||||
$chars++;
|
||||
$bytes += $charBytes;
|
||||
}
|
||||
|
||||
return $chars;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Index_TermInfo
|
||||
|
||||
@@ -15,27 +15,33 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentWriter_ */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentWriter/DocumentWriter.php';
|
||||
/** Zend_Search_Lucene_Index_SegmentWriter_DocumentWriter */
|
||||
require_once 'Zend/Search/Lucene/Index/SegmentWriter/DocumentWriter.php';
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentInfo */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentInfo.php';
|
||||
require_once 'Zend/Search/Lucene/Index/SegmentInfo.php';
|
||||
|
||||
/** Zend_Search_Lucene_Index_SegmentMerger */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentMerger.php';
|
||||
require_once 'Zend/Search/Lucene/Index/SegmentMerger.php';
|
||||
|
||||
/** Zend_Search_Lucene_LockManager */
|
||||
if (@$CFG->block_search_softlock){
|
||||
require_once "Zend/Search/Lucene/SoftLockManager.php";
|
||||
} else {
|
||||
require_once "Zend/Search/Lucene/LockManager.php";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Index
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Index_Writer
|
||||
@@ -154,33 +160,29 @@ class Zend_Search_Lucene_Index_Writer
|
||||
'.del' => '.del',
|
||||
'.sti' => '.sti' );
|
||||
|
||||
|
||||
/**
|
||||
* Opens the index for writing
|
||||
*
|
||||
* IndexWriter constructor needs Directory as a parameter. It should be
|
||||
* a string with a path to the index folder or a Directory object.
|
||||
* Second constructor parameter create is optional - true to create the
|
||||
* index or overwrite the existing one.
|
||||
* Create empty index
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $directory
|
||||
* @param array $segmentInfos
|
||||
* @param boolean $create
|
||||
* @param integer $generation
|
||||
* @param integer $nameCount
|
||||
*/
|
||||
public function __construct(Zend_Search_Lucene_Storage_Directory $directory, &$segmentInfos, $create = false)
|
||||
public static function createIndex(Zend_Search_Lucene_Storage_Directory $directory, $generation, $nameCount)
|
||||
{
|
||||
$this->_directory = $directory;
|
||||
$this->_segmentInfos = &$segmentInfos;
|
||||
if ($generation == 0) {
|
||||
// Create index in pre-2.1 mode
|
||||
|
||||
if ($create) {
|
||||
foreach ($this->_directory->fileList() as $file) {
|
||||
foreach ($directory->fileList() as $file) {
|
||||
if ($file == 'deletable' ||
|
||||
$file == 'segments' ||
|
||||
isset(self::$_indexExtensions[ substr($file, strlen($file)-4)]) ||
|
||||
preg_match('/\.f\d+$/i', $file) /* matches <segment_name>.f<decimal_nmber> file names */) {
|
||||
$this->_directory->deleteFile($file);
|
||||
$directory->deleteFile($file);
|
||||
}
|
||||
}
|
||||
$segmentsFile = $this->_directory->createFile('segments');
|
||||
|
||||
$segmentsFile = $directory->createFile('segments');
|
||||
$segmentsFile->writeInt((int)0xFFFFFFFF);
|
||||
|
||||
// write version (is initialized by current time
|
||||
@@ -190,22 +192,55 @@ class Zend_Search_Lucene_Index_Writer
|
||||
$segmentsFile->writeInt((int)($version & 0xFFFFFFFF));
|
||||
|
||||
// write name counter
|
||||
$segmentsFile->writeInt(0);
|
||||
$segmentsFile->writeInt($nameCount);
|
||||
// write segment counter
|
||||
$segmentsFile->writeInt(0);
|
||||
|
||||
$deletableFile = $this->_directory->createFile('deletable');
|
||||
$deletableFile = $directory->createFile('deletable');
|
||||
// write counter
|
||||
$deletableFile->writeInt(0);
|
||||
} else {
|
||||
$segmentsFile = $this->_directory->getFileObject('segments');
|
||||
$format = $segmentsFile->readInt();
|
||||
if ($format != (int)0xFFFFFFFF) {
|
||||
throw new Zend_Search_Lucene_Exception('Wrong segments file format');
|
||||
}
|
||||
$genFile = $directory->createFile('segments.gen');
|
||||
|
||||
$genFile->writeInt((int)0xFFFFFFFE);
|
||||
// Write generation two times
|
||||
$genFile->writeLong($generation);
|
||||
$genFile->writeLong($generation);
|
||||
|
||||
$segmentsFile = $directory->createFile(Zend_Search_Lucene::getSegmentFileName($generation));
|
||||
$segmentsFile->writeInt((int)0xFFFFFFFD);
|
||||
|
||||
// write version (is initialized by current time
|
||||
// $segmentsFile->writeLong((int)microtime(true));
|
||||
$version = microtime(true);
|
||||
$segmentsFile->writeInt((int)($version/((double)0xFFFFFFFF + 1)));
|
||||
$segmentsFile->writeInt((int)($version & 0xFFFFFFFF));
|
||||
|
||||
// write name counter
|
||||
$segmentsFile->writeInt($nameCount);
|
||||
// write segment counter
|
||||
$segmentsFile->writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the index for writing
|
||||
*
|
||||
* IndexWriter constructor needs Directory as a parameter. It should be
|
||||
* a string with a path to the index folder or a Directory object.
|
||||
* Second constructor parameter create is optional - true to create the
|
||||
* index or overwrite the existing one.
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $directory
|
||||
* @param array $segmentInfos
|
||||
* @param Zend_Search_Lucene_Storage_File $cleanUpLock
|
||||
*/
|
||||
public function __construct(Zend_Search_Lucene_Storage_Directory $directory, &$segmentInfos)
|
||||
{
|
||||
$this->_directory = $directory;
|
||||
$this->_segmentInfos = &$segmentInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a document to this index.
|
||||
*
|
||||
@@ -223,27 +258,86 @@ class Zend_Search_Lucene_Index_Writer
|
||||
$this->commit();
|
||||
}
|
||||
|
||||
$this->_versionUpdate++;
|
||||
|
||||
$this->_maybeMergeSegments();
|
||||
|
||||
$this->_versionUpdate++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merge segments if necessary
|
||||
* Check if we have anything to merge
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function _maybeMergeSegments()
|
||||
private function _hasAnythingToMerge()
|
||||
{
|
||||
$segmentSizes = array();
|
||||
foreach ($this->_segmentInfos as $segId => $segmentInfo) {
|
||||
$segmentSizes[$segId] = $segmentInfo->count();
|
||||
foreach ($this->_segmentInfos as $segName => $segmentInfo) {
|
||||
$segmentSizes[$segName] = $segmentInfo->count();
|
||||
}
|
||||
|
||||
$mergePool = array();
|
||||
$poolSize = 0;
|
||||
$sizeToMerge = $this->maxBufferedDocs;
|
||||
asort($segmentSizes, SORT_NUMERIC);
|
||||
foreach ($segmentSizes as $segId => $size) {
|
||||
foreach ($segmentSizes as $segName => $size) {
|
||||
// Check, if segment comes into a new merging block
|
||||
while ($size >= $sizeToMerge) {
|
||||
// Merge previous block if it's large enough
|
||||
if ($poolSize >= $sizeToMerge) {
|
||||
return true;
|
||||
}
|
||||
$mergePool = array();
|
||||
$poolSize = 0;
|
||||
|
||||
$sizeToMerge *= $this->mergeFactor;
|
||||
|
||||
if ($sizeToMerge > $this->maxMergeDocs) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$mergePool[] = $this->_segmentInfos[$segName];
|
||||
$poolSize += $size;
|
||||
}
|
||||
|
||||
if ($poolSize >= $sizeToMerge) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge segments if necessary
|
||||
*/
|
||||
private function _maybeMergeSegments()
|
||||
{
|
||||
if (Zend_Search_Lucene_LockManager::obtainOptimizationLock($this->_directory) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!$this->_hasAnythingToMerge()) {
|
||||
Zend_Search_Lucene_LockManager::releaseOptimizationLock($this->_directory);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update segments list to be sure all segments are not merged yet by other process
|
||||
$this->_updateSegments();
|
||||
|
||||
|
||||
// Perform standard auto-optimization procedure
|
||||
$segmentSizes = array();
|
||||
foreach ($this->_segmentInfos as $segName => $segmentInfo) {
|
||||
$segmentSizes[$segName] = $segmentInfo->count();
|
||||
}
|
||||
|
||||
$mergePool = array();
|
||||
$poolSize = 0;
|
||||
$sizeToMerge = $this->maxBufferedDocs;
|
||||
asort($segmentSizes, SORT_NUMERIC);
|
||||
foreach ($segmentSizes as $segName => $size) {
|
||||
// Check, if segment comes into a new merging block
|
||||
while ($size >= $sizeToMerge) {
|
||||
// Merge previous block if it's large enough
|
||||
@@ -256,17 +350,20 @@ class Zend_Search_Lucene_Index_Writer
|
||||
$sizeToMerge *= $this->mergeFactor;
|
||||
|
||||
if ($sizeToMerge > $this->maxMergeDocs) {
|
||||
Zend_Search_Lucene_LockManager::releaseOptimizationLock($this->_directory);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$mergePool[] = $this->_segmentInfos[$segId];
|
||||
$mergePool[] = $this->_segmentInfos[$segName];
|
||||
$poolSize += $size;
|
||||
}
|
||||
|
||||
if ($poolSize >= $sizeToMerge) {
|
||||
$this->_mergeSegments($mergePool);
|
||||
}
|
||||
|
||||
Zend_Search_Lucene_LockManager::releaseOptimizationLock($this->_directory);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,13 +375,6 @@ class Zend_Search_Lucene_Index_Writer
|
||||
*/
|
||||
private function _mergeSegments($segments)
|
||||
{
|
||||
// Try to get exclusive non-blocking lock to the 'index.optimization.lock'
|
||||
// Skip optimization if it's performed by other process right now
|
||||
$optimizationLock = $this->_directory->createFile('index.optimization.lock');
|
||||
if (!$optimizationLock->lock(LOCK_EX,true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$newName = $this->_newSegmentName();
|
||||
$merger = new Zend_Search_Lucene_Index_SegmentMerger($this->_directory,
|
||||
$newName);
|
||||
@@ -299,9 +389,6 @@ class Zend_Search_Lucene_Index_Writer
|
||||
}
|
||||
|
||||
$this->commit();
|
||||
|
||||
// optimization is finished
|
||||
$optimizationLock->unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,119 +399,299 @@ class Zend_Search_Lucene_Index_Writer
|
||||
private function _updateSegments()
|
||||
{
|
||||
// Get an exclusive index lock
|
||||
// Wait, until all parallel searchers or indexers won't stop
|
||||
// and stop all next searchers, while we are updating segments file
|
||||
$lock = $this->_directory->getFileObject('index.lock');
|
||||
if (!$lock->lock(LOCK_EX)) {
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t obtain exclusive index lock');
|
||||
}
|
||||
Zend_Search_Lucene_LockManager::obtainWriteLock($this->_directory);
|
||||
|
||||
$generation = Zend_Search_Lucene::getActualGeneration($this->_directory);
|
||||
$segmentsFile = $this->_directory->getFileObject(Zend_Search_Lucene::getSegmentFileName($generation), false);
|
||||
$newSegmentFile = $this->_directory->createFile(Zend_Search_Lucene::getSegmentFileName(++$generation), false);
|
||||
|
||||
// Do not share file handlers to get file updates from other sessions.
|
||||
$segmentsFile = $this->_directory->getFileObject('segments', false);
|
||||
$newSegmentFile = $this->_directory->createFile('segments.new', false);
|
||||
|
||||
// Write format marker
|
||||
$newSegmentFile->writeInt((int)0xFFFFFFFF);
|
||||
|
||||
// Write index version
|
||||
$segmentsFile->seek(4, SEEK_CUR);
|
||||
// $version = $segmentsFile->readLong() + $this->_versionUpdate;
|
||||
// Process version on 32-bit platforms
|
||||
$versionHigh = $segmentsFile->readInt();
|
||||
$versionLow = $segmentsFile->readInt();
|
||||
$version = $versionHigh * ((double)0xFFFFFFFF + 1) +
|
||||
(($versionLow < 0)? (double)0xFFFFFFFF - (-1 - $versionLow) : $versionLow);
|
||||
$version += $this->_versionUpdate;
|
||||
$this->_versionUpdate = 0;
|
||||
$newSegmentFile->writeInt((int)($version/((double)0xFFFFFFFF + 1)));
|
||||
$newSegmentFile->writeInt((int)($version & 0xFFFFFFFF));
|
||||
|
||||
// Write segment name counter
|
||||
$newSegmentFile->writeInt($segmentsFile->readInt());
|
||||
|
||||
// Get number of segments offset
|
||||
$numOfSegmentsOffset = $newSegmentFile->tell();
|
||||
// Write number of segemnts
|
||||
$segmentsCount = $segmentsFile->readInt();
|
||||
$newSegmentFile->writeInt(0); // Write dummy data (segment counter)
|
||||
|
||||
$segments = array();
|
||||
for ($count = 0; $count < $segmentsCount; $count++) {
|
||||
$segName = $segmentsFile->readString();
|
||||
$segSize = $segmentsFile->readInt();
|
||||
|
||||
if (!in_array($segName, $this->_segmentsToDelete)) {
|
||||
$newSegmentFile->writeString($segName);
|
||||
$newSegmentFile->writeInt($segSize);
|
||||
|
||||
$segments[$segName] = $segSize;
|
||||
}
|
||||
}
|
||||
$segmentsFile->close();
|
||||
|
||||
$segmentsCount = count($segments) + count($this->_newSegments);
|
||||
|
||||
// Remove segments, not listed in $segments (deleted)
|
||||
// Load segments, not listed in $this->_segmentInfos
|
||||
foreach ($this->_segmentInfos as $segId => $segInfo) {
|
||||
if (isset($segments[$segInfo->getName()])) {
|
||||
// Segment is already included into $this->_segmentInfos
|
||||
unset($segments[$segInfo->getName()]);
|
||||
try {
|
||||
$genFile = $this->_directory->getFileObject('segments.gen', false);
|
||||
} catch (Zend_Search_Lucene_Exception $e) {
|
||||
if (strpos($e->getMessage(), 'is not readable') !== false) {
|
||||
$genFile = $this->_directory->createFile('segments.gen');
|
||||
} else {
|
||||
// remove deleted segment from a list
|
||||
unset($this->_segmentInfos[$segId]);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
// $segments contains a list of segments to load
|
||||
// do it later
|
||||
|
||||
$genFile->writeInt((int)0xFFFFFFFE);
|
||||
// Write generation (first copy)
|
||||
$genFile->writeLong($generation);
|
||||
|
||||
foreach ($this->_newSegments as $segName => $segmentInfo) {
|
||||
$newSegmentFile->writeString($segName);
|
||||
$newSegmentFile->writeInt($segmentInfo->count());
|
||||
try {
|
||||
// Write format marker
|
||||
$newSegmentFile->writeInt((int)0xFFFFFFFD);
|
||||
|
||||
// Skip format identifier
|
||||
$segmentsFile->seek(4, SEEK_CUR);
|
||||
// $version = $segmentsFile->readLong() + $this->_versionUpdate;
|
||||
// Process version on 32-bit platforms
|
||||
$versionHigh = $segmentsFile->readInt();
|
||||
$versionLow = $segmentsFile->readInt();
|
||||
$version = $versionHigh * ((double)0xFFFFFFFF + 1) +
|
||||
(($versionLow < 0)? (double)0xFFFFFFFF - (-1 - $versionLow) : $versionLow);
|
||||
$version += $this->_versionUpdate;
|
||||
$this->_versionUpdate = 0;
|
||||
$newSegmentFile->writeInt((int)($version/((double)0xFFFFFFFF + 1)));
|
||||
$newSegmentFile->writeInt((int)($version & 0xFFFFFFFF));
|
||||
|
||||
// Write segment name counter
|
||||
$newSegmentFile->writeInt($segmentsFile->readInt());
|
||||
|
||||
// Get number of segments offset
|
||||
$numOfSegmentsOffset = $newSegmentFile->tell();
|
||||
// Write dummy data (segment counter)
|
||||
$newSegmentFile->writeInt(0);
|
||||
|
||||
// Read number of segemnts
|
||||
$segmentsCount = $segmentsFile->readInt();
|
||||
|
||||
$this->_segmentInfos[] = $segmentInfo;
|
||||
$segments = array();
|
||||
for ($count = 0; $count < $segmentsCount; $count++) {
|
||||
$segName = $segmentsFile->readString();
|
||||
$segSize = $segmentsFile->readInt();
|
||||
|
||||
if ($generation == 1 /* retrieved generation is 0 */) {
|
||||
// pre-2.1 index format
|
||||
$delGenHigh = 0;
|
||||
$delGenLow = 0;
|
||||
$hasSingleNormFile = false;
|
||||
$numField = (int)0xFFFFFFFF;
|
||||
$isCompound = 1;
|
||||
} else {
|
||||
//$delGen = $segmentsFile->readLong();
|
||||
$delGenHigh = $segmentsFile->readInt();
|
||||
$delGenLow = $segmentsFile->readInt();
|
||||
$hasSingleNormFile = $segmentsFile->readByte();
|
||||
$numField = $segmentsFile->readInt();
|
||||
|
||||
$normGens = array();
|
||||
if ($numField != (int)0xFFFFFFFF) {
|
||||
for ($count1 = 0; $count1 < $numField; $count1++) {
|
||||
$normGens[] = $segmentsFile->readLong();
|
||||
}
|
||||
}
|
||||
$isCompound = $segmentsFile->readByte();
|
||||
}
|
||||
|
||||
if (!in_array($segName, $this->_segmentsToDelete)) {
|
||||
// Load segment if necessary
|
||||
if (!isset($this->_segmentInfos[$segName])) {
|
||||
$delGen = $delGenHigh * ((double)0xFFFFFFFF + 1) +
|
||||
(($delGenLow < 0)? (double)0xFFFFFFFF - (-1 - $delGenLow) : $delGenLow);
|
||||
$this->_segmentInfos[$segName] =
|
||||
new Zend_Search_Lucene_Index_SegmentInfo($this->_directory,
|
||||
$segName,
|
||||
$segSize,
|
||||
$delGen,
|
||||
$hasSingleNormFile,
|
||||
$isCompound);
|
||||
} else {
|
||||
// Retrieve actual detetions file generation number
|
||||
$delGen = $this->_segmentInfos[$segName]->getDelGen();
|
||||
|
||||
if ($delGen >= 0) {
|
||||
$delGenHigh = (int)($delGen/((double)0xFFFFFFFF + 1));
|
||||
$delGenLow =(int)($delGen & 0xFFFFFFFF);
|
||||
} else {
|
||||
$delGenHigh = $delGenLow = (int)0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
$newSegmentFile->writeString($segName);
|
||||
$newSegmentFile->writeInt($segSize);
|
||||
$newSegmentFile->writeInt($delGenHigh);
|
||||
$newSegmentFile->writeInt($delGenLow);
|
||||
$newSegmentFile->writeByte($hasSingleNormFile);
|
||||
$newSegmentFile->writeInt($numField);
|
||||
if ($numField != (int)0xFFFFFFFF) {
|
||||
foreach ($normGens as $normGen) {
|
||||
$newSegmentFile->writeLong($normGen);
|
||||
}
|
||||
}
|
||||
$newSegmentFile->writeByte($isCompound);
|
||||
|
||||
$segments[$segName] = $segSize;
|
||||
}
|
||||
}
|
||||
$segmentsFile->close();
|
||||
|
||||
$segmentsCount = count($segments) + count($this->_newSegments);
|
||||
|
||||
foreach ($this->_newSegments as $segName => $segmentInfo) {
|
||||
$newSegmentFile->writeString($segName);
|
||||
$newSegmentFile->writeInt($segmentInfo->count());
|
||||
|
||||
// delete file generation: -1 (there is no delete file yet)
|
||||
$newSegmentFile->writeInt((int)0xFFFFFFFF);$newSegmentFile->writeInt((int)0xFFFFFFFF);
|
||||
// HasSingleNormFile
|
||||
$newSegmentFile->writeByte($segmentInfo->hasSingleNormFile());
|
||||
// NumField
|
||||
$newSegmentFile->writeInt((int)0xFFFFFFFF);
|
||||
// IsCompoundFile
|
||||
$newSegmentFile->writeByte($segmentInfo->isCompound());
|
||||
|
||||
$segments[$segmentInfo->getName()] = $segmentInfo->count();
|
||||
$this->_segmentInfos[$segName] = $segmentInfo;
|
||||
}
|
||||
$this->_newSegments = array();
|
||||
|
||||
$newSegmentFile->seek($numOfSegmentsOffset);
|
||||
$newSegmentFile->writeInt($segmentsCount); // Update segments count
|
||||
$newSegmentFile->close();
|
||||
} catch (Exception $e) {
|
||||
/** Restore previous index generation */
|
||||
$generation--;
|
||||
$genFile->seek(4, SEEK_SET);
|
||||
// Write generation number twice
|
||||
$genFile->writeLong($generation); $genFile->writeLong($generation);
|
||||
|
||||
// Release index write lock
|
||||
Zend_Search_Lucene_LockManager::releaseWriteLock($this->_directory);
|
||||
|
||||
// Throw the exception
|
||||
throw $e;
|
||||
}
|
||||
$this->_newSegments = array();
|
||||
|
||||
$newSegmentFile->seek($numOfSegmentsOffset);
|
||||
$newSegmentFile->writeInt($segmentsCount); // Update segments count
|
||||
$newSegmentFile->close();
|
||||
$this->_directory->renameFile('segments.new', 'segments');
|
||||
// Write generation (second copy)
|
||||
$genFile->writeLong($generation);
|
||||
|
||||
|
||||
// Segments file update is finished
|
||||
// Switch back to shared lock mode
|
||||
$lock->lock(LOCK_SH);
|
||||
|
||||
|
||||
$fileList = $this->_directory->fileList();
|
||||
foreach ($this->_segmentsToDelete as $nameToDelete) {
|
||||
foreach (self::$_indexExtensions as $ext) {
|
||||
if ($this->_directory->fileExists($nameToDelete . $ext)) {
|
||||
$this->_directory->deleteFile($nameToDelete . $ext);
|
||||
|
||||
// Check if another update process is not running now
|
||||
// If yes, skip clean-up procedure
|
||||
if (Zend_Search_Lucene_LockManager::escalateReadLock($this->_directory)) {
|
||||
/**
|
||||
* Clean-up directory
|
||||
*/
|
||||
$filesToDelete = array();
|
||||
$filesTypes = array();
|
||||
$filesNumbers = array();
|
||||
|
||||
// list of .del files of currently used segments
|
||||
// each segment can have several generations of .del files
|
||||
// only last should not be deleted
|
||||
$delFiles = array();
|
||||
|
||||
foreach ($this->_directory->fileList() as $file) {
|
||||
if ($file == 'deletable') {
|
||||
// 'deletable' file
|
||||
$filesToDelete[] = $file;
|
||||
$filesTypes[] = 0; // delete this file first, since it's not used starting from Lucene v2.1
|
||||
$filesNumbers[] = 0;
|
||||
} else if ($file == 'segments') {
|
||||
// 'segments' file
|
||||
|
||||
$filesToDelete[] = $file;
|
||||
$filesTypes[] = 1; // second file to be deleted "zero" version of segments file (Lucene pre-2.1)
|
||||
$filesNumbers[] = 0;
|
||||
} else if (preg_match('/^segments_[a-zA-Z0-9]+$/i', $file)) {
|
||||
// 'segments_xxx' file
|
||||
// Check if it's not a just created generation file
|
||||
if ($file != Zend_Search_Lucene::getSegmentFileName($generation)) {
|
||||
$filesToDelete[] = $file;
|
||||
$filesTypes[] = 2; // first group of files for deletions
|
||||
$filesNumbers[] = (int)base_convert(substr($file, 9), 36, 10); // ordered by segment generation numbers
|
||||
}
|
||||
} else if (preg_match('/(^_([a-zA-Z0-9]+))\.f\d+$/i', $file, $matches)) {
|
||||
// one of per segment files ('<segment_name>.f<decimal_number>')
|
||||
// Check if it's not one of the segments in the current segments set
|
||||
if (!isset($segments[$matches[1]])) {
|
||||
$filesToDelete[] = $file;
|
||||
$filesTypes[] = 3; // second group of files for deletions
|
||||
$filesNumbers[] = (int)base_convert($matches[2], 36, 10); // order by segment number
|
||||
}
|
||||
} else if (preg_match('/(^_([a-zA-Z0-9]+))(_([a-zA-Z0-9]+))\.del$/i', $file, $matches)) {
|
||||
// one of per segment files ('<segment_name>_<del_generation>.del' where <segment_name> is '_<segment_number>')
|
||||
// Check if it's not one of the segments in the current segments set
|
||||
if (!isset($segments[$matches[1]])) {
|
||||
$filesToDelete[] = $file;
|
||||
$filesTypes[] = 3; // second group of files for deletions
|
||||
$filesNumbers[] = (int)base_convert($matches[2], 36, 10); // order by segment number
|
||||
} else {
|
||||
$segmentNumber = (int)base_convert($matches[2], 36, 10);
|
||||
$delGeneration = (int)base_convert($matches[4], 36, 10);
|
||||
if (!isset($delFiles[$segmentNumber])) {
|
||||
$delFiles[$segmentNumber] = array();
|
||||
}
|
||||
$delFiles[$segmentNumber][$delGeneration] = $file;
|
||||
}
|
||||
} else if (isset(self::$_indexExtensions[substr($file, strlen($file)-4)])) {
|
||||
// one of per segment files ('<segment_name>.<ext>')
|
||||
$segmentName = substr($file, 0, strlen($file) - 4);
|
||||
// Check if it's not one of the segments in the current segments set
|
||||
if (!isset($segments[$segmentName]) &&
|
||||
($this->_currentSegment === null || $this->_currentSegment->getName() != $segmentName)) {
|
||||
$filesToDelete[] = $file;
|
||||
$filesTypes[] = 3; // second group of files for deletions
|
||||
$filesNumbers[] = (int)base_convert(substr($file, 1 /* skip '_' */, strlen($file)-5), 36, 10); // order by segment number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($fileList as $file) {
|
||||
if (substr($file, 0, strlen($nameToDelete) + 2) == ($nameToDelete . '.f') &&
|
||||
ctype_digit( substr($file, strlen($nameToDelete) + 2) )) {
|
||||
$this->_directory->deleteFile($file);
|
||||
$maxGenNumber = 0;
|
||||
// process .del files of currently used segments
|
||||
foreach ($delFiles as $segmentNumber => $segmentDelFiles) {
|
||||
ksort($delFiles[$segmentNumber], SORT_NUMERIC);
|
||||
array_pop($delFiles[$segmentNumber]); // remove last delete file generation from candidates for deleting
|
||||
|
||||
end($delFiles[$segmentNumber]);
|
||||
$lastGenNumber = key($delFiles[$segmentNumber]);
|
||||
if ($lastGenNumber > $maxGenNumber) {
|
||||
$maxGenNumber = $lastGenNumber;
|
||||
}
|
||||
}
|
||||
foreach ($delFiles as $segmentNumber => $segmentDelFiles) {
|
||||
foreach ($segmentDelFiles as $delGeneration => $file) {
|
||||
$filesToDelete[] = $file;
|
||||
$filesTypes[] = 4; // third group of files for deletions
|
||||
$filesNumbers[] = $segmentNumber*$maxGenNumber + $delGeneration; // order by <segment_number>,<del_generation> pair
|
||||
}
|
||||
}
|
||||
|
||||
// Reorder files for deleting
|
||||
array_multisort($filesTypes, SORT_ASC, SORT_NUMERIC,
|
||||
$filesNumbers, SORT_ASC, SORT_NUMERIC,
|
||||
$filesToDelete, SORT_ASC, SORT_STRING);
|
||||
|
||||
foreach ($filesToDelete as $file) {
|
||||
try {
|
||||
$this->_directory->deleteFile($file);
|
||||
} catch (Zend_Search_Lucene_Exception $e) {
|
||||
if (strpos($e->getMessage(), 'Can\'t delete file') === false) {
|
||||
// That's not "file is under processing or already deleted" exception
|
||||
// Pass it through
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return read lock into the previous state
|
||||
Zend_Search_Lucene_LockManager::deEscalateReadLock($this->_directory);
|
||||
} else {
|
||||
// Only release resources if another index reader is running now
|
||||
foreach ($this->_segmentsToDelete as $segName) {
|
||||
foreach (self::$_indexExtensions as $ext) {
|
||||
$this->_directory->purgeFile($segName . $ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_segmentsToDelete = array();
|
||||
|
||||
// Load segments, created by other process
|
||||
foreach ($segments as $segName => $segSize) {
|
||||
// Load new segments
|
||||
$this->_segmentInfos[] = new Zend_Search_Lucene_Index_SegmentInfo($segName,
|
||||
$segSize,
|
||||
$this->_directory);
|
||||
// Clean-up _segmentsToDelete container
|
||||
$this->_segmentsToDelete = array();
|
||||
|
||||
|
||||
// Release index write lock
|
||||
Zend_Search_Lucene_LockManager::releaseWriteLock($this->_directory);
|
||||
|
||||
// Remove unused segments from segments list
|
||||
foreach ($this->_segmentInfos as $segName => $segmentInfo) {
|
||||
if (!isset($segments[$segName])) {
|
||||
unset($this->_segmentInfos[$segName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Commit current changes
|
||||
*/
|
||||
@@ -438,10 +705,7 @@ class Zend_Search_Lucene_Index_Writer
|
||||
$this->_currentSegment = null;
|
||||
}
|
||||
|
||||
if (count($this->_newSegments) != 0 ||
|
||||
count($this->_segmentsToDelete) != 0) {
|
||||
$this->_updateSegments();
|
||||
}
|
||||
$this->_updateSegments();
|
||||
}
|
||||
|
||||
|
||||
@@ -459,15 +723,24 @@ class Zend_Search_Lucene_Index_Writer
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges all segments together into a single segment, optimizing
|
||||
* an index for search.
|
||||
* Input is an array of Zend_Search_Lucene_Index_SegmentInfo objects
|
||||
* Merges all segments together into new one
|
||||
*
|
||||
* Returns true on success and false if another optimization or auto-optimization process
|
||||
* is running now
|
||||
*
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
* @return boolean
|
||||
*/
|
||||
public function optimize()
|
||||
{
|
||||
if (Zend_Search_Lucene_LockManager::obtainOptimizationLock($this->_directory) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_mergeSegments($this->_segmentInfos);
|
||||
|
||||
Zend_Search_Lucene_LockManager::releaseOptimizationLock($this->_directory);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -477,16 +750,10 @@ class Zend_Search_Lucene_Index_Writer
|
||||
*/
|
||||
private function _newSegmentName()
|
||||
{
|
||||
// Do not share file handler to get file updates from other sessions.
|
||||
$segmentsFile = $this->_directory->getFileObject('segments', false);
|
||||
|
||||
// Get exclusive segments file lock
|
||||
// We have guarantee, that we will not intersect with _updateSegments() call
|
||||
// of other process, because it needs exclusive index lock and waits
|
||||
// until all other searchers won't stop
|
||||
if (!$segmentsFile->lock(LOCK_EX)) {
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t obtain exclusive index lock');
|
||||
}
|
||||
Zend_Search_Lucene_LockManager::obtainWriteLock($this->_directory);
|
||||
|
||||
$generation = Zend_Search_Lucene::getActualGeneration($this->_directory);
|
||||
$segmentsFile = $this->_directory->getFileObject(Zend_Search_Lucene::getSegmentFileName($generation), false);
|
||||
|
||||
$segmentsFile->seek(12); // 12 = 4 (int, file format marker) + 8 (long, index version)
|
||||
$segmentNameCounter = $segmentsFile->readInt();
|
||||
@@ -498,8 +765,8 @@ class Zend_Search_Lucene_Index_Writer
|
||||
// return (which calls $segmentsFile destructor)
|
||||
$segmentsFile->flush();
|
||||
|
||||
$segmentsFile->unlock();
|
||||
|
||||
Zend_Search_Lucene_LockManager::releaseWriteLock($this->_directory);
|
||||
|
||||
return '_' . base_convert($segmentNameCounter, 10, 36);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
interface Zend_Search_Lucene_Interface
|
||||
@@ -86,6 +86,24 @@ interface Zend_Search_Lucene_Interface
|
||||
*/
|
||||
public static function getDefaultSearchField();
|
||||
|
||||
/**
|
||||
* Set result set limit.
|
||||
*
|
||||
* 0 (default) means no limit
|
||||
*
|
||||
* @param integer $limit
|
||||
*/
|
||||
public static function setResultSetLimit($limit);
|
||||
|
||||
/**
|
||||
* Set result set limit.
|
||||
*
|
||||
* 0 means no limit
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public static function getResultSetLimit();
|
||||
|
||||
/**
|
||||
* Retrieve index maxBufferedDocs option
|
||||
*
|
||||
@@ -306,6 +324,43 @@ interface Zend_Search_Lucene_Interface
|
||||
*/
|
||||
public function terms();
|
||||
|
||||
|
||||
/**
|
||||
* Reset terms stream.
|
||||
*/
|
||||
public function resetTermsStream();
|
||||
|
||||
/**
|
||||
* Skip terms stream up to specified term preffix.
|
||||
*
|
||||
* Prefix contains fully specified field info and portion of searched term
|
||||
*
|
||||
* @param Zend_Search_Lucene_Index_Term $prefix
|
||||
*/
|
||||
public function skipTo(Zend_Search_Lucene_Index_Term $prefix);
|
||||
|
||||
/**
|
||||
* Scans terms dictionary and returns next term
|
||||
*
|
||||
* @return Zend_Search_Lucene_Index_Term|null
|
||||
*/
|
||||
public function nextTerm();
|
||||
|
||||
/**
|
||||
* Returns term in current position
|
||||
*
|
||||
* @return Zend_Search_Lucene_Index_Term|null
|
||||
*/
|
||||
public function currentTerm();
|
||||
|
||||
/**
|
||||
* Close terms stream
|
||||
*
|
||||
* Should be used for resources clean up if stream is not read up to the end
|
||||
*/
|
||||
public function closeTermsStream();
|
||||
|
||||
|
||||
/**
|
||||
* Undeletes all documents currently marked as deleted in this index.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Search_Lucene_PriorityQueue
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
/** Zend_Search_Lucene_Interface */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Interface.php';
|
||||
require_once 'Zend/Search/Lucene/Interface.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -29,7 +29,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Interface.php';
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Proxy implements Zend_Search_Lucene_Interface
|
||||
@@ -144,6 +144,30 @@ class Zend_Search_Lucene_Proxy implements Zend_Search_Lucene_Interface
|
||||
return Zend_Search_Lucene::getDefaultSearchField();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set result set limit.
|
||||
*
|
||||
* 0 (default) means no limit
|
||||
*
|
||||
* @param integer $limit
|
||||
*/
|
||||
public static function setResultSetLimit($limit)
|
||||
{
|
||||
Zend_Search_Lucene::setResultSetLimit($limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set result set limit.
|
||||
*
|
||||
* 0 means no limit
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public static function getResultSetLimit()
|
||||
{
|
||||
return Zend_Search_Lucene::getResultSetLimit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve index maxBufferedDocs option
|
||||
*
|
||||
@@ -436,6 +460,58 @@ class Zend_Search_Lucene_Proxy implements Zend_Search_Lucene_Interface
|
||||
return $this->_index->terms();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reset terms stream.
|
||||
*/
|
||||
public function resetTermsStream()
|
||||
{
|
||||
$this->_index->resetTermsStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip terms stream up to specified term preffix.
|
||||
*
|
||||
* Prefix contains fully specified field info and portion of searched term
|
||||
*
|
||||
* @param Zend_Search_Lucene_Index_Term $prefix
|
||||
*/
|
||||
public function skipTo(Zend_Search_Lucene_Index_Term $prefix)
|
||||
{
|
||||
return $this->_index->skipTo($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans terms dictionary and returns next term
|
||||
*
|
||||
* @return Zend_Search_Lucene_Index_Term|null
|
||||
*/
|
||||
public function nextTerm()
|
||||
{
|
||||
return $this->_index->nextTerm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns term in current position
|
||||
*
|
||||
* @return Zend_Search_Lucene_Index_Term|null
|
||||
*/
|
||||
public function currentTerm()
|
||||
{
|
||||
return $this->_index->currentTerm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close terms stream
|
||||
*
|
||||
* Should be used for resources clean up if stream is not read up to the end
|
||||
*/
|
||||
public function closeTermsStream()
|
||||
{
|
||||
$this->_index->closeTermsStream();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Undeletes all documents currently marked as deleted in this index.
|
||||
*/
|
||||
|
||||
@@ -15,29 +15,29 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_FSM */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/FSM.php';
|
||||
require_once 'Zend/Search/Lucene/FSM.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryToken */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryToken.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryToken.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParser */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParser.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryParser.php';
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_BooleanExpressionRecognizer extends Zend_Search_Lucene_FSM
|
||||
|
||||
@@ -15,19 +15,19 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
/** Zend_Search_Lucene_Document_Html */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Document/Html.php';
|
||||
require_once 'Zend/Search/Lucene/Document/Html.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Search_Lucene_Search_Query
|
||||
|
||||
@@ -15,23 +15,23 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Query.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_Weight_Boolean */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight/Boolean.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Weight/Boolean.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_Query
|
||||
@@ -39,7 +39,7 @@ class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_
|
||||
|
||||
/**
|
||||
* Subqueries
|
||||
* Array of Zend_Search_Lucene_Query
|
||||
* Array of Zend_Search_Lucene_Search_Query
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
@@ -105,7 +105,7 @@ class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_
|
||||
|
||||
|
||||
/**
|
||||
* Add a $subquery (Zend_Search_Lucene_Query) to this query.
|
||||
* Add a $subquery (Zend_Search_Lucene_Search_Query) to this query.
|
||||
*
|
||||
* The sign is specified as:
|
||||
* TRUE - subquery is required
|
||||
@@ -119,6 +119,7 @@ class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_
|
||||
public function addSubquery(Zend_Search_Lucene_Search_Query $subquery, $sign=null) {
|
||||
if ($sign !== true || $this->_signs !== null) { // Skip, if all subqueries are required
|
||||
if ($this->_signs === null) { // Check, If all previous subqueries are required
|
||||
$this->_signs = array();
|
||||
foreach ($this->_subqueries as $prevSubquery) {
|
||||
$this->_signs[] = true;
|
||||
}
|
||||
@@ -165,6 +166,31 @@ class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_
|
||||
$signs[] = ($this->_signs === null)? true : $this->_signs[$id];
|
||||
}
|
||||
|
||||
// Remove insignificant subqueries
|
||||
foreach ($subqueries as $id => $subquery) {
|
||||
if ($subquery instanceof Zend_Search_Lucene_Search_Query_Insignificant) {
|
||||
// Insignificant subquery has to be removed anyway
|
||||
unset($subqueries[$id]);
|
||||
unset($signs[$id]);
|
||||
}
|
||||
}
|
||||
if (count($subqueries) == 0) {
|
||||
// Boolean query doesn't has non-insignificant subqueries
|
||||
return new Zend_Search_Lucene_Search_Query_Insignificant();
|
||||
}
|
||||
// Check if all non-insignificant subqueries are prohibited
|
||||
$allProhibited = true;
|
||||
foreach ($signs as $sign) {
|
||||
if ($sign !== false) {
|
||||
$allProhibited = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($allProhibited) {
|
||||
return new Zend_Search_Lucene_Search_Query_Insignificant();
|
||||
}
|
||||
|
||||
|
||||
// Check for empty subqueries
|
||||
foreach ($subqueries as $id => $subquery) {
|
||||
if ($subquery instanceof Zend_Search_Lucene_Search_Query_Empty) {
|
||||
@@ -180,6 +206,10 @@ class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_
|
||||
}
|
||||
}
|
||||
|
||||
// Check, if reduced subqueries list is empty
|
||||
if (count($subqueries) == 0) {
|
||||
return new Zend_Search_Lucene_Search_Query_Empty();
|
||||
}
|
||||
|
||||
// Check if all non-empty subqueries are prohibited
|
||||
$allProhibited = true;
|
||||
@@ -210,12 +240,6 @@ class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_
|
||||
}
|
||||
|
||||
|
||||
// Check, if reduced subqueries list is empty
|
||||
if (count($subqueries) == 0) {
|
||||
return new Zend_Search_Lucene_Search_Query_Empty();
|
||||
}
|
||||
|
||||
|
||||
// Prepare first candidate for optimized query
|
||||
$optimizedQuery = new Zend_Search_Lucene_Search_Query_Boolean($subqueries, $signs);
|
||||
$optimizedQuery->setBoost($this->getBoost());
|
||||
@@ -456,11 +480,35 @@ class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_
|
||||
$this->_resVector = array();
|
||||
}
|
||||
|
||||
foreach ($this->_subqueries as $subquery) {
|
||||
$resVectors = array();
|
||||
$resVectorsSizes = array();
|
||||
$resVectorsIds = array(); // is used to prevent arrays comparison
|
||||
foreach ($this->_subqueries as $subqueryId => $subquery) {
|
||||
$resVectors[] = $subquery->matchedDocs();
|
||||
$resVectorsSizes[] = count(end($resVectors));
|
||||
$resVectorsIds[] = $subqueryId;
|
||||
}
|
||||
// sort resvectors in order of subquery cardinality increasing
|
||||
array_multisort($resVectorsSizes, SORT_ASC, SORT_NUMERIC,
|
||||
$resVectorsIds, SORT_ASC, SORT_NUMERIC,
|
||||
$resVectors);
|
||||
|
||||
foreach ($resVectors as $nextResVector) {
|
||||
if($this->_resVector === null) {
|
||||
$this->_resVector = $subquery->matchedDocs();
|
||||
$this->_resVector = $nextResVector;
|
||||
} else {
|
||||
$this->_resVector = array_intersect_key($this->_resVector, $subquery->matchedDocs());
|
||||
//$this->_resVector = array_intersect_key($this->_resVector, $nextResVector);
|
||||
|
||||
/**
|
||||
* This code is used as workaround for array_intersect_key() slowness problem.
|
||||
*/
|
||||
$updatedVector = array();
|
||||
foreach ($this->_resVector as $id => $value) {
|
||||
if (isset($nextResVector[$id])) {
|
||||
$updatedVector[$id] = $value;
|
||||
}
|
||||
}
|
||||
$this->_resVector = $updatedVector;
|
||||
}
|
||||
|
||||
if (count($this->_resVector) == 0) {
|
||||
@@ -469,7 +517,8 @@ class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_
|
||||
}
|
||||
}
|
||||
|
||||
ksort($this->_resVector, SORT_NUMERIC);
|
||||
// ksort($this->_resVector, SORT_NUMERIC);
|
||||
// Used algorithm doesn't change elements order
|
||||
}
|
||||
|
||||
|
||||
@@ -479,30 +528,61 @@ class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_
|
||||
*/
|
||||
private function _calculateNonConjunctionResult()
|
||||
{
|
||||
$required = null;
|
||||
$optional = array();
|
||||
$requiredVectors = array();
|
||||
$requiredVectorsSizes = array();
|
||||
$requiredVectorsIds = array(); // is used to prevent arrays comparison
|
||||
|
||||
$optional = array();
|
||||
|
||||
foreach ($this->_subqueries as $subqueryId => $subquery) {
|
||||
$docs = $subquery->matchedDocs();
|
||||
|
||||
if ($this->_signs[$subqueryId] === true) {
|
||||
// required
|
||||
if ($required !== null) {
|
||||
// array intersection
|
||||
$required = array_intersect_key($required, $docs);
|
||||
} else {
|
||||
$required = $docs;
|
||||
}
|
||||
$requiredVectors[] = $subquery->matchedDocs();
|
||||
$requiredVectorsSizes[] = count(end($requiredVectors));
|
||||
$requiredVectorsIds[] = $subqueryId;
|
||||
} elseif ($this->_signs[$subqueryId] === false) {
|
||||
// prohibited
|
||||
// Do nothing. matchedDocs() may include non-matching id's
|
||||
// Calculating prohibited vector may take significant time, but do not affect the result
|
||||
// Skipped.
|
||||
} else {
|
||||
// neither required, nor prohibited
|
||||
// array union
|
||||
$optional += $docs;
|
||||
$optional += $subquery->matchedDocs();
|
||||
}
|
||||
}
|
||||
|
||||
// sort resvectors in order of subquery cardinality increasing
|
||||
array_multisort($requiredVectorsSizes, SORT_ASC, SORT_NUMERIC,
|
||||
$requiredVectorsIds, SORT_ASC, SORT_NUMERIC,
|
||||
$requiredVectors);
|
||||
|
||||
$required = null;
|
||||
foreach ($requiredVectors as $nextResVector) {
|
||||
if($required === null) {
|
||||
$required = $nextResVector;
|
||||
} else {
|
||||
//$required = array_intersect_key($required, $nextResVector);
|
||||
|
||||
/**
|
||||
* This code is used as workaround for array_intersect_key() slowness problem.
|
||||
*/
|
||||
$updatedVector = array();
|
||||
foreach ($required as $id => $value) {
|
||||
if (isset($nextResVector[$id])) {
|
||||
$updatedVector[$id] = $value;
|
||||
}
|
||||
}
|
||||
$required = $updatedVector;
|
||||
}
|
||||
|
||||
if (count($required) == 0) {
|
||||
// Empty result set, we don't need to check other terms
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($required !== null) {
|
||||
$this->_resVector = &$required;
|
||||
} else {
|
||||
@@ -705,7 +785,7 @@ class Zend_Search_Lucene_Search_Query_Boolean extends Zend_Search_Lucene_Search_
|
||||
$query .= '(' . $subquery->__toString() . ')';
|
||||
|
||||
if ($subquery->getBoost() != 1) {
|
||||
$query .= '^' . $subquery->getBoost();
|
||||
$query .= '^' . round($subquery->getBoost(), 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,23 +15,23 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Query.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_Weight_Empty */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight/Empty.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Weight/Empty.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Query_Empty extends Zend_Search_Lucene_Search_Query
|
||||
|
||||
@@ -15,23 +15,23 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Query.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_Weight_MultiTerm */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight/MultiTerm.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Weight/MultiTerm.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Query_MultiTerm extends Zend_Search_Lucene_Search_Query
|
||||
@@ -103,7 +103,6 @@ class Zend_Search_Lucene_Search_Query_MultiTerm extends Zend_Search_Lucene_Searc
|
||||
*
|
||||
* @param array $terms Array of Zend_Search_Lucene_Index_Term objects
|
||||
* @param array $signs Array of signs. Sign is boolean|null.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($terms = null, $signs = null)
|
||||
{
|
||||
@@ -139,6 +138,7 @@ class Zend_Search_Lucene_Search_Query_MultiTerm extends Zend_Search_Lucene_Searc
|
||||
public function addTerm(Zend_Search_Lucene_Index_Term $term, $sign = null) {
|
||||
if ($sign !== true || $this->_signs !== null) { // Skip, if all terms are required
|
||||
if ($this->_signs === null) { // Check, If all previous terms are required
|
||||
$this->_signs = array();
|
||||
foreach ($this->_terms as $prevTerm) {
|
||||
$this->_signs[] = true;
|
||||
}
|
||||
@@ -316,22 +316,47 @@ class Zend_Search_Lucene_Search_Query_MultiTerm extends Zend_Search_Lucene_Searc
|
||||
$this->_resVector = array();
|
||||
}
|
||||
|
||||
foreach( $this->_terms as $termId=>$term ) {
|
||||
$resVectors = array();
|
||||
$resVectorsSizes = array();
|
||||
$resVectorsIds = array(); // is used to prevent arrays comparison
|
||||
foreach ($this->_terms as $termId => $term) {
|
||||
$resVectors[] = array_flip($reader->termDocs($term));
|
||||
$resVectorsSizes[] = count(end($resVectors));
|
||||
$resVectorsIds[] = $termId;
|
||||
|
||||
$this->_termsFreqs[$termId] = $reader->termFreqs($term);
|
||||
}
|
||||
// sort resvectors in order of subquery cardinality increasing
|
||||
array_multisort($resVectorsSizes, SORT_ASC, SORT_NUMERIC,
|
||||
$resVectorsIds, SORT_ASC, SORT_NUMERIC,
|
||||
$resVectors);
|
||||
|
||||
foreach ($resVectors as $nextResVector) {
|
||||
if($this->_resVector === null) {
|
||||
$this->_resVector = array_flip($reader->termDocs($term));
|
||||
$this->_resVector = $nextResVector;
|
||||
} else {
|
||||
$this->_resVector = array_intersect_key($this->_resVector, array_flip($reader->termDocs($term)));
|
||||
//$this->_resVector = array_intersect_key($this->_resVector, $nextResVector);
|
||||
|
||||
/**
|
||||
* This code is used as workaround for array_intersect_key() slowness problem.
|
||||
*/
|
||||
$updatedVector = array();
|
||||
foreach ($this->_resVector as $id => $value) {
|
||||
if (isset($nextResVector[$id])) {
|
||||
$updatedVector[$id] = $value;
|
||||
}
|
||||
}
|
||||
$this->_resVector = $updatedVector;
|
||||
}
|
||||
|
||||
if (count($this->_resVector) == 0) {
|
||||
// Empty result set, we don't need to check other terms
|
||||
break;
|
||||
}
|
||||
|
||||
$this->_termsFreqs[$termId] = $reader->termFreqs($term);
|
||||
}
|
||||
|
||||
ksort($this->_resVector, SORT_NUMERIC);
|
||||
// ksort($this->_resVector, SORT_NUMERIC);
|
||||
// Docs are returned ordered. Used algorithm doesn't change elements order.
|
||||
}
|
||||
|
||||
|
||||
@@ -343,21 +368,21 @@ class Zend_Search_Lucene_Search_Query_MultiTerm extends Zend_Search_Lucene_Searc
|
||||
*/
|
||||
private function _calculateNonConjunctionResult(Zend_Search_Lucene_Interface $reader)
|
||||
{
|
||||
$required = null;
|
||||
$requiredVectors = array();
|
||||
$requiredVectorsSizes = array();
|
||||
$requiredVectorsIds = array(); // is used to prevent arrays comparison
|
||||
|
||||
$optional = array();
|
||||
$prohibited = array();
|
||||
|
||||
|
||||
foreach ($this->_terms as $termId => $term) {
|
||||
$termDocs = array_flip($reader->termDocs($term));
|
||||
|
||||
if ($this->_signs[$termId] === true) {
|
||||
// required
|
||||
if ($required !== null) {
|
||||
// array intersection
|
||||
$required = array_intersect_key($required, $termDocs);
|
||||
} else {
|
||||
$required = $termDocs;
|
||||
}
|
||||
$requiredVectors[] = $termDocs;
|
||||
$requiredVectorsSizes[] = count($termDocs);
|
||||
$requiredVectorsIds[] = $termId;
|
||||
} elseif ($this->_signs[$termId] === false) {
|
||||
// prohibited
|
||||
// array union
|
||||
@@ -371,16 +396,65 @@ class Zend_Search_Lucene_Search_Query_MultiTerm extends Zend_Search_Lucene_Searc
|
||||
$this->_termsFreqs[$termId] = $reader->termFreqs($term);
|
||||
}
|
||||
|
||||
// sort resvectors in order of subquery cardinality increasing
|
||||
array_multisort($requiredVectorsSizes, SORT_ASC, SORT_NUMERIC,
|
||||
$requiredVectorsIds, SORT_ASC, SORT_NUMERIC,
|
||||
$requiredVectors);
|
||||
|
||||
$required = null;
|
||||
foreach ($requiredVectors as $nextResVector) {
|
||||
if($required === null) {
|
||||
$required = $nextResVector;
|
||||
} else {
|
||||
//$required = array_intersect_key($required, $nextResVector);
|
||||
|
||||
/**
|
||||
* This code is used as workaround for array_intersect_key() slowness problem.
|
||||
*/
|
||||
$updatedVector = array();
|
||||
foreach ($required as $id => $value) {
|
||||
if (isset($nextResVector[$id])) {
|
||||
$updatedVector[$id] = $value;
|
||||
}
|
||||
}
|
||||
$required = $updatedVector;
|
||||
}
|
||||
|
||||
if (count($required) == 0) {
|
||||
// Empty result set, we don't need to check other terms
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($required !== null) {
|
||||
$this->_resVector = (count($prohibited) > 0) ?
|
||||
array_diff_key($required, $prohibited) :
|
||||
$required;
|
||||
$this->_resVector = $required;
|
||||
} else {
|
||||
$this->_resVector = (count($prohibited) > 0) ?
|
||||
array_diff_key($optional, $prohibited) :
|
||||
$optional;
|
||||
$this->_resVector = $optional;
|
||||
}
|
||||
|
||||
if (count($prohibited) != 0) {
|
||||
// $this->_resVector = array_diff_key($this->_resVector, $prohibited);
|
||||
|
||||
/**
|
||||
* This code is used as workaround for array_diff_key() slowness problem.
|
||||
*/
|
||||
if (count($this->_resVector) < count($prohibited)) {
|
||||
$updatedVector = $this->_resVector;
|
||||
foreach ($this->_resVector as $id => $value) {
|
||||
if (isset($prohibited[$id])) {
|
||||
unset($updatedVector[$id]);
|
||||
}
|
||||
}
|
||||
$this->_resVector = $updatedVector;
|
||||
} else {
|
||||
$updatedVector = $this->_resVector;
|
||||
foreach ($prohibited as $id => $value) {
|
||||
unset($updatedVector[$id]);
|
||||
}
|
||||
$this->_resVector = $updatedVector;
|
||||
}
|
||||
}
|
||||
|
||||
ksort($this->_resVector, SORT_NUMERIC);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
/**
|
||||
* Zend_Search_Lucene_Search_Query
|
||||
*/
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Query.php';
|
||||
|
||||
/**
|
||||
* Zend_Search_Lucene_Search_Weight_MultiTerm
|
||||
*/
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight/Phrase.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Weight/Phrase.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -37,7 +37,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight/Phrase.php'
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Query_Phrase extends Zend_Search_Lucene_Search_Query
|
||||
@@ -416,23 +416,48 @@ class Zend_Search_Lucene_Search_Query_Phrase extends Zend_Search_Lucene_Search_Q
|
||||
$this->_resVector = array();
|
||||
}
|
||||
|
||||
foreach( $this->_terms as $termId=>$term ) {
|
||||
$resVectors = array();
|
||||
$resVectorsSizes = array();
|
||||
$resVectorsIds = array(); // is used to prevent arrays comparison
|
||||
foreach ($this->_terms as $termId => $term) {
|
||||
$resVectors[] = array_flip($reader->termDocs($term));
|
||||
$resVectorsSizes[] = count(end($resVectors));
|
||||
$resVectorsIds[] = $termId;
|
||||
|
||||
$this->_termsPositions[$termId] = $reader->termPositions($term);
|
||||
}
|
||||
// sort resvectors in order of subquery cardinality increasing
|
||||
array_multisort($resVectorsSizes, SORT_ASC, SORT_NUMERIC,
|
||||
$resVectorsIds, SORT_ASC, SORT_NUMERIC,
|
||||
$resVectors);
|
||||
|
||||
foreach ($resVectors as $nextResVector) {
|
||||
if($this->_resVector === null) {
|
||||
$this->_resVector = array_flip($reader->termDocs($term));
|
||||
$this->_resVector = $nextResVector;
|
||||
} else {
|
||||
$this->_resVector = array_intersect_key($this->_resVector, array_flip($reader->termDocs($term)));
|
||||
//$this->_resVector = array_intersect_key($this->_resVector, $nextResVector);
|
||||
|
||||
/**
|
||||
* This code is used as workaround for array_intersect_key() slowness problem.
|
||||
*/
|
||||
$updatedVector = array();
|
||||
foreach ($this->_resVector as $id => $value) {
|
||||
if (isset($nextResVector[$id])) {
|
||||
$updatedVector[$id] = $value;
|
||||
}
|
||||
}
|
||||
$this->_resVector = $updatedVector;
|
||||
}
|
||||
|
||||
if (count($this->_resVector) == 0) {
|
||||
// Empty result set, we don't need to check other terms
|
||||
break;
|
||||
}
|
||||
|
||||
$this->_termsPositions[$termId] = $reader->termPositions($term);
|
||||
}
|
||||
|
||||
ksort($this->_resVector, SORT_NUMERIC);
|
||||
|
||||
// ksort($this->_resVector, SORT_NUMERIC);
|
||||
// Docs are returned ordered. Used algorithm doesn't change elements order.
|
||||
|
||||
// Initialize weight if it's not done yet
|
||||
$this->_initWeight($reader);
|
||||
}
|
||||
|
||||
@@ -15,23 +15,23 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Query.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Weight_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight/Term.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Weight/Term.php";
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Query_Term extends Zend_Search_Lucene_Search_Query
|
||||
@@ -65,7 +65,7 @@ class Zend_Search_Lucene_Search_Query_Term extends Zend_Search_Lucene_Search_Que
|
||||
* @param Zend_Search_Lucene_Index_Term $term
|
||||
* @param boolean $sign
|
||||
*/
|
||||
public function __construct($term)
|
||||
public function __construct(Zend_Search_Lucene_Index_Term $term)
|
||||
{
|
||||
$this->_term = $term;
|
||||
}
|
||||
|
||||
@@ -15,36 +15,36 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Index_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/Term.php';
|
||||
require_once 'Zend/Search/Lucene/Index/Term.php';
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryEntry_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryEntry/Term.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryEntry/Term.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryEntry_Phrase */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryEntry/Phrase.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryEntry/Phrase.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryEntry_Subquery */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryEntry/Subquery.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryEntry/Subquery.php';
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParserException */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Search_Lucene_Search_QueryEntry
|
||||
|
||||
@@ -15,25 +15,25 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Index_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/Term.php';
|
||||
require_once 'Zend/Search/Lucene/Index/Term.php';
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryEntry */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryEntry.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryEntry.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParserException */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_QueryEntry_Phrase extends Zend_Search_Lucene_Search_QueryEntry
|
||||
@@ -118,7 +118,7 @@ class Zend_Search_Lucene_Search_QueryEntry_Phrase extends Zend_Search_Lucene_Sea
|
||||
$tokens = Zend_Search_Lucene_Analysis_Analyzer::getDefault()->tokenize($this->_phrase, $encoding);
|
||||
|
||||
if (count($tokens) == 0) {
|
||||
return new Zend_Search_Lucene_Search_Query_Empty();
|
||||
return new Zend_Search_Lucene_Search_Query_Insignificant();
|
||||
}
|
||||
|
||||
if (count($tokens) == 1) {
|
||||
@@ -130,10 +130,12 @@ class Zend_Search_Lucene_Search_QueryEntry_Phrase extends Zend_Search_Lucene_Sea
|
||||
}
|
||||
|
||||
//It's not empty or one term query
|
||||
$position = -1;
|
||||
$query = new Zend_Search_Lucene_Search_Query_Phrase();
|
||||
foreach ($tokens as $token) {
|
||||
$position += $token->getPositionIncrement();
|
||||
$term = new Zend_Search_Lucene_Index_Term($token->getTermText(), $this->_field);
|
||||
$query->addTerm($term);
|
||||
$query->addTerm($term, $position);
|
||||
}
|
||||
|
||||
if ($this->_proximityQuery) {
|
||||
|
||||
@@ -15,29 +15,29 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Index_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/Term.php';
|
||||
require_once 'Zend/Search/Lucene/Index/Term.php';
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryEntry */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryEntry.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryEntry.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParserException */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_QueryEntry_Subquery extends Zend_Search_Lucene_Search_QueryEntry
|
||||
|
||||
@@ -15,25 +15,25 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Index_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/Term.php';
|
||||
require_once 'Zend/Search/Lucene/Index/Term.php';
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryEntry */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryEntry.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryEntry.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParserException */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
|
||||
/** Zend_Search_Lucene_Analysis_Analyzer */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
require_once 'Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Analysis/Analyzer.php';
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_QueryEntry_Term extends Zend_Search_Lucene_Search_QueryEntry
|
||||
@@ -100,7 +100,7 @@ class Zend_Search_Lucene_Search_QueryEntry_Term extends Zend_Search_Lucene_Searc
|
||||
if ($parameter !== null) {
|
||||
$this->_similarity = $parameter;
|
||||
} else {
|
||||
$this->_similarity = 0.5;
|
||||
$this->_similarity = Zend_Search_Lucene_Search_Query_Fuzzy::DEFAULT_MIN_SIMILARITY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,28 +113,77 @@ class Zend_Search_Lucene_Search_QueryEntry_Term extends Zend_Search_Lucene_Searc
|
||||
*/
|
||||
public function getQuery($encoding)
|
||||
{
|
||||
if ($this->_fuzzyQuery) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Fuzzy search is not supported yet.');
|
||||
}
|
||||
|
||||
if (strpos($this->_term, '?') !== false || strpos($this->_term, '*') !== false) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Wildcard queries are not supported yet.');
|
||||
if ($this->_fuzzyQuery) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Fuzzy search is not supported for terms with wildcards.');
|
||||
}
|
||||
|
||||
$pattern = '';
|
||||
|
||||
$subPatterns = explode('*', $this->_term);
|
||||
|
||||
$astericFirstPass = true;
|
||||
foreach ($subPatterns as $subPattern) {
|
||||
if (!$astericFirstPass) {
|
||||
$pattern .= '*';
|
||||
} else {
|
||||
$astericFirstPass = false;
|
||||
}
|
||||
|
||||
$subPatternsL2 = explode('?', $subPattern);
|
||||
|
||||
$qMarkFirstPass = true;
|
||||
foreach ($subPatternsL2 as $subPatternL2) {
|
||||
if (!$qMarkFirstPass) {
|
||||
$pattern .= '?';
|
||||
} else {
|
||||
$qMarkFirstPass = false;
|
||||
}
|
||||
|
||||
$tokens = Zend_Search_Lucene_Analysis_Analyzer::getDefault()->tokenize($subPatternL2, $encoding);
|
||||
if (count($tokens) > 1) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Wildcard search is supported only for non-multiple word terms');
|
||||
}
|
||||
|
||||
foreach ($tokens as $token) {
|
||||
$pattern .= $token->getTermText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$term = new Zend_Search_Lucene_Index_Term($pattern, $this->_field);
|
||||
$query = new Zend_Search_Lucene_Search_Query_Wildcard($term);
|
||||
$query->setBoost($this->_boost);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
$tokens = Zend_Search_Lucene_Analysis_Analyzer::getDefault()->tokenize($this->_term, $encoding);
|
||||
|
||||
if (count($tokens) == 0) {
|
||||
return new Zend_Search_Lucene_Search_Query_Empty();
|
||||
return new Zend_Search_Lucene_Search_Query_Insignificant();
|
||||
}
|
||||
|
||||
if (count($tokens) == 1) {
|
||||
$term = new Zend_Search_Lucene_Index_Term($tokens[0]->getTermText(), $this->_field);
|
||||
if (count($tokens) == 1 && !$this->_fuzzyQuery) {
|
||||
$term = new Zend_Search_Lucene_Index_Term($tokens[0]->getTermText(), $this->_field);
|
||||
$query = new Zend_Search_Lucene_Search_Query_Term($term);
|
||||
$query->setBoost($this->_boost);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
if (count($tokens) == 1 && $this->_fuzzyQuery) {
|
||||
$term = new Zend_Search_Lucene_Index_Term($tokens[0]->getTermText(), $this->_field);
|
||||
$query = new Zend_Search_Lucene_Search_Query_Fuzzy($term, $this->_similarity);
|
||||
$query->setBoost($this->_boost);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
if ($this->_fuzzyQuery) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Fuzzy search is supported only for non-multiple word terms');
|
||||
}
|
||||
|
||||
//It's not empty or one term query
|
||||
$query = new Zend_Search_Lucene_Search_Query_MultiTerm();
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_QueryHit
|
||||
|
||||
@@ -15,29 +15,29 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_FSM */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/FSM.php';
|
||||
require_once 'Zend/Search/Lucene/FSM.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParser */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryToken.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryToken.php';
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParserException */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_QueryLexer extends Zend_Search_Lucene_FSM
|
||||
|
||||
@@ -15,52 +15,64 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Index_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/Term.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Index/Term.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query/Term.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Query/Term.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_MultiTerm */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query/MultiTerm.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Query/MultiTerm.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Boolean */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query/Boolean.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Query/Boolean.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Phrase */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query/Phrase.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Query/Phrase.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Wildcard */
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Query/Wildcard.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Range */
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Query/Range.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Fuzzy */
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Query/Fuzzy.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Empty */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query/Empty.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Query/Empty.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Insignificant */
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/Query/Insignificant.php";
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryLexer */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryLexer.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/QueryLexer.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParserContext */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParserContext.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/QueryParserContext.php";
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_FSM */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/FSM.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/FSM.php";
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Exception.php";
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParserException */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
require_once "{$CFG->dirroot}/search/Zend/Search/Lucene/Search/QueryParserException.php";
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
@@ -139,6 +151,26 @@ class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
*/
|
||||
private $_defaultEncoding = '';
|
||||
|
||||
/**
|
||||
* Defines query parsing mode.
|
||||
*
|
||||
* If this option is turned on, then query parser suppress query parser exceptions
|
||||
* and constructs multi-term query using all words from a query.
|
||||
*
|
||||
* That helps to avoid exceptions caused by queries, which don't conform to query language,
|
||||
* but limits possibilities to check, that query entered by user has some inconsistencies.
|
||||
*
|
||||
*
|
||||
* Default is true.
|
||||
*
|
||||
* Use {@link Zend_Search_Lucene::suppressQueryParsingExceptions()},
|
||||
* {@link Zend_Search_Lucene::dontSuppressQueryParsingExceptions()} and
|
||||
* {@link Zend_Search_Lucene::checkQueryParsingExceptionsSuppressMode()} to operate
|
||||
* with this setting.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $_suppressQueryParsingExceptions = true;
|
||||
|
||||
/**
|
||||
* Boolean operators constants
|
||||
@@ -256,6 +288,18 @@ class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
$this->_lexer = new Zend_Search_Lucene_Search_QueryLexer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get query parser instance
|
||||
*
|
||||
* @return Zend_Search_Lucene_Search_QueryParser
|
||||
*/
|
||||
private static function _getInstance()
|
||||
{
|
||||
if (self::$_instance === null) {
|
||||
self::$_instance = new self();
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set query string default encoding
|
||||
@@ -264,11 +308,7 @@ class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
*/
|
||||
public static function setDefaultEncoding($encoding)
|
||||
{
|
||||
if (self::$_instance === null) {
|
||||
self::$_instance = new Zend_Search_Lucene_Search_QueryParser();
|
||||
}
|
||||
|
||||
self::$_instance->_defaultEncoding = $encoding;
|
||||
self::_getInstance()->_defaultEncoding = $encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,11 +318,7 @@ class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
*/
|
||||
public static function getDefaultEncoding()
|
||||
{
|
||||
if (self::$_instance === null) {
|
||||
self::$_instance = new Zend_Search_Lucene_Search_QueryParser();
|
||||
}
|
||||
|
||||
return self::$_instance->_defaultEncoding;
|
||||
return self::_getInstance()->_defaultEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,11 +328,7 @@ class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
*/
|
||||
public static function setDefaultOperator($operator)
|
||||
{
|
||||
if (self::$_instance === null) {
|
||||
self::$_instance = new Zend_Search_Lucene_Search_QueryParser();
|
||||
}
|
||||
|
||||
self::$_instance->_defaultOperator = $operator;
|
||||
self::_getInstance()->_defaultOperator = $operator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,13 +338,34 @@ class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
*/
|
||||
public static function getDefaultOperator()
|
||||
{
|
||||
if (self::$_instance === null) {
|
||||
self::$_instance = new Zend_Search_Lucene_Search_QueryParser();
|
||||
}
|
||||
|
||||
return self::$_instance->_defaultOperator;
|
||||
return self::_getInstance()->_defaultOperator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on 'suppress query parser exceptions' mode.
|
||||
*/
|
||||
public static function suppressQueryParsingExceptions()
|
||||
{
|
||||
self::_getInstance()->_suppressQueryParsingExceptions = true;
|
||||
}
|
||||
/**
|
||||
* Turn off 'suppress query parser exceptions' mode.
|
||||
*/
|
||||
public static function dontSuppressQueryParsingExceptions()
|
||||
{
|
||||
self::_getInstance()->_suppressQueryParsingExceptions = false;
|
||||
}
|
||||
/**
|
||||
* Check 'suppress query parser exceptions' mode.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function queryParsingExceptionsSuppressed()
|
||||
{
|
||||
return self::_getInstance()->_suppressQueryParsingExceptions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Parses a query string
|
||||
*
|
||||
@@ -323,42 +376,62 @@ class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
*/
|
||||
public static function parse($strQuery, $encoding = null)
|
||||
{
|
||||
if (self::$_instance === null) {
|
||||
self::$_instance = new Zend_Search_Lucene_Search_QueryParser();
|
||||
}
|
||||
|
||||
self::$_instance->_encoding = ($encoding !== null) ? $encoding : self::$_instance->_defaultEncoding;
|
||||
self::$_instance->_lastToken = null;
|
||||
self::$_instance->_context = new Zend_Search_Lucene_Search_QueryParserContext(self::$_instance->_encoding);
|
||||
self::$_instance->_contextStack = array();
|
||||
self::$_instance->_tokens = self::$_instance->_lexer->tokenize($strQuery, self::$_instance->_encoding);
|
||||
|
||||
// Empty query
|
||||
if (count(self::$_instance->_tokens) == 0) {
|
||||
return new Zend_Search_Lucene_Search_Query_Empty();
|
||||
}
|
||||
|
||||
|
||||
foreach (self::$_instance->_tokens as $token) {
|
||||
try {
|
||||
self::$_instance->_currentToken = $token;
|
||||
self::$_instance->process($token->type);
|
||||
|
||||
self::$_instance->_lastToken = $token;
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), 'There is no any rule for') !== false) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException( 'Syntax error at char position ' . $token->position . '.' );
|
||||
self::_getInstance();
|
||||
|
||||
// Reset FSM if previous parse operation didn't return it into a correct state
|
||||
self::$_instance->reset();
|
||||
|
||||
try {
|
||||
self::$_instance->_encoding = ($encoding !== null) ? $encoding : self::$_instance->_defaultEncoding;
|
||||
self::$_instance->_lastToken = null;
|
||||
self::$_instance->_context = new Zend_Search_Lucene_Search_QueryParserContext(self::$_instance->_encoding);
|
||||
self::$_instance->_contextStack = array();
|
||||
self::$_instance->_tokens = self::$_instance->_lexer->tokenize($strQuery, self::$_instance->_encoding);
|
||||
|
||||
// Empty query
|
||||
if (count(self::$_instance->_tokens) == 0) {
|
||||
return new Zend_Search_Lucene_Search_Query_Insignificant();
|
||||
}
|
||||
|
||||
|
||||
foreach (self::$_instance->_tokens as $token) {
|
||||
try {
|
||||
self::$_instance->_currentToken = $token;
|
||||
self::$_instance->process($token->type);
|
||||
|
||||
self::$_instance->_lastToken = $token;
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), 'There is no any rule for') !== false) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException( 'Syntax error at char position ' . $token->position . '.' );
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
if (count(self::$_instance->_contextStack) != 0) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Syntax Error: mismatched parentheses, every opening must have closing.' );
|
||||
}
|
||||
|
||||
return self::$_instance->_context->getQuery();
|
||||
} catch (Zend_Search_Lucene_Search_QueryParserException $e) {
|
||||
if (self::$_instance->_suppressQueryParsingExceptions) {
|
||||
$queryTokens = Zend_Search_Lucene_Analysis_Analyzer::getDefault()->tokenize($strQuery, self::$_instance->_encoding);
|
||||
|
||||
$query = new Zend_Search_Lucene_Search_Query_MultiTerm();
|
||||
$termsSign = (self::$_instance->_defaultOperator == self::B_AND) ? true /* required term */ :
|
||||
null /* optional term */;
|
||||
|
||||
foreach ($queryTokens as $token) {
|
||||
$query->addTerm(new Zend_Search_Lucene_Index_Term($token->getTermText()), $termsSign);
|
||||
}
|
||||
|
||||
|
||||
return $query;
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
if (count(self::$_instance->_contextStack) != 0) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Syntax Error: mismatched parentheses, every opening must have closing.' );
|
||||
}
|
||||
|
||||
return self::$_instance->_context->getQuery();
|
||||
}
|
||||
|
||||
|
||||
@@ -433,7 +506,7 @@ class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
|
||||
default:
|
||||
// It's not a user input exception
|
||||
throw new Zend_Search_Lucene_Exception('Lexeme modifier parameter must follow lexeme modifier. Char position .' );
|
||||
throw new Zend_Search_Lucene_Exception('Lexeme modifier parameter must follow lexeme modifier. Char position 0.' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,13 +558,31 @@ class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
*/
|
||||
public function openedRQLastTerm()
|
||||
{
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Range queries are not supported yet.');
|
||||
$tokens = Zend_Search_Lucene_Analysis_Analyzer::getDefault()->tokenize($this->_rqFirstTerm, $this->_encoding);
|
||||
if (count($tokens) > 1) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Range query boundary terms must be non-multiple word terms');
|
||||
} else if (count($tokens) == 1) {
|
||||
$from = new Zend_Search_Lucene_Index_Term(reset($tokens)->getTermText(), $this->_context->getField());
|
||||
} else {
|
||||
$from = null;
|
||||
}
|
||||
|
||||
// $firstTerm = new Zend_Search_Lucene_Index_Term($this->_rqFirstTerm, $this->_context->getField());
|
||||
// $lastTerm = new Zend_Search_Lucene_Index_Term($this->_currentToken->text, $this->_context->getField());
|
||||
$tokens = Zend_Search_Lucene_Analysis_Analyzer::getDefault()->tokenize($this->_currentToken->text, $this->_encoding);
|
||||
if (count($tokens) > 1) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Range query boundary terms must be non-multiple word terms');
|
||||
} else if (count($tokens) == 1) {
|
||||
$to = new Zend_Search_Lucene_Index_Term(reset($tokens)->getTermText(), $this->_context->getField());
|
||||
} else {
|
||||
$to = null;
|
||||
}
|
||||
|
||||
// $query = new Zend_Search_Lucene_Search_Query_Range($firstTerm, $lastTerm, false);
|
||||
// $this->_context->addentry($query);
|
||||
if ($from === null && $to === null) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('At least one range query boundary term must be non-empty term');
|
||||
}
|
||||
|
||||
$rangeQuery = new Zend_Search_Lucene_Search_Query_Range($from, $to, false);
|
||||
$entry = new Zend_Search_Lucene_Search_QueryEntry_Subquery($rangeQuery);
|
||||
$this->_context->addEntry($entry);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,13 +600,31 @@ class Zend_Search_Lucene_Search_QueryParser extends Zend_Search_Lucene_FSM
|
||||
*/
|
||||
public function closedRQLastTerm()
|
||||
{
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Range queries are not supported yet.');
|
||||
$tokens = Zend_Search_Lucene_Analysis_Analyzer::getDefault()->tokenize($this->_rqFirstTerm, $this->_encoding);
|
||||
if (count($tokens) > 1) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Range query boundary terms must be non-multiple word terms');
|
||||
} else if (count($tokens) == 1) {
|
||||
$from = new Zend_Search_Lucene_Index_Term(reset($tokens)->getTermText(), $this->_context->getField());
|
||||
} else {
|
||||
$from = null;
|
||||
}
|
||||
|
||||
// $firstTerm = new Zend_Search_Lucene_Index_Term($this->_rqFirstTerm, $this->_context->getField());
|
||||
// $lastTerm = new Zend_Search_Lucene_Index_Term($this->_currentToken->text, $this->_context->getField());
|
||||
$tokens = Zend_Search_Lucene_Analysis_Analyzer::getDefault()->tokenize($this->_currentToken->text, $this->_encoding);
|
||||
if (count($tokens) > 1) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('Range query boundary terms must be non-multiple word terms');
|
||||
} else if (count($tokens) == 1) {
|
||||
$to = new Zend_Search_Lucene_Index_Term(reset($tokens)->getTermText(), $this->_context->getField());
|
||||
} else {
|
||||
$to = null;
|
||||
}
|
||||
|
||||
// $query = new Zend_Search_Lucene_Search_Query_Range($firstTerm, $lastTerm, true);
|
||||
// $this->_context->addentry($query);
|
||||
if ($from === null && $to === null) {
|
||||
throw new Zend_Search_Lucene_Search_QueryParserException('At least one range query boundary term must be non-empty term');
|
||||
}
|
||||
|
||||
$rangeQuery = new Zend_Search_Lucene_Search_Query_Range($from, $to, true);
|
||||
$entry = new Zend_Search_Lucene_Search_QueryEntry_Subquery($rangeQuery);
|
||||
$this->_context->addEntry($entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,50 +15,50 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
/** Zend_Search_Lucene_FSM */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/FSM.php';
|
||||
require_once 'Zend/Search/Lucene/FSM.php';
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Index_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/Term.php';
|
||||
require_once 'Zend/Search/Lucene/Index/Term.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryToken */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryToken.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryToken.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Term */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query/Term.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Query/Term.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_MultiTerm */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query/MultiTerm.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Query/MultiTerm.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Boolean */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query/Boolean.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Query/Boolean.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_Query_Phrase */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Query/Phrase.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Query/Phrase.php';
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryParserException */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryParserException.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_BooleanExpressionRecognizer */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/BooleanExpressionRecognizer.php';
|
||||
require_once 'Zend/Search/Lucene/Search/BooleanExpressionRecognizer.php';
|
||||
|
||||
/** Zend_Search_Lucene_Search_QueryEntry */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryEntry.php';
|
||||
require_once 'Zend/Search/Lucene/Search/QueryEntry.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_QueryParserContext
|
||||
@@ -360,7 +360,7 @@ class Zend_Search_Lucene_Search_QueryParserContext
|
||||
}
|
||||
|
||||
if (!$nonNegativeEntryFound) {
|
||||
unset($conjuctions[$conjuctionId]);
|
||||
unset($conjuctions[$conjuctionId]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ class Zend_Search_Lucene_Search_QueryParserContext
|
||||
}
|
||||
|
||||
if (count($subqueries) == 0) {
|
||||
return new Zend_Search_Lucene_Search_Query_Empty();
|
||||
return new Zend_Search_Lucene_Search_Query_Insignificant();
|
||||
}
|
||||
|
||||
if (count($subqueries) == 1) {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
/**
|
||||
* Zend_Search_Lucene base exception
|
||||
*/
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*
|
||||
* Special exception type, which may be used to intercept wrong user input
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_QueryToken
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_Similarity_Default */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Similarity/Default.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Similarity/Default.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Search_Lucene_Search_Similarity
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_Similarity */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Similarity.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Similarity.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Similarity_Default extends Zend_Search_Lucene_Search_Similarity
|
||||
@@ -38,7 +38,7 @@ class Zend_Search_Lucene_Search_Similarity_Default extends Zend_Search_Lucene_Se
|
||||
* Implemented as '1/sqrt(numTerms)'.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param integer numTerms
|
||||
* @param integer $numTerms
|
||||
* @return float
|
||||
*/
|
||||
public function lengthNorm($fieldName, $numTerms)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Search_Lucene_Search_Weight
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_Weight */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Weight.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Weight_Boolean extends Zend_Search_Lucene_Search_Weight
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_Weight */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Weight.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Weight_Empty extends Zend_Search_Lucene_Search_Weight
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_Weight */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Weight.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Weight_MultiTerm extends Zend_Search_Lucene_Search_Weight
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
/**
|
||||
* Zend_Search_Lucene_Search_Weight
|
||||
*/
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Weight.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Weight_Phrase extends Zend_Search_Lucene_Search_Weight
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Search_Weight */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Weight.php';
|
||||
require_once 'Zend/Search/Lucene/Search/Weight.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Search
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Search_Weight_Term extends Zend_Search_Lucene_Search_Weight
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to [email protected] so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
/** Zend_Search_Lucene_Storage_Directory */
|
||||
require_once 'Zend/Search/Lucene/Storage/Directory.php';
|
||||
|
||||
/** Zend_Search_Lucene_Storage_File */
|
||||
require_once 'Zend/Search/Lucene/Storage/File.php';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is an utility class which provides index locks processing functionality
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_LockManager
|
||||
{
|
||||
const WRITE_LOCK_FILE = 'write.lock.file';
|
||||
const READ_LOCK_FILE = 'read.lock.file';
|
||||
const EXCLUSIVE_READ_LOCK_FILE = 'exread.lock.file';
|
||||
const OPTIMIZATION_LOCK_FILE = 'optimization.lock.file';
|
||||
|
||||
/**
|
||||
* Obtain exclusive write lock on the index
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $lockDirectory
|
||||
* @return Zend_Search_Lucene_Storage_File
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
public static function obtainWriteLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
|
||||
{
|
||||
if ($lockDirectory->fileExists(self::WRITE_LOCK_FILE)){
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t obtain exclusive index lock : somebody else is writing');
|
||||
}
|
||||
try {
|
||||
$lock = $lockDirectory->createFile(self::WRITE_LOCK_FILE);
|
||||
return $lock;
|
||||
}
|
||||
catch(Zend_Search_Lucene_Exception $e) {
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t obtain exclusive index lock');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release exclusive write lock
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $lockDirectory
|
||||
*/
|
||||
public static function releaseWriteLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
|
||||
{
|
||||
$lockDirectory->deleteFile(self::WRITE_LOCK_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain shared read lock on the index
|
||||
*
|
||||
* It doesn't block other read or update processes, but prevent index from the premature cleaning-up
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $defaultLockDirectory
|
||||
* @return Zend_Search_Lucene_Storage_File
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
public static function obtainReadLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
|
||||
{
|
||||
// is being written. Can't read
|
||||
if ($lockDirectory->fileExists(self::WRITE_LOCK_FILE)){
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t obtain shared reading index lock : write in progress');
|
||||
}
|
||||
|
||||
if ($lockDirectory->fileExists(self::EXCLUSIVE_READ_LOCK_FILE)){
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t obtain shared reading index lock : read lock operation in progress');
|
||||
} else {
|
||||
$lock = $lockDirectory->createFile(self::EXCLUSIVE_READ_LOCK_FILE);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!$lockDirectory->fileExists(self::READ_LOCK_FILE)){
|
||||
$accesscount = 0;
|
||||
} else {
|
||||
// get the existing lock file
|
||||
$lock = $lockDirectory->getFileObject(self::READ_LOCK_FILE, false);
|
||||
$accesscount = $lock->readBytes($lock->size());
|
||||
$lock->close();
|
||||
$lockDirectory->deleteFile(self::READ_LOCK_FILE);
|
||||
}
|
||||
|
||||
// raise the access counter
|
||||
$accesscount++;
|
||||
|
||||
// store the access counter
|
||||
$lock = $lockDirectory->createFile(self::READ_LOCK_FILE);
|
||||
$lock->writeBytes($accesscount);
|
||||
$lock->flush();
|
||||
$lock->close();
|
||||
}
|
||||
catch (Zend_Search_Lucene_Exception $e) {
|
||||
$lockDirectory->deleteFile(self::EXCLUSIVE_READ_LOCK_FILE);
|
||||
print_object($e);
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t obtain shared reading index lock');
|
||||
}
|
||||
|
||||
$lockDirectory->deleteFile(self::EXCLUSIVE_READ_LOCK_FILE);
|
||||
return $lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release shared read lock
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $lockDirectory
|
||||
*/
|
||||
public static function releaseReadLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
|
||||
{
|
||||
|
||||
// get exclusive operation lock on read lock file.
|
||||
if ($lockDirectory->fileExists(self::EXCLUSIVE_READ_LOCK_FILE)){
|
||||
throw new Zend_Search_Lucene_Exception('Can\'t obtain shared reading index lock : read lock operation in progress');
|
||||
} else {
|
||||
$lock = $lockDirectory->createFile(self::EXCLUSIVE_READ_LOCK_FILE);
|
||||
}
|
||||
|
||||
try {
|
||||
$lock = $lockDirectory->getFileObject(self::READ_LOCK_FILE, false);
|
||||
$accesscounter = $lock->readBytes($lock->size());
|
||||
$lock->close();
|
||||
|
||||
$accesscounter--;
|
||||
|
||||
$lockDirectory->deleteFile(self::READ_LOCK_FILE);
|
||||
|
||||
if ($accesscounter > 1){ // we have'nt released all locks. Create the file again.
|
||||
$lock = $lockDirectory->createFile(self::READ_LOCK_FILE);
|
||||
$lock->writeBytes($accesscount);
|
||||
$lock->flush();
|
||||
$lock->close();
|
||||
}
|
||||
}
|
||||
catch(Zend_Search_Lucene_Exception $e){
|
||||
$lockDirectory->deleteFile(self::EXCLUSIVE_READ_LOCK_FILE);
|
||||
// accept failover here
|
||||
// throw new Zend_Search_Lucene_Exception('Can\'t obtain shared reading index lock');
|
||||
}
|
||||
|
||||
$lockDirectory->deleteFile(self::EXCLUSIVE_READ_LOCK_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escalate Read lock to exclusive level
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $lockDirectory
|
||||
* @return boolean
|
||||
*/
|
||||
public static function escalateReadLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
|
||||
{
|
||||
// get exclusive operation lock on read lock file.
|
||||
if ($lockDirectory->fileExists(self::EXCLUSIVE_READ_LOCK_FILE)){
|
||||
return false;
|
||||
} else {
|
||||
$lock = $lockDirectory->createFile(self::EXCLUSIVE_READ_LOCK_FILE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* De-escalate Read lock to shared level
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $lockDirectory
|
||||
*/
|
||||
public static function deEscalateReadLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
|
||||
{
|
||||
$lockDirectory->deleteFile(self::EXCLUSIVE_READ_LOCK_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain exclusive optimization lock on the index
|
||||
*
|
||||
* Returns lock object on success and false otherwise (doesn't block execution)
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $lockDirectory
|
||||
* @return mixed
|
||||
*/
|
||||
public static function obtainOptimizationLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
|
||||
{
|
||||
if ($lockDirectory->fileExists(self::OPTIMIZATION_LOCK_FILE)){
|
||||
return false;
|
||||
}
|
||||
$lock = $lockDirectory->createFile(self::OPTIMIZATION_LOCK_FILE);
|
||||
return $lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release exclusive optimization lock
|
||||
*
|
||||
* @param Zend_Search_Lucene_Storage_Directory $lockDirectory
|
||||
*/
|
||||
public static function releaseOptimizationLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
|
||||
{
|
||||
$lockDirectory->deleteFile(self::OPTIMIZATION_LOCK_FILE);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Search_Lucene_Storage_Directory
|
||||
@@ -61,7 +61,16 @@ abstract class Zend_Search_Lucene_Storage_Directory
|
||||
*/
|
||||
abstract public function deleteFile($filename);
|
||||
|
||||
|
||||
/**
|
||||
* Purge file if it's cached by directory object
|
||||
*
|
||||
* Method is used to prevent 'too many open files' error
|
||||
*
|
||||
* @param string $filename
|
||||
* @return void
|
||||
*/
|
||||
abstract public function purgeFile($filename);
|
||||
|
||||
/**
|
||||
* Returns true if a file with the given $filename exists.
|
||||
*
|
||||
|
||||
@@ -15,16 +15,16 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Storage_Directory */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Storage/Directory.php';
|
||||
require_once 'Zend/Search/Lucene/Storage/Directory.php';
|
||||
|
||||
/** Zend_Search_Lucene_Storage_File_Filesystem */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Storage/File/Filesystem.php';
|
||||
require_once 'Zend/Search/Lucene/Storage/File/Filesystem.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -33,7 +33,7 @@ require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Storage/File/Filesystem.p
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Storage_Directory_Filesystem extends Zend_Search_Lucene_Storage_Directory
|
||||
@@ -43,7 +43,7 @@ class Zend_Search_Lucene_Storage_Directory_Filesystem extends Zend_Search_Lucene
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_dirPath = null;
|
||||
protected $_dirPath = null;
|
||||
|
||||
/**
|
||||
* Cache for Zend_Search_Lucene_Storage_File_Filesystem objects
|
||||
@@ -52,7 +52,35 @@ class Zend_Search_Lucene_Storage_Directory_Filesystem extends Zend_Search_Lucene
|
||||
* @var array
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
private $_fileHandlers;
|
||||
protected $_fileHandlers;
|
||||
|
||||
/**
|
||||
* Default file permissions
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected static $_defaultFilePermissions = 0666;
|
||||
|
||||
|
||||
/**
|
||||
* Get default file permissions
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public static function getDefaultFilePermissions()
|
||||
{
|
||||
return self::$_defaultFilePermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default file permissions
|
||||
*
|
||||
* @param integer $mode
|
||||
*/
|
||||
public static function setDefaultFilePermissions($mode)
|
||||
{
|
||||
self::$_defaultFilePermissions = $mode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -144,6 +172,7 @@ class Zend_Search_Lucene_Storage_Directory_Filesystem extends Zend_Search_Lucene
|
||||
*
|
||||
* @param string $filename
|
||||
* @return Zend_Search_Lucene_Storage_File
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
public function createFile($filename)
|
||||
{
|
||||
@@ -152,6 +181,16 @@ class Zend_Search_Lucene_Storage_Directory_Filesystem extends Zend_Search_Lucene
|
||||
}
|
||||
unset($this->_fileHandlers[$filename]);
|
||||
$this->_fileHandlers[$filename] = new Zend_Search_Lucene_Storage_File_Filesystem($this->_dirPath . '/' . $filename, 'w+b');
|
||||
|
||||
global $php_errormsg;
|
||||
$trackErrors = ini_get('track_errors');
|
||||
ini_set('track_errors', '1');
|
||||
if (!@chmod($this->_dirPath . '/' . $filename, self::$_defaultFilePermissions)) {
|
||||
ini_set('track_errors', $trackErrors);
|
||||
throw new Zend_Search_Lucene_Exception($php_errormsg);
|
||||
}
|
||||
ini_set('track_errors', $trackErrors);
|
||||
|
||||
return $this->_fileHandlers[$filename];
|
||||
}
|
||||
|
||||
@@ -161,22 +200,42 @@ class Zend_Search_Lucene_Storage_Directory_Filesystem extends Zend_Search_Lucene
|
||||
*
|
||||
* @param string $filename
|
||||
* @return void
|
||||
* @throws Zend_Search_Lucene_Exception
|
||||
*/
|
||||
public function deleteFile($filename)
|
||||
{
|
||||
/**
|
||||
* @todo add support of "deletable" file
|
||||
* "deletable" is used on Windows systems if file can't be deleted
|
||||
* (while it is still open).
|
||||
*/
|
||||
|
||||
if (isset($this->_fileHandlers[$filename])) {
|
||||
$this->_fileHandlers[$filename]->close();
|
||||
}
|
||||
unset($this->_fileHandlers[$filename]);
|
||||
unlink($this->_dirPath . '/' . $filename);
|
||||
|
||||
global $php_errormsg;
|
||||
$trackErrors = ini_get('track_errors'); ini_set('track_errors', '1');
|
||||
if (!@unlink($this->_dirPath . '/' . $filename)) {
|
||||
ini_set('track_errors', $trackErrors);
|
||||
|
||||
// keep loose on failed deletion.
|
||||
// throw new Zend_Search_Lucene_Exception('Can\'t delete file: ' . $php_errormsg);
|
||||
}
|
||||
ini_set('track_errors', $trackErrors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge file if it's cached by directory object
|
||||
*
|
||||
* Method is used to prevent 'too many open files' error
|
||||
*
|
||||
* @param string $filename
|
||||
* @return void
|
||||
*/
|
||||
public function purgeFile($filename)
|
||||
{
|
||||
if (isset($this->_fileHandlers[$filename])) {
|
||||
$this->_fileHandlers[$filename]->close();
|
||||
}
|
||||
unset($this->_fileHandlers[$filename]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if a file with the given $filename exists.
|
||||
|
||||
@@ -15,21 +15,21 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Search_Lucene_Storage_File
|
||||
|
||||
@@ -15,23 +15,23 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Storage_File */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Storage/File.php';
|
||||
require_once 'Zend/Search/Lucene/Storage/File.php';
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Storage_File_Filesystem extends Zend_Search_Lucene_Storage_File
|
||||
@@ -41,7 +41,8 @@ class Zend_Search_Lucene_Storage_File_Filesystem extends Zend_Search_Lucene_Stor
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
private $_fileHandle;
|
||||
protected $_fileHandle;
|
||||
|
||||
|
||||
/**
|
||||
* Class constructor. Open the file.
|
||||
@@ -53,6 +54,11 @@ class Zend_Search_Lucene_Storage_File_Filesystem extends Zend_Search_Lucene_Stor
|
||||
{
|
||||
global $php_errormsg;
|
||||
|
||||
if (strpos($mode, 'w') === false && !is_readable($filename)) {
|
||||
// opening for reading non-readable file
|
||||
throw new Zend_Search_Lucene_Exception('File \'' . $filename . '\' is not readable.');
|
||||
}
|
||||
|
||||
$trackErrors = ini_get('track_errors');
|
||||
ini_set('track_errors', '1');
|
||||
|
||||
@@ -185,12 +191,12 @@ class Zend_Search_Lucene_Storage_File_Filesystem extends Zend_Search_Lucene_Stor
|
||||
* Lock type may be a LOCK_SH (shared lock) or a LOCK_EX (exclusive lock)
|
||||
*
|
||||
* @param integer $lockType
|
||||
* @param boolean $nonBlockinLock
|
||||
* @param boolean $nonBlockingLock
|
||||
* @return boolean
|
||||
*/
|
||||
public function lock($lockType, $nonBlockinLock = false)
|
||||
public function lock($lockType, $nonBlockingLock = false)
|
||||
{
|
||||
if ($nonBlockinLock) {
|
||||
if ($nonBlockingLock) {
|
||||
return flock($this->_fileHandle, $lockType | LOCK_NB);
|
||||
} else {
|
||||
return flock($this->_fileHandle, $lockType);
|
||||
@@ -214,3 +220,4 @@ class Zend_Search_Lucene_Storage_File_Filesystem extends Zend_Search_Lucene_Stor
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -15,23 +15,23 @@
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/** Zend_Search_Lucene_Storage_File */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Storage/File.php';
|
||||
require_once 'Zend/Search/Lucene/Storage/File.php';
|
||||
|
||||
/** Zend_Search_Lucene_Exception */
|
||||
require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
|
||||
require_once 'Zend/Search/Lucene/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Search_Lucene
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Search_Lucene_Storage_File_Memory extends Zend_Search_Lucene_Storage_File
|
||||
|
||||
@@ -0,0 +1,362 @@
|
||||
<?php
|
||||
/**
|
||||
* Global Search Engine for Moodle
|
||||
*
|
||||
* @package search
|
||||
* @category core
|
||||
* @subpackage document_wrappers
|
||||
* @author Valery Fremaux [[email protected]] > 1.8
|
||||
* @date 2008/03/31
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*
|
||||
* document handling for assignment activity module
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* includes and requires
|
||||
*/
|
||||
require_once("$CFG->dirroot/search/documents/document.php");
|
||||
require_once("$CFG->dirroot/mod/assignment/lib.php");
|
||||
|
||||
/**
|
||||
* a class for representing searchable information
|
||||
*
|
||||
*/
|
||||
class AssignmentSearchDocument extends SearchDocument {
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*/
|
||||
public function __construct(&$assignmentitem, $assignment_module_id, $itemtype, $course_id, $owner_id, $context_id) {
|
||||
// generic information; required
|
||||
$doc->docid = $assignmentitem['id'];
|
||||
$doc->documenttype = SEARCH_TYPE_ASSIGNMENT;
|
||||
$doc->itemtype = $itemtype;
|
||||
$doc->contextid = $context_id;
|
||||
|
||||
// we cannot call userdate with relevant locale at indexing time.
|
||||
$doc->title = "{$itemtype}: {$assignmentitem['name']}";
|
||||
$doc->date = $assignmentitem['date'];
|
||||
|
||||
//remove '(ip.ip.ip.ip)' from chat author list
|
||||
$doc->author = $assignmentitem['authors'];
|
||||
$doc->contents = $assignmentitem['description'];
|
||||
$doc->url = assignment_make_link($assignment_module_id, $itemtype, $owner_id);
|
||||
|
||||
// module specific information; optional
|
||||
$data->assignment = $assignment_module_id;
|
||||
$data->assignmenttype = $assignmentitem['assignmenttype'];
|
||||
|
||||
// construct the parent class
|
||||
parent::__construct($doc, $data, $course_id, 0, 0, 'mod/'.SEARCH_TYPE_ASSIGNMENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* constructs a valid link to a chat content
|
||||
* @param cm_id the chat course module
|
||||
* @param start the start time of the session
|
||||
* @param end th end time of the session
|
||||
* @uses CFG
|
||||
* @return a well formed link to session display
|
||||
*/
|
||||
function assignment_make_link($cm_id, $itemtype, $owner) {
|
||||
global $CFG;
|
||||
|
||||
if ($itemtype == 'description')
|
||||
return $CFG->wwwroot.'/mod/assignment/view.php?id='.$cm_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* part of search engine API
|
||||
*
|
||||
*/
|
||||
function assignment_iterator() {
|
||||
if ($assignments = get_records('assignment'))
|
||||
return $assignments;
|
||||
else
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* part of search engine API
|
||||
*
|
||||
*/
|
||||
function assignment_get_content_for_index(&$assignment) {
|
||||
global $CFG;
|
||||
|
||||
$documents = array();
|
||||
$course = get_record('course', 'id', $assignment->course);
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'assignment');
|
||||
$cm = get_record('course_modules', 'course', $assignment->course, 'module', $coursemodule, 'instance', $assignment->id);
|
||||
if ($cm){
|
||||
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
|
||||
|
||||
$assignment->authors = '';
|
||||
$assignment->date = $assignment->timemodified;
|
||||
$documents[] = new AssignmentSearchDocument(get_object_vars($assignment), $cm->id, 'description', $assignment->course, null, $context->id);
|
||||
|
||||
$submissions = assignment_get_all_submissions($assignment);
|
||||
if ($submissions){
|
||||
foreach($submissions as $submission){
|
||||
$owner = get_record('user', 'id', $submission->userid);
|
||||
$submission->authors = fullname($owner);
|
||||
$submission->assignmenttype = $assignment->assignmenttype;
|
||||
$submission->date = $submission->timemodified;
|
||||
$submission->name = "submission:";
|
||||
if (file_exists("{$CFG->dirroot}/mod/assignment/type/{$assignment->assignmenttype}/searchlib.php")){
|
||||
include_once("{$CFG->dirroot}/mod/assignment/type/{$assignment->assignmenttype}/searchlib.php");
|
||||
if (function_exists('assignment_get_submission_location')){
|
||||
$submitted = assignment_get_submission_location($assignment, $submission);
|
||||
}
|
||||
}
|
||||
if (empty($submitted)){
|
||||
// this is for moodle legacy types that would need not to be patched for searchlib.php
|
||||
switch($assignment->assignmenttype){
|
||||
case 'online' : {
|
||||
$submitted->source = 'text';
|
||||
$submitted->data = $submission->data1;
|
||||
}
|
||||
break;
|
||||
case 'uploadsingle' :
|
||||
case 'upload' : {
|
||||
$submitted->source = 'files';
|
||||
$submitted->data = "{$assignment->course}/moddata/assignment/{$assignment->id}/{$submission->userid}";
|
||||
}
|
||||
break;
|
||||
case 'offline' : continue; // cannot index, no content in Moodle !!
|
||||
}
|
||||
}
|
||||
if (empty($submitted)) continue; // ignoring
|
||||
|
||||
if ($submitted->source = 'text'){
|
||||
$submission->description = $submitted->data;
|
||||
$submission->description = preg_replace("/<[^>]*>/", '', $submission->description); // stip all tags
|
||||
$documents[] = new AssignmentSearchDocument(get_object_vars($submission), $cm->id, 'submission', $assignment->course, $submission->userid, $context->id);
|
||||
mtrace("finished online submission for {$submission->authors} in assignement {$assignment->name}");
|
||||
} elseif ($submitted->source = 'files'){
|
||||
$SUBMITTED = opendir($submitted->path);
|
||||
while($entry = readdir($SUBMITTED)){
|
||||
if (ereg("^\.", $entry)) continue; // exclude hidden and dirs . and ..
|
||||
$path = "{$submitted->path}/{$entry}";
|
||||
$documents[] = assignment_get_physical_file($submission, $assignment, $cm, $path, $context_id, $documents);
|
||||
mtrace("finished attachement $path for {$submission->authors} in assignement {$assignment->name}");
|
||||
}
|
||||
closedir($submission->path);
|
||||
}
|
||||
}
|
||||
}
|
||||
mtrace("finished assignment {$assignment->name}");
|
||||
return $documents;
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* get text from a physical file in an assignment submission
|
||||
* @param object $submission a submission for which to fetch some representative text
|
||||
* @param object $assignment the relevant assignment as a context
|
||||
* @param object $cm the corresponding coursemodule
|
||||
* @param string $path a file from which to fetch some representative text
|
||||
* @param int $contextid the moodle context if needed
|
||||
* @param documents the array of documents, by ref, where to add the new document.
|
||||
* @return a search document when unique or false.
|
||||
*/
|
||||
function assignment_get_physical_file(&$submission, &$assignment, &$cm, $path, $context_id, &$documents = null){
|
||||
global $CFG;
|
||||
|
||||
$fileparts = pathinfo($path);
|
||||
// cannot index unknown or masked types
|
||||
if (empty($fileparts['extension'])) {
|
||||
mtrace("Cannot index without explicit extension.");
|
||||
return false;
|
||||
}
|
||||
|
||||
$ext = strtolower($fileparts['extension']);
|
||||
|
||||
// cannot index unallowed or unhandled types
|
||||
if (!preg_match("/\b$ext\b/i", $CFG->block_search_filetypes)) {
|
||||
mtrace($fileparts['extension'] . ' is not an allowed extension for indexing');
|
||||
return false;
|
||||
}
|
||||
if (file_exists($CFG->dirroot.'/search/documents/physical_'.$ext.'.php')){
|
||||
include_once($CFG->dirroot.'/search/documents/physical_'.$ext.'.php');
|
||||
$function_name = 'get_text_for_indexing_'.$ext;
|
||||
$submission->description = $function_name(null, $path);
|
||||
|
||||
// get authors
|
||||
$user = get_record('user', 'id', $submission->userid);
|
||||
$submission->authors = fullname($user);
|
||||
|
||||
// we need a real id on file
|
||||
$submission->id = "{$submission->id}/{$path}";
|
||||
|
||||
if (!empty($submission->description)){
|
||||
if ($getsingle){
|
||||
$single = new AssignmentSearchDocument(get_object_vars($submission), $cm->id, 'submitted', $assignment->course, $submission->userid, $context_id);
|
||||
mtrace("finished submission file from {$submission->authors}");
|
||||
return $single;
|
||||
} else {
|
||||
$documents[] = new AssignmentSearchDocument(get_object_vars($submission), $cm->id, 'submitted', $assignment->course, $submission->userid, $context_id);
|
||||
}
|
||||
mtrace("finished submission file from {$submission->authors}");
|
||||
}
|
||||
} else {
|
||||
mtrace("fulltext handler not found for $ext type");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a single data search document based on an assignment
|
||||
* @param string $id the id of the searchable item
|
||||
* @param string $itemtype the type of information
|
||||
*/
|
||||
function assignment_single_document($id, $itemtype) {
|
||||
if ($itemtype == 'requirement'){
|
||||
if (!$assignment = get_record('assignment', 'id', $id)){
|
||||
return null;
|
||||
}
|
||||
} elseif ($itemtype == 'submission') {
|
||||
if ($submission = get_record('assignment_submissions', 'id', $id)){
|
||||
$assignment = get_record('assignment', 'id', $submission->assignment);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
$course = get_record('course', 'id', $assignment->course);
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'assignment');
|
||||
$cm = get_record('course_modules', 'course', $course->id, 'module', $coursemodule, 'instance', $assignment->id);
|
||||
if ($cm){
|
||||
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
|
||||
|
||||
// should be only one
|
||||
if ($itemtype == 'description'){
|
||||
$document = new AssignmentSearchDocument(get_object_vars($assignment), $cm->id, 'description', $assignment->course, null, $context->id);
|
||||
return $document;
|
||||
}
|
||||
if ($itemtype == 'submittted'){
|
||||
$document = new AssignmentSearchDocument(get_object_vars($submission), $cm->id, 'submitted', $assignment->course, null, $context->id);
|
||||
return $document;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* dummy delete function that packs id with itemtype.
|
||||
* this was here for a reason, but I can't remember it at the moment.
|
||||
*
|
||||
*/
|
||||
function assignment_delete($info, $itemtype) {
|
||||
$object->id = $info;
|
||||
$object->itemtype = $itemtype;
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the var names needed to build a sql query for addition/deletions
|
||||
* // TODO chat indexable records are virtual. Should proceed in a special way
|
||||
*/
|
||||
function assignment_db_names() {
|
||||
//[primary id], [table name], [time created field name], [time modified field name]
|
||||
return array(
|
||||
array('id', 'assignment', 'timemodified', 'timemodified', 'description'),
|
||||
array('id', 'assignment_submissions', 'timecreated', 'timemodified', 'submitted')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* this function handles the access policy to contents indexed as searchable documents. If this
|
||||
* function does not exist, the search engine assumes access is allowed.
|
||||
* When this point is reached, we already know that :
|
||||
* - user is legitimate in the surrounding context
|
||||
* - user may be guest and guest access is allowed to the module
|
||||
* - the function may perform local checks within the module information logic
|
||||
* @param path the access path to the module script code
|
||||
* @param itemtype the information subclassing (usefull for complex modules, defaults to 'standard')
|
||||
* @param this_id the item id within the information class denoted by entry_type. In chats, this id
|
||||
* points out a session history which is a close sequence of messages.
|
||||
* @param user the user record denoting the user who searches
|
||||
* @param group_id the current group used by the user when searching
|
||||
* @uses CFG
|
||||
* @return true if access is allowed, false elsewhere
|
||||
*/
|
||||
function assignment_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){
|
||||
global $CFG, $USER;
|
||||
|
||||
include_once("{$CFG->dirroot}/{$path}/lib.php");
|
||||
|
||||
// get the chat session and all related stuff
|
||||
if ($itemtype == 'description'){
|
||||
$assignment = get_record('assignment', 'id', $this_id);
|
||||
} elseif ($itemtype == 'submitted'){
|
||||
$submission = get_record('assignment_submissions', 'id', $this_id);
|
||||
$assignment = get_record('assignment', 'id', $submission->assignment);
|
||||
}
|
||||
$context = get_record('context', 'id', $context_id);
|
||||
$cm = get_record('course_modules', 'id', $context->instanceid);
|
||||
|
||||
if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $context)){
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : hidden assignment ";
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
group consistency check : checks the following situations about groups
|
||||
// trap if user is not same group and groups are separated
|
||||
$current_group = get_current_group($course->id);
|
||||
$course = get_record('course', 'id', $assignment->course);
|
||||
if ((groupmode($course, $cm) == SEPARATEGROUPS) && !ismember($group_id) && !has_capability('moodle/site:accessallgroups', $context)){
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : assignment element is in separated group ";
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
//user ownership check :
|
||||
// trap if user is not owner of the resource and the ressource is a submission/attachement
|
||||
if ($itemtype == 'submitted' && $USER->id != $submission->userid && !has_capability('mod/assignment:view', $context)){
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : i'm not owner of this assignment ";
|
||||
return false;
|
||||
}
|
||||
|
||||
//date check : no submission may be viewed before timedue
|
||||
if ($itemtype == 'submitted' && $assignment->timedue < time()){
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : cannot read submissions before end of assignment ";
|
||||
return false;
|
||||
}
|
||||
|
||||
//ownership check : checks the following situations about user
|
||||
// trap if user is not owner and cannot see other's entries
|
||||
// TODO : typically may be stored into indexing cache
|
||||
if (!has_capability('mod/assignment:view', $context)){
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : cannot read past sessions ";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* this call back is called when displaying the link for some last post processing
|
||||
*
|
||||
*/
|
||||
function assignment_link_post_processing($title){
|
||||
global $CFG;
|
||||
|
||||
if (!function_exists('search_assignment_getstring')){
|
||||
function search_assignment_getstring($matches){
|
||||
return get_string($matches[1], 'assignment');
|
||||
}
|
||||
}
|
||||
|
||||
$title = preg_replace_callback('/^(description|submitted)/', 'search_assignment_getstring', $title);
|
||||
|
||||
if ($CFG->block_search_utf8dir){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
}
|
||||
return mb_convert_encoding($title, 'auto', 'UTF-8');
|
||||
}
|
||||
?>
|
||||
@@ -32,9 +32,9 @@ class ChatTrackSearchDocument extends SearchDocument {
|
||||
/**
|
||||
* constructor
|
||||
*/
|
||||
public function __construct(&$chatsession, $chat_module_id, $course_id, $group_id, $context_id) {
|
||||
public function __construct(&$chatsession, $chat_id, $chat_module_id, $course_id, $group_id, $context_id) {
|
||||
// generic information; required
|
||||
$doc->docid = $chat_module_id.'-'.$chatsession['sessionstart'].'-'.$chatsession['sessionend'];
|
||||
$doc->docid = $chat_id.'-'.$chatsession['sessionstart'].'-'.$chatsession['sessionend'];
|
||||
$doc->documenttype = SEARCH_TYPE_CHAT;
|
||||
$doc->itemtype = 'session';
|
||||
$doc->contextid = $context_id;
|
||||
@@ -50,10 +50,10 @@ class ChatTrackSearchDocument extends SearchDocument {
|
||||
$doc->url = chat_make_link($chat_module_id, $chatsession['sessionstart'], $chatsession['sessionend']);
|
||||
|
||||
// module specific information; optional
|
||||
$data->chat = $chat_module_id;
|
||||
$data->chat = $chat_id;
|
||||
|
||||
// construct the parent class
|
||||
parent::__construct($doc, $data, $course_id, $group_id, 0, PATH_FOR_SEARCH_TYPE_CHAT);
|
||||
parent::__construct($doc, $data, $course_id, $group_id, 0, 'mod/'.SEARCH_TYPE_CHAT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ function chat_get_content_for_index(&$chat) {
|
||||
foreach($aTrack->sessionusers as $aUserId){
|
||||
$user = get_record('user', 'id', $aUserId);
|
||||
$aTrack->authors = ($user) ? fullname($user) : '' ;
|
||||
$documents[] = new ChatTrackSearchDocument(get_object_vars($aTrack), $cm->id, $chat->course, $aTrack->groupid, $context->id);
|
||||
$documents[] = new ChatTrackSearchDocument(get_object_vars($aTrack), $chat->id, $cm->id, $chat->course, $aTrack->groupid, $context->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,7 +207,7 @@ function chat_single_document($id, $itemtype) {
|
||||
$tracks = chat_get_session_tracks($chat->id, $sessionstart, $sessionstart);
|
||||
if ($tracks){
|
||||
$aTrack = $tracks[0];
|
||||
$document = new ChatTrackSearchDocument(get_object_vars($aTrack), $cm->id, $chat->course, $aTrack->groupid, $context->id);
|
||||
$document = new ChatTrackSearchDocument(get_object_vars($aTrack), $chat_id, $cm->id, $chat->course, $aTrack->groupid, $context->id);
|
||||
return $document;
|
||||
}
|
||||
}
|
||||
@@ -255,8 +255,7 @@ function chat_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c
|
||||
|
||||
include_once("{$CFG->dirroot}/{$path}/lib.php");
|
||||
|
||||
list($chat_id, $sessionstart, $sessionend) = split('-', $id);
|
||||
|
||||
list($chat_id, $sessionstart, $sessionend) = split('-', $this_id);
|
||||
// get the chat session and all related stuff
|
||||
$chat = get_record('chat', 'id', $chat_id);
|
||||
$context = get_record('context', 'id', $context_id);
|
||||
@@ -271,7 +270,6 @@ function chat_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c
|
||||
|
||||
//group consistency check : checks the following situations about groups
|
||||
// trap if user is not same group and groups are separated
|
||||
$current_group = get_current_group($course->id);
|
||||
$course = get_record('course', 'id', $chat->course);
|
||||
if ((groupmode($course, $cm) == SEPARATEGROUPS) && !ismember($group_id) && !has_capability('moodle/site:accessallgroups', $context)){
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : chat element is in separated group ";
|
||||
@@ -294,8 +292,13 @@ function chat_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c
|
||||
*
|
||||
*/
|
||||
function chat_link_post_processing($title){
|
||||
setLocale(LC_TIME, substr(current_language(), 0, 2));
|
||||
$title = preg_replace('/TT_(.*)_TT/e', "userdate(\\1)", $title);
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
global $CFG;
|
||||
setLocale(LC_TIME, substr(current_language(), 0, 2));
|
||||
$title = preg_replace('/TT_(.*)_TT/e', "userdate(\\1)", $title);
|
||||
|
||||
if ($CFG->block_search_utf8dir){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
}
|
||||
return mb_convert_encoding($title, 'auto', 'UTF-8');
|
||||
}
|
||||
?>
|
||||
@@ -54,7 +54,7 @@ class DataSearchDocument extends SearchDocument {
|
||||
$data->database = $record['dataid'];
|
||||
|
||||
// construct the parent class
|
||||
parent::__construct($doc, $data, $course_id, $record['groupid'], $record['userid'], PATH_FOR_SEARCH_TYPE_DATA);
|
||||
parent::__construct($doc, $data, $course_id, $record['groupid'], $record['userid'], 'mod/'.SEARCH_TYPE_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +203,7 @@ function data_get_content_for_index(&$database) {
|
||||
unset($records_content[$aRecordId]['_first']);
|
||||
|
||||
// concatenates all other texts
|
||||
$content = '';
|
||||
foreach($records_content[$aRecordId] as $aField){
|
||||
$content = @$content.' '.$aField;
|
||||
}
|
||||
@@ -348,7 +349,6 @@ function data_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c
|
||||
|
||||
//group consistency check : checks the following situations about groups
|
||||
// trap if user is not same group and groups are separated
|
||||
$current_group = get_current_group($course->id);
|
||||
$course = get_record('course', 'id', $data->course);
|
||||
if ((groupmode($course, $cm) == SEPARATEGROUPS) && !ismember($group_id) && !has_capability('moodle/site:accessallgroups', $context)){
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : separated group owned resource ";
|
||||
@@ -368,7 +368,7 @@ function data_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c
|
||||
// trap if unapproved and has not approval capabilities
|
||||
// TODO : report a potential capability lack of : mod/data:approve
|
||||
$approval = get_field('data_records', 'approved', 'id', $record->id);
|
||||
if (!$approval && !isteacher($data->course) && !has_capability('mod/data:manageentries', $context)){
|
||||
if (!$approval && !has_capability('mod/data:manageentries', $context)){
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : unapproved resource ";
|
||||
return false;
|
||||
}
|
||||
@@ -377,7 +377,7 @@ function data_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c
|
||||
// trap if too few records
|
||||
// TODO : report a potential capability lack of : mod/data:viewhiddenentries
|
||||
$recordsAmount = count_records('data_records', 'dataid', $data->id);
|
||||
if ($data->requiredentriestoview > $recordsAmount && !isteacher($data->course) && !has_capability('mod/data:manageentries', $context)) {
|
||||
if ($data->requiredentriestoview > $recordsAmount && !has_capability('mod/data:manageentries', $context)) {
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : not enough records to view ";
|
||||
return false;
|
||||
}
|
||||
@@ -387,12 +387,12 @@ function data_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c
|
||||
// TODO : report a potential capability lack of : mod/data:viewhiddenentries
|
||||
$now = usertime(time());
|
||||
if ($data->timeviewfrom > 0)
|
||||
if ($now < $data->timeviewfrom && !isteacher($data->course) && !has_capability('mod/data:manageentries', $context)) {
|
||||
if ($now < $data->timeviewfrom && !has_capability('mod/data:manageentries', $context)) {
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : still not open activity ";
|
||||
return false;
|
||||
}
|
||||
if ($data->timeviewto > 0)
|
||||
if ($now > $data->timeviewto && !isteacher($data->course) && !has_capability('mod/data:manageentries', $context)) {
|
||||
if ($now > $data->timeviewto && !has_capability('mod/data:manageentries', $context)) {
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : closed activity ";
|
||||
return false;
|
||||
}
|
||||
@@ -405,7 +405,12 @@ function data_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c
|
||||
* @param string $title
|
||||
*/
|
||||
function data_link_post_processing($title){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
global $CFG;
|
||||
|
||||
if ($CFG->block_search_utf8dir){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
}
|
||||
return mb_convert_encoding($title, 'auto', 'UTF-8');
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -17,7 +17,7 @@
|
||||
*
|
||||
*/
|
||||
abstract class SearchDocument extends Zend_Search_Lucene_Document {
|
||||
public function __construct(&$doc, &$data, $course_id, $group_id, $user_id, $path) {
|
||||
public function __construct(&$doc, &$data, $course_id, $group_id, $user_id, $path, $additional_keyset = null) {
|
||||
//document identification and indexing
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('docid', $doc->docid));
|
||||
//document type : the name of the Moodle element that manages it
|
||||
@@ -59,6 +59,16 @@ abstract class SearchDocument extends Zend_Search_Lucene_Document {
|
||||
// of multiple capabilities in their code. This possibility should be left open here.
|
||||
$this->addField(Zend_Search_Lucene_Field::UnIndexed('capabilities', $caps));
|
||||
*/
|
||||
|
||||
/*
|
||||
// Additional key set allows a module to ask for extensible criteria based search
|
||||
// depending on the module internal needs.
|
||||
*/
|
||||
if (!empty($additional_keyset)){
|
||||
foreach($additional_keyset as $keyname => $keyvalue){
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword($keyname, $keyvalue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class ForumSearchDocument extends SearchDocument {
|
||||
$data->forum = $forum_id;
|
||||
$data->discussion = $post['discussion'];
|
||||
|
||||
parent::__construct($doc, $data, $course_id, $post['groupid'], $post['userid'], PATH_FOR_SEARCH_TYPE_FORUM);
|
||||
parent::__construct($doc, $data, $course_id, $post['groupid'], $post['userid'], 'mod/'.SEARCH_TYPE_FORUM);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ function forum_get_content_for_index(&$forum) {
|
||||
if (!$forum) return $documents;
|
||||
|
||||
$posts = forum_get_discussions_fast($forum->id);
|
||||
mtrace("Found ".count($posts)." discussions to analyse in forum ".$forum->name);
|
||||
if (!$posts) return $documents;
|
||||
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'forum');
|
||||
@@ -96,11 +97,13 @@ function forum_get_content_for_index(&$forum) {
|
||||
foreach($posts as $aPost) {
|
||||
$aPost->itemtype = 'head';
|
||||
if ($aPost) {
|
||||
if (strlen($aPost->message) > 0) {
|
||||
if (!empty($aPost->message)) {
|
||||
echo "*";
|
||||
$documents[] = new ForumSearchDocument(get_object_vars($aPost), $forum->id, $forum->course, 'head', $context->id);
|
||||
}
|
||||
if ($children = forum_get_child_posts_fast($aPost->id, $forum->id)) {
|
||||
foreach($children as $aChild) {
|
||||
echo ".";
|
||||
$aChild->itemtype = 'post';
|
||||
if (strlen($aChild->message) > 0) {
|
||||
$documents[] = new ForumSearchDocument(get_object_vars($aChild), $forum->id, $forum->course, 'post', $context->id);
|
||||
@@ -109,6 +112,7 @@ function forum_get_content_for_index(&$forum) {
|
||||
}
|
||||
}
|
||||
}
|
||||
mtrace("Finished discussion");
|
||||
return $documents;
|
||||
}
|
||||
|
||||
@@ -166,7 +170,8 @@ function forum_get_discussions_fast($forum_id) {
|
||||
|
||||
$timelimit='';
|
||||
if (!empty($CFG->forum_enabletimedposts)) {
|
||||
if (!((isadmin() and !empty($CFG->admineditalways)) || isteacher(get_field('forum', 'course', 'id', $forum_id)))) {
|
||||
if (!((has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))
|
||||
and !empty($CFG->admineditalways)) || isteacher(get_field('forum', 'course', 'id', $forum_id)))) {
|
||||
$now = time();
|
||||
$timelimit = " AND ((d.timestart = 0 OR d.timestart <= '$now') AND (d.timeend = 0 OR d.timeend > '$now')";
|
||||
if (!empty($USER->id)) {
|
||||
@@ -302,7 +307,12 @@ function forum_check_text_access($path, $itemtype, $this_id, $user, $group_id, $
|
||||
* @param string $title
|
||||
*/
|
||||
function forum_link_post_processing($title){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
global $CFG;
|
||||
|
||||
if ($CFG->block_search_utf8dir){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
}
|
||||
return mb_convert_encoding($title, 'auto', 'UTF-8');
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -52,7 +52,7 @@ class GlossarySearchDocument extends SearchDocument {
|
||||
$data->glossary = $entry['glossaryid'];
|
||||
|
||||
// construct the parent class
|
||||
parent::__construct($doc, $data, $course_id, -1, $entry['userid'], PATH_FOR_SEARCH_TYPE_GLOSSARY);
|
||||
parent::__construct($doc, $data, $course_id, -1, $entry['userid'], 'mod/'.SEARCH_TYPE_GLOSSARY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@ function glossary_iterator() {
|
||||
* @return an array of searchable documents
|
||||
*/
|
||||
function glossary_get_content_for_index(&$glossary) {
|
||||
// global $DB;
|
||||
|
||||
// get context
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'glossary');
|
||||
@@ -144,8 +145,7 @@ function glossary_get_content_for_index(&$glossary) {
|
||||
|
||||
// index comments
|
||||
if (count($entryIds)){
|
||||
$entryIdList = implode(',', $entryIds);
|
||||
$comments = get_records_list('glossary_comments', 'entryid', $entryIdList);
|
||||
$comments = get_records_list('glossary_comments', 'entryid', implode(',',$entryIds));
|
||||
if ($comments){
|
||||
foreach($comments as $comment) {
|
||||
if (strlen($comment->entrycomment) > 0) {
|
||||
@@ -227,7 +227,7 @@ function glossary_check_text_access($path, $itemtype, $this_id, $user, $group_id
|
||||
global $CFG;
|
||||
|
||||
// get the glossary object and all related stuff
|
||||
$entry = get_record('glossary_entries', 'id', $id);
|
||||
$entry = get_record('glossary_entries', 'id', $this_id);
|
||||
$glossary = get_record('glossary', 'id', $entry->glossaryid);
|
||||
$context = get_record('context', 'id', $context_id);
|
||||
$cm = get_record('course_modules', 'id', $context->instanceid);
|
||||
@@ -251,7 +251,12 @@ function glossary_check_text_access($path, $itemtype, $this_id, $user, $group_id
|
||||
* @param string $title
|
||||
*/
|
||||
function glossary_link_post_processing($title){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
global $CFG;
|
||||
|
||||
if ($CFG->block_search_utf8dir){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
}
|
||||
return mb_convert_encoding($title, 'auto', 'UTF-8');
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
/**
|
||||
* Global Search Engine for Moodle
|
||||
*
|
||||
* @package search
|
||||
* @category core
|
||||
* @subpackage document_wrappers
|
||||
* @author Valery Fremaux [[email protected]] > 1.9
|
||||
* @date 2008/03/31
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*
|
||||
* document handling for all resources
|
||||
* This file contains the mapping between a resource and it's indexable counterpart,
|
||||
*
|
||||
* Functions for iterating and retrieving the necessary records are now also included
|
||||
* in this file, rather than mod/resource/lib.php
|
||||
*/
|
||||
|
||||
/**
|
||||
* requires and includes
|
||||
*/
|
||||
require_once("$CFG->dirroot/search/documents/document.php");
|
||||
require_once("$CFG->dirroot/mod/resource/lib.php");
|
||||
|
||||
/* *
|
||||
* a class for representing searchable information
|
||||
*
|
||||
*/
|
||||
class LabelSearchDocument extends SearchDocument {
|
||||
public function __construct(&$label, $context_id) {
|
||||
// generic information; required
|
||||
$doc->docid = $label['course'];
|
||||
$doc->documenttype = SEARCH_TYPE_LABEL;
|
||||
$doc->itemtype = 'label';
|
||||
$doc->contextid = $context_id;
|
||||
|
||||
$doc->title = strip_tags($label['name']);
|
||||
$doc->date = $label['timemodified'];
|
||||
$doc->author = '';
|
||||
$doc->contents = strip_tags($label['name']);
|
||||
$doc->url = label_make_link($label['course']);
|
||||
|
||||
// module specific information; optional
|
||||
$data = array();
|
||||
|
||||
// construct the parent class
|
||||
parent::__construct($doc, $data, $label['course'], 0, 0, 'mod/'.SEARCH_TYPE_LABEL);
|
||||
} //constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* constructs valid access links to information
|
||||
* @param resourceId the of the resource
|
||||
* @return a full featured link element as a string
|
||||
*/
|
||||
function label_make_link($course_id) {
|
||||
global $CFG;
|
||||
|
||||
return $CFG->wwwroot.'/course/view.php?id='.$course_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* part of standard API
|
||||
*
|
||||
*/
|
||||
function label_iterator() {
|
||||
//trick to leave search indexer functionality intact, but allow
|
||||
//this document to only use the below function to return info
|
||||
//to be searched
|
||||
$labels = get_records('label');
|
||||
return $labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* part of standard API
|
||||
* this function does not need a content iterator, returns all the info
|
||||
* itself;
|
||||
* @param notneeded to comply API, remember to fake the iterator array though
|
||||
* @uses CFG
|
||||
* @return an array of searchable documents
|
||||
*/
|
||||
function label_get_content_for_index(&$label) {
|
||||
global $CFG;
|
||||
|
||||
// starting with Moodle native resources
|
||||
$documents = array();
|
||||
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'label');
|
||||
$cm = get_record('course_modules', 'course', $label->course, 'module', $coursemodule, 'instance', $label->id);
|
||||
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
|
||||
|
||||
$documents[] = new LabelSearchDocument(get_object_vars($label), $context->id);
|
||||
|
||||
mtrace("finished label {$label->id}");
|
||||
return $documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* part of standard API.
|
||||
* returns a single resource search document based on a label id
|
||||
* @param id the id of the accessible document
|
||||
* @return a searchable object or null if failure
|
||||
*/
|
||||
function label_single_document($id, $itemtype) {
|
||||
global $CFG;
|
||||
|
||||
$label = get_record('label', 'id', $id);
|
||||
|
||||
if ($label){
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'label');
|
||||
$cm = get_record('course_modules', 'id', $label->id);
|
||||
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
|
||||
return new LabelSearchDocument(get_object_vars($label), $context->id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* dummy delete function that aggregates id with itemtype.
|
||||
* this was here for a reason, but I can't remember it at the moment.
|
||||
*
|
||||
*/
|
||||
function label_delete($info, $itemtype) {
|
||||
$object->id = $info;
|
||||
$object->itemtype = $itemtype;
|
||||
return $object;
|
||||
} //resource_delete
|
||||
|
||||
/**
|
||||
* returns the var names needed to build a sql query for addition/deletions
|
||||
*
|
||||
*/
|
||||
function label_db_names() {
|
||||
//[primary id], [table name], [time created field name], [time modified field name], [docsubtype], [additional where conditions for sql]
|
||||
return array(array('id', 'label', 'timemodified', 'timemodified', 'label', ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* this function handles the access policy to contents indexed as searchable documents. If this
|
||||
* function does not exist, the search engine assumes access is allowed.
|
||||
* @param path the access path to the module script code
|
||||
* @param itemtype the information subclassing (usefull for complex modules, defaults to 'standard')
|
||||
* @param this_id the item id within the information class denoted by itemtype. In resources, this id
|
||||
* points to the resource record and not to the module that shows it.
|
||||
* @param user the user record denoting the user who searches
|
||||
* @param group_id the current group used by the user when searching
|
||||
* @return true if access is allowed, false elsewhere
|
||||
*/
|
||||
function label_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){
|
||||
global $CFG;
|
||||
|
||||
// include_once("{$CFG->dirroot}/{$path}/lib.php");
|
||||
|
||||
$r = get_record('label', 'id', $this_id);
|
||||
$module_context = get_record('context', 'id', $context_id);
|
||||
$cm = get_record('course_modules', 'id', $module_context->instanceid);
|
||||
$course_context = get_context_instance(COURSE_CONTEXT, $r->course);
|
||||
|
||||
//check if englobing course is visible
|
||||
if (!has_capability('moodle/course:view', $course_context)){
|
||||
return false;
|
||||
}
|
||||
|
||||
//check if found course module is visible
|
||||
if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $module_context)){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* post processes the url for cleaner output.
|
||||
* @param string $title
|
||||
*/
|
||||
function label_link_post_processing($title){
|
||||
global $CFG;
|
||||
|
||||
if ($CFG->block_search_utf8dir){
|
||||
return mb_convert_encoding("(".shorten_text(clean_text($title), 60)."...) ", 'UTF-8', 'auto');
|
||||
}
|
||||
return mb_convert_encoding("(".shorten_text(clean_text($title), 60)."...) ", 'auto', 'UTF-8');
|
||||
}
|
||||
?>
|
||||
@@ -49,7 +49,7 @@ class LessonPageSearchDocument extends SearchDocument {
|
||||
// module specific information
|
||||
$data->lesson = $page['lessonid'];
|
||||
|
||||
parent::__construct($doc, $data, $course_id, 0, 0, PATH_FOR_SEARCH_TYPE_LESSON);
|
||||
parent::__construct($doc, $data, $course_id, 0, 0, 'mod/'.SEARCH_TYPE_LESSON);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +73,11 @@ function lesson_make_link($lessonmoduleid, $itemid, $itemtype) {
|
||||
*
|
||||
*/
|
||||
function lesson_iterator() {
|
||||
$lessons = get_records('lesson');
|
||||
return $lessons;
|
||||
if ($lessons = get_records('lesson')){
|
||||
return $lessons;
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,7 +213,12 @@ function lesson_check_text_access($path, $itemtype, $this_id, $user, $group_id,
|
||||
*
|
||||
*/
|
||||
function lesson_link_post_processing($title){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
global $CFG;
|
||||
|
||||
if ($CFG->block_search_utf8dir){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
}
|
||||
return mb_convert_encoding($title, 'auto', 'UTF-8');
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -16,13 +16,13 @@
|
||||
/**
|
||||
* MS Word extractor
|
||||
* @param object $resource
|
||||
* @uses CFG, USER
|
||||
* @uses $CFG
|
||||
*/
|
||||
function get_text_for_indexing_doc(&$resource){
|
||||
global $CFG, $USER;
|
||||
function get_text_for_indexing_doc(&$resource, $directfile = ''){
|
||||
global $CFG;
|
||||
|
||||
// SECURITY : do not allow non admin execute anything on system !!
|
||||
if (!isadmin($USER->id)) return;
|
||||
if (!has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))) return;
|
||||
|
||||
$moodleroot = (@$CFG->block_search_usemoodleroot) ? "{$CFG->dirroot}/" : '' ;
|
||||
|
||||
@@ -30,26 +30,27 @@ function get_text_for_indexing_doc(&$resource){
|
||||
if (!empty($CFG->block_search_word_to_text_cmd)){
|
||||
if (!file_exists("{$moodleroot}{$CFG->block_search_word_to_text_cmd}")){
|
||||
mtrace('Error with MSWord to text converter command : exectuable not found.');
|
||||
}
|
||||
else{
|
||||
$file = escapeshellarg($CFG->dataroot.'/'.$resource->course.'/'.$resource->reference);
|
||||
} else {
|
||||
if ($directfile == ''){
|
||||
$file = escapeshellarg("{$CFG->dataroot}/{$resource->course}/{$resource->reference}");
|
||||
} else {
|
||||
$file = escapeshellarg("{$CFG->dataroot}/{$directfile}");
|
||||
}
|
||||
$command = trim($CFG->block_search_word_to_text_cmd);
|
||||
$text_converter_cmd = "{$moodleroot}{$command} $file";
|
||||
$text_converter_cmd = "{$moodleroot}{$command} -m UTF-8.txt $file";
|
||||
if ($CFG->block_search_word_to_text_env){
|
||||
putenv($CFG->block_search_word_to_text_env);
|
||||
}
|
||||
mtrace("Executing : $text_converter_cmd");
|
||||
$result = shell_exec($text_converter_cmd);
|
||||
if ($result){
|
||||
return mb_convert_encoding($result, 'UTF8', 'auto');
|
||||
}
|
||||
else{
|
||||
return mb_convert_encoding($result, 'UTF-8', 'auto');
|
||||
} else {
|
||||
mtrace('Error with MSWord to text converter command : execution failed. ');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
mtrace('Error with MSWord to text converter command : command not set up. Execute once search block configuration.');
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -15,16 +15,20 @@
|
||||
|
||||
/**
|
||||
* @param object $resource
|
||||
* @uses CFG, USER
|
||||
* @uses $CFG
|
||||
*/
|
||||
function get_text_for_indexing_htm(&$resource){
|
||||
global $CFG, $USER;
|
||||
function get_text_for_indexing_htm(&$resource, $directfile = ''){
|
||||
global $CFG;
|
||||
|
||||
// SECURITY : do not allow non admin execute anything on system !!
|
||||
if (!isadmin($USER->id)) return;
|
||||
if (!has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))) return;
|
||||
|
||||
// just get text
|
||||
$text = implode('', file("{$CFG->dataroot}/{$resource->course}/{$resource->reference}"));
|
||||
if ($directfile == ''){
|
||||
$text = implode('', file("{$CFG->dataroot}/{$resource->course}/{$resource->reference}"));
|
||||
} else {
|
||||
$text = implode('', file("{$CFG->dataroot}/{$directfile}"));
|
||||
}
|
||||
|
||||
// extract keywords and other interesting meta information and put it back as real content for indexing
|
||||
if (preg_match('/(.*)<meta ([^>]*)>(.*)/is', $text, $matches)){
|
||||
@@ -40,7 +44,7 @@ function get_text_for_indexing_htm(&$resource){
|
||||
$text = preg_replace("/<[^>]*>/", '', $text);
|
||||
$text = preg_replace("/<!--[^>]*-->/", '', $text);
|
||||
$text = html_entity_decode($text, ENT_COMPAT, 'UTF-8');
|
||||
$text = mb_convert_encoding($text, 'UTF-8', 'AUTO');
|
||||
$text = mb_convert_encoding($text, 'UTF-8', 'auto');
|
||||
|
||||
/*
|
||||
* debug code for tracing input
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
/**
|
||||
* @param object $resource
|
||||
*/
|
||||
function get_text_for_indexing_html(&$resource){
|
||||
function get_text_for_indexing_html(&$resource, $directfile = ''){
|
||||
|
||||
// wraps to htm handler
|
||||
include_once 'physical_htm.php';
|
||||
return get_text_for_indexing_htm($resource);
|
||||
return get_text_for_indexing_htm($resource, $directfile);
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* Global Search Engine for Moodle
|
||||
*
|
||||
* @package search
|
||||
* @category core
|
||||
* @subpackage document_wrappers
|
||||
* @author Valery Fremaux [[email protected]] > 1.8
|
||||
* @date 2008/03/31
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*
|
||||
* this is a format handler for getting text out of the opensource ODT binary format
|
||||
* so it can be indexed by Lucene search engine
|
||||
*/
|
||||
|
||||
/**
|
||||
* OpenOffice Odt extractor
|
||||
* @param object $resource
|
||||
* @uses $CFG
|
||||
*/
|
||||
function get_text_for_indexing_odt(&$resource, $directfile = ''){
|
||||
global $CFG;
|
||||
|
||||
// SECURITY : do not allow non admin execute anything on system !!
|
||||
if (!has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))) return;
|
||||
|
||||
$moodleroot = (@$CFG->block_search_usemoodleroot) ? "{$CFG->dirroot}/" : '' ;
|
||||
|
||||
// just call pdftotext over stdout and capture the output
|
||||
if (!empty($CFG->block_search_odt_to_text_cmd)){
|
||||
if (!file_exists("{$moodleroot}{$CFG->block_search_odt_to_text_cmd}")){
|
||||
mtrace('Error with OpenOffice ODT to text converter command : exectuable not found.');
|
||||
} else {
|
||||
if ($directfile == ''){
|
||||
$file = escapeshellarg("{$CFG->dataroot}/{$resource->course}/{$resource->reference}");
|
||||
} else {
|
||||
$file = escapeshellarg("{$CFG->dataroot}/{$directfile}");
|
||||
}
|
||||
$command = trim($CFG->block_search_odt_to_text_cmd);
|
||||
$text_converter_cmd = "{$moodleroot}{$command} --encoding=UTF-8 $file";
|
||||
mtrace("Executing : $text_converter_cmd");
|
||||
$result = shell_exec($text_converter_cmd);
|
||||
if ($result){
|
||||
return $result;
|
||||
} else {
|
||||
mtrace('Error with OpenOffice ODT to text converter command : execution failed. ');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mtrace('Error with OpenOffice ODT to text converter command : command not set up. Execute once search block configuration.');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -15,13 +15,13 @@
|
||||
|
||||
/**
|
||||
* @param object $resource
|
||||
* @uses CFG, USER
|
||||
* @uses $CFG
|
||||
*/
|
||||
function get_text_for_indexing_pdf(&$resource){
|
||||
global $CFG, $USER;
|
||||
function get_text_for_indexing_pdf(&$resource, $directfile = ''){
|
||||
global $CFG;
|
||||
|
||||
// SECURITY : do not allow non admin execute anything on system !!
|
||||
if (!isadmin($USER->id)) return;
|
||||
if (!has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))) return;
|
||||
|
||||
// adds moodle root switch if none was defined
|
||||
if (!isset($CFG->block_search_usemoodleroot)){
|
||||
@@ -35,22 +35,23 @@ function get_text_for_indexing_pdf(&$resource){
|
||||
preg_match("/^\S+/", $CFG->block_search_pdf_to_text_cmd, $matches);
|
||||
if (!file_exists("{$moodleroot}{$matches[0]}")){
|
||||
mtrace('Error with pdf to text converter command : executable not found at '.$moodleroot.$matches[0]);
|
||||
}
|
||||
else{
|
||||
$file = escapeshellarg($CFG->dataroot.'/'.$resource->course.'/'.$resource->reference);
|
||||
} else {
|
||||
if ($directfile == ''){
|
||||
$file = escapeshellarg("{$CFG->dataroot}/{$resource->course}/{$resource->reference}");
|
||||
} else {
|
||||
$file = escapeshellarg("{$CFG->dataroot}/{$directfile}");
|
||||
}
|
||||
$command = trim($CFG->block_search_pdf_to_text_cmd);
|
||||
$text_converter_cmd = "{$moodleroot}{$command} $file -";
|
||||
$result = shell_exec($text_converter_cmd);
|
||||
if ($result){
|
||||
return $result;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
mtrace('Error with pdf to text converter command : execution failed for '.$text_converter_cmd.'. Check for execution permission on pdf converter executable.');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
mtrace('Error with pdf to text converter command : command not set up. Execute once search block configuration.');
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -29,17 +29,21 @@
|
||||
|
||||
/**
|
||||
* @param object $resource
|
||||
* @uses CFG, USER
|
||||
* @uses $CFG
|
||||
*/
|
||||
function get_text_for_indexing_ppt(&$resource){
|
||||
global $CFG, $USER;
|
||||
function get_text_for_indexing_ppt(&$resource, $directfile = ''){
|
||||
global $CFG;
|
||||
|
||||
$indextext = null;
|
||||
|
||||
// SECURITY : do not allow non admin execute anything on system !!
|
||||
if (!isadmin($USER->id)) return;
|
||||
if (!has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))) return;
|
||||
|
||||
$text = implode('', file("{$CFG->dataroot}/{$resource->course}/{$resource->reference}"));
|
||||
if ($directfile == ''){
|
||||
$text = implode('', file("{$CFG->dataroot}/{$resource->course}/{$resource->reference}"));
|
||||
} else {
|
||||
$text = implode('', file("{$CFG->dataroot}/{$directfile}"));
|
||||
}
|
||||
|
||||
$remains = $text;
|
||||
$fragments = array();
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Global Search Engine for Moodle
|
||||
*
|
||||
* @package search
|
||||
* @category core
|
||||
* @subpackage document_wrappers
|
||||
* @author Valery Fremaux [[email protected]] > 1.8
|
||||
* @date 2008/03/31
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*
|
||||
* @note : The Adobe SWF Converters library is not GPL, although it can be of free use in some
|
||||
* situations. This file is provided for convenience, but should use having a glance at
|
||||
* {@link http://www.adobe.com/licensing/developer/}
|
||||
*
|
||||
* this is a format handler for getting text out of a proprietary binary format
|
||||
* so it can be indexed by Lucene search engine
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param object $resource
|
||||
* @uses $CFG
|
||||
*/
|
||||
function get_text_for_indexing_swf(&$resource, $directfile = ''){
|
||||
global $CFG;
|
||||
|
||||
// SECURITY : do not allow non admin execute anything on system !!
|
||||
if (!has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))) return;
|
||||
|
||||
// adds moodle root switch if none was defined
|
||||
if (!isset($CFG->block_search_usemoodleroot)){
|
||||
set_config('block_search_usemoodleroot', 1);
|
||||
}
|
||||
|
||||
$moodleroot = ($CFG->block_search_usemoodleroot) ? "{$CFG->dirroot}/" : '' ;
|
||||
|
||||
// just call pdftotext over stdout and capture the output
|
||||
if (!empty($CFG->block_search_pdf_to_text_cmd)){
|
||||
$command = trim($CFG->block_search_swf_to_text_cmd);
|
||||
if (!file_exists("{$moodleroot}{$command}")){
|
||||
mtrace('Error with swf to text converter command : executable not found as '.$moodleroot.$command);
|
||||
} else {
|
||||
if ($directfile == ''){
|
||||
$file = escapeshellarg("{$CFG->dataroot}/{$resource->course}/{$resource->reference}");
|
||||
} else {
|
||||
$file = escapeshellarg("{$CFG->dataroot}/{$directfile}");
|
||||
}
|
||||
$text_converter_cmd = "{$moodleroot}{$command} -t $file";
|
||||
$result = shell_exec($text_converter_cmd);
|
||||
|
||||
// result is in html. We must strip it off
|
||||
$result = preg_replace("/<[^>]*>/", '', $result);
|
||||
$result = preg_replace("/<!--[^>]*-->/", '', $result);
|
||||
$result = html_entity_decode($result, ENT_COMPAT, 'UTF-8');
|
||||
$result = mb_convert_encoding($result, 'UTF-8', 'auto');
|
||||
|
||||
if ($result){
|
||||
return $result;
|
||||
} else {
|
||||
mtrace('Error with swf to text converter command : execution failed for '.$text_converter_cmd.'. Check for execution permission on swf converter executable.');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mtrace('Error with swf to text converter command : command not set up. Execute once search block configuration.');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -15,16 +15,21 @@
|
||||
|
||||
/**
|
||||
* @param object $resource
|
||||
* @uses CFG, USER
|
||||
* @uses $CFG
|
||||
*/
|
||||
function get_text_for_indexing_txt(&$resource){
|
||||
global $CFG, $USER;
|
||||
function get_text_for_indexing_txt(&$resource, $directfile = ''){
|
||||
global $CFG;
|
||||
|
||||
// SECURITY : do not allow non admin execute anything on system !!
|
||||
if (!isadmin($USER->id)) return;
|
||||
if (!has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))) return;
|
||||
|
||||
// just try to get text empirically from ppt binary flow
|
||||
$text = implode('', file("{$CFG->dataroot}/{$resource->course}/{$resource->reference}"));
|
||||
if ($directfile == ''){
|
||||
$text = implode('', file("{$CFG->dataroot}/{$resource->course}/{$resource->reference}"));
|
||||
} else {
|
||||
$text = implode('', file("{$CFG->dataroot}/{$directfile}"));
|
||||
}
|
||||
|
||||
if (!empty($CFG->block_search_limit_index_body)){
|
||||
$text = shorten($text, $CFG->block_search_limit_index_body);
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
|
||||
/**
|
||||
* @param object $resource
|
||||
* @uses CFG, USER
|
||||
* @uses $CFG
|
||||
*/
|
||||
function get_text_for_indexing_xml(&$resource, $directfile = ''){
|
||||
global $CFG, $USER;
|
||||
global $CFG;
|
||||
|
||||
// SECURITY : do not allow non admin execute anything on system !!
|
||||
if (!isadmin($USER->id)) return;
|
||||
if (!has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))) return;
|
||||
|
||||
// just get text
|
||||
if ($directfile == ''){
|
||||
|
||||
@@ -44,7 +44,7 @@ class ResourceSearchDocument extends SearchDocument {
|
||||
$data = array();
|
||||
|
||||
// construct the parent class
|
||||
parent::__construct($doc, $data, $resource['course'], 0, 0, PATH_FOR_SEARCH_TYPE_RESOURCE);
|
||||
parent::__construct($doc, $data, $resource['course'], 0, 0, 'mod/'.SEARCH_TYPE_RESOURCE);
|
||||
} //constructor
|
||||
} //ResourceSearchDocument
|
||||
|
||||
@@ -95,15 +95,15 @@ function resource_get_content_for_index(&$notneeded) {
|
||||
alltext != ' ' AND
|
||||
type != 'file'
|
||||
";
|
||||
$resources = get_records_sql($query);
|
||||
|
||||
foreach($resources as $aResource){
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'resource');
|
||||
$cm = get_record('course_modules', 'course', $aResource->course, 'module', $coursemodule, 'instance', $aResource->id);
|
||||
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
|
||||
$aResource->id = $cm->id;
|
||||
$documents[] = new ResourceSearchDocument(get_object_vars($aResource), $context->id);
|
||||
mtrace("finished $aResource->name");
|
||||
if ($resources = get_records_sql($query)){
|
||||
foreach($resources as $aResource){
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'resource');
|
||||
$cm = get_record('course_modules', 'course', $aResource->course, 'module', $coursemodule, 'instance', $aResource->id);
|
||||
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
|
||||
$aResource->id = $cm->id;
|
||||
$documents[] = new ResourceSearchDocument(get_object_vars($aResource), $context->id);
|
||||
mtrace("finished $aResource->name");
|
||||
}
|
||||
}
|
||||
|
||||
// special physical files handling
|
||||
@@ -135,10 +135,8 @@ function resource_get_content_for_index(&$notneeded) {
|
||||
cm.module = m.id AND
|
||||
m.name = 'resource'
|
||||
";
|
||||
$resources = get_records_sql($query);
|
||||
|
||||
if ($resources = get_records_sql($query)){
|
||||
// invokes external content extractor if exists.
|
||||
if ($resources){
|
||||
foreach($resources as $aResource){
|
||||
// fetches a physical indexable document and adds it to documents passed by ref
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'resource');
|
||||
@@ -323,6 +321,11 @@ function resource_check_text_access($path, $itemtype, $this_id, $user, $group_id
|
||||
* @param string $title
|
||||
*/
|
||||
function resource_link_post_processing($title){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
global $CFG;
|
||||
|
||||
if ($CFG->block_search_utf8dir){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
}
|
||||
return mb_convert_encoding($title, 'auto', 'UTF-8');
|
||||
}
|
||||
?>
|
||||
@@ -1,301 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Global Search Engine for Moodle
|
||||
*
|
||||
* @package search
|
||||
* @category core
|
||||
* @subpackage document_wrappers
|
||||
* @author Michael Campanis, Valery Fremaux [[email protected]] > 1.8
|
||||
* @date 2008/03/31
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*
|
||||
* document handling for techproject activity module
|
||||
*/
|
||||
|
||||
/**
|
||||
* requires and includes
|
||||
*/
|
||||
require_once("$CFG->dirroot/search/documents/document.php");
|
||||
require_once("$CFG->dirroot/mod/techproject/lib.php");
|
||||
|
||||
/**
|
||||
* a class for representing searchable information
|
||||
*
|
||||
*/
|
||||
class TechprojectEntrySearchDocument extends SearchDocument {
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*
|
||||
*/
|
||||
public function __construct(&$entry, $course_id, $context_id) {
|
||||
// generic information
|
||||
$doc->docid = $entry['id'];
|
||||
$doc->documenttype = SEARCH_TYPE_TECHPROJECT;
|
||||
$doc->itemtype = $entry['entry_type'];
|
||||
$doc->contextid = $context_id;
|
||||
|
||||
|
||||
$doc->title = $entry['abstract'];
|
||||
$doc->author = ($entry['userid']) ? $entry['author'] : '';
|
||||
$doc->contents = strip_tags($entry['description']);
|
||||
$doc->date = '';
|
||||
|
||||
$doc->url = techproject_make_link($entry['projectid'], $entry['id'], $entry['entry_type'], $entry['groupid']);
|
||||
|
||||
// module specific information
|
||||
$data->techproject = $entry['projectid'];
|
||||
|
||||
parent::__construct($doc, $data, $course_id, $entry['groupid'], $entry['userid'], PATH_FOR_SEARCH_TYPE_TECHPROJECT);
|
||||
} //constructor
|
||||
} //TechprojectEntrySearchDocument
|
||||
|
||||
/**
|
||||
* constructs a valid link to a description detail
|
||||
*
|
||||
*/
|
||||
function techproject_make_link($techproject_id, $entry_id, $entry_type, $group_id) {
|
||||
global $CFG;
|
||||
return $CFG->wwwroot.'/mod/techproject/view.php?view=view_detail&id='.$techproject_id.'&objectId='.$entry_id.'&objectClass='.$entry_type.'&group='.$group_id;
|
||||
} //techproject_make_link
|
||||
|
||||
/**
|
||||
* search standard API
|
||||
*
|
||||
*/
|
||||
function techproject_iterator() {
|
||||
$techprojects = get_records('techproject');
|
||||
return $techprojects;
|
||||
} //techproject_iterator
|
||||
|
||||
/**
|
||||
* search standard API
|
||||
* @param techproject a techproject instance
|
||||
* @return an array of collected searchable documents
|
||||
*/
|
||||
function techproject_get_content_for_index(&$techproject) {
|
||||
$documents = array();
|
||||
if (!$techproject) return $documents;
|
||||
|
||||
$requirements = techproject_get_entries($techproject->id, 'requirement');
|
||||
$specifications = techproject_get_entries($techproject->id, 'specification');
|
||||
$tasks = techproject_get_tasks($techproject->id);
|
||||
$milestones = techproject_get_entries($techproject->id, 'milestone');
|
||||
$deliverables = techproject_get_entries($techproject->id, 'deliverable');
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'techproject');
|
||||
$cm = get_record('course_modules', 'course', $techproject->course, 'module', $coursemodule, 'instance', $techproject->id);
|
||||
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
|
||||
|
||||
$entries = @array_merge($requirements, $specifications, $milestones, $deliverables);
|
||||
if ($entries){
|
||||
foreach($entries as $anEntry) {
|
||||
if ($anEntry) {
|
||||
if (strlen($anEntry->description) > 0) {
|
||||
$anEntry->author = '';
|
||||
$documents[] = new TechprojectEntrySearchDocument(get_object_vars($anEntry), $techproject->course, $context->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($tasks){
|
||||
foreach($tasks as $aTask) {
|
||||
if ($aTask) {
|
||||
if (strlen($aTask->description) > 0) {
|
||||
if ($aTask->assignee){
|
||||
$user = get_record('user', 'id', $aTask->assignee);
|
||||
$aTask->author = $user->firstname.' '.$user->lastname;
|
||||
}
|
||||
$documents[] = new TechprojectEntrySearchDocument(get_object_vars($aTask), $techproject->course, $context->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $documents;
|
||||
} //techproject_get_content_for_index
|
||||
|
||||
/**
|
||||
* returns a single techproject search document based on a techproject_entry id and itemtype
|
||||
*
|
||||
*/
|
||||
function techproject_single_document($id, $itemtype) {
|
||||
switch ($itemtype){
|
||||
case 'requirement':{
|
||||
$entry = get_record('techproject_requirement', 'id', $id);
|
||||
$entry->author = '';
|
||||
break;
|
||||
}
|
||||
case 'specification':{
|
||||
$entry = get_record('techproject_specification', 'id', $id);
|
||||
$entry->author = '';
|
||||
break;
|
||||
}
|
||||
case 'milestone':{
|
||||
$entry = get_record('techproject_milestone', 'id', $id);
|
||||
$entry->author = '';
|
||||
break;
|
||||
}
|
||||
case 'deliverable':{
|
||||
$entry = get_record('techproject_deliverable', 'id', $id);
|
||||
$entry->author = '';
|
||||
break;
|
||||
}
|
||||
case 'task':{
|
||||
$entry = get_record('techproject_task', 'id', $id);
|
||||
if ($entry->assignee){
|
||||
$user = get_record('user', 'id', $entry->assignee);
|
||||
$entry->author = $user->firstname.' '.$user->lastname;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
$techproject_course = get_field('techproject', 'course', 'id', $entry->projectid);
|
||||
$coursemodule = get_field('modules', 'id', 'name', 'techproject');
|
||||
$cm = get_record('course_modules', 'course', $techproject_course, 'module', $coursemodule, 'instance', $entry->projectid);
|
||||
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
|
||||
$entry->type = $itemtype;
|
||||
$techproject = get_record('techproject', 'id', $requirement->projectid);
|
||||
return new TechprojectEntrySearchDocument(get_object_vars($anEntry), $techproject->course, $context->id);
|
||||
} //techproject_single_document
|
||||
|
||||
/**
|
||||
* dummy delete function that packs id with itemtype.
|
||||
* this was here for a reason, but I can't remember it at the moment.
|
||||
*
|
||||
*/
|
||||
function techproject_delete($info, $itemtype) {
|
||||
$object->id = $info;
|
||||
$object->itemtype = $itemtype;
|
||||
return $object;
|
||||
} //techproject_delete
|
||||
|
||||
/**
|
||||
* returns the var names needed to build a sql query for addition/deletions
|
||||
*
|
||||
*/
|
||||
// TODO : what should we do there ?
|
||||
function techproject_db_names() {
|
||||
//[primary id], [table name], [time created field name], [time modified field name]
|
||||
return array(
|
||||
array('id', 'techproject_requirement', 'created', 'modified', 'requirement'),
|
||||
array('id', 'techproject_specification', 'created', 'modified', 'specification'),
|
||||
array('id', 'techproject_task', 'created', 'modified', 'task'),
|
||||
array('id', 'techproject_milestone', 'created', 'modified', 'milestone'),
|
||||
array('id', 'techproject_deliverable', 'created', 'modified', 'deliverable')
|
||||
);
|
||||
} //techproject_db_names
|
||||
|
||||
/**
|
||||
* get a complete list of entries of one particular type
|
||||
* @param techprojectId the project instance
|
||||
* @param type the entity type
|
||||
* @return an array of records
|
||||
*/
|
||||
function techproject_get_entries($techproject_id, $type) {
|
||||
global $CFG;
|
||||
|
||||
$query = "
|
||||
SELECT
|
||||
e.id,
|
||||
e.abstract,
|
||||
e.description,
|
||||
e.projectid,
|
||||
e.groupid,
|
||||
e.userid,
|
||||
'$type' AS entry_type
|
||||
FROM
|
||||
{$CFG->prefix}techproject_{$type} AS e
|
||||
WHERE
|
||||
e.projectid = '{$techproject_id}'
|
||||
";
|
||||
return get_records_sql($query);
|
||||
} //techproject_get_entries
|
||||
|
||||
/**
|
||||
* get the task list for a project instance
|
||||
* @param techprojectId the project
|
||||
* @return an array of records that represent tasks
|
||||
*/
|
||||
function techproject_get_tasks($techproject_id) {
|
||||
global $CFG;
|
||||
|
||||
$query = "
|
||||
SELECT
|
||||
t.id,
|
||||
t.abstract,
|
||||
t.description,
|
||||
t.projectid,
|
||||
t.groupid,
|
||||
t.owner as userid,
|
||||
u.firstname,
|
||||
u.lastname,
|
||||
'task' as entry_type
|
||||
FROM
|
||||
{$CFG->prefix}techproject_task AS t
|
||||
LEFT JOIN
|
||||
{$CFG->prefix}user AS u
|
||||
ON
|
||||
t.owner = u.id
|
||||
WHERE
|
||||
t.projectid = '{$techproject_id}'
|
||||
ORDER BY
|
||||
t.taskstart ASC
|
||||
";
|
||||
return get_records_sql($query);
|
||||
} //techproject_get_tasks
|
||||
|
||||
/**
|
||||
* this function handles the access policy to contents indexed as searchable documents. If this
|
||||
* function does not exist, the search engine assumes access is allowed.
|
||||
* When this point is reached, we already know that :
|
||||
* - user is legitimate in the surrounding context
|
||||
* - user may be guest and guest access is allowed to the module
|
||||
* - the function may perform local checks within the module information logic
|
||||
* @param path the access path to the module script code
|
||||
* @param entry_type the information subclassing (usefull for complex modules, defaults to 'standard')
|
||||
* @param this_id the item id within the information class denoted by entry_type. In techprojects, this id
|
||||
* points to the techproject instance in which all resources are indexed.
|
||||
* @param user the user record denoting the user who searches
|
||||
* @param group_id the current group used by the user when searching
|
||||
* @return true if access is allowed, false elsewhere
|
||||
*/
|
||||
function techproject_check_text_access($path, $entry_type, $this_id, $user, $group_id, $context_id){
|
||||
global $CFG;
|
||||
|
||||
include_once("{$CFG->dirroot}/{$path}/lib.php");
|
||||
|
||||
// get the techproject object and all related stuff
|
||||
$techproject = get_record('techproject', 'id', $this_id);
|
||||
$course = get_record('course', 'id', $techproject->course);
|
||||
$module_context = get_record('context', 'id', $context_id);
|
||||
$cm = get_record('course_modules', 'id', $module_context->instanceid);
|
||||
if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $module_context)) return false;
|
||||
|
||||
//group consistency check : checks the following situations about groups
|
||||
// if user is guest check access capabilities for guests :
|
||||
// guests can see default project, and other records if groups are liberal
|
||||
// TODO : change guestsallowed in a capability
|
||||
if (isguest() && $techproject->guestsallowed){
|
||||
if ($group_id && groupmode($course, $cm) == SEPARATEGROUPS)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// trap if user is not same group and groups are separated
|
||||
$current_group = get_current_group($course->id);
|
||||
if ((groupmode($course) == SEPARATEGROUPS) && $group_id != $current_group && $group_id) return false;
|
||||
|
||||
//trap if ungroupedsees is off in strict access mode and user is not teacher
|
||||
if ((groupmode($course) == SEPARATEGROUPS) && !$techproject->ungroupedsees && !$group_id && isteacher($user->id)) return false;
|
||||
|
||||
return true;
|
||||
} //techproject_check_text_access
|
||||
|
||||
/**
|
||||
* this call back is called when displaying the link for some last post processing
|
||||
*
|
||||
*/
|
||||
function techproject_link_post_processing($title){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
/**
|
||||
* Global Search Engine for Moodle
|
||||
*
|
||||
* @package search
|
||||
* @category core
|
||||
* @subpackage document_wrappers
|
||||
* @author Valery Fremaux [[email protected]] > 1.8
|
||||
* @date 2008/03/31
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*
|
||||
* special (EXTRA) document handling for user related data
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* includes and requires
|
||||
*/
|
||||
require_once("$CFG->dirroot/search/documents/document.php");
|
||||
require_once("$CFG->dirroot/blog/lib.php");
|
||||
|
||||
/**
|
||||
* a class for representing searchable information in user metadata
|
||||
*
|
||||
*/
|
||||
class UserSearchDocument extends SearchDocument {
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*/
|
||||
public function __construct(&$userhash, $user_id, $context_id) {
|
||||
|
||||
// generic information; required
|
||||
$doc->docid = $userhash['id'];
|
||||
$doc->documenttype = SEARCH_TYPE_USER;
|
||||
$doc->itemtype = 'user';
|
||||
$doc->contextid = $context_id;
|
||||
|
||||
$user = get_record('user', 'id', $user_id);
|
||||
$doc->title = get_string('user').': '.fullname($user);
|
||||
$doc->date = ($userhash['lastaccess']) ? $userhash['lastaccess'] : time() ;
|
||||
|
||||
//remove '(ip.ip.ip.ip)' from chat author list
|
||||
$doc->author = $user->id;
|
||||
$doc->contents = $userhash['description'];
|
||||
$doc->url = user_make_link($user_id, 'user');
|
||||
|
||||
// module specific information; optional
|
||||
|
||||
// construct the parent class
|
||||
parent::__construct($doc, $data, 0, 0, 0, PATH_FOR_SEARCH_TYPE_USER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* a class for representing searchable information in user metadata
|
||||
*
|
||||
*/
|
||||
class UserPostSearchDocument extends SearchDocument {
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*/
|
||||
public function __construct(&$post, $user_id, $context_id) {
|
||||
// generic information; required
|
||||
$doc->docid = $post['id'];
|
||||
$doc->documenttype = SEARCH_TYPE_USER;
|
||||
$doc->itemtype = 'post';
|
||||
$doc->contextid = $context_id;
|
||||
|
||||
$user = get_record('user', 'id', $user_id);
|
||||
|
||||
// we cannot call userdate with relevant locale at indexing time.
|
||||
$doc->title = get_string('post').': '.fullname($user);
|
||||
$doc->date = $post['created'];
|
||||
|
||||
//remove '(ip.ip.ip.ip)' from chat author list
|
||||
$doc->author = fullname($user);
|
||||
$doc->contents = $post['description'];
|
||||
$doc->url = user_make_link($user_id, 'post');
|
||||
|
||||
// module specific information; optional
|
||||
|
||||
// construct the parent class
|
||||
parent::__construct($doc, $data, 0, 0, 0, PATH_FOR_SEARCH_TYPE_USER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* a class for representing searchable information in user metadata
|
||||
*
|
||||
*/
|
||||
class UserBlogAttachmentSearchDocument extends SearchDocument {
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*/
|
||||
public function __construct(&$post, $context_id) {
|
||||
// generic information; required
|
||||
$doc->docid = $post['id'];
|
||||
$doc->documenttype = SEARCH_TYPE_USER;
|
||||
$doc->itemtype = 'attachment';
|
||||
$doc->contextid = $context_id;
|
||||
|
||||
$user = get_record('user', 'id', $post['userid']);
|
||||
|
||||
// we cannot call userdate with relevant locale at indexing time.
|
||||
$doc->title = get_string('file').' : '.$post['subject'];
|
||||
$doc->date = $post['created'];
|
||||
|
||||
//remove '(ip.ip.ip.ip)' from chat author list
|
||||
$doc->author = fullname($user);
|
||||
$doc->contents = $post['alltext'];
|
||||
$doc->url = user_make_link($post['id'], 'attachment');
|
||||
|
||||
// module specific information; optional
|
||||
|
||||
// construct the parent class
|
||||
parent::__construct($doc, $data, 0, 0, 0, PATH_FOR_SEARCH_TYPE_USER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* constructs a valid link to a user record
|
||||
* @param userid the user
|
||||
* @param itemtype
|
||||
* @uses CFG
|
||||
* @return a well formed link to user information
|
||||
*/
|
||||
function user_make_link($itemid, $itemtype) {
|
||||
global $CFG;
|
||||
|
||||
if ($itemtype == 'user'){
|
||||
return $CFG->wwwroot.'/user/view.php?id='.$itemid;
|
||||
} elseif ($itemtype == 'post') {
|
||||
return $CFG->wwwroot.'/blog/index.php?userid='.$itemid;
|
||||
} elseif ($itemtype == 'attachment') {
|
||||
$post = get_record('post', 'id', $itemid);
|
||||
if (!$CFG->slasharguments){
|
||||
return $CFG->wwwroot."/file.php?file=/blog/attachments/{$post->id}/{$post->attachment}";
|
||||
} else {
|
||||
return $CFG->wwwroot."/file.php/blog/attachments/{$post->id}/{$post->attachment}";
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* part of search engine API
|
||||
*
|
||||
*/
|
||||
function user_iterator() {
|
||||
$users = get_records('user');
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* part of search engine API
|
||||
* @uses CFG
|
||||
* @return an array of documents generated from data
|
||||
*/
|
||||
function user_get_content_for_index(&$user) {
|
||||
global $CFG;
|
||||
|
||||
$documents = array();
|
||||
|
||||
$userhash = get_object_vars($user);
|
||||
$documents[] = new UserSearchDocument($userhash, $user->id, null);
|
||||
|
||||
if ($posts = get_records('post', 'userid', $user->id, 'created')){
|
||||
foreach($posts as $post){
|
||||
$texts = array();
|
||||
$texts[] = $post->subject;
|
||||
$texts[] = $post->summary;
|
||||
$texts[] = $post->content;
|
||||
$post->description = implode(" ", $texts);
|
||||
|
||||
// record the attachment if any and physical files can be indexed
|
||||
if (@$CFG->block_search_enable_file_indexing){
|
||||
if ($post->attachment){
|
||||
user_get_physical_file($post, null, false, $documents);
|
||||
}
|
||||
}
|
||||
|
||||
$posthash = get_object_vars($post);
|
||||
$documents[] = new UserPostSearchDocument($posthash, $user->id, null);
|
||||
}
|
||||
}
|
||||
return $documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* get text from a physical file
|
||||
* @param object $post a post to whech the file is attached to
|
||||
* @param boolean $context_id if in future we need recording a context along with the search document, pass it here
|
||||
* @param boolean $getsingle if true, returns a single search document, elsewhere return the array
|
||||
* given as documents increased by one
|
||||
* @param array $documents the array of documents, by ref, where to add the new document.
|
||||
* @return a search document when unique or false.
|
||||
*/
|
||||
function user_get_physical_file(&$post, $context_id, $getsingle, &$documents = null){
|
||||
global $CFG;
|
||||
|
||||
// cannot index empty references
|
||||
if (empty($post->attachment)){
|
||||
mtrace("Cannot index, empty reference.");
|
||||
return false;
|
||||
}
|
||||
|
||||
$fileparts = pathinfo($post->attachment);
|
||||
// cannot index unknown or masked types
|
||||
if (empty($fileparts['extension'])) {
|
||||
mtrace("Cannot index without explicit extension.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// cannot index non existent file
|
||||
$file = "{$CFG->dataroot}/blog/attachments/{$post->id}/{$post->attachment}";
|
||||
if (!file_exists($file)){
|
||||
mtrace("Missing attachment file $file : will not be indexed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
$ext = strtolower($fileparts['extension']);
|
||||
|
||||
// cannot index unallowed or unhandled types
|
||||
if (!preg_match("/\b$ext\b/i", $CFG->block_search_filetypes)) {
|
||||
mtrace($fileparts['extension'] . ' is not an allowed extension for indexing');
|
||||
return false;
|
||||
}
|
||||
if (file_exists($CFG->dirroot.'/search/documents/physical_'.$ext.'.php')){
|
||||
include_once($CFG->dirroot.'/search/documents/physical_'.$ext.'.php');
|
||||
$function_name = 'get_text_for_indexing_'.$ext;
|
||||
$directfile = "blog/attachments/{$post->id}/{$post->attachment}";
|
||||
$post->alltext = $function_name($post, $directfile);
|
||||
if (!empty($post->alltext)){
|
||||
if ($getsingle){
|
||||
$posthash = get_object_vars($post);
|
||||
$single = new UserBlogAttachmentSearchDocument($posthash, $context_id);
|
||||
mtrace("finished attachment {$post->attachment} in {$post->title}");
|
||||
return $single;
|
||||
} else {
|
||||
$posthash = get_object_vars($post);
|
||||
$documents[] = new UserBlogAttachmentSearchDocument($posthash, $context_id);
|
||||
}
|
||||
mtrace("finished attachment {$post->attachment} in {$post->subject}");
|
||||
}
|
||||
} else {
|
||||
mtrace("fulltext handler not found for $ext type");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a single user search document
|
||||
* @param composite $id a unique document id made with
|
||||
* @param itemtype the type of information (session is the only type)
|
||||
*/
|
||||
function user_single_document($id, $itemtype) {
|
||||
if ($itemtype == 'user'){
|
||||
if ($user = get_record('user', 'id', $id)){
|
||||
$userhash = get_object_vars($user);
|
||||
return new UserSearchDocument($userhash, $user->id, 'user', null);
|
||||
}
|
||||
} elseif ($itemtype == 'post') {
|
||||
if ($post = get_records('post', 'id', $id)){
|
||||
$texts = array();
|
||||
$texts[] = $post->subject;
|
||||
$texts[] = $post->summary;
|
||||
$texts[] = $post->content;
|
||||
$post->description = implode(" ", $texts);
|
||||
$posthash = get_object_vars($post);
|
||||
return new UserPostSearchDocument($posthash, $user->id, 'post', null);
|
||||
}
|
||||
} elseif ($itemtype == 'attachment' && @$CFG->block_search_enable_file_indexing) {
|
||||
if ($post = get_records('post', 'id', $id)){
|
||||
if ($post->attachment){
|
||||
return user_get_physical_file($post, null, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* dummy delete function that packs id with itemtype.
|
||||
* this was here for a reason, but I can't remember it at the moment.
|
||||
*
|
||||
*/
|
||||
function user_delete($info, $itemtype) {
|
||||
$object->id = $info;
|
||||
$object->itemtype = $itemtype;
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the var names needed to build a sql query for addition/deletions
|
||||
* attachments are indirect records, linked to its post
|
||||
*/
|
||||
function user_db_names() {
|
||||
//[primary id], [table name], [time created field name], [time modified field name] [itemtype] [select restriction clause]
|
||||
return array(
|
||||
array('id', 'user', 'firstaccess', 'timemodified', 'user'),
|
||||
array('id', 'post', 'created', 'lastmodified', 'post'),
|
||||
array('id', 'post', 'created', 'lastmodified', 'attachment')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* this function handles the access policy to contents indexed as searchable documents. If this
|
||||
* function does not exist, the search engine assumes access is allowed.
|
||||
* When this point is reached, we already know that :
|
||||
* - user is legitimate in the surrounding context
|
||||
* - user may be guest and guest access is allowed to the module
|
||||
* - the function may perform local checks within the module information logic
|
||||
* @param path the access path to the module script code
|
||||
* @param itemtype the information subclassing (usefull for complex modules, defaults to 'standard')
|
||||
* @param this_id the item id within the information class denoted by entry_type. In chats, this id
|
||||
* points out a session history which is a close sequence of messages.
|
||||
* @param user the user record denoting the user who searches
|
||||
* @param group_id the current group used by the user when searching
|
||||
* @uses CFG
|
||||
* @return true if access is allowed, false elsewhere
|
||||
*/
|
||||
function user_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){
|
||||
global $CFG;
|
||||
|
||||
include_once("{$CFG->dirroot}/{$path}/lib.php");
|
||||
|
||||
if ($itemtype == 'user'){
|
||||
// get the user
|
||||
$userrecord = get_record('user', 'id', $this_id);
|
||||
|
||||
// we cannot see nothing from unconfirmed users
|
||||
if (!$userrecord->confirmed and !has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))){
|
||||
if (!empty($CFG->search_access_debug)) echo "search reject : unconfirmed user ";
|
||||
return false;
|
||||
}
|
||||
} elseif ($itemtype == 'post' || $itemtype == 'attachment'){
|
||||
// get the post
|
||||
$post = get_record('post', 'id', $this_id);
|
||||
$userrecord = get_record('user', 'id', $post->userid);
|
||||
|
||||
// we can try using blog visibility check
|
||||
return blog_user_can_view_user_post($user->id, $post);
|
||||
}
|
||||
$context = get_record('context', 'id', $context_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* this call back is called when displaying the link for some last post processing
|
||||
*
|
||||
*/
|
||||
function user_link_post_processing($title){
|
||||
global $CFG;
|
||||
|
||||
if ($CFG->block_search_utf8dir){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
}
|
||||
return mb_convert_encoding($title, 'auto', 'UTF-8');
|
||||
}
|
||||
?>
|
||||
@@ -50,7 +50,7 @@ class WikiSearchDocument extends SearchDocument {
|
||||
$data->wiki = $wiki_id;
|
||||
|
||||
// construct the parent class
|
||||
parent::__construct($doc, $data, $course_id, $group_id, $user_id, PATH_FOR_SEARCH_TYPE_WIKI);
|
||||
parent::__construct($doc, $data, $course_id, $group_id, $user_id, 'mod/'.SEARCH_TYPE_WIKI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +268,12 @@ function wiki_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c
|
||||
*
|
||||
*/
|
||||
function wiki_link_post_processing($title){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
global $CFG;
|
||||
|
||||
if ($CFG->block_search_utf8dir){
|
||||
return mb_convert_encoding($title, 'UTF-8', 'auto');
|
||||
}
|
||||
return mb_convert_encoding($title, 'auto', 'UTF-8');
|
||||
}
|
||||
|
||||
?>
|
||||
+121
-79
@@ -1,106 +1,148 @@
|
||||
<?php
|
||||
|
||||
/* Used to test if modules/blocks are ready to included in the search index.
|
||||
* Carries out some basic function/file existence tests - the search module
|
||||
* is expected to exist, along with the db schema files and the search data
|
||||
* directory.
|
||||
* */
|
||||
/* Used to test if modules/blocks are ready to included in the search index.
|
||||
* Carries out some basic function/file existence tests - the search module
|
||||
* is expected to exist, along with the db schema files and the search data
|
||||
* directory.
|
||||
**/
|
||||
|
||||
@set_time_limit(0);
|
||||
@ob_implicit_flush(true);
|
||||
@ob_end_flush();
|
||||
@set_time_limit(0);
|
||||
@ob_implicit_flush(true);
|
||||
@ob_end_flush();
|
||||
|
||||
require_once('../../config.php');
|
||||
require_once("$CFG->dirroot/search/lib.php");
|
||||
require_once('../../config.php');
|
||||
require_once("$CFG->dirroot/search/lib.php");
|
||||
|
||||
require_login();
|
||||
|
||||
$strsearch = get_string('search', 'search');
|
||||
$strquery = get_string('stats');
|
||||
/// makes inclusions of the Zend Engine more reliable
|
||||
$separator = (array_key_exists('WINDIR', $_SERVER)) ? ';' : ':' ;
|
||||
ini_set('include_path', $CFG->dirroot.'\search'.$separator.ini_get('include_path'));
|
||||
|
||||
require_login();
|
||||
|
||||
$navlinks[] = array('name' => $strsearch, 'link' => "../index.php", 'type' => 'misc');
|
||||
$navlinks[] = array('name' => $strquery, 'link' => "../stats.php", 'type' => 'misc');
|
||||
$navlinks[] = array('name' => get_string('runindexertest','search'), 'link' => null, 'type' => 'misc');
|
||||
$navigation = build_navigation($navlinks);
|
||||
$site = get_site();
|
||||
print_header("$strsearch", "$site->fullname" , $navigation, "", "", true, " ", navmenu($site));
|
||||
|
||||
if (empty($CFG->enableglobalsearch)) {
|
||||
error('Global searching is not enabled.');
|
||||
}
|
||||
if (empty($CFG->enableglobalsearch)) {
|
||||
error('Global searching is not enabled.');
|
||||
}
|
||||
|
||||
if (!has_capability('moodle/site:doanything', get_context_instance(CONTEXT_SYSTEM))) {
|
||||
error("You need to be an admin user to use this page.", "$CFG->wwwroot/login/index.php");
|
||||
} //if
|
||||
|
||||
mtrace('<pre>Server Time: '.date('r',time()));
|
||||
mtrace("Testing global search capabilities:\n");
|
||||
|
||||
$phpversion = phpversion();
|
||||
|
||||
//fix paths for testing
|
||||
set_include_path(get_include_path().":../");
|
||||
require_once("$CFG->dirroot/search/Zend/Search/Lucene.php");
|
||||
|
||||
mtrace("Checking activity modules:\n");
|
||||
|
||||
//the presence of the required search functions -
|
||||
// * mod_iterator
|
||||
// * mod_get_content_for_index
|
||||
//are the sole basis for including a module in the index at the moment.
|
||||
|
||||
/// get all installed modules
|
||||
if ($mods = get_records('modules', '', '', 'name', 'id,name')){
|
||||
|
||||
if (!isadmin()) {
|
||||
error("You need to be an admin user to use this page.", "$CFG->wwwroot/login/index.php");
|
||||
} //if
|
||||
$searchabletypes = array_values(search_get_document_types());
|
||||
|
||||
mtrace('<pre>Server Time: '.date('r',time()));
|
||||
mtrace("Testing global search capabilities:\n");
|
||||
foreach($mods as $mod){
|
||||
if (in_array($mod->name, $searchabletypes)){
|
||||
$mod->location = 'internal';
|
||||
$searchables[] = $mod;
|
||||
} else {
|
||||
$documentfile = $CFG->dirroot."/mod/{$mod->name}/search_document.php";
|
||||
$mod->location = 'mod';
|
||||
if (file_exists($documentfile)){
|
||||
$searchables[] = $mod;
|
||||
}
|
||||
}
|
||||
}
|
||||
mtrace(count($searchables).' modules to search in / '.count($mods).' modules found.');
|
||||
}
|
||||
|
||||
/// collects blocks as indexable information may be found in blocks either
|
||||
if ($blocks = get_records('block', '', '', 'name', 'id,name')) {
|
||||
$blocks_searchables = array();
|
||||
// prepend the "block_" prefix to discriminate document type plugins
|
||||
foreach($blocks as $block){
|
||||
$block->dirname = $block->name;
|
||||
$block->name = 'block_'.$block->name;
|
||||
if (in_array('SEARCH_TYPE_'.strtoupper($block->name), $searchabletypes)){
|
||||
$mod->location = 'internal';
|
||||
$blocks_searchables[] = $block;
|
||||
} else {
|
||||
$documentfile = $CFG->dirroot."/blocks/{$block->dirname}/search_document.php";
|
||||
if (file_exists($documentfile)){
|
||||
$mod->location = 'blocks';
|
||||
$blocks_searchables[] = $block;
|
||||
}
|
||||
}
|
||||
}
|
||||
mtrace(count($blocks_searchables).' blocks to search in / '.count($blocks).' blocks found.');
|
||||
$searchables = array_merge($searchables, $blocks_searchables);
|
||||
}
|
||||
|
||||
/// add virtual modules onto the back of the array
|
||||
|
||||
$phpversion = phpversion();
|
||||
$additional = search_get_additional_modules();
|
||||
mtrace(count($additional).' additional to search in.');
|
||||
$searchables = array_merge($searchables, $additional);
|
||||
|
||||
foreach ($searchables as $mod) {
|
||||
|
||||
if (!search_check_php5()) {
|
||||
mtrace("ERROR: PHP 5.0.0 or later required (currently using version $phpversion).");
|
||||
exit(0);
|
||||
} else {
|
||||
mtrace("Success: PHP 5.0.0 or later is installed ($phpversion).\n");
|
||||
} //else
|
||||
|
||||
//fix paths for testing
|
||||
set_include_path(get_include_path().":../");
|
||||
require_once("$CFG->dirroot/search/Zend/Search/Lucene.php");
|
||||
|
||||
mtrace("Checking activity modules:\n");
|
||||
|
||||
//the presence of the required search functions -
|
||||
// * mod_iterator
|
||||
// * mod_get_content_for_index
|
||||
//are the sole basis for including a module in the index at the moment.
|
||||
|
||||
if ($mods = get_records_select('modules')) {
|
||||
$mods = array_merge($mods, search_get_additional_modules());
|
||||
|
||||
foreach ($mods as $mod) {
|
||||
$class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
|
||||
$key = 'search_in_'.$mod->name;
|
||||
if (isset($CFG->$key) && !$CFG->$key) {
|
||||
mtrace("module $key has been administratively disabled. Skipping...\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($mod->location == 'internal'){
|
||||
$class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
|
||||
} else {
|
||||
$class_file = $CFG->dirroot.'/'.$mod->location.'/'.$mod->name.'/search_document.php';
|
||||
}
|
||||
|
||||
if (file_exists($class_file)) {
|
||||
include_once($class_file);
|
||||
|
||||
if (!defined('SEARCH_TYPE_'.strtoupper($mod->name))) {
|
||||
mtrace("ERROR: Constant 'SEARCH_TYPE_".strtoupper($mod->name)."' is not defined in /search/lib.php");
|
||||
|
||||
if ($mod->location != 'internal' && !defined('X_SEARCH_TYPE_'.strtoupper($mod->name))) {
|
||||
mtrace("ERROR: Constant 'X_SEARCH_TYPE_".strtoupper($mod->name)."' is not defined in search/searchtypes.php or in module");
|
||||
continue;
|
||||
} //if
|
||||
|
||||
}
|
||||
|
||||
$iter_function = $mod->name.'_iterator';
|
||||
$index_function = $mod->name.'_get_content_for_index';
|
||||
|
||||
|
||||
if (function_exists($index_function) && function_exists($iter_function)) {
|
||||
if (is_array($iter_function())) {
|
||||
$documents = $index_function(array_pop($iter_function()));
|
||||
|
||||
$entries = $iter_function();
|
||||
if (!empty($entries)) {
|
||||
$documents = $index_function(array_pop($entries));
|
||||
|
||||
if (is_array($documents)) {
|
||||
mtrace("Success: '$mod->name' module seems to be ready for indexing.");
|
||||
} else {
|
||||
mtrace("ERROR: $index_function() doesn't seem to be returning an array.");
|
||||
} //else
|
||||
}
|
||||
} else {
|
||||
mtrace("ERROR: $iter_function() doesn't seem to be returning an object array.");
|
||||
} //else
|
||||
mtrace("Success : '$mod->name' has nothing to index.");
|
||||
}
|
||||
} else {
|
||||
mtrace("ERROR: $iter_function() and/or $index_function() does not exist in $class_file");
|
||||
} //else
|
||||
}
|
||||
} else {
|
||||
mtrace("Notice: $class_file does not exist, this module will not be indexed.");
|
||||
} //else
|
||||
} //foreach
|
||||
} //if
|
||||
|
||||
//finished modules
|
||||
mtrace("\nFinished checking activity modules.");
|
||||
|
||||
//now blocks...
|
||||
//
|
||||
|
||||
mtrace("<br/><a href='../index.php'>Back to query page</a> or <a href='../indexersplash.php'>Start indexing</a>.");
|
||||
mtrace('</pre>');
|
||||
print_footer();
|
||||
}
|
||||
}
|
||||
|
||||
//finished modules
|
||||
mtrace("\nFinished checking activity modules.");
|
||||
|
||||
//now blocks...
|
||||
//
|
||||
|
||||
mtrace("<br/><a href='../index.php'>Back to query page</a> or <a href='../indexersplash.php'>Start indexing</a>.");
|
||||
mtrace('</pre>');
|
||||
?>
|
||||
Reference in New Issue
Block a user