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

Last change on this file since 2299 was 2299, checked in by plg, 16 years ago

Bug fixed: as rvelices notified me by email, my header replacement script was
bugged (r2297 was repeating new and old header).

By the way, I've also removed the replacement keywords. We were using them
because it was a common usage with CVS but it is advised not to use them with
Subversion. Personnaly, it is a problem when I search differences between 2
Piwigo installations outside Subversion.

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