/** * Search contacts * * @param array List of fields to search in * @param string Search value * @param boolean True for strict, False for partial (fuzzy) matching * @param boolean True if results are requested, False if count only * @return array Indexed list of contact records and 'count' value */ function search($fields, $value, $strict = false, $select = true) { // special treatment for ID-based search if ($fields == 'ID' || $fields == $this->primary_key) { $ids = explode(',', $value); $result = new rcube_result_set(); foreach ($ids as $id) { if ($rec = $this->get_record($id, true)) { $result->add($rec); $result->count++; } } return $result; } $filter = '(|'; $wc = !$strict && $this->prop['fuzzy_search'] ? '*' : ''; if (is_array($this->prop['search_fields'])) { foreach ($this->prop['search_fields'] as $k => $field) { $filter .= "({$field}={$wc}" . rcube_ldap::quote_string($value) . "{$wc})"; } } else { foreach ((array) $fields as $field) { if ($f = $this->_map_field($field)) { $filter .= "({$f}={$wc}" . rcube_ldap::quote_string($value) . "{$wc})"; } } } $filter .= ')'; // avoid double-wildcard if $value is empty $filter = preg_replace('/\\*+/', '*', $filter); // add general filter to query if (!empty($this->prop['filter'])) { $filter = '(&(' . preg_replace('/^\\(|\\)$/', '', $this->prop['filter']) . ')' . $filter . ')'; } // set filter string and execute search $this->set_search_set($filter); $this->_exec_search(); if ($select) { $this->list_records(); } else { $this->result = $this->count(); } return $this->result; }
/** * Search contacts * * @param mixed $fields The field name of array of field names to search in * @param mixed $value Search value (or array of values when $fields is array) * @param int $mode Matching mode: * 0 - partial (*abc*), * 1 - strict (=), * 2 - prefix (abc*) * @param boolean $select True if results are requested, False if count only * @param boolean $nocount (Not used) * @param array $required List of fields that cannot be empty * * @return array Indexed list of contact records and 'count' value */ function search($fields, $value, $mode = 0, $select = true, $nocount = false, $required = array()) { $mode = intval($mode); // special treatment for ID-based search if ($fields == 'ID' || $fields == $this->primary_key) { $ids = !is_array($value) ? explode(',', $value) : $value; $result = new rcube_result_set(); foreach ($ids as $id) { if ($rec = $this->get_record($id, true)) { $result->add($rec); $result->count++; } } return $result; } // use VLV pseudo-search for autocompletion $rcube = rcube::get_instance(); $list_fields = $rcube->config->get('contactlist_fields'); if ($this->prop['vlv_search'] && $this->ready && join(',', (array) $fields) == join(',', $list_fields)) { $this->result = new rcube_result_set(0); $search_suffix = $this->prop['fuzzy_search'] && $mode != 1 ? '*' : ''; $ldap_data = $this->ldap->search($this->base_dn, $this->prop['filter'], $this->prop['scope'], $this->prop['attributes'], array('search' => $value . $search_suffix)); if ($ldap_data === false) { return $this->result; } // get all entries of this page and post-filter those that really match the query $search = mb_strtolower($value); foreach ($ldap_data as $i => $entry) { $rec = $this->_ldap2result($entry); foreach ($fields as $f) { foreach ((array) $rec[$f] as $val) { if ($this->compare_search_value($f, $val, $search, $mode)) { $this->result->add($rec); $this->result->count++; break 2; } } } } return $this->result; } // use AND operator for advanced searches $filter = is_array($value) ? '(&' : '(|'; // set wildcards $wp = $ws = ''; if (!empty($this->prop['fuzzy_search']) && $mode != 1) { $ws = '*'; if (!$mode) { $wp = '*'; } } if ($fields == '*') { // search_fields are required for fulltext search if (empty($this->prop['search_fields'])) { $this->set_error(self::ERROR_SEARCH, 'nofulltextsearch'); $this->result = new rcube_result_set(); return $this->result; } if (is_array($this->prop['search_fields'])) { foreach ($this->prop['search_fields'] as $field) { $filter .= "({$field}={$wp}" . rcube_ldap_generic::quote_string($value) . "{$ws})"; } } } else { foreach ((array) $fields as $idx => $field) { $val = is_array($value) ? $value[$idx] : $value; if ($attrs = $this->_map_field($field)) { if (count($attrs) > 1) { $filter .= '(|'; } foreach ($attrs as $f) { $filter .= "({$f}={$wp}" . rcube_ldap_generic::quote_string($val) . "{$ws})"; } if (count($attrs) > 1) { $filter .= ')'; } } } } $filter .= ')'; // add required (non empty) fields filter $req_filter = ''; foreach ((array) $required as $field) { if (in_array($field, (array) $fields)) { // required field is already in search filter continue; } if ($attrs = $this->_map_field($field)) { if (count($attrs) > 1) { $req_filter .= '(|'; } foreach ($attrs as $f) { $req_filter .= "({$f}=*)"; } if (count($attrs) > 1) { $req_filter .= ')'; } } } if (!empty($req_filter)) { $filter = '(&' . $req_filter . $filter . ')'; } // avoid double-wildcard if $value is empty $filter = preg_replace('/\\*+/', '*', $filter); // add general filter to query if (!empty($this->prop['filter'])) { $filter = '(&(' . preg_replace('/^\\(|\\)$/', '', $this->prop['filter']) . ')' . $filter . ')'; } // set filter string and execute search $this->set_search_set($filter); if ($select) { $this->list_records(); } else { $this->result = $this->count(); } return $this->result; }
/** * Search contacts * * @param mixed $fields The field name of array of field names to search in * @param mixed $value Search value (or array of values when $fields is array) * @param int $mode Matching mode: * 0 - partial (*abc*), * 1 - strict (=), * 2 - prefix (abc*) * @param boolean $select True if results are requested, False if count only * @param boolean $nocount (Not used) * @param array $required List of fields that cannot be empty * * @return array Indexed list of contact records and 'count' value */ function search($fields, $value, $mode = 0, $select = true, $nocount = false, $required = array()) { $mode = intval($mode); // special treatment for ID-based search if ($fields == 'ID' || $fields == $this->primary_key) { $ids = !is_array($value) ? explode(',', $value) : $value; $result = new rcube_result_set(); foreach ($ids as $id) { if ($rec = $this->get_record($id, true)) { $result->add($rec); $result->count++; } } return $result; } // use VLV pseudo-search for autocompletion if ($this->prop['vlv_search'] && $this->conn && join(',', (array) $fields) == 'email,name') { // add general filter to query if (!empty($this->prop['filter']) && empty($this->filter)) { $this->set_search_set($this->prop['filter']); } // set VLV controls with encoded search string $this->_vlv_set_controls($this->prop, $this->list_page, $this->page_size, $value); $function = $this->_scope2func($this->prop['scope']); $this->ldap_result = @$function($this->conn, $this->base_dn, $this->filter ? $this->filter : '(objectclass=*)', array_values($this->fieldmap), 0, $this->page_size, (int) $this->prop['timelimit']); $this->result = new rcube_result_set(0); if (!$this->ldap_result) { $this->_debug("S: " . ldap_error($this->conn)); return $this->result; } $this->_debug("S: " . ldap_count_entries($this->conn, $this->ldap_result) . " record(s)"); // get all entries of this page and post-filter those that really match the query $search = mb_strtolower($value); $entries = ldap_get_entries($this->conn, $this->ldap_result); for ($i = 0; $i < $entries['count']; $i++) { $rec = $this->_ldap2result($entries[$i]); foreach ($fields as $f) { foreach ((array) $rec[$f] as $val) { $val = mb_strtolower($val); switch ($mode) { case 1: $got = $val == $search; break; case 2: $got = $search == substr($val, 0, strlen($search)); break; default: $got = strpos($val, $search) !== false; break; } if ($got) { $this->result->add($rec); $this->result->count++; break 2; } } } } return $this->result; } // use AND operator for advanced searches $filter = is_array($value) ? '(&' : '(|'; // set wildcards $wp = $ws = ''; if (!empty($this->prop['fuzzy_search']) && $mode != 1) { $ws = '*'; if (!$mode) { $wp = '*'; } } if ($fields == '*') { // search_fields are required for fulltext search if (empty($this->prop['search_fields'])) { $this->set_error(self::ERROR_SEARCH, 'nofulltextsearch'); $this->result = new rcube_result_set(); return $this->result; } if (is_array($this->prop['search_fields'])) { foreach ($this->prop['search_fields'] as $field) { $filter .= "({$field}={$wp}" . $this->_quote_string($value) . "{$ws})"; } } } else { foreach ((array) $fields as $idx => $field) { $val = is_array($value) ? $value[$idx] : $value; if ($f = $this->_map_field($field)) { $filter .= "({$f}={$wp}" . $this->_quote_string($val) . "{$ws})"; } } } $filter .= ')'; // add required (non empty) fields filter $req_filter = ''; foreach ((array) $required as $field) { if ($f = $this->_map_field($field)) { $req_filter .= "({$f}=*)"; } } if (!empty($req_filter)) { $filter = '(&' . $req_filter . $filter . ')'; } // avoid double-wildcard if $value is empty $filter = preg_replace('/\\*+/', '*', $filter); // add general filter to query if (!empty($this->prop['filter'])) { $filter = '(&(' . preg_replace('/^\\(|\\)$/', '', $this->prop['filter']) . ')' . $filter . ')'; } // set filter string and execute search $this->set_search_set($filter); $this->_exec_search(); if ($select) { $this->list_records(); } else { $this->result = $this->count(); } return $this->result; }