Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
search_manager_plugin_pgsql.inc
1 <?php
30 {
31 
32  //list of silent characters that are not going to be indexed
33  private $_silent_chars_to_space; //the list of silent characters that will be converted to space character (' ')
34  private $_silent_chars_to_empty; //the list of silent characters that will be converted to empty string ('')
35 
40  function __construct()
41  {
42  //These are lists of silent characters that are not going to be indexed. They are listed here instead of remove_silent_chars()
43  //function in text.inc because they are common characters but are not ASCII characters. Therefore, they will be encoded
44  //differently in different character encodings. That makes the str_replace() function used in remove_silent_chars()
45  //function not working properly if static strings are used.
46  $silent_chars_to_space = Array('&cent;', '&pound;', '&curren;', '&yen;', '&brvbar;', '&sect;', '&laquo;', '&raquo;', '&plusmn;', '&lsquo;', '&ldquo;', '&rdquo;', '&euro;', '&sbquo;', '&ndash;', '&mdash;', '&bull;');
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);
49  }
50  $this->_silent_chars_to_space = $silent_chars_to_space;
51 
52  //Just like the apostrophe (') in remove_silent_chars() function in text.inc, "you've" will become "youve"
53  $silent_chars_to_empty = Array('&rsquo;');
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);
56  }
57  $this->_silent_chars_to_empty = $silent_chars_to_empty;
58 
59  }//end constructor
60 
61 
86  function processWordSearch(&$sm, $search_term, $data_source, $base_query, $word_logic='AND')
87  {
88  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('dbsearch');
89 
90  switch ($data_source['type']) {
91 
92  case 'include_all':
93  if (!$sm->isWordIndexable($search_term)) {
94  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
95  return NULL;
96  }
97 
98  $base_query['where'][] = 'ai.value LIKE '.MatrixDAL::quote(($sm->attr('enable_begins_with') ? '%' : '').$search_term.'%');
99  break;
100 
101  case 'asset_attrib':
102  if (!$sm->isWordIndexable($search_term)) {
103  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
104  return NULL;
105  }
106 
107  $attrid = $data_source['params']['attrid'];
108  $attr_info = $GLOBALS['SQ_SYSTEM']->am->getAttributeInfo(Array($attrid));
109  $attr_info = $attr_info[$attrid];
110 
111  $attr_type = $attr_info['type'];
112  $base_query['where'][] = 'ai.component = '.MatrixDAL::quote('attr:'.$attr_info['name']);
113 
114  // work out what attribute type it is and perform a cast if
115  // it's a numeric search
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);
120  } else {
121  $base_query['where'][] = 'ai.value LIKE '.MatrixDAL::quote(($sm->attr('enable_begins_with') ? '%' : '').$search_term.'%');
122  }
123  break;
124 
125  case 'metadata':
126  $metadata_field = $GLOBALS['SQ_SYSTEM']->am->getAsset($data_source['params']['assetid']);
127  $key_types = Array(
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',
133  );
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');
136 
137  if ($key_type !== 'selection') {
138  if (!$sm->isWordIndexable($search_term)) {
139  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
140  return NULL;
141  }
142  }
143 
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);
148  } else {
149  $base_query['where'][] = 'ai.value LIKE '.MatrixDAL::quote(($sm->attr('enable_begins_with') ? '%' : '').$search_term.'%');
150  }
151  break;
152 
153  case 'standard':
154  if (!$sm->isWordIndexable($search_term)) {
155  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
156  return NULL;
157  }
158 
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.'%');
163  } else {
164  trigger_error('Invalid standard search field '.$field, E_USER_WARNING);
165  }
166  break;
167 
168  }//end switch
169 
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) {
174  MatrixDAL::bindValueToPdo($query, $bind_var, $value);
175  }//end foreach
176  if (count($base_query['select']) > 2) {
177  $result = MatrixDAL::executePdoAssoc($query);
178  } else {
179  $result = MatrixDAL::executePdoGroupedAssoc($query);
180  // (3.18) only selecting assetid and search score
181  // use old format and don't worry about result format later
182  $result_old_format = Array();
183  foreach ($result as $assetid => $info) {
184  $result_old_format[$assetid] = $info[0]['search_score'];
185  }
186 
187  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
188 
189  return $result_old_format;
190  }
191 
192  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
193 
194  return $result;
195 
196  }//end processWordSearch()
197 
198 
217  function processNumericSearch(&$sm, $numeric_range, $data_source, $base_query)
218  {
219  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('dbsearch');
220 
221  switch ($data_source['type']) {
222 
223  case 'asset_attrib':
224  $attrid = $data_source['params']['attrid'];
225  $attr_info = $GLOBALS['SQ_SYSTEM']->am->getAttributeInfo(Array($attrid));
226  $attr_info = $attr_info[$attrid];
227 
228  $attr_type = $attr_info['type'];
229  $base_query['where'][] = 'ai.component = '.MatrixDAL::quote('attr:'.$attr_info['name']);
230 
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']) {
238  // upper > lower as expected
239  $search_compare = 'BETWEEN '.MatrixDAL::quote($numeric_range['lower']).' AND '.MatrixDAL::quote($numeric_range['upper']);
240  } else {
241  // accept lower > upper but we need to switch values because
242  // some DB engines won't accept BETWEEN upper AND lower
243  $search_compare = 'BETWEEN '.MatrixDAL::quote($numeric_range['upper']).' AND '.MatrixDAL::quote($numeric_range['lower']);
244  }
245 
246  if ($attr_type == 'int') {
247  $base_query['where'][] = 'CAST (ai.value AS int) '.$search_compare;
248  } else {
249  $base_query['where'][] = 'CAST(ai.value AS double precision) '.$search_compare;
250  }
251  break;
252 
253  case 'metadata':
254  // not implemented yet
255  break;
256 
257  case 'standard':
258  // not implemented yet
259  break;
260 
261  }//end switch $data_source['type']
262 
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) {
267  MatrixDAL::bindValueToPdo($query, $bind_var, $value);
268  }//end foreach
269  if (count($base_query['select']) > 2) {
270  $result = MatrixDAL::executePdoAssoc($query);
271  } else {
272  $result = MatrixDAL::executePdoGroupedAssoc($query);
273  // (3.18) only selecting assetid and search score
274  // use old format and don't worry about result format later
275  $result_old_format = Array();
276  foreach ($result as $assetid => $info) {
277  $result_old_format[$assetid] = $info[0]['search_score'];
278  }
279 
280  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
281 
282  return $result_old_format;
283  }
284 
285  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
286 
287  return $result;
288 
289  }//end processNumericSearch()
290 
291 
310  function processDateSearch(&$sm, $date_range, $data_source, $base_query)
311  {
312  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('dbsearch');
313 
314  switch ($data_source['type']) {
315 
316  case 'asset_attrib':
317  // TODO: restrict by asset type here?
318  $attribute = $GLOBALS['SQ_SYSTEM']->am->getAttribute($data_source['params']['attrid']);
319  $base_query['where'][] = 'ai.component = '.MatrixDAL::quote('attr:'.$attribute->name);
320  break;
321 
322  case 'metadata':
323  $metadata_field = $GLOBALS['SQ_SYSTEM']->am->getAsset($data_source['params']['assetid']);
324  $key_types = Array(
325  'metadata_field_select' => 'selection',
326  'metadata_field_thesaurus' => 'thesaurus',
327  'metadata_field_date' => 'datetime',
328  );
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']);
332  break;
333 
334  case 'standard':
335  $field = $data_source['params']['field'];
336  if (isset($sm->standard_date_fields[$field])) {
337  $base_query['where'][] = 'ai.component = '.MatrixDAL::quote('__'.$field.'__');
338  } else {
339  trigger_error('Invalid standard date search field '.$field, E_USER_WARNING);
340  }
341  break;
342 
343  }
344 
345  // when one field is left blank, we are searching for anything before or after that date
346  // else we look between the given dates
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']);
351  } else {
352  $base_query['where'][] = 'ai.value BETWEEN '.MatrixDAL::quote($date_range['from']).' AND '.MatrixDAL::quote($date_range['to']);
353  }
354 
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) {
359  MatrixDAL::bindValueToPdo($query, $bind_var, $value);
360  }//end foreach
361  if (count($base_query['select']) > 2) {
362  $result = MatrixDAL::executePdoAssoc($query);
363  } else {
364  $result = MatrixDAL::executePdoGroupedAssoc($query);
365  // (3.18) only selecting assetid and search score
366  // use old format and don't worry about result format later
367  $result_old_format = Array();
368  foreach ($result as $assetid => $info) {
369  $result_old_format[$assetid] = $info[0]['search_score'];
370  }
371 
372  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
373 
374  return $result_old_format;
375  }
376 
377  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
378 
379  return $result;
380 
381  }//end processDateSearch()
382 
383 
397  function processExcludeQuery(&$sm, $search_term, $base_query)
398  {
399  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('dbsearch');
400 
401  $words = Array();
402  foreach ($search_term as $exclude_value) {
403  $words = array_merge($words, $this->generateWordList($exclude_value));
404  }
405  $words = array_unique($words);
406  foreach($words as $key => $val) {
407  $words[$key] = strtolower($val);
408  }
409 
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) {
418  MatrixDAL::bindValueToPdo($query, $bind_var, $value);
419  }//end foreach
420 
421  try {
422  $result = MatrixDAL::executePdoGrouped($query);
423  } catch (Exception $e) {
424  throw new Exception('Unable to process exclude query due to database error: '.$e->getMessage());
425  return Array();
426  }
427 
428  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
429 
430  return $result;
431 
432  }//end processExcludeQuery()
433 
434 
448  function constructBaseSearchQuery($search_info)
449  {
450  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('dbsearch');
451 
452  $query = Array(
453  'select' => Array(),
454  'from' => Array('sq_ast a'),
455  'where' => Array(),
456  'where_joiner' => 'AND',
457  'order_by' => Array(),
458  );
459 
460  // TREE LOCATIONS
461  if (!empty($search_info['roots'])) {
462  $root_logic = array_get_index($search_info, 'root_logic', 'OR');
463  // get the treeids of our search roots
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']).')';
468  // getAssoc only gives us the first treeid for each minorid, which is actually just what we want!
469  $root_tree_ids = MatrixDAL::executeSqlGroupedAssoc($treeid_sql);
470 
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'; // join the link tree and link tables
474  $query['join'][] = 'INNER JOIN sq_ast_lnk_tree t'.$i.' ON l'.$i.'.linkid = t'.$i.'.linkid'; // join them to the asset table
475 
476  $treeid = $root_tree_ids[$rootid][0]['treeid'];
477  $query['where'][] = 't'.$i.'.treeid LIKE '.MatrixDAL::quote($treeid.'%');
478  }
479  } else {
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';
482 
483  $treeid_wheres = Array();
484  foreach ($root_tree_ids as $treeid) {
485  $treeid_wheres[] = '(t.treeid LIKE '.MatrixDAL::quote($treeid.'%').')';
486  }
487  if (!empty($treeid_wheres)) {
488  $query['where'][] = implode(' OR ', $treeid_wheres);
489  }
490  }
491  }//end if !empty($search_info['roots'])
492 
493  // ACCESS RESTRICTIONS
494  $user_restrictions = (!$GLOBALS['SQ_SYSTEM']->userRoot() && !$GLOBALS['SQ_SYSTEM']->userSystemAdmin());
495  if ($user_restrictions) {
496 
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) ';
500  }
501 
502  $public_userid = (String)$GLOBALS['SQ_SYSTEM']->am->getSystemAssetid('public_user');
503 
504  // sanity check; if the global user isn't set, assume we're a public user
505  if (empty($GLOBALS['SQ_SYSTEM']->user->id) || $GLOBALS['SQ_SYSTEM']->user->id == $public_userid) {
506  $userids = Array($public_userid);
507  } else {
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);
510  }
511 
512  for (reset($userids); NULL !== ($i = key($userids)); next($userids)) {
513  $userids[$i] = MatrixDAL::quote($userids[$i]);
514  }
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.')';
519  }
520  $query['where'][] = $where;
521  $where = '(
522  (p.permission = '.MatrixDAL::quote(SQ_PERMISSION_READ).'
523  AND (
524  p.userid <> '.MatrixDAL::quote($public_userid).'
525  OR (p.userid = '.MatrixDAL::quote($public_userid).' AND granted = \'1\')';
526 
527  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
528  $where .= ' OR r.userid <> '.MatrixDAL::quote($public_userid).'
529  OR (r.userid = '.MatrixDAL::quote($public_userid).' AND granted = \'1\')';
530  }
531 
532  $query['where'][] = $where . '
533  )
534  )
535  OR
536  (p.permission > '.MatrixDAL::quote(SQ_PERMISSION_READ).' AND p.granted = \'1\')
537  )';
538  $query['having'][] = 'MIN(p.granted) <> \'0\'';
539  $query['group_by'][] = 'a.assetid';
540  }//end if
541 
542  // STATUS RESTRICTIONS
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) {
547  $statuses[$i] = MatrixDAL::quote($status);
548  }
549  $query['where'][] = 'a.status IN ('.implode(', ', $statuses).')';
550  }
551  } else {
552  // if there are no status restrictions, default to LIVE assets only
553  $query['where'][] = 'a.status >= '.MatrixDAL::quote(SQ_STATUS_LIVE);
554  }
555 
556  // ASSET TYPE RESTRICTIONS
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) {
562  $inherited_types[] = MatrixDAL::quote($i);
563  } else {
564  $normal_types[] = MatrixDAL::quote($i);
565  }
566  }
567 
568  $type_code_cond = Array();
569 
570  // if we have inherited types and/or normal types
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).')';
575  }
576  $type_code_cond = implode(' OR ', $type_code_cond);
577  $query['where'][] = 'a.type_code IN (
578  SELECT type_code
579  FROM sq_ast_typ_inhd
580  WHERE '.$type_code_cond.'
581  )';
582  } else {
583  // if we only got normal type instead we are not using the subquery
584  $query['where'][] = 'a.type_code IN ('.implode(', ', $normal_types).')';
585  }
586  }
587 
588  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
589 
590  return $query;
591 
592  }//end constructBaseSearchQuery()
593 
594 
610  function extractKeywords(&$asset, $include_metadata=FALSE, $include_scores=FALSE)
611  {
612  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('dbsearch');
613 
614  $sql = 'SELECT
615  LOWER(value), SUM(score)
616  FROM
617  sq_sch_idx
618  WHERE
619  assetid = :assetid'.
620  ($include_metadata ? '' : ' AND component NOT LIKE '.MatrixDAL::quote('metadata:%')).'
621  GROUP BY
622  LOWER(value)
623  ORDER BY
624  SUM(score) DESC';
625 
626  try {
627  $query = MatrixDAL::preparePdoQuery($sql);
628  MatrixDAL::bindValueToPdo($query, 'assetid', $asset->id);
629  $result = MatrixDAL::executePdoGroupedAssoc($query);
630  } catch (Exception $e) {
631  throw new Exception('Unable to extract keywords due to database error: '.$e->getMessage());
632  }
633 
634  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
635 
636  // force lowercase keys (= keywords) - CASE_LOWER is default for this function
637 // ALL THE KEYS ARE IN LOWERCASE ALREADY. THIS FUNCTION CHANGE THE STRING WHEN THE STRING CONTAINS SPECIAL CHARACTERS LIKE &ouml;
638 // $result = array_change_key_case($result);
639 
640  if ($include_scores) {
641  // return result with scores, change code to work with 3.18 result format
642  $result_w_score = Array();
643  foreach ($result as $key => $info) {
644  $result_w_score[$key] = $info[0]['sum'];
645  }
646  return $result_w_score;
647  } else {
648  return array_keys($result); // just return the keywords
649  }
650 
651  }//end extractKeywords()
652 
653 
662  function generateWordList($words)
663  {
664  if (!is_array($words)) {
665  //convert wildcard symbols to corresponding SQL wildcards
666 //DO NOT NEED TO CONVERT THOSE CHARACTERS BECAUSE THEY WILL BE REMOVED IN remove_silent_chars FUNCTION IN text.inc
667 // $words = strtr($words, '*?', '%_');
668 
669  //remove silent characters which are not in the silent chars list in remove_silent_chars of text.inc
670  $words = str_replace($this->_silent_chars_to_empty, '', $words);
671  $words = str_replace($this->_silent_chars_to_space, ' ', $words);
672 
673  //invoke remove_silent_chars in text.inc
674  $words = remove_silent_chars($words);
675 
676  $words = preg_split('/\s+/', $words, -1, PREG_SPLIT_NO_EMPTY);
677  }
678 
679  return $words;
680 
681  }//end generateWordList()
682 
683 
698  function splitIndexableContent($contents, $type_code, $data_type, $component, $weighting, $contextid, $use_default)
699  {
700  $index_content = Array();
701 
702  //only use mb_strtolower() function if it is supported
703  if (function_exists('mb_strtolower')) {
704  //use mbstring function because the input contents can be different from ASCII characters
705  $contents = mb_strtolower($contents, SQ_CONF_DEFAULT_CHARACTER_SET);
706  } else {
707  //lowercase the string which has non-ASCII characters by encoding them to HTML entities
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);
711  }
712  $contents = str_replace('&nbsp;', ' ', $contents);
713  $contents = trim($contents);
714 
715  if (($data_type == 'text') || ($data_type == 'wysiwyg')) {
716  //the wysiwyg tool converts special characters to html entities in the HTML editor so they need to be converted back
717  $contents = html_entity_decode($contents, ENT_QUOTES, SQ_CONF_DEFAULT_CHARACTER_SET);
718  }
719 
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,
729  );
730  return $index_content;
731  }
732 
733  //remove silent characters which are not in the silent chars list in remove_silent_chars of text.inc
734  $contents = str_replace($this->_silent_chars_to_empty, '', $contents);
735  $contents = str_replace($this->_silent_chars_to_space, ' ', $contents);
736 
737  if (trim($contents) != '') {
738  foreach (get_word_counts($contents) as $word => $count) {
739  $index_content[] = Array(
740  'value' => $word,
741  'type_code' => $type_code,
742  'type' => $data_type,
743  'component' => $component,
744  'score' => $count * $weighting,
745  'contextid' => $contextid,
746  'use_default' => $use_default,
747  );
748  }
749  }
750 
751  return $index_content;
752 
753  }//end splitIndexableContent()
754 
755 
768  {
769  return $value;
770 
771  }//end handleMultipleMetadataSelect()
772 
773 
783  function getAssetidsByWordIntersection($source_id, $type=NULL)
784  {
785  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('dbsearch');
786  require_once SQ_INCLUDE_PATH.'/general_occasional.inc';
787 
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';
792 
793  if (!empty($type)) {
794  $sql_components['where'][] = 'target.type_code = :type';
795  }
796 
797  $sql = implode_sql($sql_components);
798  try {
799  $query = MatrixDAL::preparePdoQuery($sql);
800  MatrixDAL::bindValueToPdo($query, 'source_id1', $source_id);
801  MatrixDAL::bindValueToPdo($query, 'source_id2', $source_id);
802  MatrixDAL::bindValueToPdo($query, 'type', $type);
803  $result = MatrixDAL::executePdoAssoc($query, 0);
804  } catch (Exception $e) {
805  throw new Exception('Unable to get assetid by word intersection due to database error: '.$e->getMessage());
806  }
807 
808  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
809 
810  return $result;
811 
812  }//end getAssetidsByWordIntersection()
813 
814 
821  function getMaxWordLength()
822  {
823  return 255;
824 
825  }//end getMaxWordLength()
826 
827 
837  function getWords($search_string)
838  {
839  return preg_split("|\s|", $search_string);
840 
841  }//end getWords()
842 
843 
853  function getSearchListAssets(&$search_list, &$search_page)
854  {
855  // get information about the search field
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)) {
859  // if search field has not been setup properly
860  return Array();
861  }
862  $search_field = $search_page_fields[$search_field_name];
863 
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);
868 
869  $query_comps['select'][] = 'ai.value';
870  $query_comps['select'][] = 'ai.assetid';
871  $query_comps['select'][] = 'SUBSTR(ai.value, 1, 1) AS first_letter';
872 
873  $data_source_comps = Array();
874 
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'];
880 
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);
884  break;
885  case 'metadata' :
886  $assetid = $data_source['params']['assetid'];
887  $data_source_comps[] = 'ai.component = '.MatrixDAL::quote('metadata:'.$assetid);
888  break;
889  case 'standard' :
890  $param_field = $data_source['params']['field'];
891  $data_source_comps[] = 'ai.component = '.MatrixDAL::quote('__'.$param_field.'__');
892  break;
893 
894  default :
895  return Array();
896  break;
897  }
898  }
899 
900  if (!empty($data_source_comps)) {
901  $query_comps['where'][] = '('.implode(') OR (', $data_source_comps).')';
902  }
903 
904  $query_comps['group_by'][] = 'ai.value';
905  $query_comps['group_by'][] = 'ai.assetid';
906 
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) {
911  MatrixDAL::bindValueToPdo($query, $bind_var, $value);
912  }//end foreach
913 
914  try {
915  $results = MatrixDAL::executePdoGroupedAssoc($query);
916  } catch (Exception $e) {
917  throw new Exception('Unable to get search list assets due to database error: '.$e->getMessage());
918  return Array();
919  }
920 
921  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
922 
923  $children = Array();
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;
929  }
930 
931  return $children;
932 
933  }//end getSearchListAssets()
934 
935 
936 }//end class