33 private $_silent_chars_to_space;
34 private $_silent_chars_to_empty;
46 $silent_chars_to_space = Array(
'¢',
'£',
'¤',
'¥',
'¦',
'§',
'«',
'»',
'±',
'‘',
'“',
'”',
'€',
'‚',
'–',
'—',
'•');
47 foreach ($silent_chars_to_space as $key => $value) {
48 $silent_chars_to_space[$key] = html_entity_decode($value, ENT_QUOTES, SQ_CONF_DEFAULT_CHARACTER_SET);
50 $this->_silent_chars_to_space = $silent_chars_to_space;
53 $silent_chars_to_empty = Array(
'’');
54 foreach ($silent_chars_to_empty as $key => $value) {
55 $silent_chars_to_empty[$key] = html_entity_decode($value, ENT_QUOTES, SQ_CONF_DEFAULT_CHARACTER_SET);
57 $this->_silent_chars_to_empty = $silent_chars_to_empty;
86 function processWordSearch(&$sm, $search_term, $data_source, $base_query, $word_logic=
'AND')
88 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'dbsearch');
90 switch ($data_source[
'type']) {
93 if (!$sm->isWordIndexable($search_term)) {
94 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
98 $base_query[
'where'][] =
'ai.value LIKE '.MatrixDAL::quote(($sm->attr(
'enable_begins_with') ?
'%' :
'').$search_term.
'%');
102 if (!$sm->isWordIndexable($search_term)) {
103 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
107 $attrid = $data_source[
'params'][
'attrid'];
108 $attr_info = $GLOBALS[
'SQ_SYSTEM']->am->getAttributeInfo(Array($attrid));
109 $attr_info = $attr_info[$attrid];
111 $attr_type = $attr_info[
'type'];
112 $base_query[
'where'][] =
'ai.component = '.MatrixDAL::quote(
'attr:'.$attr_info[
'name']);
116 if ($attr_type ==
'int') {
117 $base_query[
'where'][] =
'CAST (ai.value AS int) = '.MatrixDAL::quote($search_term);
118 }
else if ($attr_type ==
'float') {
119 $base_query[
'where'][] =
'CAST(ai.value AS double precision) = '.MatrixDAL::quote($search_term);
121 $base_query[
'where'][] =
'ai.value LIKE '.MatrixDAL::quote(($sm->attr(
'enable_begins_with') ?
'%' :
'').$search_term.
'%');
126 $metadata_field = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($data_source[
'params'][
'assetid']);
128 'metadata_field_hierarchy' =>
'selection',
129 'metadata_field_select' =>
'selection',
130 'metadata_field_multiple_text' =>
'selection',
131 'metadata_field_thesaurus' =>
'thesaurus',
132 'metadata_field_wysiwyg' =>
'metadata_field_wysiwyg',
134 $exact_type = Array(
'metadata_field_hierarchy',
'metadata_field_select',
'metadata_field_multiple_text');
135 $key_type = array_get_index($key_types, get_class_lower($metadata_field),
'text');
137 if ($key_type !==
'selection') {
138 if (!$sm->isWordIndexable($search_term)) {
139 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
144 $base_query[
'where'][] =
'ai.type = '.MatrixDAL::quote($key_type);
145 $base_query[
'where'][] =
'ai.component = '.MatrixDAL::quote(
'metadata:'.(
int)$data_source[
'params'][
'assetid']);
146 if (in_array(get_class_lower($metadata_field), $exact_type)) {
147 $base_query[
'where'][] =
'ai.value = '.MatrixDAL::quote($search_term);
149 $base_query[
'where'][] =
'ai.value LIKE '.MatrixDAL::quote(($sm->attr(
'enable_begins_with') ?
'%' :
'').$search_term.
'%');
154 if (!$sm->isWordIndexable($search_term)) {
155 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
159 $field = $data_source[
'params'][
'field'];
160 if (isset($sm->standard_text_fields[$field])) {
161 $base_query[
'where'][] =
'ai.component = '.MatrixDAL::quote(
'__'.$field.
'__');
162 $base_query[
'where'][] =
'ai.value LIKE '.MatrixDAL::quote(($sm->attr(
'enable_begins_with') ?
'%' :
'').$search_term.
'%');
164 trigger_error(
'Invalid standard search field '.$field, E_USER_WARNING);
170 $bind_vars = array_get_index($base_query,
'bind_vars', Array());
171 $sql = implode_sql($base_query);
172 $query = MatrixDAL::preparePDOQuery($sql);
173 foreach ($bind_vars as $bind_var => $value) {
176 if (count($base_query[
'select']) > 2) {
182 $result_old_format = Array();
183 foreach ($result as $assetid => $info) {
184 $result_old_format[$assetid] = $info[0][
'search_score'];
187 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
189 return $result_old_format;
192 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
219 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'dbsearch');
221 switch ($data_source[
'type']) {
224 $attrid = $data_source[
'params'][
'attrid'];
225 $attr_info = $GLOBALS[
'SQ_SYSTEM']->am->getAttributeInfo(Array($attrid));
226 $attr_info = $attr_info[$attrid];
228 $attr_type = $attr_info[
'type'];
229 $base_query[
'where'][] =
'ai.component = '.MatrixDAL::quote(
'attr:'.$attr_info[
'name']);
231 if ($numeric_range[
'upper'] == $numeric_range[
'lower']) {
232 $search_compare =
'= '.MatrixDAL::quote($numeric_range[
'upper']);
233 }
else if (is_null($numeric_range[
'upper'])) {
234 $search_compare =
'>= '.MatrixDAL::quote($numeric_range[
'lower']);
235 }
else if (is_null($numeric_range[
'lower'])) {
236 $search_compare =
'<= '.MatrixDAL::quote($numeric_range[
'upper']);
237 }
else if ($numeric_range[
'upper'] > $numeric_range[
'lower']) {
239 $search_compare =
'BETWEEN '.MatrixDAL::quote($numeric_range[
'lower']).
' AND '.
MatrixDAL::quote($numeric_range[
'upper']);
243 $search_compare =
'BETWEEN '.MatrixDAL::quote($numeric_range[
'upper']).
' AND '.
MatrixDAL::quote($numeric_range[
'lower']);
246 if ($attr_type ==
'int') {
247 $base_query[
'where'][] =
'CAST (ai.value AS int) '.$search_compare;
249 $base_query[
'where'][] =
'CAST(ai.value AS double precision) '.$search_compare;
263 $bind_vars = array_get_index($base_query,
'bind_vars', Array());
264 $sql = implode_sql($base_query);
265 $query = MatrixDAL::preparePDOQuery($sql);
266 foreach ($bind_vars as $bind_var => $value) {
269 if (count($base_query[
'select']) > 2) {
275 $result_old_format = Array();
276 foreach ($result as $assetid => $info) {
277 $result_old_format[$assetid] = $info[0][
'search_score'];
280 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
282 return $result_old_format;
285 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
312 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'dbsearch');
314 switch ($data_source[
'type']) {
318 $attribute = $GLOBALS[
'SQ_SYSTEM']->am->getAttribute($data_source[
'params'][
'attrid']);
319 $base_query[
'where'][] =
'ai.component = '.MatrixDAL::quote(
'attr:'.$attribute->name);
323 $metadata_field = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($data_source[
'params'][
'assetid']);
325 'metadata_field_select' =>
'selection',
326 'metadata_field_thesaurus' =>
'thesaurus',
327 'metadata_field_date' =>
'datetime',
329 $key_type = array_get_index($key_types, get_class_lower($metadata_field),
'text');
330 $base_query[
'where'][] =
'ai.type = '.MatrixDAL::quote($key_type);
331 $base_query[
'where'][] =
'ai.component = '.MatrixDAL::quote(
'metadata:'.(
int)$data_source[
'params'][
'assetid']);
335 $field = $data_source[
'params'][
'field'];
336 if (isset($sm->standard_date_fields[$field])) {
337 $base_query[
'where'][] =
'ai.component = '.MatrixDAL::quote(
'__'.$field.
'__');
339 trigger_error(
'Invalid standard date search field '.$field, E_USER_WARNING);
347 if ($date_range[
'from'] ==
'---------- --:--:--' && $date_range[
'to'] !=
'---------- --:--:--') {
348 $base_query[
'where'][] =
'ai.value <= '.MatrixDAL::quote($date_range[
'to']);
349 }
else if ($date_range[
'to'] ==
'---------- --:--:--' && $date_range[
'from'] !=
'---------- --:--:--') {
350 $base_query[
'where'][] =
'ai.value >= '.MatrixDAL::quote($date_range[
'from']);
352 $base_query[
'where'][] =
'ai.value BETWEEN '.MatrixDAL::quote($date_range[
'from']).
' AND '.
MatrixDAL::quote($date_range[
'to']);
355 $bind_vars = array_get_index($base_query,
'bind_vars', Array());
356 $sql = implode_sql($base_query);
357 $query = MatrixDAL::preparePDOQuery($sql);
358 foreach ($bind_vars as $bind_var => $value) {
361 if (count($base_query[
'select']) > 2) {
367 $result_old_format = Array();
368 foreach ($result as $assetid => $info) {
369 $result_old_format[$assetid] = $info[0][
'search_score'];
372 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
374 return $result_old_format;
377 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
399 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'dbsearch');
402 foreach ($search_term as $exclude_value) {
405 $words = array_unique($words);
406 foreach($words as $key => $val) {
407 $words[$key] = strtolower($val);
410 $new_base = $base_query;
411 $new_base[
'where'][] =
'ai.value LIKE \''.($sm->attr(
'enable_begins_with') ?
'%' :
'').implode(
"%' OR ai.value LIKE '".($sm->attr(
'enable_begins_with') ?
'%' :
''), $words).
'%\'';
412 $new_base[
'select'] = Array(
'asset_check.assetid');
413 $new_base[
'group_by'] = Array(
'asset_check.assetid');
414 $bind_vars = array_get_index($new_base,
'bind_vars', Array());
415 $sql = implode_sql($new_base);
416 $query = MatrixDAL::preparePDOQuery($sql);
417 foreach ($bind_vars as $bind_var => $value) {
423 }
catch (Exception $e) {
424 throw new Exception(
'Unable to process exclude query due to database error: '.$e->getMessage());
428 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
450 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'dbsearch');
454 'from' => Array(
'sq_ast a'),
456 'where_joiner' =>
'AND',
457 'order_by' => Array(),
461 if (!empty($search_info[
'roots'])) {
462 $root_logic = array_get_index($search_info,
'root_logic',
'OR');
464 $treeid_sql =
'SELECT l.minorid, t.treeid
465 FROM sq_ast_lnk_tree t
466 JOIN sq_ast_lnk l on t.linkid = l.linkid
467 WHERE l.minorid IN ('.implode(
',', $search_info[
'roots']).
')';
471 if ($root_logic ==
'AND') {
472 foreach (array_values($search_info[
'roots']) as $i => $rootid) {
473 $query[
'join'][] =
'INNER JOIN sq_ast_lnk l'.$i.
' ON l'.$i.
'.minorid = a.assetid';
474 $query[
'join'][] =
'INNER JOIN sq_ast_lnk_tree t'.$i.
' ON l'.$i.
'.linkid = t'.$i.
'.linkid';
476 $treeid = $root_tree_ids[$rootid][0][
'treeid'];
480 $query[
'join'][] =
'INNER JOIN sq_ast_lnk l ON l.minorid = a.assetid';
481 $query[
'join'][] =
'INNER JOIN sq_ast_lnk_tree t ON t.linkid = l.linkid';
483 $treeid_wheres = Array();
484 foreach ($root_tree_ids as $treeid) {
485 $treeid_wheres[] =
'(t.treeid LIKE '.MatrixDAL::quote($treeid.
'%').
')';
487 if (!empty($treeid_wheres)) {
488 $query[
'where'][] = implode(
' OR ', $treeid_wheres);
494 $user_restrictions = (!$GLOBALS[
'SQ_SYSTEM']->userRoot() && !$GLOBALS[
'SQ_SYSTEM']->userSystemAdmin());
495 if ($user_restrictions) {
497 $query[
'join'][] =
'INNER JOIN sq_ast_perm p ON p.assetid = a.assetid';
498 if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM ==
'1') {
499 $query[
'join'][] =
'LEFT JOIN sq_vw_ast_role r ON (p.userid = r.roleid AND r.assetid=a.assetid) ';
502 $public_userid = (String)$GLOBALS[
'SQ_SYSTEM']->am->getSystemAssetid(
'public_user');
505 if (empty($GLOBALS[
'SQ_SYSTEM']->user->id) || $GLOBALS[
'SQ_SYSTEM']->user->id == $public_userid) {
506 $userids = Array($public_userid);
508 $userids = array_keys($GLOBALS[
'SQ_SYSTEM']->am->getParents($GLOBALS[
'SQ_SYSTEM']->user->id,
'user_group', FALSE));
509 array_push($userids, $public_userid, $GLOBALS[
'SQ_SYSTEM']->user->id);
512 for (reset($userids); NULL !== ($i = key($userids)); next($userids)) {
515 $usrids_str = implode(
',', $userids);
516 $where =
'p.userid IN ('.$usrids_str.
')';
517 if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM ==
'1') {
518 $where .=
' OR '.
'r.userid IN ('.$usrids_str.
')';
520 $query[
'where'][] = $where;
522 (p.permission = '.MatrixDAL::quote(SQ_PERMISSION_READ).
'
527 if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM ==
'1') {
528 $where .=
' OR r.userid <> '.MatrixDAL::quote($public_userid).
'
532 $query[
'where'][] = $where .
'
536 (p.permission > '.MatrixDAL::quote(SQ_PERMISSION_READ).
' AND p.granted = \'1\')
538 $query[
'having'][] =
'MIN(p.granted) <> \'0\'';
539 $query[
'group_by'][] =
'a.assetid';
543 if (!empty($search_info[
'statuses'])) {
544 $statuses = $search_info[
'statuses'];
545 if (array_sum($statuses) != SQ_SC_STATUS_ALL) {
546 foreach ($statuses as $i => $status) {
549 $query[
'where'][] =
'a.status IN ('.implode(
', ', $statuses).
')';
553 $query[
'where'][] =
'a.status >= '.MatrixDAL::quote(SQ_STATUS_LIVE);
557 if (!empty($search_info[
'asset_types'])) {
558 $inherited_types = Array();
559 $normal_types = Array();
560 for (reset($search_info[
'asset_types']); NULL !== ($i = key($search_info[
'asset_types'])); next($search_info[
'asset_types'])) {
561 if ($search_info[
'asset_types'][$i] == 1) {
568 $type_code_cond = Array();
571 if (!empty($inherited_types)) {
572 $type_code_cond[] =
'inhd_type_code IN ('.implode(
', ', $inherited_types).
')';
573 if (!empty($normal_types)) {
574 $type_code_cond[] =
'type_code IN ('.implode(
', ', $normal_types).
')';
576 $type_code_cond = implode(
' OR ', $type_code_cond);
577 $query[
'where'][] =
'a.type_code IN (
580 WHERE '.$type_code_cond.
'
584 $query[
'where'][] =
'a.type_code IN ('.implode(
', ', $normal_types).
')';
588 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
612 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'dbsearch');
615 LOWER(value), SUM(score)
620 ($include_metadata ?
'' :
' AND component NOT LIKE '.MatrixDAL::quote(
'metadata:%')).
'
630 }
catch (Exception $e) {
631 throw new Exception(
'Unable to extract keywords due to database error: '.$e->getMessage());
634 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
640 if ($include_scores) {
642 $result_w_score = Array();
643 foreach ($result as $key => $info) {
644 $result_w_score[$key] = $info[0][
'sum'];
646 return $result_w_score;
648 return array_keys($result);
664 if (!is_array($words)) {
670 $words = str_replace($this->_silent_chars_to_empty,
'', $words);
671 $words = str_replace($this->_silent_chars_to_space,
' ', $words);
674 $words = remove_silent_chars($words);
676 $words = preg_split(
'/\s+/', $words, -1, PREG_SPLIT_NO_EMPTY);
700 $index_content = Array();
703 if (function_exists(
'mb_strtolower')) {
705 $contents = mb_strtolower($contents, SQ_CONF_DEFAULT_CHARACTER_SET);
708 $contents = htmlentities($contents, ENT_NOQUOTES, SQ_CONF_DEFAULT_CHARACTER_SET);
709 $contents = strtolower($contents);
710 $contents = html_entity_decode($contents, ENT_NOQUOTES, SQ_CONF_DEFAULT_CHARACTER_SET);
712 $contents = str_replace(
' ',
' ', $contents);
713 $contents = trim($contents);
715 if (($data_type ==
'text') || ($data_type ==
'wysiwyg')) {
717 $contents = html_entity_decode($contents, ENT_QUOTES, SQ_CONF_DEFAULT_CHARACTER_SET);
720 if ($data_type ==
'float') {
721 $index_content[] = Array(
722 'value' => $contents,
723 'type_code' => $type_code,
724 'type' => $data_type,
725 'component' => $component,
726 'score' => $weighting,
727 'contextid' => $contextid,
728 'use_default' => $use_default,
730 return $index_content;
734 $contents = str_replace($this->_silent_chars_to_empty,
'', $contents);
735 $contents = str_replace($this->_silent_chars_to_space,
' ', $contents);
737 if (trim($contents) !=
'') {
738 foreach (get_word_counts($contents) as $word => $count) {
739 $index_content[] = Array(
741 'type_code' => $type_code,
742 'type' => $data_type,
743 'component' => $component,
744 'score' => $count * $weighting,
745 'contextid' => $contextid,
746 'use_default' => $use_default,
751 return $index_content;
785 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'dbsearch');
786 require_once SQ_INCLUDE_PATH.
'/general_occasional.inc';
788 $sql_components[
'select'][] =
'DISTINCT target.assetid';
789 $sql_components[
'from'][] =
'sq_sch_idx source INNER JOIN sq_sch_idx target ON target.value = source.value';
790 $sql_components[
'where'][] =
'source.assetid = :source_id1';
791 $sql_components[
'where'][] =
'target.assetid <> :source_id2';
794 $sql_components[
'where'][] =
'target.type_code = :type';
797 $sql = implode_sql($sql_components);
804 }
catch (Exception $e) {
805 throw new Exception(
'Unable to get assetid by word intersection due to database error: '.$e->getMessage());
808 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
839 return preg_split(
"|\s|", $search_string);
856 $search_page_fields = $search_page->attr(
'fields');
857 $search_field_name = $search_list->attr(
'search_field');
858 if (empty($search_page_fields) || empty($search_field_name)) {
862 $search_field = $search_page_fields[$search_field_name];
864 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'dbsearch');
865 $sm = $GLOBALS[
'SQ_SYSTEM']->am->getSystemAsset(
'search_manager');
866 $search_info = $search_page->populateBaseSearchInfo();
867 $query_comps = $sm->constructBaseSearchQuery($search_info);
869 $query_comps[
'select'][] =
'ai.value';
870 $query_comps[
'select'][] =
'ai.assetid';
871 $query_comps[
'select'][] =
'SUBSTR(ai.value, 1, 1) AS first_letter';
873 $data_source_comps = Array();
875 foreach ($search_field[
'data_sources'] as $data_source) {
876 switch ($data_source[
'type']) {
877 case 'asset_attrib' :
878 $type_code = $data_source[
'params'][
'asset_type'];
879 $attrid = $data_source[
'params'][
'attrid'];
881 $attr_info = $GLOBALS[
'SQ_SYSTEM']->am->getAttributeInfo(Array($attrid));
882 $name = $attr_info[$attrid][
'name'];
883 $data_source_comps[] =
'ai.component = '.MatrixDAL::quote(
'attr:'.$name);
886 $assetid = $data_source[
'params'][
'assetid'];
887 $data_source_comps[] =
'ai.component = '.MatrixDAL::quote(
'metadata:'.$assetid);
890 $param_field = $data_source[
'params'][
'field'];
891 $data_source_comps[] =
'ai.component = '.MatrixDAL::quote(
'__'.$param_field.
'__');
900 if (!empty($data_source_comps)) {
901 $query_comps[
'where'][] =
'('.implode(
') OR (', $data_source_comps).
')';
904 $query_comps[
'group_by'][] =
'ai.value';
905 $query_comps[
'group_by'][] =
'ai.assetid';
907 $sql = implode_sql($query_comps);
908 $bind_vars = array_get_index($query_comps,
'bind_vars', Array());
909 $query = MatrixDAL::preparePDOQuery($sql);
910 foreach ($bind_vars as $bind_var => $value) {
916 }
catch (Exception $e) {
917 throw new Exception(
'Unable to get search list assets due to database error: '.$e->getMessage());
921 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
924 foreach ($results as $word => $word_data) {
925 $children[$word][
'num_values'] = count($word_data);
926 $base_data = array_pop($word_data);
927 $children[$word][
'first_letter'] = $base_data[
'first_letter'];
928 $children[$word][
'type_code'] = NULL;