source: extensions/SmartAlbums/include/functions.inc.php @ 17677

Last change on this file since 17677 was 17677, checked in by mistic100, 12 years ago

add album filter

File size: 15.1 KB
Line 
1<?php
2if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
3
4/*
5 * Associates images to the category according to the filters
6 * @param int category_id
7 * @return array
8 */
9function smart_make_associations($cat_id)
10{
11  $query = '
12DELETE FROM '.IMAGE_CATEGORY_TABLE.'
13  WHERE
14    category_id = '.$cat_id.'
15    AND smart = true
16;';
17  pwg_query($query);
18 
19  $images = smart_get_pictures($cat_id);
20 
21  if (count($images) != 0)
22  {
23    foreach ($images as $img)
24    {
25      $datas[] = array(
26        'image_id' => $img,
27        'category_id' => $cat_id,
28        'smart' => true,
29        );
30    }
31    mass_inserts_ignore(
32      IMAGE_CATEGORY_TABLE, 
33      array_keys($datas[0]), 
34      $datas
35      );
36  }
37 
38  // representant, try to not overwrite if still in images list
39  $query = '
40SELECT representative_picture_id
41  FROM '.CATEGORIES_TABLE.'
42  WHERE id = '.$cat_id.'
43;';
44  list($rep_id) = pwg_db_fetch_row(pwg_query($query));
45 
46  if ( !in_array($rep_id, $images) )
47  {
48    include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
49    set_random_representant(array($cat_id));
50  }
51 
52  return $images;
53}
54
55
56/*
57 * Make associations for all SmartAlbums
58 * Called with invalidate_user_cache
59 */
60function smart_make_all_associations()
61{
62  global $conf;
63 
64  if ( defined('SMART_NOT_UPDATE') OR !$conf['SmartAlbums']['update_on_upload'] ) return;
65 
66  /* get categories with smart filters */
67  $query = '
68SELECT DISTINCT id
69  FROM '.CATEGORIES_TABLE.' AS c
70    INNER JOIN '.CATEGORY_FILTERS_TABLE.' AS cf
71    ON c.id = cf.category_id
72;';
73 
74  /* regenerate photo list */
75  $smart_cats = array_from_query($query, 'id');
76  array_map('smart_make_associations', $smart_cats);
77}
78
79
80/*
81 * Generates the list of images, according to the filters of the category
82 * @param int category_id
83 * @param array filters, if null => catch from db
84 * @return array
85 */
86function smart_get_pictures($cat_id, $filters = null)
87{
88  global $conf;
89
90  /* get filters */
91  if ($filters === null)
92  {
93    $query = '
94SELECT *
95  FROM '.CATEGORY_FILTERS_TABLE.'
96  WHERE category_id = '.$cat_id.'
97  ORDER BY type ASC, cond ASC
98;';
99    $result = pwg_query($query);
100   
101    if (!pwg_db_num_rows($result)) return array();
102   
103    $filters = array();
104    while ($row = pwg_db_fetch_assoc($result))
105    {
106      $filters[] = array(
107        'type' => $row['type'],
108        'cond' => $row['cond'],
109        'value' => $row['value'],
110        );
111    }
112  }
113  else if (!count($filters))
114  {
115    return array();
116  }
117   
118  /* build constrains */
119  ## generate 'join', 'where' arrays and 'limit' string to create the SQL query
120  ## inspired by PicsEngine 3 by Michael Villar
121  $i_tags = 1;
122  foreach ($filters as $filter)
123  {
124    switch ($filter['type'])
125    {
126      // tags
127      case 'tags':
128      {
129        switch ($filter['cond'])
130        {
131          // search images which have all tags
132          case 'all':
133          {
134            $tags_arr = explode(',', $filter['value']);
135            foreach($tags_arr as $value)
136            {
137              $join[] = IMAGE_TAG_TABLE.' AS it'.$i_tags.' ON i.id = it'.$i_tags.'.image_id';
138              $where[] = 'it'.$i_tags.'.tag_id = '.$value;
139              $i_tags++;
140            }
141           
142            break;
143          }
144          // search images which tags are in the list
145          case 'one':
146          {
147            $join[] = IMAGE_TAG_TABLE.' AS it'.$i_tags.' ON i.id = it'.$i_tags.'.image_id';
148            $where[] = 'it'.$i_tags.'.tag_id IN ('.$filter['value'].')';
149            $i_tags++;
150           
151            break;
152          }
153          // exclude images which tags are in the list
154          case 'none':
155          {
156            $sub_query = '
157      SELECT it'.$i_tags.'.image_id
158        FROM '.IMAGE_TAG_TABLE.' AS it'.$i_tags.'
159        WHERE
160          it'.$i_tags.'.image_id = i.id AND
161          it'.$i_tags.'.tag_id IN ('.$filter['value'].')
162        GROUP BY it'.$i_tags.'.image_id
163      ';
164            $join[] = IMAGE_TAG_TABLE.' AS it'.$i_tags.' ON i.id = it'.$i_tags.'.image_id';
165            $where[] = 'NOT EXISTS ('.$sub_query.')';
166            $i_tags++;
167           
168            break;
169          }
170          // exclude images which tags are not in the list and search images which have all tags
171          case 'only':
172          {
173            $sub_query = '
174      SELECT it'.$i_tags.'.image_id
175        FROM '.IMAGE_TAG_TABLE.' AS it'.$i_tags.'
176        WHERE
177          it'.$i_tags.'.image_id = i.id AND
178          it'.$i_tags.'.tag_id NOT IN ('.$filter['value'].')
179        GROUP BY it'.$i_tags.'.image_id
180      ';
181            $join[] = IMAGE_TAG_TABLE.' AS it'.$i_tags.' ON i.id = it'.$i_tags.'.image_id';
182            $where[] = 'NOT EXISTS ('.$sub_query.')';
183            $i_tags++;
184           
185            $tags_arr = explode(',', $filter['value']);
186            foreach($tags_arr as $value)
187            {
188              $join[] = IMAGE_TAG_TABLE.' AS it'.$i_tags.' ON i.id = it'.$i_tags.'.image_id';
189              $where[] = 'it'.$i_tags.'.tag_id = '.$value;
190              $i_tags++;
191            }
192           
193            break;
194          }
195        }
196       
197        break;
198      }
199   
200      // date
201      case 'date':
202      {
203        switch ($filter['cond'])
204        {
205          case 'the_post':
206            $where[] = 'date_available BETWEEN "'.$filter['value'].' 00:00:00" AND "'.$filter['value'].' 23:59:59"';
207            break;
208          case 'before_post':
209            $where[] = 'date_available < "'.$filter['value'].' 00:00:00"';
210            break;
211          case 'after_post':
212            $where[] = 'date_available > "'.$filter['value'].' 23:59:59"';
213            break;
214          case 'the_taken':
215            $where[] = 'date_creation BETWEEN "'.$filter['value'].' 00:00:00" AND "'.$filter['value'].' 23:59:59"';
216            break;
217          case 'before_taken':
218            $where[] = 'date_creation < "'.$filter['value'].' 00:00:00"';
219            break;
220          case 'after_taken':
221            $where[] = 'date_creation > "'.$filter['value'].' 23:59:59"';
222            break;
223        }
224       
225        break;
226      }
227     
228      // name
229      case 'name':
230      {
231        switch ($filter['cond'])
232        {
233          case 'contain':
234            $where[] = 'name LIKE "%'.$filter['value'].'%"';
235            break;
236          case 'begin':
237            $where[] = 'name LIKE "'.$filter['value'].'%"';
238            break;
239          case 'end':
240            $where[] = 'name LIKE "%'.$filter['value'].'"';
241            break;
242          case 'not_contain':
243            $where[] = 'name NOT LIKE "%'.$filter['value'].'%"';
244            break;
245          case 'not_begin':
246            $where[] = 'name NOT LIKE "'.$filter['value'].'%"';
247            break;
248          case 'not_end':
249            $where[] = 'name NOT LIKE "%'.$filter['value'].'"';
250            break;
251        }
252       
253        break;
254      }
255     
256      // album
257      case 'album':
258      {
259        switch ($filter['cond'])
260        {
261          // search images existing in all albums
262          case 'all':
263          {
264            $albums_arr = explode(',', $filter['value']);
265            foreach($albums_arr as $value)
266            {
267              $sub_query = '
268      SELECT image_id
269        FROM '.IMAGE_CATEGORY_TABLE.'
270        WHERE category_id = '.$value.'
271      ';
272              $where[] = 'i.id IN ('.$sub_query.')';
273            }
274           
275            break;
276          }
277          // search images existing in one of these albums
278          case 'one':
279          {
280            $sub_query = '
281      SELECT image_id
282        FROM '.IMAGE_CATEGORY_TABLE.'
283        WHERE category_id IN('.$filter['value'].')
284      ';
285            $where[] = 'i.id IN ('.$sub_query.')';
286           
287            break;
288          }
289          // exclude images existing in one of these albums
290          case 'none':
291          {
292            $sub_query = '
293      SELECT image_id
294        FROM '.IMAGE_CATEGORY_TABLE.'
295        WHERE category_id IN('.$filter['value'].')
296      ';
297            $where[] = 'i.id NOT IN ('.$sub_query.')';
298           
299            break;
300          }
301          // exclude images existing on other albums, and search images existing in all albums
302          case 'only':
303          {
304            $sub_query = '
305      SELECT image_id
306        FROM '.IMAGE_CATEGORY_TABLE.'
307        WHERE category_id NOT IN('.$filter['value'].')
308      ';
309            $where[] = 'i.id NOT IN ('.$sub_query.')';
310           
311            $albums_arr = explode(',', $filter['value']);
312            foreach($albums_arr as $value)
313            {
314              $sub_query = '
315      SELECT image_id
316        FROM '.IMAGE_CATEGORY_TABLE.'
317        WHERE category_id = '.$value.'
318      ';
319              $where[] = 'i.id IN ('.$sub_query.')';
320            }
321           
322            break;
323          }
324        }
325       
326        break;
327      }
328     
329      // author
330      case 'author':
331      {
332        switch ($filter['cond'])
333        {
334          case 'is':
335            if ($filter['value'] != 'NULL') $filter['value'] = '"'.$filter['value'].'"';
336            $where[] = 'author = '.$filter['value'].'';
337            break;
338          case 'not_is':
339            if ($filter['value'] != 'NULL') $filter['value'] = '"'.$filter['value'].'"';
340            $where[] = 'author != '.$filter['value'].'';
341            break;
342          case 'in':
343            $filter['value'] = '"'.str_replace(',', '","', $filter['value']).'"';
344            $where[] = 'author IN('.$filter['value'].')';
345            break;
346          case 'not_in':
347            $filter['value'] = '"'.str_replace(',', '","', $filter['value']).'"';
348            $where[] = 'author NOT IN('.$filter['value'].')';
349            break;
350        }
351       
352        break;
353      }
354     
355      // hit
356      case 'hit':
357      {
358        switch ($filter['cond'])
359        {
360          case 'less':
361            $where[] = 'hit < '.$filter['value'].'';
362            break;
363          case 'more':
364            $where[] = 'hit >= '.$filter['value'].'';
365            break;
366        }
367       
368        break;
369      }
370     
371      // rating_score
372      case 'rating_score':
373      {
374        switch ($filter['cond'])
375        {
376          case 'less':
377            $where[] = 'rating_score < '.$filter['value'].'';
378            break;
379          case 'more':
380            $where[] = 'rating_score >= '.$filter['value'].'';
381            break;
382        }
383       
384        break;
385      }
386     
387      // level
388      case 'level':
389      {
390        $where[] = 'level = '.$filter['value'].'';
391        break;
392      }
393     
394      // limit
395      case 'limit':
396      {
397        $limit = '0, '.$filter['value'];
398        break;
399      }
400    }
401  }
402 
403  /* bluid query */
404  $MainQuery = '
405SELECT i.id
406  FROM '.IMAGES_TABLE.' AS i';
407   
408    if (isset($join))
409    {
410      $MainQuery.= '
411    LEFT JOIN '.implode("\n    LEFT JOIN ", $join);
412    }
413    if (isset($where))
414    {
415      $MainQuery.= '
416  WHERE
417    '.implode("\n    AND ", $where);
418    }
419
420  $MainQuery.= '
421  GROUP BY i.id
422  '.$conf['order_by'].'
423  '.(isset($limit) ? "LIMIT ".$limit : null).'
424;';
425
426  // file_put_contents(SMART_PATH.'query.sql', $MainQuery);
427  return array_from_query($MainQuery, 'id');
428}
429
430
431/**
432 * Check if the filter is proper
433 * @param array filter
434 * @return array or false
435 */
436function smart_check_filter($filter)
437{
438  global $page, $limit_is_set, $level_is_set;
439  $error = false;
440 
441  if (!isset($limit_is_set)) $limit_is_set = false;
442  if (!isset($level_is_set)) $level_is_set = false;
443 
444  # tags
445  if ($filter['type'] == 'tags')
446  {
447    if ($filter['value'] == null)
448    {
449      $error = true;
450      array_push($page['errors'], l10n('No tag selected'));
451    }
452    else
453    {
454      $filter['value'] = implode(',', get_tag_ids($filter['value']));
455    }
456  }
457  # date
458  else if ($filter['type'] == 'date')
459  {
460    if (!preg_match('#([0-9]{4})-([0-9]{2})-([0-9]{2})#', $filter['value']))
461    {
462      $error = true;
463      array_push($page['errors'], l10n('Date string is malformed'));
464    }
465  }
466  # name
467  else if ($filter['type'] == 'name')
468  {
469    if (empty($filter['value']))
470    {
471      $error = true;
472      array_push($page['errors'], l10n('Name is empty'));
473    }
474  }
475  # album
476  else if ($filter['type'] == 'album')
477  {
478    if (@$filter['value'] == null)
479    {
480      $error = true;
481      array_push($page['errors'], l10n('No album selected'));
482    }
483    else
484    {
485      $filter['value'] = implode(',', $filter['value']);
486    }
487  }
488  # author
489  else if ($filter['type'] == 'author')
490  {
491    if (empty($filter['value']))
492    {
493      $error = true;
494      array_push($page['errors'], l10n('Author is empty'));
495    }
496    else
497    {
498      $filter['value'] = preg_replace('#([ ]?),([ ]?)#', ',', $filter['value']);
499    }
500  }
501  # hit
502  else if ($filter['type'] == 'hit')
503  {
504    if (!preg_match('#([0-9]{1,})#', $filter['value']))
505    {
506      $error = true;
507      array_push($page['errors'], l10n('Hits must be an integer'));
508    }
509  }
510  # rating_score
511  else if ($filter['type'] == 'rating_score')
512  {
513    if (!preg_match('#([0-9]{1,})#', $filter['value']))
514    {
515      $error = true;
516      array_push($page['errors'], l10n('Rating score must be an integer'));
517    }
518  }
519  # level
520  else if ($filter['type'] == 'level')
521  {
522    if ($level_is_set == true) // only one level is allowed, first is saved
523    {
524      $error = true;
525      array_push($page['errors'], l10n('You can\'t use more than one level filter'));
526    }
527    else
528    {
529      $level_is_set = true;
530    }
531  }
532  # limit
533  else if ($filter['type'] == 'limit')
534  {
535    if (!preg_match('#([0-9]{1,})#', $filter['value']))
536    {
537      $error = true;
538      array_push($page['errors'], l10n('Limit must be an integer'));
539    }
540    else if ($limit_is_set == true) // only one limit is allowed, first is saved
541    {
542      $error = true;
543      array_push($page['errors'], l10n('You can\'t use more than one limit filter'));
544    }
545    else
546    {
547      $limit_is_set = true;
548    }
549  }
550 
551  # out
552  if ($error == false)
553  {
554    return $filter;
555  }
556  else
557  {
558    return false;
559  }
560}
561
562
563/**
564 * inserts multiple lines in a table, ignore duplicate entries
565 * @param string table_name
566 * @param array dbfields
567 * @param array inserts
568 * @return void
569 */
570function mass_inserts_ignore($table_name, $dbfields, $datas)
571{
572  if (count($datas) != 0)
573  {
574    $first = true;
575
576    $query = 'SHOW VARIABLES LIKE \'max_allowed_packet\'';
577    list(, $packet_size) = pwg_db_fetch_row(pwg_query($query));
578    $packet_size = $packet_size - 2000; // The last list of values MUST not exceed 2000 character*/
579    $query = '';
580
581    foreach ($datas as $insert)
582    {
583      if (strlen($query) >= $packet_size)
584      {
585        pwg_query($query);
586        $first = true;
587      }
588
589      if ($first)
590      {
591        $query = '
592INSERT IGNORE INTO '.$table_name.'
593  ('.implode(',', $dbfields).')
594  VALUES';
595        $first = false;
596      }
597      else
598      {
599        $query .= '
600  , ';
601      }
602
603      $query .= '(';
604      foreach ($dbfields as $field_id => $dbfield)
605      {
606        if ($field_id > 0)
607        {
608          $query .= ',';
609        }
610
611        if (!isset($insert[$dbfield]) or $insert[$dbfield] === '')
612        {
613          $query .= 'NULL';
614        }
615        else
616        {
617          $query .= "'".$insert[$dbfield]."'";
618        }
619      }
620      $query .= ')';
621    }
622    pwg_query($query);
623  }
624}
625
626/**
627 * clean table when categories are deleted
628 */
629function smart_delete_categories($ids)
630{
631  $query = '
632DELETE FROM '.CATEGORY_FILTERS_TABLE.'
633  WHERE category_id IN('.implode(',', $ids).')
634;';
635  pwg_query($query);
636}
637
638?>
Note: See TracBrowser for help on using the repository browser.