source: trunk/admin/include/functions.php @ 2502

Last change on this file since 2502 was 2502, checked in by rvelices, 16 years ago
  • better management of fatal errors (instead of die or trigger_error rather use fatal_error ...)
  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 43.5 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based picture gallery                                  |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008      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
24include(PHPWG_ROOT_PATH.'admin/include/functions_metadata.php');
25
26
27// The function delete_site deletes a site and call the function
28// delete_categories for each primary category of the site
29function delete_site( $id )
30{
31  // destruction of the categories of the site
32  $query = '
33SELECT id
34  FROM '.CATEGORIES_TABLE.'
35  WHERE site_id = '.$id.'
36;';
37  $result = pwg_query($query);
38  $category_ids = array();
39  while ($row = mysql_fetch_array($result))
40  {
41    array_push($category_ids, $row['id']);
42  }
43  delete_categories($category_ids);
44
45  // destruction of the site
46  $query = '
47DELETE FROM '.SITES_TABLE.'
48  WHERE id = '.$id.'
49;';
50  pwg_query($query);
51}
52
53
54// The function delete_categories deletes the categories identified by the
55// (numeric) key of the array $ids. It also deletes (in the database) :
56//    - all the elements of the category (delete_elements, see further)
57//    - all the links between elements and this category
58//    - all the restrictions linked to the category
59// The function works recursively.
60function delete_categories($ids)
61{
62  if (count($ids) == 0)
63  {
64    return;
65  }
66
67  // add sub-category ids to the given ids : if a category is deleted, all
68  // sub-categories must be so
69  $ids = get_subcat_ids($ids);
70
71  // destruction of all the related elements
72  $query = '
73SELECT id
74  FROM '.IMAGES_TABLE.'
75  WHERE storage_category_id IN (
76'.wordwrap(implode(', ', $ids), 80, "\n").')
77;';
78  $result = pwg_query($query);
79  $element_ids = array();
80  while ($row = mysql_fetch_array($result))
81  {
82    array_push($element_ids, $row['id']);
83  }
84  delete_elements($element_ids);
85
86  // destruction of the links between images and this category
87  $query = '
88DELETE FROM '.IMAGE_CATEGORY_TABLE.'
89  WHERE category_id IN (
90'.wordwrap(implode(', ', $ids), 80, "\n").')
91;';
92  pwg_query($query);
93
94  // destruction of the access linked to the category
95  $query = '
96DELETE FROM '.USER_ACCESS_TABLE.'
97  WHERE cat_id IN (
98'.wordwrap(implode(', ', $ids), 80, "\n").')
99;';
100  pwg_query($query);
101
102  $query = '
103DELETE FROM '.GROUP_ACCESS_TABLE.'
104  WHERE cat_id IN (
105'.wordwrap(implode(', ', $ids), 80, "\n").')
106;';
107  pwg_query($query);
108
109  // destruction of the category
110  $query = '
111DELETE FROM '.CATEGORIES_TABLE.'
112  WHERE id IN (
113'.wordwrap(implode(', ', $ids), 80, "\n").')
114;';
115  pwg_query($query);
116
117   $query='
118DELETE FROM '.OLD_PERMALINKS_TABLE.'
119  WHERE cat_id IN ('.implode(',',$ids).')';
120  pwg_query($query);
121
122  trigger_action('delete_categories', $ids);
123}
124
125// The function delete_elements deletes the elements identified by the
126// (numeric) values of the array $ids. It also deletes (in the database) :
127//    - all the comments related to elements
128//    - all the links between categories and elements
129//    - all the favorites associated to elements
130function delete_elements($ids)
131{
132  if (count($ids) == 0)
133  {
134    return;
135  }
136
137  // destruction of the comments on the image
138  $query = '
139DELETE FROM '.COMMENTS_TABLE.'
140  WHERE image_id IN (
141'.wordwrap(implode(', ', $ids), 80, "\n").')
142;';
143  pwg_query($query);
144
145  // destruction of the links between images and this category
146  $query = '
147DELETE FROM '.IMAGE_CATEGORY_TABLE.'
148  WHERE image_id IN (
149'.wordwrap(implode(', ', $ids), 80, "\n").')
150;';
151  pwg_query($query);
152
153  // destruction of the links between images and tags
154  $query = '
155DELETE FROM '.IMAGE_TAG_TABLE.'
156  WHERE image_id IN (
157'.wordwrap(implode(', ', $ids), 80, "\n").')
158;';
159  pwg_query($query);
160
161  // destruction of the favorites associated with the picture
162  $query = '
163DELETE FROM '.FAVORITES_TABLE.'
164  WHERE image_id IN (
165'.wordwrap(implode(', ', $ids), 80, "\n").')
166;';
167  pwg_query($query);
168
169  // destruction of the rates associated to this element
170  $query = '
171DELETE FROM '.RATE_TABLE.'
172  WHERE element_id IN (
173'.wordwrap(implode(', ', $ids), 80, "\n").')
174;';
175  pwg_query($query);
176
177  // destruction of the rates associated to this element
178  $query = '
179DELETE FROM '.CADDIE_TABLE.'
180  WHERE element_id IN (
181'.wordwrap(implode(', ', $ids), 80, "\n").')
182;';
183  pwg_query($query);
184
185  // destruction of the image
186  $query = '
187DELETE FROM '.IMAGES_TABLE.'
188  WHERE id IN (
189'.wordwrap(implode(', ', $ids), 80, "\n").')
190;';
191  pwg_query($query);
192
193  trigger_action('delete_elements', $ids);
194}
195
196// The delete_user function delete a user identified by the $user_id
197// It also deletes :
198//     - all the access linked to this user
199//     - all the links to any group
200//     - all the favorites linked to this user
201//     - calculated permissions linked to the user
202//     - all datas about notifications for the user
203function delete_user($user_id)
204{
205  global $conf;
206  $tables = array(
207    // destruction of the access linked to the user
208    USER_ACCESS_TABLE,
209    // destruction of data notification by mail for this user
210    USER_MAIL_NOTIFICATION_TABLE,
211    // destruction of data RSS notification for this user
212    USER_FEED_TABLE,
213    // deletion of calculated permissions linked to the user
214    USER_CACHE_TABLE,
215    // deletion of computed cache data linked to the user
216    USER_CACHE_CATEGORIES_TABLE,
217    // destruction of the group links for this user
218    USER_GROUP_TABLE,
219    // destruction of the favorites associated with the user
220    FAVORITES_TABLE,
221    // destruction of the caddie associated with the user
222    CADDIE_TABLE,
223    // deletion of piwigo specific informations
224    USER_INFOS_TABLE,
225    );
226
227  foreach ($tables as $table)
228  {
229    $query = '
230DELETE FROM '.$table.'
231  WHERE user_id = '.$user_id.'
232;';
233    pwg_query($query);
234  }
235
236  // destruction of the user
237  $query = '
238DELETE FROM '.SESSIONS_TABLE.'
239  WHERE data LIKE "pwg_uid|i:'.(int)$user_id.';%"
240;';
241  pwg_query($query);
242
243  // destruction of the user
244  $query = '
245DELETE FROM '.USERS_TABLE.'
246  WHERE '.$conf['user_fields']['id'].' = '.$user_id.'
247;';
248  pwg_query($query);
249
250  trigger_action('delete_user', $user_id);
251}
252
253/**
254 * Verifies that the representative picture really exists in the db and
255 * picks up a random represantive if possible and based on config.
256 *
257 * @param mixed category id
258 * @returns void
259 */
260function update_category($ids = 'all')
261{
262  global $conf;
263
264  if ($ids=='all')
265  {
266    $where_cats = '1=1';
267  }
268  elseif ( !is_array($ids) )
269  {
270    $where_cats = '%s='.$ids;
271  }
272  else
273  {
274    if (count($ids) == 0)
275    {
276      return false;
277    }
278    $where_cats = '%s IN('.wordwrap(implode(', ', $ids), 120, "\n").')';
279  }
280
281  // find all categories where the setted representative is not possible :
282  // the picture does not exist
283  $query = '
284SELECT DISTINCT c.id
285  FROM '.CATEGORIES_TABLE.' AS c LEFT JOIN '.IMAGES_TABLE.' AS i
286    ON c.representative_picture_id = i.id
287  WHERE representative_picture_id IS NOT NULL
288    AND '.sprintf($where_cats, 'c.id').'
289    AND i.id IS NULL
290;';
291  $wrong_representant = array_from_query($query, 'id');
292
293  if (count($wrong_representant) > 0)
294  {
295    $query = '
296UPDATE '.CATEGORIES_TABLE.'
297  SET representative_picture_id = NULL
298  WHERE id IN ('.wordwrap(implode(', ', $wrong_representant), 120, "\n").')
299;';
300    pwg_query($query);
301  }
302
303  if (!$conf['allow_random_representative'])
304  {
305    // If the random representant is not allowed, we need to find
306    // categories with elements and with no representant. Those categories
307    // must be added to the list of categories to set to a random
308    // representant.
309    $query = '
310SELECT DISTINCT id
311  FROM '.CATEGORIES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.'
312    ON id = category_id
313  WHERE representative_picture_id IS NULL
314    AND '.sprintf($where_cats, 'category_id').'
315;';
316    $to_rand = array_from_query($query, 'id');
317    if (count($to_rand) > 0)
318    {
319      set_random_representant($to_rand);
320    }
321  }
322}
323
324/**
325 * returns an array containing sub-directories which can be a category,
326 * recursive by default
327 *
328 * directories nammed "thumbnail", "pwg_high" or "pwg_representative" are
329 * omitted
330 *
331 * @param string $basedir
332 * @return array
333 */
334function get_fs_directories($path, $recursive = true)
335{
336  $dirs = array();
337
338  if (is_dir($path))
339  {
340    if ($contents = opendir($path))
341    {
342      while (($node = readdir($contents)) !== false)
343      {
344        if (is_dir($path.'/'.$node)
345            and $node != '.'
346            and $node != '..'
347            and $node != '.svn'
348            and $node != 'thumbnail'
349            and $node != 'pwg_high'
350            and $node != 'pwg_representative')
351        {
352          array_push($dirs, $path.'/'.$node);
353          if ($recursive)
354          {
355            $dirs = array_merge($dirs, get_fs_directories($path.'/'.$node));
356          }
357        }
358      }
359      closedir($contents);
360    }
361  }
362
363  return $dirs;
364}
365
366/**
367 * inserts multiple lines in a table
368 *
369 * @param string table_name
370 * @param array dbfields
371 * @param array inserts
372 * @return void
373 */
374function mass_inserts($table_name, $dbfields, $datas)
375{
376  if (count($datas) != 0)
377  {
378    $first = true;
379
380    $query = 'SHOW VARIABLES LIKE \'max_allowed_packet\'';
381    list(, $packet_size) = mysql_fetch_row(pwg_query($query));
382    $packet_size = $packet_size - 2000; // The last list of values MUST not exceed 2000 character*/
383    $query = '';
384
385    foreach ($datas as $insert)
386    {
387      if (strlen($query) >= $packet_size)
388      {
389        pwg_query($query);
390        $first = true;
391      }
392
393      if ($first)
394      {
395        $query = '
396INSERT INTO '.$table_name.'
397  ('.implode(',', $dbfields).')
398  VALUES';
399        $first = false;
400      }
401      else
402      {
403        $query .= '
404  , ';
405      }
406
407      $query .= '(';
408      foreach ($dbfields as $field_id => $dbfield)
409      {
410        if ($field_id > 0)
411        {
412          $query .= ',';
413        }
414
415        if (!isset($insert[$dbfield]) or $insert[$dbfield] === '')
416        {
417          $query .= 'NULL';
418        }
419        else
420        {
421          $query .= "'".$insert[$dbfield]."'";
422        }
423      }
424      $query .= ')';
425    }
426    pwg_query($query);
427  }
428}
429
430define('MASS_UPDATES_SKIP_EMPTY', 1);
431/**
432 * updates multiple lines in a table
433 *
434 * @param string table_name
435 * @param array dbfields
436 * @param array datas
437 * @param int flags - if MASS_UPDATES_SKIP_EMPTY - empty values do not overwrite existing ones
438 * @return void
439 */
440function mass_updates($tablename, $dbfields, $datas, $flags=0)
441{
442  if (count($datas) == 0)
443    return;
444  // depending on the MySQL version, we use the multi table update or N update queries
445  if (count($datas) < 10 or version_compare(mysql_get_server_info(), '4.0.4') < 0)
446  { // MySQL is prior to version 4.0.4, multi table update feature is not available
447    foreach ($datas as $data)
448    {
449      $query = '
450UPDATE '.$tablename.'
451  SET ';
452      $is_first = true;
453      foreach ($dbfields['update'] as $key)
454      {
455        $separator = $is_first ? '' : ",\n    ";
456
457        if (isset($data[$key]) and $data[$key] != '')
458        {
459          $query.= $separator.$key.' = \''.$data[$key].'\'';
460        }
461        else
462        {
463          if ($flags & MASS_UPDATES_SKIP_EMPTY )
464            continue; // next field
465          $query.= "$separator$key = NULL";
466        }
467        $is_first = false;
468      }
469      if (!$is_first)
470      {// only if one field at least updated
471        $query.= '
472  WHERE ';
473        $is_first = true;
474        foreach ($dbfields['primary'] as $key)
475        {
476          if (!$is_first)
477          {
478            $query.= ' AND ';
479          }
480          if ( isset($data[$key]) )
481          {
482            $query.= $key.' = \''.$data[$key].'\'';
483          }
484          else
485          {
486            $query.= $key.' IS NULL';
487          }
488          $is_first = false;
489        }
490        pwg_query($query);
491      }
492    } // foreach update
493  } // if mysql_ver or count<X
494  else
495  {
496    // creation of the temporary table
497    $query = '
498SHOW FULL COLUMNS FROM '.$tablename;
499    $result = pwg_query($query);
500    $columns = array();
501    $all_fields = array_merge($dbfields['primary'], $dbfields['update']);
502    while ($row = mysql_fetch_array($result))
503    {
504      if (in_array($row['Field'], $all_fields))
505      {
506        $column = $row['Field'];
507        $column.= ' '.$row['Type'];
508
509        $nullable = true;
510        if (!isset($row['Null']) or $row['Null'] == '' or $row['Null']=='NO')
511        {
512          $column.= ' NOT NULL';
513          $nullable = false;
514        }
515        if (isset($row['Default']))
516        {
517          $column.= " default '".$row['Default']."'";
518        }
519        elseif ($nullable)
520        {
521          $column.= " default NULL";
522        }
523        if (isset($row['Collation']) and $row['Collation'] != 'NULL')
524        {
525          $column.= " collate '".$row['Collation']."'";
526        }
527        array_push($columns, $column);
528      }
529    }
530
531    $temporary_tablename = $tablename.'_'.micro_seconds();
532
533    $query = '
534CREATE TABLE '.$temporary_tablename.'
535(
536  '.implode(",\n  ", $columns).',
537  UNIQUE KEY the_key ('.implode(',', $dbfields['primary']).')
538)';
539
540    pwg_query($query);
541    mass_inserts($temporary_tablename, $all_fields, $datas);
542    if ( $flags & MASS_UPDATES_SKIP_EMPTY )
543      $func_set = create_function('$s', 'return "t1.$s = IFNULL(t2.$s, t1.$s)";');
544    else
545      $func_set = create_function('$s', 'return "t1.$s = t2.$s";');
546
547    // update of images table by joining with temporary table
548    $query = '
549UPDATE '.$tablename.' AS t1, '.$temporary_tablename.' AS t2
550  SET '.
551      implode(
552        "\n    , ",
553        array_map($func_set,$dbfields['update'])
554        ).'
555  WHERE '.
556      implode(
557        "\n    AND ",
558        array_map(
559          create_function('$s', 'return "t1.$s = t2.$s";'),
560          $dbfields['primary']
561          )
562        );
563    pwg_query($query);
564    $query = '
565DROP TABLE '.$temporary_tablename;
566    pwg_query($query);
567  }
568}
569
570/**
571 * order categories (update categories.rank and global_rank database fields)
572 * so that rank field are consecutive integers starting at 1 for each child
573 * @return void
574 */
575function update_global_rank()
576{
577  $query = '
578SELECT id, if(id_uppercat is null,\'\',id_uppercat) AS id_uppercat, uppercats, rank, global_rank
579  FROM '.CATEGORIES_TABLE.'
580  ORDER BY id_uppercat,rank,name';
581
582  $cat_map = array();
583
584  $current_rank = 0;
585  $current_uppercat = '';
586
587  $result = pwg_query($query);
588  while ($row = mysql_fetch_array($result))
589  {
590    if ($row['id_uppercat'] != $current_uppercat)
591    {
592      $current_rank = 0;
593      $current_uppercat = $row['id_uppercat'];
594    }
595    ++$current_rank;
596    $cat =
597      array(
598        'rank' =>        $current_rank,
599        'rank_changed' =>$current_rank!=$row['rank'],
600        'global_rank' => $row['global_rank'],
601        'uppercats' =>   $row['uppercats'],
602        );
603    $cat_map[ $row['id'] ] = $cat;
604  }
605
606  $datas = array();
607
608  foreach( $cat_map as $id=>$cat )
609  {
610    $new_global_rank = preg_replace(
611          '/(\d+)/e',
612          "\$cat_map['$1']['rank']",
613          str_replace(',', '.', $cat['uppercats'] )
614          );
615    if ( $cat['rank_changed']
616      or $new_global_rank!=$cat['global_rank']
617      )
618    {
619      $datas[] = array(
620          'id' => $id,
621          'rank' => $cat['rank'],
622          'global_rank' => $new_global_rank,
623        );
624    }
625  }
626
627  mass_updates(
628    CATEGORIES_TABLE,
629    array(
630      'primary' => array('id'),
631      'update'  => array('rank', 'global_rank')
632      ),
633    $datas
634    );
635  return count($datas);
636}
637
638/**
639 * change the visible property on a set of categories
640 *
641 * @param array categories
642 * @param string value
643 * @return void
644 */
645function set_cat_visible($categories, $value)
646{
647  if (!in_array($value, array('true', 'false')))
648  {
649    trigger_error("set_cat_visible invalid param $value", E_USER_WARNING);
650    return false;
651  }
652
653  // unlocking a category => all its parent categories become unlocked
654  if ($value == 'true')
655  {
656    $uppercats = get_uppercat_ids($categories);
657    $query = '
658UPDATE '.CATEGORIES_TABLE.'
659  SET visible = \'true\'
660  WHERE id IN ('.implode(',', $uppercats).')';
661    pwg_query($query);
662  }
663  // locking a category   => all its child categories become locked
664  if ($value == 'false')
665  {
666    $subcats = get_subcat_ids($categories);
667    $query = '
668UPDATE '.CATEGORIES_TABLE.'
669  SET visible = \'false\'
670  WHERE id IN ('.implode(',', $subcats).')';
671    pwg_query($query);
672  }
673}
674
675/**
676 * change the status property on a set of categories : private or public
677 *
678 * @param array categories
679 * @param string value
680 * @return void
681 */
682function set_cat_status($categories, $value)
683{
684  if (!in_array($value, array('public', 'private')))
685  {
686    trigger_error("set_cat_status invalid param $value", E_USER_WARNING);
687    return false;
688  }
689
690  // make public a category => all its parent categories become public
691  if ($value == 'public')
692  {
693    $uppercats = get_uppercat_ids($categories);
694    $query = '
695UPDATE '.CATEGORIES_TABLE.'
696  SET status = \'public\'
697  WHERE id IN ('.implode(',', $uppercats).')
698;';
699    pwg_query($query);
700  }
701  // make a category private => all its child categories become private
702  if ($value == 'private')
703  {
704    $subcats = get_subcat_ids($categories);
705    $query = '
706UPDATE '.CATEGORIES_TABLE.'
707  SET status = \'private\'
708  WHERE id IN ('.implode(',', $subcats).')';
709    pwg_query($query);
710  }
711}
712
713/**
714 * returns all uppercats category ids of the given category ids
715 *
716 * @param array cat_ids
717 * @return array
718 */
719function get_uppercat_ids($cat_ids)
720{
721  if (!is_array($cat_ids) or count($cat_ids) < 1)
722  {
723    return array();
724  }
725
726  $uppercats = array();
727
728  $query = '
729SELECT uppercats
730  FROM '.CATEGORIES_TABLE.'
731  WHERE id IN ('.implode(',', $cat_ids).')
732;';
733  $result = pwg_query($query);
734  while ($row = mysql_fetch_array($result))
735  {
736    $uppercats = array_merge($uppercats,
737                             explode(',', $row['uppercats']));
738  }
739  $uppercats = array_unique($uppercats);
740
741  return $uppercats;
742}
743
744/**
745 * set a new random representant to the categories
746 *
747 * @param array categories
748 */
749function set_random_representant($categories)
750{
751  $datas = array();
752  foreach ($categories as $category_id)
753  {
754    $query = '
755SELECT image_id
756  FROM '.IMAGE_CATEGORY_TABLE.'
757  WHERE category_id = '.$category_id.'
758  ORDER BY RAND()
759  LIMIT 0,1
760;';
761    list($representative) = mysql_fetch_array(pwg_query($query));
762
763    array_push(
764      $datas,
765      array(
766        'id' => $category_id,
767        'representative_picture_id' => $representative,
768        )
769      );
770  }
771
772  mass_updates(
773    CATEGORIES_TABLE,
774    array(
775      'primary' => array('id'),
776      'update' => array('representative_picture_id')
777      ),
778    $datas
779    );
780}
781
782/**
783 * returns the fulldir for each given category id
784 *
785 * @param array cat_ids
786 * @return array
787 */
788function get_fulldirs($cat_ids)
789{
790  if (count($cat_ids) == 0)
791  {
792    return array();
793  }
794
795  // caching directories of existing categories
796  $query = '
797SELECT id, dir
798  FROM '.CATEGORIES_TABLE.'
799  WHERE dir IS NOT NULL
800;';
801  $result = pwg_query($query);
802  $cat_dirs = array();
803  while ($row = mysql_fetch_array($result))
804  {
805    $cat_dirs[$row['id']] = $row['dir'];
806  }
807
808  // caching galleries_url
809  $query = '
810SELECT id, galleries_url
811  FROM '.SITES_TABLE.'
812;';
813  $result = pwg_query($query);
814  $galleries_url = array();
815  while ($row = mysql_fetch_array($result))
816  {
817    $galleries_url[$row['id']] = $row['galleries_url'];
818  }
819
820  // categories : id, site_id, uppercats
821  $categories = array();
822
823  $query = '
824SELECT id, uppercats, site_id
825  FROM '.CATEGORIES_TABLE.'
826  WHERE id IN (
827'.wordwrap(implode(', ', $cat_ids), 80, "\n").')
828;';
829  $result = pwg_query($query);
830  while ($row = mysql_fetch_array($result))
831  {
832    array_push($categories, $row);
833  }
834
835  // filling $cat_fulldirs
836  $cat_fulldirs = array();
837  foreach ($categories as $category)
838  {
839    $uppercats = str_replace(',', '/', $category['uppercats']);
840    $cat_fulldirs[$category['id']] = $galleries_url[$category['site_id']];
841    $cat_fulldirs[$category['id']].= preg_replace('/(\d+)/e',
842                                                  "\$cat_dirs['$1']",
843                                                  $uppercats);
844  }
845
846  return $cat_fulldirs;
847}
848
849/**
850 * returns an array with all file system files according to
851 * $conf['file_ext']
852 *
853 * @param string $path
854 * @param bool recursive
855 * @return array
856 */
857function get_fs($path, $recursive = true)
858{
859  global $conf;
860
861  // because isset is faster than in_array...
862  if (!isset($conf['flip_picture_ext']))
863  {
864    $conf['flip_picture_ext'] = array_flip($conf['picture_ext']);
865  }
866  if (!isset($conf['flip_file_ext']))
867  {
868    $conf['flip_file_ext'] = array_flip($conf['file_ext']);
869  }
870
871  $fs['elements'] = array();
872  $fs['thumbnails'] = array();
873  $fs['representatives'] = array();
874  $subdirs = array();
875
876  if (is_dir($path))
877  {
878    if ($contents = opendir($path))
879    {
880      while (($node = readdir($contents)) !== false)
881      {
882        if (is_file($path.'/'.$node))
883        {
884          $extension = get_extension($node);
885
886//          if (in_array($extension, $conf['picture_ext']))
887          if (isset($conf['flip_picture_ext'][$extension]))
888          {
889            if (basename($path) == 'thumbnail')
890            {
891              array_push($fs['thumbnails'], $path.'/'.$node);
892            }
893            else if (basename($path) == 'pwg_representative')
894            {
895              array_push($fs['representatives'], $path.'/'.$node);
896            }
897            else
898            {
899              array_push($fs['elements'], $path.'/'.$node);
900            }
901          }
902//          else if (in_array($extension, $conf['file_ext']))
903          else if (isset($conf['flip_file_ext'][$extension]))
904          {
905            array_push($fs['elements'], $path.'/'.$node);
906          }
907        }
908        else if (is_dir($path.'/'.$node)
909                 and $node != '.'
910                 and $node != '..'
911                 and $node != 'pwg_high'
912                 and $recursive)
913        {
914          array_push($subdirs, $node);
915        }
916      }
917    }
918    closedir($contents);
919
920    foreach ($subdirs as $subdir)
921    {
922      $tmp_fs = get_fs($path.'/'.$subdir);
923
924      $fs['elements']        = array_merge($fs['elements'],
925                                           $tmp_fs['elements']);
926
927      $fs['thumbnails']      = array_merge($fs['thumbnails'],
928                                           $tmp_fs['thumbnails']);
929
930      $fs['representatives'] = array_merge($fs['representatives'],
931                                           $tmp_fs['representatives']);
932    }
933  }
934  return $fs;
935}
936
937/**
938 * stupidly returns the current microsecond since Unix epoch
939 */
940function micro_seconds()
941{
942  $t1 = explode(' ', microtime());
943  $t2 = explode('.', $t1[0]);
944  $t2 = $t1[1].substr($t2[1], 0, 6);
945  return $t2;
946}
947
948/**
949 * synchronize base users list and related users list
950 *
951 * compares and synchronizes base users table (USERS_TABLE) with its child
952 * tables (USER_INFOS_TABLE, USER_ACCESS, USER_CACHE, USER_GROUP) : each
953 * base user must be present in child tables, users in child tables not
954 * present in base table must be deleted.
955 *
956 * @return void
957 */
958function sync_users()
959{
960  global $conf;
961
962  $query = '
963SELECT '.$conf['user_fields']['id'].' AS id
964  FROM '.USERS_TABLE.'
965;';
966  $base_users = array_from_query($query, 'id');
967
968  $query = '
969SELECT user_id
970  FROM '.USER_INFOS_TABLE.'
971;';
972  $infos_users = array_from_query($query, 'user_id');
973
974  // users present in $base_users and not in $infos_users must be added
975  $to_create = array_diff($base_users, $infos_users);
976
977  if (count($to_create) > 0)
978  {
979    create_user_infos($to_create);
980  }
981
982  // users present in user related tables must be present in the base user
983  // table
984  $tables = array(
985    USER_MAIL_NOTIFICATION_TABLE,
986    USER_FEED_TABLE,
987    USER_INFOS_TABLE,
988    USER_ACCESS_TABLE,
989    USER_CACHE_TABLE,
990    USER_CACHE_CATEGORIES_TABLE,
991    USER_GROUP_TABLE
992    );
993
994  foreach ($tables as $table)
995  {
996    $query = '
997SELECT DISTINCT user_id
998  FROM '.$table.'
999;';
1000    $to_delete = array_diff(
1001      array_from_query($query, 'user_id'),
1002      $base_users
1003      );
1004
1005    if (count($to_delete) > 0)
1006    {
1007      $query = '
1008DELETE
1009  FROM '.$table.'
1010  WHERE user_id in ('.implode(',', $to_delete).')
1011;';
1012      pwg_query($query);
1013    }
1014  }
1015}
1016
1017/**
1018 * updates categories.uppercats field based on categories.id +
1019 * categories.id_uppercat
1020 *
1021 * @return void
1022 */
1023function update_uppercats()
1024{
1025  $query = '
1026SELECT id, id_uppercat, uppercats
1027  FROM '.CATEGORIES_TABLE.'
1028;';
1029  $cat_map = hash_from_query($query, 'id');
1030
1031  $datas = array();
1032  foreach ($cat_map as $id => $cat)
1033  {
1034    $upper_list = array();
1035
1036    $uppercat = $id;
1037    while ($uppercat)
1038    {
1039      array_push($upper_list, $uppercat);
1040      $uppercat = $cat_map[$uppercat]['id_uppercat'];
1041    }
1042
1043    $new_uppercats = implode(',', array_reverse($upper_list));
1044    if ($new_uppercats != $cat['uppercats'])
1045    {
1046      array_push(
1047        $datas,
1048        array(
1049          'id' => $id,
1050          'uppercats' => $new_uppercats
1051          )
1052        );
1053    }
1054  }
1055  $fields = array('primary' => array('id'), 'update' => array('uppercats'));
1056  mass_updates(CATEGORIES_TABLE, $fields, $datas);
1057}
1058
1059/**
1060 * update images.path field
1061 *
1062 * @return void
1063 */
1064function update_path()
1065{
1066  $query = '
1067SELECT DISTINCT(storage_category_id)
1068  FROM '.IMAGES_TABLE.'
1069;';
1070  $cat_ids = array_from_query($query, 'storage_category_id');
1071  $fulldirs = get_fulldirs($cat_ids);
1072
1073  foreach ($cat_ids as $cat_id)
1074  {
1075    $query = '
1076UPDATE '.IMAGES_TABLE.'
1077  SET path = CONCAT(\''.$fulldirs[$cat_id].'\',\'/\',file)
1078  WHERE storage_category_id = '.$cat_id.'
1079;';
1080    pwg_query($query);
1081  }
1082}
1083
1084/**
1085 * update images.average_rate field
1086 * param int $element_id optional, otherwise applies to all
1087 * @return void
1088 */
1089function update_average_rate( $element_id=-1 )
1090{
1091  $query = '
1092SELECT element_id,
1093       ROUND(AVG(rate),2) AS average_rate
1094  FROM '.RATE_TABLE;
1095  if ( $element_id != -1 )
1096  {
1097    $query .= ' WHERE element_id=' . $element_id;
1098  }
1099  $query .= ' GROUP BY element_id;';
1100
1101  $result = pwg_query($query);
1102
1103  $datas = array();
1104
1105  while ($row = mysql_fetch_array($result))
1106  {
1107    array_push(
1108      $datas,
1109      array(
1110        'id' => $row['element_id'],
1111        'average_rate' => $row['average_rate']
1112        )
1113      );
1114  }
1115
1116  mass_updates(
1117    IMAGES_TABLE,
1118    array(
1119      'primary' => array('id'),
1120      'update' => array('average_rate')
1121      ),
1122    $datas
1123    );
1124
1125  $query='
1126SELECT id FROM '.IMAGES_TABLE .'
1127  LEFT JOIN '.RATE_TABLE.' ON id=element_id
1128  WHERE element_id IS NULL AND average_rate IS NOT NULL';
1129  if ( $element_id != -1 )
1130  {
1131    $query .= ' AND id=' . $element_id;
1132  }
1133  $to_update = array_from_query( $query, 'id');
1134
1135  if ( !empty($to_update) )
1136  {
1137    $query='
1138UPDATE '.IMAGES_TABLE .'
1139  SET average_rate=NULL
1140  WHERE id IN (' . implode(',',$to_update) . ')';
1141    pwg_query($query);
1142  }
1143}
1144
1145/**
1146 * change the parent category of the given categories. The categories are
1147 * supposed virtual.
1148 *
1149 * @param array category identifiers
1150 * @param int parent category identifier
1151 * @return void
1152 */
1153function move_categories($category_ids, $new_parent = -1)
1154{
1155  global $page;
1156
1157  if (count($category_ids) == 0)
1158  {
1159    return;
1160  }
1161
1162  $new_parent = $new_parent < 1 ? 'NULL' : $new_parent;
1163
1164  $categories = array();
1165
1166  $query = '
1167SELECT id, id_uppercat, status, uppercats
1168  FROM '.CATEGORIES_TABLE.'
1169  WHERE id IN ('.implode(',', $category_ids).')
1170;';
1171  $result = pwg_query($query);
1172  while ($row = mysql_fetch_array($result))
1173  {
1174    $categories[$row['id']] =
1175      array(
1176        'parent' => empty($row['id_uppercat']) ? 'NULL' : $row['id_uppercat'],
1177        'status' => $row['status'],
1178        'uppercats' => $row['uppercats']
1179        );
1180  }
1181
1182  // is the movement possible? The movement is impossible if you try to move
1183  // a category in a sub-category or itself
1184  if ('NULL' != $new_parent)
1185  {
1186    $query = '
1187SELECT uppercats
1188  FROM '.CATEGORIES_TABLE.'
1189  WHERE id = '.$new_parent.'
1190;';
1191    list($new_parent_uppercats) = mysql_fetch_row(pwg_query($query));
1192
1193    foreach ($categories as $category)
1194    {
1195      // technically, you can't move a category with uppercats 12,125,13,14
1196      // into a new parent category with uppercats 12,125,13,14,24
1197      if (preg_match('/^'.$category['uppercats'].'/', $new_parent_uppercats))
1198      {
1199        array_push(
1200          $page['errors'],
1201          l10n('You cannot move a category in its own sub category')
1202          );
1203        return;
1204      }
1205    }
1206  }
1207
1208  $tables =
1209    array(
1210      USER_ACCESS_TABLE => 'user_id',
1211      GROUP_ACCESS_TABLE => 'group_id'
1212      );
1213
1214  $query = '
1215UPDATE '.CATEGORIES_TABLE.'
1216  SET id_uppercat = '.$new_parent.'
1217  WHERE id IN ('.implode(',', $category_ids).')
1218;';
1219  pwg_query($query);
1220
1221  update_uppercats();
1222  update_global_rank();
1223
1224  // status and related permissions management
1225  if ('NULL' == $new_parent)
1226  {
1227    $parent_status = 'public';
1228  }
1229  else
1230  {
1231    $query = '
1232SELECT status
1233  FROM '.CATEGORIES_TABLE.'
1234  WHERE id = '.$new_parent.'
1235;';
1236    list($parent_status) = mysql_fetch_row(pwg_query($query));
1237  }
1238
1239  if ('private' == $parent_status)
1240  {
1241    foreach ($categories as $cat_id => $category)
1242    {
1243      switch ($category['status'])
1244      {
1245        case 'public' :
1246        {
1247          set_cat_status(array($cat_id), 'private');
1248          break;
1249        }
1250        case 'private' :
1251        {
1252          $subcats = get_subcat_ids(array($cat_id));
1253
1254          foreach ($tables as $table => $field)
1255          {
1256            $query = '
1257SELECT '.$field.'
1258  FROM '.$table.'
1259  WHERE cat_id = '.$cat_id.'
1260;';
1261            $category_access = array_from_query($query, $field);
1262
1263            $query = '
1264SELECT '.$field.'
1265  FROM '.$table.'
1266  WHERE cat_id = '.$new_parent.'
1267;';
1268            $parent_access = array_from_query($query, $field);
1269
1270            $to_delete = array_diff($parent_access, $category_access);
1271
1272            if (count($to_delete) > 0)
1273            {
1274              $query = '
1275DELETE FROM '.$table.'
1276  WHERE '.$field.' IN ('.implode(',', $to_delete).')
1277    AND cat_id IN ('.implode(',', $subcats).')
1278;';
1279              pwg_query($query);
1280            }
1281          }
1282          break;
1283        }
1284      }
1285    }
1286  }
1287
1288  array_push(
1289    $page['infos'],
1290    l10n_dec(
1291      '%d category moved', '%d categories moved',
1292      count($categories)
1293      )
1294    );
1295}
1296
1297/**
1298 * create a virtual category
1299 *
1300 * @param string category name
1301 * @param int parent category id
1302 * @return array with ('info' and 'id') or ('error') key
1303 */
1304function create_virtual_category($category_name, $parent_id=null)
1305{
1306  global $conf;
1307
1308  // is the given category name only containing blank spaces ?
1309  if (preg_match('/^\s*$/', $category_name))
1310  {
1311    return array('error' => l10n('cat_error_name'));
1312  }
1313
1314  $parent_id = !empty($parent_id) ? $parent_id : 'NULL';
1315
1316  $query = '
1317SELECT MAX(rank)
1318  FROM '.CATEGORIES_TABLE.'
1319  WHERE id_uppercat '.(is_numeric($parent_id) ? '= '.$parent_id : 'IS NULL').'
1320;';
1321  list($current_rank) = mysql_fetch_array(pwg_query($query));
1322
1323  $insert = array(
1324    'name' => $category_name,
1325    'rank' => ++$current_rank,
1326    'commentable' => boolean_to_string($conf['newcat_default_commentable']),
1327    'uploadable' => 'false',
1328    );
1329
1330  if ($parent_id != 'NULL')
1331  {
1332    $query = '
1333SELECT id, uppercats, global_rank, visible, status
1334  FROM '.CATEGORIES_TABLE.'
1335  WHERE id = '.$parent_id.'
1336;';
1337    $parent = mysql_fetch_array(pwg_query($query));
1338
1339    $insert{'id_uppercat'} = $parent{'id'};
1340    $insert{'global_rank'} = $parent{'global_rank'}.'.'.$insert{'rank'};
1341
1342    // at creation, must a category be visible or not ? Warning : if the
1343    // parent category is invisible, the category is automatically create
1344    // invisible. (invisible = locked)
1345    if ('false' == $parent['visible'])
1346    {
1347      $insert{'visible'} = 'false';
1348    }
1349    else
1350    {
1351      $insert{'visible'} = boolean_to_string($conf['newcat_default_visible']);
1352    }
1353
1354    // at creation, must a category be public or private ? Warning : if the
1355    // parent category is private, the category is automatically create
1356    // private.
1357    if ('private' == $parent['status'])
1358    {
1359      $insert{'status'} = 'private';
1360    }
1361    else
1362    {
1363      $insert{'status'} = $conf['newcat_default_status'];
1364    }
1365  }
1366  else
1367  {
1368    $insert{'visible'} = boolean_to_string($conf['newcat_default_visible']);
1369    $insert{'status'} = $conf['newcat_default_status'];
1370    $insert{'global_rank'} = $insert{'rank'};
1371  }
1372
1373  // we have then to add the virtual category
1374  mass_inserts(
1375    CATEGORIES_TABLE,
1376    array(
1377      'site_id', 'name', 'id_uppercat', 'rank', 'commentable',
1378      'uploadable', 'visible', 'status', 'global_rank',
1379      ),
1380    array($insert)
1381    );
1382
1383  $inserted_id = mysql_insert_id();
1384
1385  $query = '
1386UPDATE
1387  '.CATEGORIES_TABLE.'
1388  SET uppercats = \''.
1389    (isset($parent) ? $parent{'uppercats'}.',' : '').
1390    $inserted_id.
1391    '\'
1392  WHERE id = '.$inserted_id.'
1393;';
1394  pwg_query($query);
1395
1396  return array(
1397    'info' => l10n('cat_virtual_added'),
1398    'id'   => $inserted_id,
1399    );
1400}
1401
1402/**
1403 * Set tags to an image. Warning: given tags are all tags associated to the
1404 * image, not additionnal tags.
1405 *
1406 * @param array tag ids
1407 * @param int image id
1408 * @return void
1409 */
1410function set_tags($tags, $image_id)
1411{
1412  $query = '
1413DELETE
1414  FROM '.IMAGE_TAG_TABLE.'
1415  WHERE image_id = '.$image_id.'
1416;';
1417  pwg_query($query);
1418
1419  if (count($tags) > 0)
1420  {
1421    $inserts = array();
1422    foreach ($tags as $tag_id)
1423    {
1424      array_push(
1425        $inserts,
1426        array(
1427          'tag_id' => $tag_id,
1428          'image_id' => $image_id
1429          )
1430        );
1431    }
1432    mass_inserts(
1433      IMAGE_TAG_TABLE,
1434      array_keys($inserts[0]),
1435      $inserts
1436      );
1437  }
1438}
1439
1440/**
1441 * Add new tags to a set of images.
1442 *
1443 * @param array tag ids
1444 * @param array image ids
1445 * @return void
1446 */
1447function add_tags($tags, $images)
1448{
1449  if (count($tags) == 0 or count($tags) == 0)
1450  {
1451    return;
1452  }
1453
1454  // we can't insert twice the same {image_id,tag_id} so we must first
1455  // delete lines we'll insert later
1456  $query = '
1457DELETE
1458  FROM '.IMAGE_TAG_TABLE.'
1459  WHERE image_id IN ('.implode(',', $images).')
1460    AND tag_id IN ('.implode(',', $tags).')
1461;';
1462  pwg_query($query);
1463
1464  $inserts = array();
1465  foreach ($images as $image_id)
1466  {
1467    foreach ($tags as $tag_id)
1468    {
1469      array_push(
1470        $inserts,
1471        array(
1472          'image_id' => $image_id,
1473          'tag_id' => $tag_id,
1474          )
1475        );
1476    }
1477  }
1478  mass_inserts(
1479    IMAGE_TAG_TABLE,
1480    array_keys($inserts[0]),
1481    $inserts
1482    );
1483}
1484
1485function tag_id_from_tag_name($tag_name)
1486{
1487  global $page;
1488
1489  $tag_name = trim($tag_name);
1490  if (isset($page['tag_id_from_tag_name_cache'][$tag_name]))
1491  {
1492    return $page['tag_id_from_tag_name_cache'][$tag_name];
1493  }
1494
1495  // does the tag already exists?
1496  $query = '
1497SELECT id
1498  FROM '.TAGS_TABLE.'
1499  WHERE name = \''.$tag_name.'\'
1500;';
1501  $existing_tags = array_from_query($query, 'id');
1502
1503  if (count($existing_tags) == 0)
1504  {
1505    mass_inserts(
1506      TAGS_TABLE,
1507      array('name', 'url_name'),
1508      array(
1509        array(
1510          'name' => $tag_name,
1511          'url_name' => str2url($tag_name),
1512          )
1513        )
1514      );
1515
1516    $page['tag_id_from_tag_name_cache'][$tag_name] = mysql_insert_id();
1517  }
1518  else
1519  {
1520    $page['tag_id_from_tag_name_cache'][$tag_name] = $existing_tags[0];
1521  }
1522
1523  return $page['tag_id_from_tag_name_cache'][$tag_name];
1524}
1525
1526function set_tags_of($tags_of)
1527{
1528  if (count($tags_of) > 0)
1529  {
1530    $query = '
1531DELETE
1532  FROM '.IMAGE_TAG_TABLE.'
1533  WHERE image_id IN ('.implode(',', array_keys($tags_of)).')
1534;';
1535    pwg_query($query);
1536
1537    $inserts = array();
1538
1539    foreach ($tags_of as $image_id => $tag_ids)
1540    {
1541      foreach ($tag_ids as $tag_id)
1542      {
1543        array_push(
1544          $inserts,
1545          array(
1546            'image_id' => $image_id,
1547            'tag_id' => $tag_id,
1548            )
1549          );
1550      }
1551    }
1552
1553    mass_inserts(
1554      IMAGE_TAG_TABLE,
1555      array_keys($inserts[0]),
1556      $inserts
1557      );
1558  }
1559}
1560
1561/**
1562 * Do maintenance on all PWG tables
1563 *
1564 * @return nono
1565 */
1566function do_maintenance_all_tables()
1567{
1568  global $prefixeTable, $page;
1569
1570  $all_tables = array();
1571
1572  // List all tables
1573  $query = 'SHOW TABLES LIKE \''.$prefixeTable.'%\'';
1574  $result = pwg_query($query);
1575  while ($row = mysql_fetch_array($result))
1576  {
1577    array_push($all_tables, $row[0]);
1578  }
1579
1580  // Repair all tables
1581  $query = 'REPAIR TABLE '.implode(', ', $all_tables);
1582  $mysql_rc = pwg_query($query);
1583
1584  // Re-Order all tables
1585  foreach ($all_tables as $table_name)
1586  {
1587    $all_primary_key = array();
1588
1589    $query = 'DESC '.$table_name.';';
1590    $result = pwg_query($query);
1591    while ($row = mysql_fetch_array($result))
1592    {
1593      if ($row['Key'] == 'PRI')
1594      {
1595        array_push($all_primary_key, $row['Field']);
1596      }
1597    }
1598
1599    if (count($all_primary_key) != 0)
1600    {
1601      $query = 'ALTER TABLE '.$table_name.' ORDER BY '.implode(', ', $all_primary_key).';';
1602      $mysql_rc = $mysql_rc && pwg_query($query);
1603    }
1604  }
1605
1606  // Optimize all tables
1607  $query = 'OPTIMIZE TABLE '.implode(', ', $all_tables);
1608  $mysql_rc = $mysql_rc && pwg_query($query);
1609  if ($mysql_rc)
1610  {
1611    array_push(
1612          $page['infos'],
1613          l10n('Optimization completed')
1614          );
1615  }
1616  else
1617  {
1618    array_push(
1619          $page['errors'],
1620          l10n('Optimizations errors')
1621          );
1622  }
1623}
1624
1625/**
1626 * Associate a list of images to a list of categories.
1627 *
1628 * The function will not duplicate links
1629 *
1630 * @param array images
1631 * @param array categories
1632 * @return void
1633 */
1634function associate_images_to_categories($images, $categories)
1635{
1636  if (count($images) == 0
1637      or count($categories) == 0)
1638  {
1639    return false;
1640  }
1641
1642  $query = '
1643DELETE
1644  FROM '.IMAGE_CATEGORY_TABLE.'
1645  WHERE image_id IN ('.implode(',', $images).')
1646    AND category_id IN ('.implode(',', $categories).')
1647;';
1648  pwg_query($query);
1649
1650  $inserts = array();
1651  foreach ($categories as $category_id)
1652  {
1653    foreach ($images as $image_id)
1654    {
1655      array_push(
1656        $inserts,
1657        array(
1658          'image_id' => $image_id,
1659          'category_id' => $category_id,
1660          )
1661        );
1662    }
1663  }
1664
1665  mass_inserts(
1666    IMAGE_CATEGORY_TABLE,
1667    array_keys($inserts[0]),
1668    $inserts
1669    );
1670
1671  update_category($categories);
1672}
1673
1674/**
1675 * Associate images associated to a list of source categories to a list of
1676 * destination categories.
1677 *
1678 * @param array sources
1679 * @param array destinations
1680 * @return void
1681 */
1682function associate_categories_to_categories($sources, $destinations)
1683{
1684  if (count($sources) == 0)
1685  {
1686    return false;
1687  }
1688
1689  $query = '
1690SELECT image_id
1691  FROM '.IMAGE_CATEGORY_TABLE.'
1692  WHERE category_id IN ('.implode(',', $sources).')
1693;';
1694  $images = array_from_query($query, 'image_id');
1695
1696  associate_images_to_categories($images, $destinations);
1697}
1698
1699/**
1700 * Create an XML file with Piwigo informations about a list of
1701 * pictures.
1702 *
1703 * The goal of the export feature is to make easier the reading of
1704 * informations related to pictures outside of Piwigo.
1705 *
1706 * @param array image_ids
1707 */
1708function export_pwg_data($image_ids)
1709{
1710  global $conf;
1711
1712  if (count($image_ids) == 0)
1713  {
1714    return;
1715  }
1716
1717  $fp = fopen($conf['export_file'], 'w');
1718  $xml_string = '<export>'."\n";
1719
1720  $query = '
1721SELECT tag_id,
1722       image_id
1723  FROM '.IMAGE_TAG_TABLE.'
1724  WHERE image_id IN ('.implode(',', $image_ids).')
1725;';
1726  $result = pwg_query($query);
1727  $tags_of = array();
1728  $all_tag_ids = array();
1729  $tag_name_of = array();
1730
1731  if (mysql_num_rows($result))
1732  {
1733      while ($row = mysql_fetch_array($result))
1734      {
1735        array_push($all_tag_ids, $row['tag_id']);
1736
1737        if (!isset($tags_of[ $row['image_id'] ])) {
1738          $tags_of[ $row['image_id'] ] = array();
1739        }
1740
1741        array_push(
1742          $tags_of[ $row['image_id'] ],
1743          $row['tag_id']
1744          );
1745      }
1746
1747      $all_tag_ids = array_unique($all_tag_ids);
1748
1749      $query = '
1750SELECT id,
1751       name
1752  FROM '.TAGS_TABLE.'
1753  WHERE id IN ('.implode(',', $all_tag_ids).')
1754;';
1755      $result = pwg_query($query);
1756
1757      while ($row = mysql_fetch_array($result))
1758      {
1759        $tag_name_of[ $row['id'] ] = $row['name'];
1760      }
1761  }
1762
1763  $query = '
1764SELECT id,
1765       path
1766  FROM '.IMAGES_TABLE.'
1767  WHERE id IN ('.implode(',', $image_ids).')
1768;';
1769  $result = pwg_query($query);
1770
1771  while ($row = mysql_fetch_array($result))
1772  {
1773    $xml_string.= "  <photo>\n";
1774    $xml_string.= "    <id>".$row['id']."</id>\n";
1775    $xml_string.= "    <path>".$row['path']."</path>\n";
1776
1777    foreach ($tags_of[ $row['id'] ] as $tag_id)
1778    {
1779      $xml_string.= "    <tag>".$tag_name_of[$tag_id]."</tag>\n";
1780    }
1781
1782    $xml_string.= "  </photo>\n";
1783  }
1784
1785  $xml_string.= '</export>';
1786  fwrite($fp, $xml_string);
1787  fclose($fp);
1788}
1789
1790/**
1791 * Refer main Piwigo URLs (currently PHPWG_DOMAIN domain)
1792 *
1793 * @param void
1794 * @return array like $conf['links']
1795 */
1796function pwg_URL()
1797{
1798  global $lang_info;
1799  $urls = array(
1800    'WIKI'       => 'http://'.PHPWG_DOMAIN.'/doc/',
1801    'HOME'       => 'http://'.PHPWG_DOMAIN.'/',
1802    'DEMO'       => 'http://demo.'.PHPWG_DOMAIN.'/',
1803    'FORUM'      => 'http://forum.'.PHPWG_DOMAIN.'/',
1804    'BUGS'       => 'http://bugs.'.PHPWG_DOMAIN.'/',
1805    'EXTENSIONS' => 'http://'.PHPWG_DOMAIN.'/ext',
1806    );
1807  if ( isset($lang_info['code']) and
1808       in_array($lang_info['code'], array('fr','en')) )
1809  { /* current wiki languages are French or English */
1810    $urls['WIKI'] .= 'doku.php?id='.$lang_info['code'].':'.$lang_info['code'];
1811    $urls['HOME'] .= '?lang='.$lang_info['code'];
1812  }
1813  return $urls;
1814}
1815
1816/**
1817 * Invalidates cahed data (permissions and category counts) for all users.
1818 */
1819function invalidate_user_cache()
1820{
1821  $query = '
1822UPDATE '.USER_CACHE_TABLE.'
1823  SET need_update = \'true\'';
1824  pwg_query($query);
1825  trigger_action('invalidate_user_cache');
1826}
1827
1828/**
1829 * adds the caracter set to a create table sql query.
1830 * all CREATE TABLE queries must call this function
1831 * @param string query - the sql query
1832 */
1833function create_table_add_character_set($query)
1834{
1835  defined('DB_CHARSET') or fatal_error('create_table_add_character_set DB_CHARSET undefined');
1836  if ('DB_CHARSET'!='')
1837  {
1838    if ( version_compare(mysql_get_server_info(), '4.1.0', '<') )
1839    {
1840      return $query;
1841    }
1842    $charset_collate = " DEFAULT CHARACTER SET ".DB_CHARSET;
1843    if (DB_COLLATE!='')
1844    {
1845      $charset_collate .= " COLLATE ".DB_COLLATE;
1846    }
1847    if ( is_array($query) )
1848    {
1849      foreach( $query as $id=>$q)
1850      {
1851        $q=trim($q);
1852        $q=trim($q, ';');
1853        if (preg_match('/^CREATE\s+TABLE/i',$q))
1854        {
1855          $q.=$charset_collate;
1856        }
1857        $q .= ';';
1858        $query[$id] = $q;
1859      }
1860    }
1861    else
1862    {
1863      $query=trim($query);
1864      $query=trim($query, ';');
1865      if (preg_match('/^CREATE\s+TABLE/i',$query))
1866      {
1867        $query.=$charset_collate;
1868      }
1869      $query .= ';';
1870    }
1871  }
1872  return $query;
1873}
1874
1875/**
1876 * Returns array use on template with html_options method
1877 * @param Min and Max access to use
1878 * @return array of user access level
1879 */
1880function get_user_access_level_html_options($MinLevelAccess = ACCESS_FREE, $MaxLevelAccess = ACCESS_CLOSED)
1881{
1882  $tpl_options = array();
1883  for ($level = $MinLevelAccess; $level <= $MaxLevelAccess; $level++)
1884  {
1885    $tpl_options[$level] = l10n(sprintf('ACCESS_%d', $level));
1886  }
1887  return $tpl_options;
1888}
1889
1890?>
Note: See TracBrowser for help on using the repository browser.