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

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

updated for Piwigo 2.4
new filters : name, author, level, hits

File size: 12.2 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      // author
257      case 'author':
258      {
259        switch ($filter['cond'])
260        {
261          case 'is':
262            if ($filter['value'] != 'NULL') $filter['value'] = '"'.$filter['value'].'"';
263            $where[] = 'author = '.$filter['value'].'';
264            break;
265          case 'not_is':
266            if ($filter['value'] != 'NULL') $filter['value'] = '"'.$filter['value'].'"';
267            $where[] = 'author != '.$filter['value'].'';
268            break;
269          case 'in':
270            $filter['value'] = '"'.str_replace(',', '","', $filter['value']).'"';
271            $where[] = 'author IN('.$filter['value'].')';
272            break;
273          case 'not_in':
274            $filter['value'] = '"'.str_replace(',', '","', $filter['value']).'"';
275            $where[] = 'author NOT IN('.$filter['value'].')';
276            break;
277        }
278       
279        break;
280      }
281     
282      // hit
283      case 'hit':
284      {
285        switch ($filter['cond'])
286        {
287          case 'less':
288            $where[] = 'hit < '.$filter['value'].'';
289            break;
290          case 'more':
291            $where[] = 'hit >= '.$filter['value'].'';
292            break;
293        }
294       
295        break;
296      }
297     
298      // level
299      case 'level':
300      {
301        $where[] = 'level = '.$filter['value'].'';
302        break;
303      }
304     
305      // limit
306      case 'limit':
307      {
308        $limit = '0, '.$filter['value'];
309        break;
310      }
311    }
312  }
313 
314  /* bluid query */
315  $MainQuery = '
316SELECT i.id
317  FROM '.IMAGES_TABLE.' AS i';
318   
319    if (isset($join))
320    {
321      $MainQuery.= '
322    LEFT JOIN '.implode("\n    LEFT JOIN ", $join);
323    }
324    if (isset($where))
325    {
326      $MainQuery.= '
327  WHERE
328    '.implode("\n    AND ", $where);
329    }
330
331  $MainQuery.= '
332  GROUP BY i.id
333  '.$conf['order_by'].'
334  '.(isset($limit) ? "LIMIT ".$limit : null).'
335;';
336
337  // file_put_contents(SMART_PATH.'query.sql', $MainQuery);
338  return array_from_query($MainQuery, 'id');
339}
340
341
342/**
343 * Check if the filter is proper
344 * @param array filter
345 * @return array or false
346 */
347function smart_check_filter($filter)
348{
349  global $page, $limit_is_set, $level_is_set;
350  $error = false;
351 
352  if (!isset($limit_is_set)) $limit_is_set = false;
353  if (!isset($level_is_set)) $level_is_set = false;
354 
355  # tags
356  if ($filter['type'] == 'tags')
357  {
358    if ($filter['value'] == null)
359    {
360      $error = true;
361      array_push($page['errors'], l10n('No tag selected'));
362    }
363    else
364    {
365      $filter['value'] = implode(',', get_tag_ids($filter['value']));
366    }
367  }
368  # date
369  else if ($filter['type'] == 'date')
370  {
371    if (!preg_match('#([0-9]{4})-([0-9]{2})-([0-9]{2})#', $filter['value']))
372    {
373      $error = true;
374      array_push($page['errors'], l10n('Date string is malformed'));
375    }
376  }
377  # name
378  else if ($filter['type'] == 'name')
379  {
380    if (empty($filter['value']))
381    {
382      $error = true;
383      array_push($page['errors'], l10n('Name is empty'));
384    }
385  }
386  # author
387  else if ($filter['type'] == 'author')
388  {
389    if (empty($filter['value']))
390    {
391      $error = true;
392      array_push($page['errors'], l10n('Author is empty'));
393    }
394    else
395    {
396      $filter['value'] = preg_replace('#([ ]?),([ ]?)#', ',', $filter['value']);
397    }
398  }
399  # hit
400  else if ($filter['type'] == 'hit')
401  {
402    if (!preg_match('#([0-9]{1,})#', $filter['value']))
403    {
404      $error = true;
405      array_push($page['errors'], l10n('Hits must be an integer'));
406    }
407  }
408  # level
409  else if ($filter['type'] == 'level')
410  {
411    if ($level_is_set == true) // only one level is allowed, first is saved
412    {
413      $error = true;
414      array_push($page['errors'], l10n('You can\'t use more than one level filter'));
415    }
416    else
417    {
418      $level_is_set = true;
419    }
420  }
421  # limit
422  else if ($filter['type'] == 'limit')
423  {
424    if (!preg_match('#([0-9]{1,})#', $filter['value']))
425    {
426      $error = true;
427      array_push($page['errors'], l10n('Limit must be an integer'));
428    }
429    else if ($limit_is_set == true) // only one limit is allowed, first is saved
430    {
431      $error = true;
432      array_push($page['errors'], l10n('You can\'t use more than one limit filter'));
433    }
434    else
435    {
436      $limit_is_set = true;
437    }
438  }
439 
440  # out
441  if ($error == false)
442  {
443    return $filter;
444  }
445  else
446  {
447    return false;
448  }
449}
450
451
452/**
453 * inserts multiple lines in a table, ignore duplicate entries
454 * @param string table_name
455 * @param array dbfields
456 * @param array inserts
457 * @return void
458 */
459function mass_inserts_ignore($table_name, $dbfields, $datas)
460{
461  if (count($datas) != 0)
462  {
463    $first = true;
464
465    $query = 'SHOW VARIABLES LIKE \'max_allowed_packet\'';
466    list(, $packet_size) = pwg_db_fetch_row(pwg_query($query));
467    $packet_size = $packet_size - 2000; // The last list of values MUST not exceed 2000 character*/
468    $query = '';
469
470    foreach ($datas as $insert)
471    {
472      if (strlen($query) >= $packet_size)
473      {
474        pwg_query($query);
475        $first = true;
476      }
477
478      if ($first)
479      {
480        $query = '
481INSERT IGNORE INTO '.$table_name.'
482  ('.implode(',', $dbfields).')
483  VALUES';
484        $first = false;
485      }
486      else
487      {
488        $query .= '
489  , ';
490      }
491
492      $query .= '(';
493      foreach ($dbfields as $field_id => $dbfield)
494      {
495        if ($field_id > 0)
496        {
497          $query .= ',';
498        }
499
500        if (!isset($insert[$dbfield]) or $insert[$dbfield] === '')
501        {
502          $query .= 'NULL';
503        }
504        else
505        {
506          $query .= "'".$insert[$dbfield]."'";
507        }
508      }
509      $query .= ')';
510    }
511    pwg_query($query);
512  }
513}
514
515?>
Note: See TracBrowser for help on using the repository browser.