PathFilter - return right neighbours of search terms
authorPaul Mehrer <p.mehrer@metaways.de>
Mon, 3 Apr 2017 15:44:03 +0000 (17:44 +0200)
committerCornelius Weiss <c.weiss@metaways.de>
Tue, 4 Apr 2017 15:24:09 +0000 (17:24 +0200)
the path filter returns the record ids of right path neighbours of search
terms hits in the whole path.

Change-Id: I263388ffb9f24352e723dbfeab4c4d1fde225ed5
Reviewed-on: http://gerrit.tine20.com/customers/4485
Reviewed-by: Cornelius Weiss <c.weiss@metaways.de>
Tested-by: Cornelius Weiss <c.weiss@metaways.de>
scripts/vagrant/Vagrantfile
tine20/Tinebase/Model/Filter/FullText.php
tine20/Tinebase/Model/Filter/Path.php
tine20/Tinebase/Record/Path.php

index ec2b764..5c8157d 100644 (file)
@@ -38,7 +38,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
        # backing providers for Vagrant. These expose provider-specific options.
        # Example for VirtualBox:
        config.vm.provider :virtualbox do |vb|
-               vb.customize ["modifyvm", :id, "--memory", "1024"]
+               vb.customize ["modifyvm", :id, "--memory", "1524"]
                vb.customize ["modifyvm", :id, "--cpus", "2"]
                vb.customize ["modifyvm", :id, "--ioapic", "on"]
        end
index 6997023..33c8395 100644 (file)
@@ -51,7 +51,7 @@ class Tinebase_Model_Filter_FullText extends Tinebase_Model_Filter_Abstract
             foreach ($this->_value as $value) {
                 //replace full text meta characters
                 //$value = str_replace(array('+', '-', '<', '>', '~', '*', '(', ')', '"'), ' ', $value);
-                $value = preg_replace('#[^\w\d ]|_#u', ' ', $value);
+                $value = preg_replace('#\W#u', ' ', $value);
                 // replace multiple spaces with just one
                 $value = preg_replace('# +#u', ' ', trim($value));
                 $values = explode(' ', $value);
@@ -73,7 +73,7 @@ class Tinebase_Model_Filter_FullText extends Tinebase_Model_Filter_Abstract
             foreach ($this->_value as $value) {
                 //replace full text meta characters
                 //$value = str_replace(array('+', '-', '<', '>', '~', '*', '(', ')', '"'), ' ', $value);
-                $value = preg_replace('#[^\w\d ]|_#u', ' ', $value);
+                $value = preg_replace('#\W#u', ' ', $value);
                 // replace multiple spaces with just one
                 $value = preg_replace('# +#u', ' +', trim($value));
                 $searchTerm .= ($searchTerm === '' ? '+' : ' +') . $value;
index fae9748..c81e905 100644 (file)
@@ -81,12 +81,81 @@ class Tinebase_Model_Filter_Path extends Tinebase_Model_Filter_Text
     protected function _resolvePathIds($_model)
     {
         if (! is_array($this->_pathRecordIds)) {
-            // TODO this should be improved if it turns out to be a performance issue:
-            //  we only need the record_ids here and not complete records, so we could directly use the path sql backend
-            //  and just request the property we need
-            $this->_pathRecordIds = $this->_getController()->search(new Tinebase_Model_PathFilter(array(
+             $paths = $this->_getController()->search(new Tinebase_Model_PathFilter(array(
                 array('field' => 'query', 'operator' => $this->_operator, 'value' => $this->_value)
-            )))->__call('getRecordIdsOfModel', array($_model));
+            )));
+
+            $this->_pathRecordIds = array();
+            if ($paths->count() > 0) {
+                if (!is_array($this->_value)) {
+                    $this->_value = array($this->_value);
+                }
+                $searchTerms = array();
+                foreach ($this->_value as $value) {
+                    //replace full text meta characters
+                    //$value = str_replace(array('+', '-', '<', '>', '~', '*', '(', ')', '"'), ' ', $value);
+                    $value = preg_replace('#[^\w\d ]|_#u', ' ', $value);
+                    // replace multiple spaces with just one
+                    $searchTerms = array_merge($searchTerms, explode(' ', preg_replace('# +#u', ' ', trim($value))));
+                }
+
+                if (count($searchTerms) < 1) {
+                    if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ .
+                        ' found paths, but search terms array is empty. value: ' . print_r($this->_value, true));
+                    return;
+                }
+
+                $searchTerms = array_filter($searchTerms, 'mb_strtolower');
+                $hitNeighbours = array();
+                $hitIds = array();
+
+                /** @var Tinebase_Model_Path $path */
+                foreach($paths as $path) {
+                    $pathParts = explode('/', trim($path->path, '/'));
+                    $shadowPathParts = explode('/', trim($path->shadow_path, '/'));
+                    $offset = 0;
+                    $hit = false;
+                    foreach($pathParts as $pathPart) {
+                        $pathPart = mb_strtolower($pathPart);
+
+                        $shadowPathPart = $shadowPathParts[$offset++];
+                        $model = substr($shadowPathPart, 1, strpos($shadowPathPart, '}') - 1);
+                        $id = substr($shadowPathPart, strpos($shadowPathPart, '}') + 1);
+                        if (false !== ($pos = strpos($id, '{'))) {
+                            $id = substr($id, 0, $pos - 1);
+                        }
+
+                        $newHit = true;
+                        foreach($searchTerms as $searchTerm) {
+                            if (false === strpos($pathPart, $searchTerm)) {
+                                $newHit = false;
+                                break;
+                            }
+                        }
+                        if (true === $newHit) {
+                            $hitIds[] = $id;
+                            $hit = true;
+                            continue;
+                        }
+                        if (false === $hit) {
+                            continue;
+                        }
+
+                        if ($model !== $_model) {
+                            continue;
+                        }
+
+                        $hitNeighbours[] = $id;
+                        $hit = false;
+                    }
+                }
+
+                if (count($hitNeighbours) > 0) {
+                    $this->_pathRecordIds = $hitNeighbours;
+                } else {
+                    $this->_pathRecordIds = $hitIds;
+                }
+            }
         }
 
         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' foreign ids: ' 
index dcaf2e6..06b13aa 100644 (file)
@@ -296,7 +296,7 @@ class Tinebase_Record_Path extends Tinebase_Controller_Record_Abstract
                 $newPath = '';
                 $i = 0;
                 while($i < $pathDept) {
-                    $newPath .= '/' . $pathParts[$i++];
+                    $newPath = '/' . $pathParts[$i++] . $newPath;
                 }
 
                 $uniquePaths[$tailPart] = array('path' => $newPath, 'record' => $path);
@@ -371,7 +371,7 @@ class Tinebase_Record_Path extends Tinebase_Controller_Record_Abstract
 
             foreach($_uniqueChildPaths as $childShadowPathPart => $childData) {
                 if (isset($childData['record']) && $childData['record']->shadow_path === $childShadowPathPart) {
-                    $path = $data['record'];
+                    $path = $childData['record'];
                 } elseif (true === $reUsePath) {
                     $path = $data['record'];
                     $reUsePath = false;