diff --git a/core/src/plugins/core.index/class.AbstractSearchEngineIndexer.php b/core/src/plugins/core.index/class.AbstractSearchEngineIndexer.php index 43dd9ba7cc..3e8530f892 100644 --- a/core/src/plugins/core.index/class.AbstractSearchEngineIndexer.php +++ b/core/src/plugins/core.index/class.AbstractSearchEngineIndexer.php @@ -8,6 +8,19 @@ abstract class AbstractSearchEngineIndexer extends AJXP_AbstractMetaSource { + /** + * @param DOMNode $contribNode + */ + public function parseSpecificContributions(&$contribNode){ + parent::parseSpecificContributions($contribNode); + if($this->getFilteredOption("HIDE_MYSHARES_SECTION") !== true) return; + if($contribNode->nodeName != "client_configs") return ; + $actionXpath=new DOMXPath($contribNode->ownerDocument); + $nodeList = $actionXpath->query('component_config[@className="AjxpPane::navigation_scroller"]', $contribNode); + if(!$nodeList->length) return ; + $contribNode->removeChild($nodeList->item(0)); + } + /** * @param AJXP_Node $ajxpNode * @return null|string @@ -63,4 +76,63 @@ protected function extractIndexableContent($ajxpNode){ return null; } + /** + * @param String $query + * @return String mixed + */ + protected function filterSearchRangesKeywords($query) + { + if (strpos($query, "AJXP_SEARCH_RANGE_TODAY") !== false) { + $t1 = date("Ymd"); + $t2 = date("Ymd"); + $query = str_replace("AJXP_SEARCH_RANGE_TODAY", "[$t1 TO $t2]", $query); + } else if (strpos($query, "AJXP_SEARCH_RANGE_YESTERDAY") !== false) { + $t1 = date("Ymd", mktime(0,0,0,date('m'), date('d')-1, date('Y'))); + $t2 = date("Ymd", mktime(0,0,0,date('m'), date('d')-1, date('Y'))); + $query = str_replace("AJXP_SEARCH_RANGE_YESTERDAY", "[$t1 TO $t2]", $query); + } else if (strpos($query, "AJXP_SEARCH_RANGE_LAST_WEEK") !== false) { + $t1 = date("Ymd", mktime(0,0,0,date('m'), date('d')-7, date('Y'))); + $t2 = date("Ymd", mktime(0,0,0,date('m'), date('d'), date('Y'))); + $query = str_replace("AJXP_SEARCH_RANGE_LAST_WEEK", "[$t1 TO $t2]", $query); + } else if (strpos($query, "AJXP_SEARCH_RANGE_LAST_MONTH") !== false) { + $t1 = date("Ymd", mktime(0,0,0,date('m')-1, date('d'), date('Y'))); + $t2 = date("Ymd", mktime(0,0,0,date('m'), date('d'), date('Y'))); + $query = str_replace("AJXP_SEARCH_RANGE_LAST_MONTH", "[$t1 TO $t2]", $query); + } else if (strpos($query, "AJXP_SEARCH_RANGE_LAST_YEAR") !== false) { + $t1 = date("Ymd", mktime(0,0,0,date('m'), date('d'), date('Y')-1)); + $t2 = date("Ymd", mktime(0,0,0,date('m'), date('d'), date('Y'))); + $query = str_replace("AJXP_SEARCH_RANGE_LAST_YEAR", "[$t1 TO $t2]", $query); + } + + $split = array_map("trim", explode("AND", $query)); + foreach($split as $s){ + list($k, $v) = explode(":", $s, 2); + if($k == "ajxp_bytesize"){ + //list($from, $to) = sscanf($v, "[%s TO %s]"); + preg_match('/\[(.*) TO (.*)\]/', $v, $matches); + $oldSize = $s; + $newSize = "ajxp_bytesize:[".intval(AJXP_Utils::convertBytes($matches[1]))." TO ".intval(AJXP_Utils::convertBytes($matches[2]))."]"; + } + } + if(isSet($newSize) && isSet($oldSize)){ + $query = str_replace($oldSize, $newSize, $query); + } + + return $query; + } + + /** + * @param String $repositoryId + * @param String $userId + * @return string + */ + protected function buildSpecificId($repositoryId, $userId = null){ + $specificId = ""; + $specKey = $this->getFilteredOption("repository_specific_keywords"); + if (!empty($specKey)) { + $specificId = "-".str_replace(array(",", "/"), array("-", "__"), AJXP_VarsFilter::filter($specKey, $userId)); + } + return $repositoryId.$specificId; + } + } \ No newline at end of file diff --git a/core/src/plugins/index.elasticsearch/class.AjxpElasticSearch.php b/core/src/plugins/index.elasticsearch/class.AjxpElasticSearch.php index 5eed18d0c7..ec50d04421 100644 --- a/core/src/plugins/index.elasticsearch/class.AjxpElasticSearch.php +++ b/core/src/plugins/index.elasticsearch/class.AjxpElasticSearch.php @@ -62,7 +62,7 @@ class AjxpElasticSearch extends AbstractSearchEngineIndexer public function init($options) { - parent::init($options);; + parent::init($options); $metaFields = $this->getFilteredOption("index_meta_fields"); $specKey = $this->getFilteredOption("repository_specific_keywords"); if (!empty($metaFields)) { @@ -113,7 +113,7 @@ public function indexationIndexNode($node){ * @param AJXP_Node $parentNode */ public function indexationStarts($parentNode){ - $this->loadIndex($parentNode->getRepositoryId(), true); + $this->loadIndex($parentNode->getRepositoryId(), true, $parentNode->getUser()); } /** @@ -145,6 +145,42 @@ public function applyAction($actionName, $httpVars, $fileVars) throw new Exception($messages["index.lucene.7"]); } + $textQuery = $httpVars["query"]; + if($this->getFilteredOption("AUTO_WILDCARD") === true && strlen($textQuery) > 0 && ctype_alnum($textQuery)){ + if($textQuery[0] == '"' && $textQuery[strlen($textQuery)-1] == '"'){ + $textQuery = substr($textQuery, 1, -1); + }else if($textQuery[strlen($textQuery)-1] != "*" ){ + $textQuery.="*"; + } + } + + + $this->currentIndex->open(); + $fieldQuery = new Elastica\Query\QueryString(); + $fieldQuery->setAllowLeadingWildcard(false); + $fieldQuery->setFuzzyMinSim(0.8); + + if($textQuery == "*"){ + + $fields = array("ajxp_node"); + $fieldQuery->setQuery("yes"); + $fieldQuery->setFields($fields); + + }else if(strpos($textQuery, ":") !== false){ + + // USE LUCENE DSL DIRECTLY (key1:value1 AND key2:value2...) + $textQuery = str_replace("ajxp_meta_ajxp_document_content:","body:", $textQuery); + $textQuery = $this->filterSearchRangesKeywords($textQuery); + $fieldQuery->setQuery($textQuery); + + } else{ + + $fields = array("basename","ajxp_meta_*", "node_*","body"); + $fieldQuery->setQuery($textQuery); + $fieldQuery->setFields($fields); + + } + /* TODO : READAPT QUERY WITH EACH FIELD if ((isSet($this->metaFields) || $this->indexContent) && isSet($httpVars["fields"])) { @@ -165,22 +201,8 @@ public function applyAction($actionName, $httpVars, $fileVars) $this->logDebug("Query : $query"); } else { */ - $this->currentIndex->open(); - $query = $httpVars["query"]; - $fieldQuery = new Elastica\Query\QueryString(); //} - //$this->setDefaultAnalyzer(); - if ($query == "*") { - $fields = array("ajxp_node"); - $fieldQuery->setQuery("yes"); - } else { - $fields = array("basename","ajxp_meta_*", "node_*","body"); - $fieldQuery->setQuery($query); - } - $fieldQuery->setFields($fields); - $fieldQuery->setAllowLeadingWildcard(false); - $fieldQuery->setFuzzyMinSim(0.8); /* We create this object search because it'll allow us to fetch the number of results we want at once. We just have to set some parameters, the query type and the size of the result set. @@ -196,14 +218,20 @@ public function applyAction($actionName, $httpVars, $fileVars) \Elastica\Search::OPTION_SEARCH_TYPE => \Elastica\Search::OPTION_SEARCH_TYPE_QUERY_THEN_FETCH, \Elastica\Search::OPTION_SIZE => $maxResults); - $this->logDebug(__FUNCTION__,"Executing query: ", $query); + $this->logDebug(__FUNCTION__,"Executing query: ", $textQuery); $fullQuery = new Elastica\Query(); $fullQuery->setQuery($fieldQuery); - // ADD SCOPE FILTER - $term = new Elastica\Filter\Term(); - $term->setTerm("ajxp_scope", "shared"); - $fullQuery->setPostFilter($term); + $qb = new Elastica\QueryBuilder(); + $fullQuery = new Elastica\Query(); + $fullQuery->setQuery( + $qb->query()->filtered( + $fieldQuery, + $qb->filter()->bool() + ->addMust(new Elastica\Filter\Term(array("ajxp_scope" => "shared"))) + ) + ); + $result = $search->search($fullQuery, $searchOptions); $this->logDebug(__FUNCTION__,"Search finished. "); @@ -236,7 +264,7 @@ public function applyAction($actionName, $httpVars, $fileVars) $scope = "user"; try { - $this->loadIndex(ConfService::getRepository()->getId(), false); + $this->loadIndex($repoId, false); } catch (Exception $ex) { throw new Exception($messages["index.lucene.7"]); } @@ -351,7 +379,7 @@ public function recursiveIndexation($url) */ public function updateNodeIndexMeta($node) { - $this->loadIndex(ConfService::getRepository()->getId()); + $this->loadIndex($node->getRepositoryId(), true, $node->getUser()); if (AuthService::usersEnabled() && AuthService::getLoggedUser()!=null) { $query = new Elastica\Query\Term(); @@ -387,9 +415,9 @@ public function updateNodeIndexMeta($node) public function updateNodeIndex($oldNode, $newNode = null, $copy = false, $recursive = false) { if($oldNode == null){ - $this->loadIndex($newNode->getRepositoryId()); + $this->loadIndex($newNode->getRepositoryId(), true, $newNode->getUser()); }else{ - $this->loadIndex($oldNode->getRepositoryId()); + $this->loadIndex($oldNode->getRepositoryId(), true, $oldNode->getUser()); } if ($oldNode != null && $copy == false) { @@ -412,14 +440,21 @@ public function updateNodeIndex($oldNode, $newNode = null, $copy = false, $recur // Make sure it does not already exists anyway $newDocId = $this->getIndexedDocumentId($newNode); if ($newDocId != null) { - $this->currentType->deleteById($newDocId); + try{ + $this->currentType->deleteById($newDocId); + }catch (Elastica\Exception\NotFoundException $eEx){ + $this->logError(__FUNCTION__, "Trying to delete a non existing document"); + } $childrenHits = $this->getIndexedChildrenDocuments($newNode); - if ($childrenHits != null) { $childrenHits = $childrenHits->getResults(); foreach ($childrenHits as $hit) { - $this->currentType->deleteById($hit->getId()); + try{ + $this->currentType->deleteById($hit->getId()); + }catch (Elastica\Exception\NotFoundException $eEx){ + $this->logError(__FUNCTION__, "Trying to delete a non existing document"); + } } } } @@ -473,6 +508,14 @@ public function createIndexedDocument($ajxpNode) $data["ajxp_node"] = "yes"; $data["ajxp_scope"] = "shared"; $data["serialized_metadata"] = base64_encode(serialize($ajxpNode->metadata)); + $data["ajxp_modiftime"] = date("Ymd", $ajxpNode->ajxp_modiftime); + $data["ajxp_bytesize"] = $ajxpNode->bytesize; + $ajxpMime = $ajxpNode->ajxp_mime; + if (empty($ajxpMime)) { + $data["ajxp_mime"] = pathinfo($ajxpNode->getLabel(), PATHINFO_EXTENSION); + } else { + $data["ajxp_mime"] = $ajxpNode->ajxp_mime; + } if (isSet($ajxpNode->indexableMetaKeys["shared"])) { foreach ($ajxpNode->indexableMetaKeys["shared"] as $sharedField) { @@ -540,9 +583,10 @@ protected function dataToMappingProperties($data){ $mapping_properties[$key] = array("type" => "string", "index" => "not_analyzed"); } else if($key == "serialized_metadata"){ $mapping_properties[$key] = array("type" => "string" /*, "index" => "no" */); + } else if ($key == "ajxp_bytesize"){ + $mapping_properties[$key] = array("type" => "long"); } else { $type = gettype($value); - if ($type != "integer" && $type != "boolean" && $type != "double") { $type = "string"; } @@ -599,23 +643,26 @@ public function getIndexedChildrenDocuments($ajxpNode) * load the index into the class parameter currentIndex * @param Integer $repositoryId * @param bool $create + * @param null $resolveUserId */ - protected function loadIndex($repositoryId, $create = true) + protected function loadIndex($repositoryId, $create = true, $resolveUserId = null) { - $this->currentIndex = $this->client->getIndex($repositoryId); + $specificId = $this->buildSpecificId($repositoryId, $resolveUserId); + + $this->currentIndex = $this->client->getIndex($specificId); /* if the cache directory for the repository index is not created we do create it */ - $iPath = (defined('AJXP_SHARED_CACHE_DIR')?AJXP_SHARED_CACHE_DIR:AJXP_CACHE_DIR)."/indexes/".$repositoryId; + $iPath = (defined('AJXP_SHARED_CACHE_DIR')?AJXP_SHARED_CACHE_DIR:AJXP_CACHE_DIR)."/indexes/".$specificId; if(!is_dir($iPath)) mkdir($iPath,0755, true); - if (!$this->currentIndex->exists() && $create) { + if ($create && !$this->currentIndex->exists()) { $this->currentIndex->create(); } - $this->currentType = new Elastica\Type($this->currentIndex, "type_".$repositoryId); + $this->currentType = new Elastica\Type($this->currentIndex, "type_".$specificId); /* we fetch the last id we used to create a document and set the variable nextId */ - $this->lastIdPath = (defined('AJXP_SHARED_CACHE_DIR')?AJXP_SHARED_CACHE_DIR:AJXP_CACHE_DIR)."/indexes/".$repositoryId."/last_id"; + $this->lastIdPath = (defined('AJXP_SHARED_CACHE_DIR')?AJXP_SHARED_CACHE_DIR:AJXP_CACHE_DIR)."/indexes/".$specificId."/last_id"; if (file_exists($this->lastIdPath)) { $file = fopen($this->lastIdPath, "r"); $this->nextId = floatval(fgets($file)) + 1; diff --git a/core/src/plugins/index.elasticsearch/manifest.xml b/core/src/plugins/index.elasticsearch/manifest.xml index 36c9fbabe0..f307fd4f34 100644 --- a/core/src/plugins/index.elasticsearch/manifest.xml +++ b/core/src/plugins/index.elasticsearch/manifest.xml @@ -23,7 +23,7 @@ - + diff --git a/core/src/plugins/index.lucene/class.AjxpLuceneIndexer.php b/core/src/plugins/index.lucene/class.AjxpLuceneIndexer.php index 8a6fe41841..5bab7e78b1 100644 --- a/core/src/plugins/index.lucene/class.AjxpLuceneIndexer.php +++ b/core/src/plugins/index.lucene/class.AjxpLuceneIndexer.php @@ -34,7 +34,6 @@ class AjxpLuceneIndexer extends AbstractSearchEngineIndexer private $currentIndex; private $metaFields = array(); private $indexContent = false; - private $specificId = ""; private $verboseIndexation = false; public function init($options) @@ -45,23 +44,9 @@ public function init($options) if (!empty($metaFields)) { $this->metaFields = explode(",",$metaFields); } - $specKey = $this->getFilteredOption("repository_specific_keywords"); - if (!empty($specKey)) { - $this->specificId = "-".str_replace(array(",", "/"), array("-", "__"), AJXP_VarsFilter::filter($specKey)); - } $this->indexContent = ($this->getFilteredOption("index_content") == true); } - public function parseSpecificContributions(&$contribNode){ - parent::parseSpecificContributions($contribNode); - if($this->getFilteredOption("HIDE_MYSHARES_SECTION") !== true) return; - if($contribNode->nodeName != "client_configs") return ; - $actionXpath=new DOMXPath($contribNode->ownerDocument); - $nodeList = $actionXpath->query('component_config[@className="AjxpPane::navigation_scroller"]', $contribNode); - if(!$nodeList->length) return ; - $contribNode->removeChild($nodeList->item(0)); - } - public function initMeta($accessDriver) { parent::initMeta($accessDriver); @@ -117,32 +102,6 @@ protected function setDefaultAnalyzer() } - protected function filterSearchRangesKeywords($query) - { - if (strpos($query, "AJXP_SEARCH_RANGE_TODAY") !== false) { - $t1 = date("Ymd"); - $t2 = date("Ymd"); - $query = str_replace("AJXP_SEARCH_RANGE_TODAY", "[$t1 TO $t2]", $query); - } else if (strpos($query, "AJXP_SEARCH_RANGE_YESTERDAY") !== false) { - $t1 = date("Ymd", mktime(0,0,0,date('m'), date('d')-1, date('Y'))); - $t2 = date("Ymd", mktime(0,0,0,date('m'), date('d')-1, date('Y'))); - $query = str_replace("AJXP_SEARCH_RANGE_YESTERDAY", "[$t1 TO $t2]", $query); - } else if (strpos($query, "AJXP_SEARCH_RANGE_LAST_WEEK") !== false) { - $t1 = date("Ymd", mktime(0,0,0,date('m'), date('d')-7, date('Y'))); - $t2 = date("Ymd", mktime(0,0,0,date('m'), date('d'), date('Y'))); - $query = str_replace("AJXP_SEARCH_RANGE_LAST_WEEK", "[$t1 TO $t2]", $query); - } else if (strpos($query, "AJXP_SEARCH_RANGE_LAST_MONTH") !== false) { - $t1 = date("Ymd", mktime(0,0,0,date('m')-1, date('d'), date('Y'))); - $t2 = date("Ymd", mktime(0,0,0,date('m'), date('d'), date('Y'))); - $query = str_replace("AJXP_SEARCH_RANGE_LAST_MONTH", "[$t1 TO $t2]", $query); - } else if (strpos($query, "AJXP_SEARCH_RANGE_LAST_YEAR") !== false) { - $t1 = date("Ymd", mktime(0,0,0,date('m'), date('d'), date('Y')-1)); - $t2 = date("Ymd", mktime(0,0,0,date('m'), date('d'), date('Y'))); - $query = str_replace("AJXP_SEARCH_RANGE_LAST_YEAR", "[$t1 TO $t2]", $query); - } - return $query; - } - public function applyAction($actionName, $httpVars, $fileVars) { $messages = ConfService::getMessages(); @@ -642,16 +601,8 @@ public function getIndexedChildrenDocuments($index, $ajxpNode) */ protected function getIndexPath($repositoryId, $resolveUserId = null){ $mainCacheDir = (defined('AJXP_SHARED_CACHE_DIR')?AJXP_SHARED_CACHE_DIR:AJXP_CACHE_DIR); - $specificId = $this->specificId; - if($resolveUserId != null){ - $specKey = $this->getFilteredOption("repository_specific_keywords"); - if (!empty($specKey)) { - $specKey = str_replace("AJXP_USER", $resolveUserId, $specKey); - $specificId = "-".str_replace(array(",", "/"), array("-", "__"), AJXP_VarsFilter::filter($specKey)); - } - } if(!is_dir($mainCacheDir."/indexes")) mkdir($mainCacheDir."/indexes",0755,true); - $iPath = $mainCacheDir."/indexes/index-$repositoryId".$specificId; + $iPath = $mainCacheDir."/indexes/index-".$this->buildSpecificId($repositoryId, $resolveUserId); return $iPath; }