PathFilter - return right neighbours of search terms
[tine20] / tine20 / Tinebase / Model / Filter / FullText.php
1 <?php
2 /**
3  * Tine 2.0
4  *
5  * @package     Tinebase
6  * @subpackage  Filter
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @copyright   Copyright (c) 2016-2017 Metaways Infosystems GmbH (http://www.metaways.de)
9  * @author      Paul Mehrer <p.mehrer@metaways.de>
10  */
11
12 /**
13  * Tinebase_Model_Filter_Text
14  *
15  * filters one filterstring in one property
16  *
17  * @package     Tinebase
18  * @subpackage  Filter
19  */
20 class Tinebase_Model_Filter_FullText extends Tinebase_Model_Filter_Abstract
21 {
22     /**
23      * @var array list of allowed operators
24      */
25     protected $_operators = array(
26         0 => 'contains',
27     );
28
29     /**
30      * appends sql to given select statement
31      *
32      * @param  Zend_Db_Select                $_select
33      * @param  Tinebase_Backend_Sql_Abstract $_backend
34      * @throws Tinebase_Exception_InvalidArgument
35      */
36     public function appendFilterSql($_select, $_backend)
37     {
38         $db = $_select->getAdapter();
39
40         // mysql supports full text for InnoDB as of 5.6
41         if ( ! Setup_Backend_Factory::factory()->supports('mysql >= 5.6.4') ) {
42
43             if (Setup_Core::isLogLevel(Zend_Log::NOTICE)) Setup_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ .
44                 ' full text search is only supported on mysql/mariadb 5.6.4+ ... do yourself a favor and migrate. This query now maybe very slow for larger amount of data!');
45
46             $filterGroup = new Tinebase_Model_Filter_FilterGroup();
47
48             if (!is_array($this->_value)) {
49                 $this->_value = array($this->_value);
50             }
51             foreach ($this->_value as $value) {
52                 //replace full text meta characters
53                 //$value = str_replace(array('+', '-', '<', '>', '~', '*', '(', ')', '"'), ' ', $value);
54                 $value = preg_replace('#\W#u', ' ', $value);
55                 // replace multiple spaces with just one
56                 $value = preg_replace('# +#u', ' ', trim($value));
57                 $values = explode(' ', $value);
58                 foreach($values as $value) {
59                     $filter = new Tinebase_Model_Filter_Text($this->_field, 'contains', $value, isset($this->_options['tablename']) ? array('tablename' => $this->_options['tablename']) : array());
60                     $filterGroup->addFilter($filter);
61                 }
62             }
63
64             Tinebase_Backend_Sql_Filter_FilterGroup::appendFilters($_select, $filterGroup, $_backend);
65         } else {
66
67             $field = $this->_getQuotedFieldName($_backend);
68
69             $searchTerm = '';
70             if (!is_array($this->_value)) {
71                 $this->_value = array($this->_value);
72             }
73             foreach ($this->_value as $value) {
74                 //replace full text meta characters
75                 //$value = str_replace(array('+', '-', '<', '>', '~', '*', '(', ')', '"'), ' ', $value);
76                 $value = preg_replace('#\W#u', ' ', $value);
77                 // replace multiple spaces with just one
78                 $value = preg_replace('# +#u', ' +', trim($value));
79                 $searchTerm .= ($searchTerm === '' ? '+' : ' +') . $value;
80             }
81
82             $_select->where('MATCH (' . $field . $db->quoteInto(') AGAINST (? IN BOOLEAN MODE)', $searchTerm));
83         }
84     }
85 }