source: branches/2.5/include/functions_search.inc.php @ 27933

Last change on this file since 27933 was 27933, checked in by plg, 10 years ago

merge r26825 from trunk to branch 2.5

bug 3020 and bug 3021 fixed: additionnal checks in search inputs

  • Property svn:eol-style set to LF
File size: 22.2 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2013 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24
25/**
26 * returns search rules stored into a serialized array in "search"
27 * table. Each search rules set is numericaly identified.
28 *
29 * @param int search_id
30 * @return array
31 */
32function get_search_array($search_id)
33{
34  if (!is_numeric($search_id))
35  {
36    die('Search id must be an integer');
37  }
38
39  $query = '
40SELECT rules
41  FROM '.SEARCH_TABLE.'
42  WHERE id = '.$search_id.'
43;';
44  list($serialized_rules) = pwg_db_fetch_row(pwg_query($query));
45
46  return unserialize($serialized_rules);
47}
48
49/**
50 * returns the SQL clause from a search identifier
51 *
52 * Search rules are stored in search table as a serialized array. This array
53 * need to be transformed into an SQL clause to be used in queries.
54 *
55 * @param array search
56 * @return string
57 */
58function get_sql_search_clause($search)
59{
60  // SQL where clauses are stored in $clauses array during query
61  // construction
62  $clauses = array();
63
64  foreach (array('file','name','comment','author') as $textfield)
65  {
66    if (isset($search['fields'][$textfield]))
67    {
68      $local_clauses = array();
69      foreach ($search['fields'][$textfield]['words'] as $word)
70      {
71        array_push($local_clauses, $textfield." LIKE '%".$word."%'");
72      }
73
74      // adds brackets around where clauses
75      $local_clauses = prepend_append_array_items($local_clauses, '(', ')');
76
77      array_push(
78        $clauses,
79        implode(
80          ' '.$search['fields'][$textfield]['mode'].' ',
81          $local_clauses
82          )
83        );
84    }
85  }
86
87  if (isset($search['fields']['allwords']))
88  {
89    $fields = array('file', 'name', 'comment', 'author');
90    // in the OR mode, request bust be :
91    // ((field1 LIKE '%word1%' OR field2 LIKE '%word1%')
92    // OR (field1 LIKE '%word2%' OR field2 LIKE '%word2%'))
93    //
94    // in the AND mode :
95    // ((field1 LIKE '%word1%' OR field2 LIKE '%word1%')
96    // AND (field1 LIKE '%word2%' OR field2 LIKE '%word2%'))
97    $word_clauses = array();
98    foreach ($search['fields']['allwords']['words'] as $word)
99    {
100      $field_clauses = array();
101      foreach ($fields as $field)
102      {
103        array_push($field_clauses, $field." LIKE '%".$word."%'");
104      }
105      // adds brackets around where clauses
106      array_push(
107        $word_clauses,
108        implode(
109          "\n          OR ",
110          $field_clauses
111          )
112        );
113    }
114
115    array_walk(
116      $word_clauses,
117      create_function('&$s','$s="(".$s.")";')
118      );
119
120    // make sure the "mode" is either OR or AND
121    if ($search['fields']['allwords']['mode'] != 'AND' and $search['fields']['allwords']['mode'] != 'OR')
122    {
123      $search['fields']['allwords']['mode'] = 'AND';
124    }
125
126    $clauses[] = "\n         ".
127      implode(
128        "\n         ".
129              $search['fields']['allwords']['mode'].
130        "\n         ",
131        $word_clauses
132        )
133      );
134  }
135
136  foreach (array('date_available', 'date_creation') as $datefield)
137  {
138    if (isset($search['fields'][$datefield]))
139    {
140      array_push(
141        $clauses,
142        $datefield." = '".$search['fields'][$datefield]['date']."'"
143        );
144    }
145
146    foreach (array('after','before') as $suffix)
147    {
148      $key = $datefield.'-'.$suffix;
149
150      if (isset($search['fields'][$key]))
151      {
152        array_push(
153          $clauses,
154
155          $datefield.
156          ($suffix == 'after'             ? ' >' : ' <').
157          ($search['fields'][$key]['inc'] ? '='  : '').
158          " '".$search['fields'][$key]['date']."'"
159
160          );
161      }
162    }
163  }
164
165  if (isset($search['fields']['cat']))
166  {
167    if ($search['fields']['cat']['sub_inc'])
168    {
169      // searching all the categories id of sub-categories
170      $cat_ids = get_subcat_ids($search['fields']['cat']['words']);
171    }
172    else
173    {
174      $cat_ids = $search['fields']['cat']['words'];
175    }
176
177    $local_clause = 'category_id IN ('.implode(',', $cat_ids).')';
178    array_push($clauses, $local_clause);
179  }
180
181  // adds brackets around where clauses
182  $clauses = prepend_append_array_items($clauses, '(', ')');
183
184  $where_separator =
185    implode(
186      "\n    ".$search['mode'].' ',
187      $clauses
188      );
189
190  $search_clause = $where_separator;
191
192  return $search_clause;
193}
194
195/**
196 * returns the list of items corresponding to the advanced search array
197 *
198 * @param array search
199 * @return array
200 */
201function get_regular_search_results($search, $images_where)
202{
203  global $conf;
204  $forbidden = get_sql_condition_FandF(
205        array
206          (
207            'forbidden_categories' => 'category_id',
208            'visible_categories' => 'category_id',
209            'visible_images' => 'id'
210          ),
211        "\n  AND"
212    );
213
214  $items = array();
215  $tag_items = array();
216
217  if (isset($search['fields']['tags']))
218  {
219    $tag_items = get_image_ids_for_tags(
220      $search['fields']['tags']['words'],
221      $search['fields']['tags']['mode']
222      );
223  }
224
225  $search_clause = get_sql_search_clause($search);
226
227  if (!empty($search_clause))
228  {
229    $query = '
230SELECT DISTINCT(id)
231  FROM '.IMAGES_TABLE.' i
232    INNER JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON id = ic.image_id
233  WHERE '.$search_clause;
234    if (!empty($images_where))
235    {
236      $query .= "\n  AND ".$images_where;
237    }
238    $query .= $forbidden.'
239  '.$conf['order_by'];
240    $items = array_from_query($query, 'id');
241  }
242
243  if ( !empty($tag_items) )
244  {
245    switch ($search['mode'])
246    {
247      case 'AND':
248        if (empty($search_clause))
249        {
250          $items = $tag_items;
251        }
252        else
253        {
254          $items = array_values( array_intersect($items, $tag_items) );
255        }
256        break;
257      case 'OR':
258        $before_count = count($items);
259        $items = array_unique(
260          array_merge(
261            $items,
262            $tag_items
263            )
264          );
265        break;
266    }
267  }
268
269  return $items;
270}
271
272
273function is_word_char($ch)
274{
275  return ($ch>='0' && $ch<='9') || ($ch>='a' && $ch<='z') || ($ch>='A' && $ch<='Z') || ord($ch)>127;
276}
277
278function is_odd_wbreak_begin($ch)
279{
280  return strpos('[{<=*+', $ch)===false ? false:true;
281}
282
283function is_odd_wbreak_end($ch)
284{
285  return strpos(']}>=*+', $ch)===false ? false:true;
286}
287
288define('QST_QUOTED',   0x01);
289define('QST_NOT',      0x02);
290define('QST_WILDCARD_BEGIN',0x04);
291define('QST_WILDCARD_END',  0x08);
292define('QST_WILDCARD', QST_WILDCARD_BEGIN|QST_WILDCARD_END);
293
294
295/**
296 * analyzes and splits the quick/query search query $q into tokens
297 * q='john bill' => 2 tokens 'john' 'bill'
298 * Special characters for MySql full text search (+,<,>,~) appear in the token modifiers.
299 * The query can contain a phrase: 'Pierre "New York"' will return 'pierre' qnd 'new york'.
300 */
301function analyse_qsearch($q, &$qtokens, &$qtoken_modifiers)
302{
303  $q = stripslashes($q);
304  $tokens = array();
305  $token_modifiers = array();
306  $crt_token = "";
307  $crt_token_modifier = 0;
308
309  for ($i=0; $i<strlen($q); $i++)
310  {
311    $ch = $q[$i];
312    if ( ($crt_token_modifier&QST_QUOTED)==0)
313    {
314        if ($ch=='"')
315        {
316          if (strlen($crt_token))
317          {
318            $tokens[] = $crt_token; $token_modifiers[] = $crt_token_modifier;
319            $crt_token = ""; $crt_token_modifier = 0;
320          }
321          $crt_token_modifier |= QST_QUOTED;
322        }
323        elseif ( strcspn($ch, '*+-><~')==0 )
324        { //special full text modifier
325          if (strlen($crt_token))
326          {
327            $crt_token .= $ch;
328          }
329          else
330          {
331            if ( $ch=='*' )
332              $crt_token_modifier |= QST_WILDCARD_BEGIN;
333            if ( $ch=='-' )
334              $crt_token_modifier |= QST_NOT;
335          }
336        }
337        elseif (preg_match('/[\s,.;!\?]+/', $ch))
338        { // white space
339          if (strlen($crt_token))
340          {
341            $tokens[] = $crt_token; $token_modifiers[] = $crt_token_modifier;
342            $crt_token = "";
343          }
344          $crt_token_modifier = 0;
345        }
346        else
347        {
348          $crt_token .= $ch;
349        }
350    }
351    else // qualified with quotes
352    {
353      if ($ch=='"')
354      {
355        if ($i+1 < strlen($q) && $q[$i+1]=='*')
356        {
357          $crt_token_modifier |= QST_WILDCARD_END;
358          $i++;
359        }
360        $tokens[] = $crt_token; $token_modifiers[] = $crt_token_modifier;
361        $crt_token = ""; $crt_token_modifier = 0;
362        $state=0;
363      }
364      else
365        $crt_token .= $ch;
366    }
367  }
368
369  if (strlen($crt_token))
370  {
371    $tokens[] = $crt_token;
372    $token_modifiers[] = $crt_token_modifier;
373  }
374
375  $qtokens = array();
376  $qtoken_modifiers = array();
377  for ($i=0; $i<count($tokens); $i++)
378  {
379    if (strstr($token_modifiers[$i], 'q')===false)
380    {
381      if ( substr($tokens[$i], -1)=='*' )
382      {
383        $tokens[$i] = rtrim($tokens[$i], '*');
384        $token_modifiers[$i] .= '*';
385      }
386    }
387    if ( strlen($tokens[$i])==0)
388      continue;
389    $qtokens[] = $tokens[$i];
390    $qtoken_modifiers[] = $token_modifiers[$i];
391  }
392}
393
394
395/**
396 * returns the LIKE sql clause corresponding to the quick search query
397 * that has been split into tokens
398 * for example file LIKE '%john%' OR file LIKE '%bill%'.
399 */
400function get_qsearch_like_clause($tokens, $token_modifiers, $field)
401{
402  $clauses = array();
403  for ($i=0; $i<count($tokens); $i++)
404  {
405    $token = trim($tokens[$i], '%');
406    if ($token_modifiers[$i]&QST_NOT)
407      continue;
408    if ( strlen($token)==0 )
409      continue;
410    $token = addslashes($token);
411    $token = str_replace( array('%','_'), array('\\%','\\_'), $token); // escape LIKE specials %_
412    $clauses[] = $field.' LIKE \'%'.$token.'%\'';
413  }
414
415  return count($clauses) ? '('.implode(' OR ', $clauses).')' : null;
416}
417
418/**
419*/
420function get_qsearch_tags($tokens, $token_modifiers, &$token_tag_ids, &$not_tag_ids, &$all_tags)
421{
422  $token_tag_ids = array_fill(0, count($tokens), array() );
423  $not_tag_ids = $all_tags = array();
424
425  $token_tag_scores = $token_tag_ids;
426  $transliterated_tokens = array();
427  foreach ($tokens as $token)
428  {
429    $transliterated_tokens[] = transliterate($token);
430  }
431
432  $query = '
433SELECT t.*, COUNT(image_id) AS counter
434  FROM '.TAGS_TABLE.' t
435    INNER JOIN '.IMAGE_TAG_TABLE.' ON id=tag_id
436  GROUP BY id';
437  $result = pwg_query($query);
438  while ($tag = pwg_db_fetch_assoc($result))
439  {
440    $transliterated_tag = transliterate($tag['name']);
441
442    // find how this tag matches query tokens
443    for ($i=0; $i<count($tokens); $i++)
444    {
445      $transliterated_token = $transliterated_tokens[$i];
446
447      $match = false;
448      $pos = 0;
449      while ( ($pos = strpos($transliterated_tag, $transliterated_token, $pos)) !== false)
450      {
451        if ( ($token_modifiers[$i]&QST_WILDCARD)==QST_WILDCARD )
452        {// wildcard in this token
453          $match = 1;
454          break;
455        }
456        $token_len = strlen($transliterated_token);
457
458        // search begin of word
459        $wbegin_len=0; $wbegin_char=' ';
460        while ($pos-$wbegin_len > 0)
461        {
462          if (! is_word_char($transliterated_tag[$pos-$wbegin_len-1]) )
463          {
464            $wbegin_char = $transliterated_tag[$pos-$wbegin_len-1];
465            break;
466          }
467          $wbegin_len++;
468        }
469
470        // search end of word
471        $wend_len=0; $wend_char=' ';
472        while ($pos+$token_len+$wend_len < strlen($transliterated_tag))
473        {
474          if (! is_word_char($transliterated_tag[$pos+$token_len+$wend_len]) )
475          {
476            $wend_char = $transliterated_tag[$pos+$token_len+$wend_len];
477            break;
478          }
479          $wend_len++;
480        }
481
482        $this_score = 0;
483        if ( ($token_modifiers[$i]&QST_WILDCARD)==0 )
484        {// no wildcard begin or end
485          if ($token_len <= 2)
486          {// search for 1 or 2 characters must match exactly to avoid retrieving too much data
487            if ($wbegin_len==0 && $wend_len==0 && !is_odd_wbreak_begin($wbegin_char) && !is_odd_wbreak_end($wend_char) )
488              $this_score = 1;
489          }
490          elseif ($token_len == 3)
491          {
492            if ($wbegin_len==0)
493              $this_score = $token_len / ($token_len + $wend_len);
494          }
495          else
496          {
497            $this_score = $token_len / ($token_len + 1.1 * $wbegin_len + 0.9 * $wend_len);
498          }
499        }
500
501        if ($this_score>0)
502          $match = max($match, $this_score );
503        $pos++;
504      }
505
506      if ($match)
507      {
508        $tag_id = (int)$tag['id'];
509        $all_tags[$tag_id] = $tag;
510        $token_tag_ids[$i][] = $tag_id;
511        $token_tag_scores[$i][] = $match;
512      }
513    }
514  }
515
516  // process not tags
517  for ($i=0; $i<count($tokens); $i++)
518  {
519    if ( ! ($token_modifiers[$i]&QST_NOT) )
520      continue;
521
522    array_multisort($token_tag_scores[$i], SORT_DESC|SORT_NUMERIC, $token_tag_ids[$i]);
523
524    for ($j=0; $j<count($token_tag_scores[$i]); $j++)
525    {
526      if ($token_tag_scores[$i][$j] < 0.8)
527        break;
528      if ($j>0 && $token_tag_scores[$i][$j] < $token_tag_scores[$i][0])
529        break;
530      $tag_id = $token_tag_ids[$i][$j];
531      if ( isset($all_tags[$tag_id]) )
532      {
533        unset($all_tags[$tag_id]);
534        $not_tag_ids[] = $tag_id;
535      }
536    }
537    $token_tag_ids[$i] = array();
538  }
539
540  // process regular tags
541  for ($i=0; $i<count($tokens); $i++)
542  {
543    if ( $token_modifiers[$i]&QST_NOT )
544      continue;
545
546    array_multisort($token_tag_scores[$i], SORT_DESC|SORT_NUMERIC, $token_tag_ids[$i]);
547
548    $counter = 0;
549    for ($j=0; $j<count($token_tag_scores[$i]); $j++)
550    {
551      $tag_id = $token_tag_ids[$i][$j];
552      if ( ! isset($all_tags[$tag_id]) )
553      {
554        array_splice($token_tag_ids[$i], $j, 1);
555        array_splice($token_tag_scores[$i], $j, 1);
556      }
557
558      $counter += $all_tags[$tag_id]['counter'];
559      if ($counter > 200 && $j>0 && $token_tag_scores[$i][0] > $token_tag_scores[$i][$j] )
560      {// "many" images in previous tags and starting from this tag is less relevent
561        array_splice($token_tag_ids[$i], $j);
562        array_splice($token_tag_scores[$i], $j);
563        break;
564      }
565    }
566  }
567 
568  usort($all_tags, 'tag_alpha_compare');
569  foreach ( $all_tags as &$tag )
570    $tag['name'] = trigger_event('render_tag_name', $tag['name']);
571}
572
573/**
574 * returns the search results corresponding to a quick/query search.
575 * A quick/query search returns many items (search is not strict), but results
576 * are sorted by relevance unless $super_order_by is true. Returns:
577 * array (
578 * 'items' => array(85,68,79...)
579 * 'qs'    => array(
580 *    'matching_tags' => array of matching tags
581 *    'matching_cats' => array of matching categories
582 *    'matching_cats_no_images' =>array(99) - matching categories without images
583 *      ))
584 *
585 * @param string q
586 * @param bool super_order_by
587 * @param string images_where optional aditional restriction on images table
588 * @return array
589 */
590function get_quick_search_results($q, $super_order_by, $images_where='')
591{
592  global $user, $conf;
593
594  $search_results =
595    array(
596      'items' => array(),
597      'qs' => array('q'=>stripslashes($q)),
598    );
599  $q = trim($q);
600  analyse_qsearch($q, $tokens, $token_modifiers);
601  if (count($tokens)==0)
602  {
603    return $search_results;
604  }
605  $debug[] = '<!--'.count($tokens).' tokens';
606
607  $q_like_field = '@@__db_field__@@'; //something never in a search
608  $q_like_clause = get_qsearch_like_clause($tokens, $token_modifiers, $q_like_field );
609
610  // Step 1 - first we find matches in #images table ===========================
611  $where_clauses='MATCH(i.name, i.comment) AGAINST( \''.$q.'\' IN BOOLEAN MODE)';
612  if (!empty($q_like_clause))
613  {
614    $where_clauses .= '
615    OR '. str_replace($q_like_field, 'CONVERT(file, CHAR)', $q_like_clause);
616    $where_clauses = '('.$where_clauses.')';
617  }
618  $where_clauses = array($where_clauses);
619  if (!empty($images_where))
620  {
621    $where_clauses[]='('.$images_where.')';
622  }
623  $where_clauses[] .= get_sql_condition_FandF
624      (
625        array( 'visible_images' => 'i.id' ), null, true
626      );
627  $query = '
628SELECT i.id,
629    MATCH(i.name, i.comment) AGAINST( \''.$q.'\' IN BOOLEAN MODE) AS weight
630  FROM '.IMAGES_TABLE.' i
631  WHERE '.implode("\n AND ", $where_clauses);
632
633  $by_weights=array();
634  $result = pwg_query($query);
635  while ($row = pwg_db_fetch_assoc($result))
636  { // weight is important when sorting images by relevance
637    if ($row['weight'])
638    {
639      $by_weights[(int)$row['id']] =  2*$row['weight'];
640    }
641    else
642    {//full text does not match but file name match
643      $by_weights[(int)$row['id']] =  2;
644    }
645  }
646  $debug[] = count($by_weights).' fulltext';
647  if (!empty($by_weights))
648  {
649    $debug[] = 'ft score min:'.min($by_weights).' max:'.max($by_weights);
650  }
651
652
653  // Step 2 - get the tags and the images for tags
654  get_qsearch_tags($tokens, $token_modifiers, $token_tag_ids, $not_tag_ids, $search_results['qs']['matching_tags']);
655  $debug[] = count($search_results['qs']['matching_tags']).' tags';
656
657  for ($i=0; $i<count($token_tag_ids); $i++)
658  {
659    $tag_ids = $token_tag_ids[$i];
660    $debug[] = count($tag_ids).' unique tags';
661
662    if (!empty($tag_ids))
663    {
664      $tag_photo_count=0;
665      $query = '
666SELECT image_id FROM '.IMAGE_TAG_TABLE.'
667  WHERE tag_id IN ('.implode(',',$tag_ids).')
668  GROUP BY image_id';
669      $result = pwg_query($query);
670      while ($row = pwg_db_fetch_assoc($result))
671      { // weight is important when sorting images by relevance
672        $image_id=(int)$row['image_id'];
673        @$by_weights[$image_id] += 1;
674        $tag_photo_count++;
675      }
676      $debug[] = $tag_photo_count.' photos for tag';
677      $debug[] = count($by_weights).' photos after';
678    }
679  }
680
681  // Step 3 - search categories corresponding to the query $q ==================
682  $query = '
683SELECT id, name, permalink, nb_images
684  FROM '.CATEGORIES_TABLE.'
685    INNER JOIN '.USER_CACHE_CATEGORIES_TABLE.' ON id=cat_id
686  WHERE user_id='.$user['id'].'
687    AND MATCH(name, comment) AGAINST( \''.$q.'\' IN BOOLEAN MODE)'.
688  get_sql_condition_FandF (
689      array( 'visible_categories' => 'cat_id' ), "\n    AND"
690    );
691  $result = pwg_query($query);
692  while ($row = pwg_db_fetch_assoc($result))
693  { // weight is important when sorting images by relevance
694    if ($row['nb_images']==0)
695    {
696      $search_results['qs']['matching_cats_no_images'][] = $row;
697    }
698    else
699    {
700      $search_results['qs']['matching_cats'][$row['id']] = $row;
701    }
702  }
703  $debug[] = count(@$search_results['qs']['matching_cats']).' albums with images';
704
705  if ( empty($by_weights) and empty($search_results['qs']['matching_cats']) )
706  {
707    return $search_results;
708  }
709
710  if (!empty($not_tag_ids))
711  {
712    $query = '
713SELECT image_id FROM '.IMAGE_TAG_TABLE.'
714  WHERE tag_id IN ('.implode(',',$not_tag_ids).')
715  GROUP BY image_id';
716      $result = pwg_query($query);
717      while ($row = pwg_db_fetch_row($result))
718      {
719        $id = $row[0];
720        unset($by_weights[$id]);
721      }
722      $debug[] = count($by_weights).' after not tags';
723  }
724  // Step 4 - now we have $by_weights ( array image id => weight ) that need
725  // permission checks and/or matching categories to get images from
726  $where_clauses = array();
727  if ( !empty($by_weights) )
728  {
729    $where_clauses[]='i.id IN ('
730      . implode(',', array_keys($by_weights)) . ')';
731  }
732  if ( !empty($search_results['qs']['matching_cats']) )
733  {
734    $where_clauses[]='category_id IN ('.
735      implode(',',array_keys($search_results['qs']['matching_cats'])).')';
736  }
737  $where_clauses = array( '('.implode("\n    OR ",$where_clauses).')' );
738  if (!empty($images_where))
739  {
740    $where_clauses[]='('.$images_where.')';
741  }
742  $where_clauses[] = get_sql_condition_FandF(
743      array
744        (
745          'forbidden_categories' => 'category_id',
746          'visible_categories' => 'category_id',
747          'visible_images' => 'i.id'
748        ),
749      null,true
750    );
751
752  $query = '
753SELECT DISTINCT(id)
754  FROM '.IMAGES_TABLE.' i
755    INNER JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON id = ic.image_id
756  WHERE '.implode("\n AND ", $where_clauses)."\n".
757  $conf['order_by'];
758
759  $allowed_images = array_from_query( $query, 'id');
760
761  $debug[] = count($allowed_images).' final photo count -->';
762  global $template;
763  $template->append('footer_elements', implode(', ', $debug) );
764
765  if ( $super_order_by or empty($by_weights) )
766  {
767    $search_results['items'] = $allowed_images;
768    return $search_results;
769  }
770
771  $allowed_images = array_flip( $allowed_images );
772  $divisor = 5.0 * count($allowed_images);
773  foreach ($allowed_images as $id=>$rank )
774  {
775    $weight = isset($by_weights[$id]) ? $by_weights[$id] : 1;
776    $weight -= $rank/$divisor;
777    $allowed_images[$id] = $weight;
778  }
779  arsort($allowed_images, SORT_NUMERIC);
780  $search_results['items'] = array_keys($allowed_images);
781  return $search_results;
782}
783
784/**
785 * returns an array of 'items' corresponding to the search id
786 *
787 * @param int search id
788 * @param string images_where optional aditional restriction on images table
789 * @return array
790 */
791function get_search_results($search_id, $super_order_by, $images_where='')
792{
793  $search = get_search_array($search_id);
794  if ( !isset($search['q']) )
795  {
796    $result['items'] = get_regular_search_results($search, $images_where);
797    return $result;
798  }
799  else
800  {
801    return get_quick_search_results($search['q'], $super_order_by, $images_where);
802  }
803}
804?>
Note: See TracBrowser for help on using the repository browser.