source: branches/2.4/admin/include/functions.php @ 17982

Last change on this file since 17982 was 17982, checked in by plg, 12 years ago

merge r17980 from trunk to branch 2.4

little code refactoring over r17424

bug fixed on Edit Photo page when associating with no album.

  • Property svn:eol-style set to LF
File size: 55.7 KB
RevLine 
[2]1<?php
[362]2// +-----------------------------------------------------------------------+
[8728]3// | Piwigo - a PHP based photo gallery                                    |
[2297]4// +-----------------------------------------------------------------------+
[12917]5// | Copyright(C) 2008-2012 Piwigo Team                  http://piwigo.org |
[2297]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// +-----------------------------------------------------------------------+
[2]23
[491]24include(PHPWG_ROOT_PATH.'admin/include/functions_metadata.php');
25
[467]26// The function delete_site deletes a site and call the function
27// delete_categories for each primary category of the site
[12]28function delete_site( $id )
29{
30  // destruction of the categories of the site
[467]31  $query = '
32SELECT id
33  FROM '.CATEGORIES_TABLE.'
34  WHERE site_id = '.$id.'
35;';
[587]36  $result = pwg_query($query);
[467]37  $category_ids = array();
[4325]38  while ($row = pwg_db_fetch_assoc($result))
[12]39  {
[467]40    array_push($category_ids, $row['id']);
[12]41  }
[467]42  delete_categories($category_ids);
[1060]43
[12]44  // destruction of the site
[467]45  $query = '
46DELETE FROM '.SITES_TABLE.'
47  WHERE id = '.$id.'
48;';
[587]49  pwg_query($query);
[12]50}
[345]51
[1060]52
[467]53// The function delete_categories deletes the categories identified by the
54// (numeric) key of the array $ids. It also deletes (in the database) :
[8265]55//    - all the elements physically linked to the category (delete_elements, see further)
[467]56//    - all the links between elements and this category
[12]57//    - all the restrictions linked to the category
58// The function works recursively.
[8265]59//
60// the $photo_deletion_mode is for photos virtually linked to the categorty
61//   * no_delete : delete no photo, may create orphans
62//   * delete_orphans : delete photos that are no longer linked to any category
63//   * force_delete : delete photos even if they are linked to another category
64function delete_categories($ids, $photo_deletion_mode='no_delete')
[12]65{
[521]66  if (count($ids) == 0)
67  {
68    return;
69  }
[657]70
71  // add sub-category ids to the given ids : if a category is deleted, all
72  // sub-categories must be so
73  $ids = get_subcat_ids($ids);
[1060]74
[8265]75  // destruction of all photos physically linked to the category
[467]76  $query = '
[1121]77SELECT id
78  FROM '.IMAGES_TABLE.'
79  WHERE storage_category_id IN (
80'.wordwrap(implode(', ', $ids), 80, "\n").')
[467]81;';
[587]82  $result = pwg_query($query);
[467]83  $element_ids = array();
[4325]84  while ($row = pwg_db_fetch_assoc($result))
[12]85  {
[1121]86    array_push($element_ids, $row['id']);
[12]87  }
[521]88  delete_elements($element_ids);
[21]89
[8265]90  // now, should we delete photos that are virtually linked to the category?
91  if ('delete_orphans' == $photo_deletion_mode or 'force_delete' == $photo_deletion_mode)
92  {
93    $query = '
94SELECT
95    DISTINCT(image_id)
96  FROM '.IMAGE_CATEGORY_TABLE.'
97  WHERE category_id IN ('.implode(',', $ids).')
98;';
99    $image_ids_linked = array_from_query($query, 'image_id');
[8848]100
101    if (count($image_ids_linked) > 0)
[8265]102    {
[8848]103      if ('delete_orphans' == $photo_deletion_mode)
104      {
105        $query = '
[8265]106SELECT
107    DISTINCT(image_id)
108  FROM '.IMAGE_CATEGORY_TABLE.'
109  WHERE image_id IN ('.implode(',', $image_ids_linked).')
110    AND category_id NOT IN ('.implode(',', $ids).')
111;';
[8848]112        $image_ids_not_orphans = array_from_query($query, 'image_id');
113        $image_ids_to_delete = array_diff($image_ids_linked, $image_ids_not_orphans);
114      }
[8265]115
[8848]116      if ('force_delete' == $photo_deletion_mode)
117      {
118        $image_ids_to_delete = $image_ids_linked;
119      }
120
121      delete_elements($image_ids_to_delete, true);
[8265]122    }
123  }
124
[61]125  // destruction of the links between images and this category
[467]126  $query = '
127DELETE FROM '.IMAGE_CATEGORY_TABLE.'
[657]128  WHERE category_id IN (
129'.wordwrap(implode(', ', $ids), 80, "\n").')
[467]130;';
[587]131  pwg_query($query);
[61]132
[21]133  // destruction of the access linked to the category
[467]134  $query = '
135DELETE FROM '.USER_ACCESS_TABLE.'
[657]136  WHERE cat_id IN (
137'.wordwrap(implode(', ', $ids), 80, "\n").')
[467]138;';
[587]139  pwg_query($query);
[1068]140
[467]141  $query = '
142DELETE FROM '.GROUP_ACCESS_TABLE.'
[657]143  WHERE cat_id IN (
144'.wordwrap(implode(', ', $ids), 80, "\n").')
[467]145;';
[587]146  pwg_query($query);
[21]147
[12]148  // destruction of the category
[467]149  $query = '
150DELETE FROM '.CATEGORIES_TABLE.'
[657]151  WHERE id IN (
152'.wordwrap(implode(', ', $ids), 80, "\n").')
[467]153;';
[587]154  pwg_query($query);
[498]155
[2882]156  $query='
[1866]157DELETE FROM '.OLD_PERMALINKS_TABLE.'
[1879]158  WHERE cat_id IN ('.implode(',',$ids).')';
[1866]159  pwg_query($query);
160
[2882]161  $query='
162DELETE FROM '.USER_CACHE_CATEGORIES_TABLE.'
163  WHERE cat_id IN ('.implode(',',$ids).')';
164  pwg_query($query);
165
[1605]166  trigger_action('delete_categories', $ids);
[12]167}
[345]168
[9191]169// Deletes all files (on disk) related to given image ids
170// @return image ids where files are deleted successfully
171function delete_element_files($ids)
[12]172{
[13651]173  global $conf;
[521]174  if (count($ids) == 0)
175  {
[6873]176    return 0;
[521]177  }
[1060]178
[9191]179  $new_ids = array();
[3145]180
[9191]181  $query = '
[2678]182SELECT
183    id,
184    path,
[6873]185    representative_ext
[2678]186  FROM '.IMAGES_TABLE.'
187  WHERE id IN ('.implode(',', $ids).')
188;';
[9191]189  $result = pwg_query($query);
190  while ($row = pwg_db_fetch_assoc($result))
191  {
192    if (url_is_remote($row['path']))
[2678]193    {
[9191]194      continue;
195    }
[12917]196
[9191]197    $files = array();
198    $files[] = get_element_path($row);
[2678]199
[9191]200    if (!empty($row['representative_ext']))
201    {
[12855]202      $files[] = original_to_representative( $files[0], $row['representative_ext']);
[9191]203    }
204
205    $ok = true;
[13052]206    if (!isset($conf['never_delete_originals']))
207    {
208      foreach ($files as $path)
209      {
210        if (is_file($path) and !unlink($path))
211        {
212          $ok = false;
213          trigger_error('"'.$path.'" cannot be removed', E_USER_WARNING);
214          break;
215        }
216      }
217    }
[12917]218
[9191]219    if ($ok)
220    {
[12917]221      delete_element_derivatives($row);
[17725]222      $new_ids[] = $row['id'];
[9191]223    }
224    else
225    {
226      break;
227    }
228  }
229  return $new_ids;
230}
231
232// The function delete_elements deletes the elements identified by the
233// (numeric) values of the array $ids. It also deletes (in the database) :
234//    - all the comments related to elements
235//    - all the links between categories and elements
236//    - all the favorites associated to elements
237// @return number of deleted elements
238function delete_elements($ids, $physical_deletion=false)
239{
240  if (count($ids) == 0)
241  {
242    return 0;
243  }
244  trigger_action('begin_delete_elements', $ids);
245
246  if ($physical_deletion)
247  {
248    $ids = delete_element_files($ids);
[6873]249    if (count($ids)==0)
250    {
251      return 0;
252    }
[2678]253  }
254
[12]255  // destruction of the comments on the image
[467]256  $query = '
257DELETE FROM '.COMMENTS_TABLE.'
[491]258  WHERE image_id IN (
259'.wordwrap(implode(', ', $ids), 80, "\n").')
[467]260;';
[587]261  pwg_query($query);
[61]262
263  // destruction of the links between images and this category
[467]264  $query = '
265DELETE FROM '.IMAGE_CATEGORY_TABLE.'
[491]266  WHERE image_id IN (
267'.wordwrap(implode(', ', $ids), 80, "\n").')
[467]268;';
[587]269  pwg_query($query);
[61]270
[1119]271  // destruction of the links between images and tags
272  $query = '
273DELETE FROM '.IMAGE_TAG_TABLE.'
274  WHERE image_id IN (
275'.wordwrap(implode(', ', $ids), 80, "\n").')
276;';
277  pwg_query($query);
278
[12]279  // destruction of the favorites associated with the picture
[467]280  $query = '
281DELETE FROM '.FAVORITES_TABLE.'
[491]282  WHERE image_id IN (
283'.wordwrap(implode(', ', $ids), 80, "\n").')
[467]284;';
[587]285  pwg_query($query);
[523]286
287  // destruction of the rates associated to this element
288  $query = '
289DELETE FROM '.RATE_TABLE.'
290  WHERE element_id IN (
291'.wordwrap(implode(', ', $ids), 80, "\n").')
292;';
[587]293  pwg_query($query);
[764]294
295  // destruction of the rates associated to this element
296  $query = '
297DELETE FROM '.CADDIE_TABLE.'
298  WHERE element_id IN (
299'.wordwrap(implode(', ', $ids), 80, "\n").')
300;';
301  pwg_query($query);
[1060]302
[12]303  // destruction of the image
[467]304  $query = '
305DELETE FROM '.IMAGES_TABLE.'
[491]306  WHERE id IN (
307'.wordwrap(implode(', ', $ids), 80, "\n").')
[467]308;';
[587]309  pwg_query($query);
[491]310
[4731]311  // are the photo used as category representant?
312  $query = '
313SELECT
314    id
315  FROM '.CATEGORIES_TABLE.'
316  WHERE representative_picture_id IN (
317'.wordwrap(implode(', ', $ids), 80, "\n").')
318;';
319  $category_ids = array_from_query($query, 'id');
320  if (count($category_ids) > 0)
321  {
322    update_category($category_ids);
323  }
[5691]324
[1605]325  trigger_action('delete_elements', $ids);
[6873]326  return count($ids);
[12]327}
[345]328
[12]329// The delete_user function delete a user identified by the $user_id
330// It also deletes :
[21]331//     - all the access linked to this user
332//     - all the links to any group
[12]333//     - all the favorites linked to this user
[680]334//     - calculated permissions linked to the user
[1028]335//     - all datas about notifications for the user
[650]336function delete_user($user_id)
[12]337{
[808]338  global $conf;
[1863]339  $tables = array(
340    // destruction of the access linked to the user
341    USER_ACCESS_TABLE,
342    // destruction of data notification by mail for this user
343    USER_MAIL_NOTIFICATION_TABLE,
344    // destruction of data RSS notification for this user
345    USER_FEED_TABLE,
346    // deletion of calculated permissions linked to the user
347    USER_CACHE_TABLE,
348    // deletion of computed cache data linked to the user
349    USER_CACHE_CATEGORIES_TABLE,
350    // destruction of the group links for this user
351    USER_GROUP_TABLE,
352    // destruction of the favorites associated with the user
353    FAVORITES_TABLE,
354    // destruction of the caddie associated with the user
355    CADDIE_TABLE,
[2339]356    // deletion of piwigo specific informations
[1863]357    USER_INFOS_TABLE,
358    );
[1060]359
[1863]360  foreach ($tables as $table)
361  {
362    $query = '
363DELETE FROM '.$table.'
[650]364  WHERE user_id = '.$user_id.'
365;';
[1863]366    pwg_query($query);
367  }
[21]368
[1863]369  // destruction of the user
[650]370  $query = '
[1863]371DELETE FROM '.SESSIONS_TABLE.'
[6664]372  WHERE data LIKE \'pwg_uid|i:'.(int)$user_id.';%\'
[650]373;';
374  pwg_query($query);
[21]375
[12]376  // destruction of the user
[650]377  $query = '
378DELETE FROM '.USERS_TABLE.'
[808]379  WHERE '.$conf['user_fields']['id'].' = '.$user_id.'
[650]380;';
381  pwg_query($query);
[1605]382
383  trigger_action('delete_user', $user_id);
[12]384}
[21]385
[491]386/**
[8762]387 * Deletes all tags linked to no photo
388 */
389function delete_orphan_tags()
390{
391  $orphan_tags = get_orphan_tags();
[12917]392
[8762]393  if (count($orphan_tags) > 0)
394  {
395    $orphan_tag_ids = array();
396    foreach ($orphan_tags as $tag)
397    {
398      array_push($orphan_tag_ids, $tag['id']);
399    }
400
401    $query = '
402DELETE
403  FROM '.TAGS_TABLE.'
404  WHERE id IN ('.implode(',', $orphan_tag_ids).')
405;';
406    pwg_query($query);
407  }
408}
409
410/**
411 * Get all tags (id + name) linked to no photo
412 */
413function get_orphan_tags()
414{
415  $orphan_tags = array();
[12917]416
[8762]417  $query = '
418SELECT
419    id,
420    name
421  FROM '.TAGS_TABLE.'
422    LEFT JOIN '.IMAGE_TAG_TABLE.' ON id = tag_id
423  WHERE tag_id IS NULL
424;';
425  $result = pwg_query($query);
426  while ($row = pwg_db_fetch_assoc($result))
427  {
428    array_push($orphan_tags, $row);
429  }
430
431  return $orphan_tags;
432}
433
434/**
[2324]435 * Verifies that the representative picture really exists in the db and
436 * picks up a random represantive if possible and based on config.
[491]437 *
438 * @param mixed category id
439 * @returns void
440 */
[2324]441function update_category($ids = 'all')
[61]442{
[809]443  global $conf;
[1060]444
[2324]445  if ($ids=='all')
[61]446  {
[2324]447    $where_cats = '1=1';
[61]448  }
[2324]449  elseif ( !is_array($ids) )
[635]450  {
[2324]451    $where_cats = '%s='.$ids;
[635]452  }
[2324]453  else
[61]454  {
[2324]455    if (count($ids) == 0)
456    {
457      return false;
458    }
459    $where_cats = '%s IN('.wordwrap(implode(', ', $ids), 120, "\n").')';
[491]460  }
[2333]461
[2324]462  // find all categories where the setted representative is not possible :
463  // the picture does not exist
464  $query = '
465SELECT DISTINCT c.id
[809]466  FROM '.CATEGORIES_TABLE.' AS c LEFT JOIN '.IMAGES_TABLE.' AS i
467    ON c.representative_picture_id = i.id
[491]468  WHERE representative_picture_id IS NOT NULL
[2324]469    AND '.sprintf($where_cats, 'c.id').'
[809]470    AND i.id IS NULL
[491]471;';
[2324]472  $wrong_representant = array_from_query($query, 'id');
[809]473
[2324]474  if (count($wrong_representant) > 0)
475  {
476    $query = '
[809]477UPDATE '.CATEGORIES_TABLE.'
478  SET representative_picture_id = NULL
[2324]479  WHERE id IN ('.wordwrap(implode(', ', $wrong_representant), 120, "\n").')
[809]480;';
[2324]481    pwg_query($query);
482  }
[809]483
[2324]484  if (!$conf['allow_random_representative'])
485  {
486    // If the random representant is not allowed, we need to find
487    // categories with elements and with no representant. Those categories
488    // must be added to the list of categories to set to a random
489    // representant.
490    $query = '
491SELECT DISTINCT id
492  FROM '.CATEGORIES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.'
493    ON id = category_id
[635]494  WHERE representative_picture_id IS NULL
[2324]495    AND '.sprintf($where_cats, 'category_id').'
[491]496;';
[2324]497    $to_rand = array_from_query($query, 'id');
498    if (count($to_rand) > 0)
499    {
500      set_random_representant($to_rand);
[133]501    }
[61]502  }
503}
504
[825]505/**
[657]506 * returns an array containing sub-directories which can be a category,
507 * recursive by default
508 *
509 * directories nammed "thumbnail", "pwg_high" or "pwg_representative" are
510 * omitted
511 *
512 * @param string $basedir
513 * @return array
514 */
515function get_fs_directories($path, $recursive = true)
516{
517  $dirs = array();
[1060]518
[657]519  if (is_dir($path))
520  {
521    if ($contents = opendir($path))
522    {
523      while (($node = readdir($contents)) !== false)
524      {
[12642]525        if ($node != '.'
[657]526            and $node != '..'
[1006]527            and $node != '.svn'
[657]528            and $node != 'thumbnail'
529            and $node != 'pwg_high'
[12642]530            and $node != 'pwg_representative'
531            and is_dir($path.'/'.$node))
[657]532        {
533          array_push($dirs, $path.'/'.$node);
534          if ($recursive)
535          {
536            $dirs = array_merge($dirs, get_fs_directories($path.'/'.$node));
537          }
538        }
539      }
[2478]540      closedir($contents);
[657]541    }
542  }
543
544  return $dirs;
545}
546
[606]547/**
[2306]548 * order categories (update categories.rank and global_rank database fields)
549 * so that rank field are consecutive integers starting at 1 for each child
[625]550 * @return void
551 */
[2306]552function update_global_rank()
[625]553{
554  $query = '
[4385]555SELECT id, id_uppercat, uppercats, rank, global_rank
[625]556  FROM '.CATEGORIES_TABLE.'
[2491]557  ORDER BY id_uppercat,rank,name';
[625]558
[2306]559  $cat_map = array();
[625]560
[2306]561  $current_rank = 0;
562  $current_uppercat = '';
563
[625]564  $result = pwg_query($query);
[4325]565  while ($row = pwg_db_fetch_assoc($result))
[625]566  {
[2306]567    if ($row['id_uppercat'] != $current_uppercat)
568    {
569      $current_rank = 0;
570      $current_uppercat = $row['id_uppercat'];
571    }
572    ++$current_rank;
573    $cat =
574      array(
575        'rank' =>        $current_rank,
576        'rank_changed' =>$current_rank!=$row['rank'],
577        'global_rank' => $row['global_rank'],
578        'uppercats' =>   $row['uppercats'],
579        );
580    $cat_map[ $row['id'] ] = $cat;
[625]581  }
[1060]582
[625]583  $datas = array();
[2306]584
585  foreach( $cat_map as $id=>$cat )
[625]586  {
[2306]587    $new_global_rank = preg_replace(
[1082]588          '/(\d+)/e',
[2306]589          "\$cat_map['$1']['rank']",
590          str_replace(',', '.', $cat['uppercats'] )
591          );
592    if ( $cat['rank_changed']
593      or $new_global_rank!=$cat['global_rank']
594      )
595    {
596      $datas[] = array(
597          'id' => $id,
598          'rank' => $cat['rank'],
599          'global_rank' => $new_global_rank,
600        );
601    }
[625]602  }
603
[1082]604  mass_updates(
605    CATEGORIES_TABLE,
606    array(
607      'primary' => array('id'),
[2306]608      'update'  => array('rank', 'global_rank')
[1082]609      ),
610    $datas
611    );
[2306]612  return count($datas);
[625]613}
[632]614
615/**
616 * change the visible property on a set of categories
617 *
618 * @param array categories
619 * @param string value
620 * @return void
621 */
622function set_cat_visible($categories, $value)
623{
624  if (!in_array($value, array('true', 'false')))
625  {
[2491]626    trigger_error("set_cat_visible invalid param $value", E_USER_WARNING);
[632]627    return false;
628  }
629
630  // unlocking a category => all its parent categories become unlocked
631  if ($value == 'true')
632  {
[657]633    $uppercats = get_uppercat_ids($categories);
[632]634    $query = '
635UPDATE '.CATEGORIES_TABLE.'
636  SET visible = \'true\'
[2491]637  WHERE id IN ('.implode(',', $uppercats).')';
[632]638    pwg_query($query);
639  }
640  // locking a category   => all its child categories become locked
641  if ($value == 'false')
642  {
643    $subcats = get_subcat_ids($categories);
644    $query = '
645UPDATE '.CATEGORIES_TABLE.'
646  SET visible = \'false\'
[2491]647  WHERE id IN ('.implode(',', $subcats).')';
[632]648    pwg_query($query);
649  }
650}
651
652/**
653 * change the status property on a set of categories : private or public
654 *
655 * @param array categories
656 * @param string value
657 * @return void
658 */
659function set_cat_status($categories, $value)
660{
661  if (!in_array($value, array('public', 'private')))
662  {
[2491]663    trigger_error("set_cat_status invalid param $value", E_USER_WARNING);
[632]664    return false;
665  }
666
667  // make public a category => all its parent categories become public
668  if ($value == 'public')
669  {
[657]670    $uppercats = get_uppercat_ids($categories);
[632]671    $query = '
672UPDATE '.CATEGORIES_TABLE.'
673  SET status = \'public\'
674  WHERE id IN ('.implode(',', $uppercats).')
675;';
676    pwg_query($query);
677  }
678  // make a category private => all its child categories become private
679  if ($value == 'private')
680  {
681    $subcats = get_subcat_ids($categories);
682    $query = '
683UPDATE '.CATEGORIES_TABLE.'
684  SET status = \'private\'
[2491]685  WHERE id IN ('.implode(',', $subcats).')';
[632]686    pwg_query($query);
687  }
688}
[633]689
690/**
[657]691 * returns all uppercats category ids of the given category ids
692 *
693 * @param array cat_ids
694 * @return array
695 */
696function get_uppercat_ids($cat_ids)
697{
698  if (!is_array($cat_ids) or count($cat_ids) < 1)
699  {
700    return array();
701  }
[1060]702
[657]703  $uppercats = array();
704
705  $query = '
706SELECT uppercats
707  FROM '.CATEGORIES_TABLE.'
708  WHERE id IN ('.implode(',', $cat_ids).')
709;';
710  $result = pwg_query($query);
[4325]711  while ($row = pwg_db_fetch_assoc($result))
[657]712  {
713    $uppercats = array_merge($uppercats,
714                             explode(',', $row['uppercats']));
715  }
716  $uppercats = array_unique($uppercats);
717
718  return $uppercats;
719}
720
721/**
[633]722 * set a new random representant to the categories
723 *
724 * @param array categories
725 */
726function set_random_representant($categories)
727{
728  $datas = array();
729  foreach ($categories as $category_id)
730  {
731    $query = '
732SELECT image_id
733  FROM '.IMAGE_CATEGORY_TABLE.'
734  WHERE category_id = '.$category_id.'
[4331]735  ORDER BY '.DB_RANDOM_FUNCTION.'()
[4334]736  LIMIT 1
[633]737;';
[4325]738    list($representative) = pwg_db_fetch_row(pwg_query($query));
[1428]739
740    array_push(
741      $datas,
742      array(
743        'id' => $category_id,
744        'representative_picture_id' => $representative,
745        )
746      );
[633]747  }
748
[1428]749  mass_updates(
750    CATEGORIES_TABLE,
751    array(
752      'primary' => array('id'),
753      'update' => array('representative_picture_id')
754      ),
755    $datas
756    );
[633]757}
[638]758
759/**
[657]760 * returns the fulldir for each given category id
761 *
762 * @param array cat_ids
763 * @return array
764 */
765function get_fulldirs($cat_ids)
766{
767  if (count($cat_ids) == 0)
768  {
769    return array();
770  }
[1060]771
[657]772  // caching directories of existing categories
773  $query = '
774SELECT id, dir
775  FROM '.CATEGORIES_TABLE.'
776  WHERE dir IS NOT NULL
777;';
[2560]778  $cat_dirs = simple_hash_from_query($query, 'id', 'dir');
[657]779
[672]780  // caching galleries_url
781  $query = '
782SELECT id, galleries_url
783  FROM '.SITES_TABLE.'
784;';
[2560]785  $galleries_url = simple_hash_from_query($query, 'id', 'galleries_url');
[672]786
787  // categories : id, site_id, uppercats
788  $categories = array();
[1060]789
[657]790  $query = '
[672]791SELECT id, uppercats, site_id
[657]792  FROM '.CATEGORIES_TABLE.'
[2560]793  WHERE dir IS NOT NULL
794    AND id IN (
[657]795'.wordwrap(implode(', ', $cat_ids), 80, "\n").')
796;';
797  $result = pwg_query($query);
[4325]798  while ($row = pwg_db_fetch_assoc($result))
[657]799  {
[672]800    array_push($categories, $row);
[657]801  }
[1060]802
[657]803  // filling $cat_fulldirs
804  $cat_fulldirs = array();
[672]805  foreach ($categories as $category)
[657]806  {
[672]807    $uppercats = str_replace(',', '/', $category['uppercats']);
808    $cat_fulldirs[$category['id']] = $galleries_url[$category['site_id']];
809    $cat_fulldirs[$category['id']].= preg_replace('/(\d+)/e',
810                                                  "\$cat_dirs['$1']",
811                                                  $uppercats);
[657]812  }
813
814  return $cat_fulldirs;
815}
816
817/**
818 * returns an array with all file system files according to
819 * $conf['file_ext']
820 *
821 * @param string $path
822 * @param bool recursive
823 * @return array
824 */
825function get_fs($path, $recursive = true)
826{
827  global $conf;
828
829  // because isset is faster than in_array...
830  if (!isset($conf['flip_picture_ext']))
831  {
832    $conf['flip_picture_ext'] = array_flip($conf['picture_ext']);
833  }
834  if (!isset($conf['flip_file_ext']))
835  {
836    $conf['flip_file_ext'] = array_flip($conf['file_ext']);
837  }
838
839  $fs['elements'] = array();
840  $fs['thumbnails'] = array();
841  $fs['representatives'] = array();
842  $subdirs = array();
843
844  if (is_dir($path))
845  {
846    if ($contents = opendir($path))
847    {
848      while (($node = readdir($contents)) !== false)
849      {
[12640]850        if ($node == '.' or $node == '..') continue;
851
[657]852        if (is_file($path.'/'.$node))
853        {
854          $extension = get_extension($node);
[1060]855
[657]856//          if (in_array($extension, $conf['picture_ext']))
857          if (isset($conf['flip_picture_ext'][$extension]))
858          {
859            if (basename($path) == 'thumbnail')
860            {
861              array_push($fs['thumbnails'], $path.'/'.$node);
862            }
863            else if (basename($path) == 'pwg_representative')
864            {
865              array_push($fs['representatives'], $path.'/'.$node);
866            }
867            else
868            {
869              array_push($fs['elements'], $path.'/'.$node);
870            }
871          }
872//          else if (in_array($extension, $conf['file_ext']))
873          else if (isset($conf['flip_file_ext'][$extension]))
874          {
875            array_push($fs['elements'], $path.'/'.$node);
876          }
877        }
[12640]878        else if (is_dir($path.'/'.$node) and $node != 'pwg_high' and $recursive)
[657]879        {
880          array_push($subdirs, $node);
881        }
882      }
883    }
884    closedir($contents);
885
886    foreach ($subdirs as $subdir)
887    {
888      $tmp_fs = get_fs($path.'/'.$subdir);
889
890      $fs['elements']        = array_merge($fs['elements'],
891                                           $tmp_fs['elements']);
[1060]892
[657]893      $fs['thumbnails']      = array_merge($fs['thumbnails'],
894                                           $tmp_fs['thumbnails']);
[1060]895
[657]896      $fs['representatives'] = array_merge($fs['representatives'],
897                                           $tmp_fs['representatives']);
898    }
899  }
900  return $fs;
901}
[672]902
903/**
[809]904 * synchronize base users list and related users list
905 *
906 * compares and synchronizes base users table (USERS_TABLE) with its child
907 * tables (USER_INFOS_TABLE, USER_ACCESS, USER_CACHE, USER_GROUP) : each
908 * base user must be present in child tables, users in child tables not
909 * present in base table must be deleted.
910 *
911 * @return void
[808]912 */
913function sync_users()
914{
915  global $conf;
[1060]916
[808]917  $query = '
918SELECT '.$conf['user_fields']['id'].' AS id
919  FROM '.USERS_TABLE.'
920;';
921  $base_users = array_from_query($query, 'id');
922
923  $query = '
924SELECT user_id
925  FROM '.USER_INFOS_TABLE.'
926;';
927  $infos_users = array_from_query($query, 'user_id');
928
929  // users present in $base_users and not in $infos_users must be added
930  $to_create = array_diff($base_users, $infos_users);
931
932  if (count($to_create) > 0)
933  {
[1926]934    create_user_infos($to_create);
[808]935  }
936
[809]937  // users present in user related tables must be present in the base user
938  // table
[1082]939  $tables = array(
940    USER_MAIL_NOTIFICATION_TABLE,
941    USER_FEED_TABLE,
942    USER_INFOS_TABLE,
943    USER_ACCESS_TABLE,
944    USER_CACHE_TABLE,
[1624]945    USER_CACHE_CATEGORIES_TABLE,
[1082]946    USER_GROUP_TABLE
947    );
[1592]948
[809]949  foreach ($tables as $table)
[808]950  {
951    $query = '
[2095]952SELECT DISTINCT user_id
[809]953  FROM '.$table.'
954;';
[1082]955    $to_delete = array_diff(
956      array_from_query($query, 'user_id'),
957      $base_users
958      );
[1060]959
[809]960    if (count($to_delete) > 0)
961    {
962      $query = '
[808]963DELETE
[809]964  FROM '.$table.'
[808]965  WHERE user_id in ('.implode(',', $to_delete).')
966;';
[809]967      pwg_query($query);
968    }
969  }
970}
971
972/**
973 * updates categories.uppercats field based on categories.id +
974 * categories.id_uppercat
975 *
976 * @return void
977 */
978function update_uppercats()
979{
980  $query = '
[2304]981SELECT id, id_uppercat, uppercats
[809]982  FROM '.CATEGORIES_TABLE.'
983;';
[2304]984  $cat_map = hash_from_query($query, 'id');
[1060]985
[2304]986  $datas = array();
987  foreach ($cat_map as $id => $cat)
[809]988  {
[2304]989    $upper_list = array();
[809]990
991    $uppercat = $id;
[2304]992    while ($uppercat)
993    {
994      array_push($upper_list, $uppercat);
995      $uppercat = $cat_map[$uppercat]['id_uppercat'];
996    }
[809]997
[2304]998    $new_uppercats = implode(',', array_reverse($upper_list));
999    if ($new_uppercats != $cat['uppercats'])
[809]1000    {
[2304]1001      array_push(
1002        $datas,
1003        array(
1004          'id' => $id,
1005          'uppercats' => $new_uppercats
1006          )
1007        );
[809]1008    }
1009  }
1010  $fields = array('primary' => array('id'), 'update' => array('uppercats'));
1011  mass_updates(CATEGORIES_TABLE, $fields, $datas);
1012}
1013
1014/**
1015 * update images.path field
1016 *
1017 * @return void
1018 */
1019function update_path()
1020{
1021  $query = '
[1121]1022SELECT DISTINCT(storage_category_id)
1023  FROM '.IMAGES_TABLE.'
[2575]1024  WHERE storage_category_id IS NOT NULL
[809]1025;';
[1121]1026  $cat_ids = array_from_query($query, 'storage_category_id');
1027  $fulldirs = get_fulldirs($cat_ids);
[1060]1028
[1121]1029  foreach ($cat_ids as $cat_id)
[809]1030  {
1031    $query = '
1032UPDATE '.IMAGES_TABLE.'
[5691]1033  SET path = '.pwg_db_concat(array("'".$fulldirs[$cat_id]."/'",'file')).'
[1121]1034  WHERE storage_category_id = '.$cat_id.'
[809]1035;';
[808]1036    pwg_query($query);
[809]1037  }
[808]1038}
[809]1039
1040/**
[881]1041 * change the parent category of the given categories. The categories are
[809]1042 * supposed virtual.
1043 *
[881]1044 * @param array category identifiers
[809]1045 * @param int parent category identifier
1046 * @return void
1047 */
[881]1048function move_categories($category_ids, $new_parent = -1)
[809]1049{
[881]1050  global $page;
1051
1052  if (count($category_ids) == 0)
1053  {
1054    return;
1055  }
1056
1057  $new_parent = $new_parent < 1 ? 'NULL' : $new_parent;
1058
1059  $categories = array();
[1060]1060
[809]1061  $query = '
[881]1062SELECT id, id_uppercat, status, uppercats
[809]1063  FROM '.CATEGORIES_TABLE.'
[881]1064  WHERE id IN ('.implode(',', $category_ids).')
[809]1065;';
[881]1066  $result = pwg_query($query);
[4325]1067  while ($row = pwg_db_fetch_assoc($result))
[809]1068  {
[881]1069    $categories[$row['id']] =
1070      array(
1071        'parent' => empty($row['id_uppercat']) ? 'NULL' : $row['id_uppercat'],
1072        'status' => $row['status'],
1073        'uppercats' => $row['uppercats']
1074        );
[809]1075  }
[1060]1076
[881]1077  // is the movement possible? The movement is impossible if you try to move
1078  // a category in a sub-category or itself
1079  if ('NULL' != $new_parent)
1080  {
1081    $query = '
1082SELECT uppercats
1083  FROM '.CATEGORIES_TABLE.'
1084  WHERE id = '.$new_parent.'
1085;';
[4325]1086    list($new_parent_uppercats) = pwg_db_fetch_row(pwg_query($query));
[881]1087
1088    foreach ($categories as $category)
1089    {
1090      // technically, you can't move a category with uppercats 12,125,13,14
1091      // into a new parent category with uppercats 12,125,13,14,24
[8967]1092      if (preg_match('/^'.$category['uppercats'].'(,|$)/', $new_parent_uppercats))
[881]1093      {
1094        array_push(
1095          $page['errors'],
[6993]1096          l10n('You cannot move an album in its own sub album')
[881]1097          );
1098        return;
1099      }
1100    }
1101  }
[1060]1102
[881]1103  $tables =
1104    array(
1105      USER_ACCESS_TABLE => 'user_id',
1106      GROUP_ACCESS_TABLE => 'group_id'
1107      );
[1060]1108
[809]1109  $query = '
1110UPDATE '.CATEGORIES_TABLE.'
1111  SET id_uppercat = '.$new_parent.'
[881]1112  WHERE id IN ('.implode(',', $category_ids).')
[809]1113;';
1114  pwg_query($query);
1115
1116  update_uppercats();
1117  update_global_rank();
1118
1119  // status and related permissions management
1120  if ('NULL' == $new_parent)
1121  {
1122    $parent_status = 'public';
1123  }
1124  else
1125  {
1126    $query = '
1127SELECT status
1128  FROM '.CATEGORIES_TABLE.'
1129  WHERE id = '.$new_parent.'
1130;';
[4325]1131    list($parent_status) = pwg_db_fetch_row(pwg_query($query));
[809]1132  }
1133
1134  if ('private' == $parent_status)
1135  {
[881]1136    foreach ($categories as $cat_id => $category)
[809]1137    {
[881]1138      switch ($category['status'])
[809]1139      {
[881]1140        case 'public' :
1141        {
1142          set_cat_status(array($cat_id), 'private');
1143          break;
1144        }
1145        case 'private' :
1146        {
1147          $subcats = get_subcat_ids(array($cat_id));
[1060]1148
[881]1149          foreach ($tables as $table => $field)
1150          {
1151            $query = '
[809]1152SELECT '.$field.'
1153  FROM '.$table.'
[881]1154  WHERE cat_id = '.$cat_id.'
[809]1155;';
[881]1156            $category_access = array_from_query($query, $field);
[809]1157
[881]1158            $query = '
[809]1159SELECT '.$field.'
1160  FROM '.$table.'
[881]1161  WHERE cat_id = '.$new_parent.'
[809]1162;';
[881]1163            $parent_access = array_from_query($query, $field);
[1060]1164
[881]1165            $to_delete = array_diff($parent_access, $category_access);
[1060]1166
[881]1167            if (count($to_delete) > 0)
1168            {
1169              $query = '
[809]1170DELETE FROM '.$table.'
1171  WHERE '.$field.' IN ('.implode(',', $to_delete).')
[881]1172    AND cat_id IN ('.implode(',', $subcats).')
[809]1173;';
[881]1174              pwg_query($query);
1175            }
[809]1176          }
[881]1177          break;
[809]1178        }
1179      }
1180    }
1181  }
[881]1182
1183  array_push(
1184    $page['infos'],
[1932]1185    l10n_dec(
[6951]1186      '%d album moved', '%d albums moved',
[881]1187      count($categories)
1188      )
1189    );
[809]1190}
[1064]1191
1192/**
1193 * create a virtual category
1194 *
1195 * @param string category name
1196 * @param int parent category id
1197 * @return array with ('info' and 'id') or ('error') key
1198 */
[17668]1199function create_virtual_category($category_name, $parent_id=null, $options=array())
[1064]1200{
[11728]1201  global $conf, $user;
[1068]1202
[1064]1203  // is the given category name only containing blank spaces ?
1204  if (preg_match('/^\s*$/', $category_name))
1205  {
[6988]1206    return array('error' => l10n('The name of an album must not be empty'));
[1064]1207  }
[17766]1208
[1064]1209  $insert = array(
1210    'name' => $category_name,
[12763]1211    'rank' => 0,
[17668]1212    'global_rank' => 0,
[1064]1213    );
[1068]1214
[17668]1215  // is the album commentable?
1216  if (isset($options['commentable']) and is_bool($options['commentable']))
[1064]1217  {
[17668]1218    $insert['commentable'] = $options['commentable'];
1219  }
1220  else
1221  {
1222    $insert['commentable'] = $conf['newcat_default_commentable'];
1223  }
1224  $insert['commentable'] = boolean_to_string($insert['commentable']);
1225
1226  // is the album temporarily locked? (only visible by administrators,
1227  // whatever permissions) (may be overwritten if parent album is not
1228  // visible)
1229  if (isset($options['visible']) and is_bool($options['visible']))
1230  {
1231    $insert['visible'] = $options['visible'];
1232  }
1233  else
1234  {
1235    $insert['visible'] = $conf['newcat_default_visible'];
1236  }
1237  $insert['visible'] = boolean_to_string($insert['visible']);
1238
1239  // is the album private? (may be overwritten if parent album is private)
1240  if (isset($options['status']) and 'private' == $options['status'])
1241  {
1242    $insert['status'] = 'private';
1243  }
1244  else
1245  {
1246    $insert['status'] = $conf['newcat_default_status'];
1247  }
1248
1249  // any description for this album?
1250  if (isset($options['comment']))
1251  {
1252    $insert['comment'] = strip_tags($options['comment']);
1253  }
1254
1255  if (!empty($parent_id) and is_numeric($parent_id))
1256  {
[1064]1257    $query = '
1258SELECT id, uppercats, global_rank, visible, status
1259  FROM '.CATEGORIES_TABLE.'
1260  WHERE id = '.$parent_id.'
1261;';
[4325]1262    $parent = pwg_db_fetch_assoc(pwg_query($query));
[1064]1263
[4265]1264    $insert['id_uppercat'] = $parent['id'];
1265    $insert['global_rank'] = $parent['global_rank'].'.'.$insert['rank'];
[1068]1266
[1064]1267    // at creation, must a category be visible or not ? Warning : if the
1268    // parent category is invisible, the category is automatically create
1269    // invisible. (invisible = locked)
1270    if ('false' == $parent['visible'])
1271    {
[4265]1272      $insert['visible'] = 'false';
[1064]1273    }
[1068]1274
[1064]1275    // at creation, must a category be public or private ? Warning : if the
1276    // parent category is private, the category is automatically create
1277    // private.
1278    if ('private' == $parent['status'])
1279    {
[4265]1280      $insert['status'] = 'private';
[1064]1281    }
[17668]1282
1283    $uppercats_prefix = $parent['uppercats'].',';
[1064]1284  }
1285  else
1286  {
[17668]1287    $uppercats_prefix = '';
[1064]1288  }
1289
1290  // we have then to add the virtual category
[17668]1291  single_insert(CATEGORIES_TABLE, $insert);
1292  $inserted_id = pwg_db_insert_id(CATEGORIES_TABLE);
1293
1294  single_update(
[1064]1295    CATEGORIES_TABLE,
[17668]1296    array('uppercats' => $uppercats_prefix.$inserted_id),
1297    array('id' => $inserted_id)
[1064]1298    );
1299
[12763]1300  update_global_rank();
1301
[11728]1302  if ('private' == $insert['status'])
1303  {
1304    add_permission_on_category($inserted_id, array_unique(array_merge(get_admins(), array($user['id']))));
1305  }
1306
[1064]1307  return array(
[6969]1308    'info' => l10n('Virtual album added'),
[1064]1309    'id'   => $inserted_id,
1310    );
1311}
[1111]1312
1313/**
[1119]1314 * Set tags to an image. Warning: given tags are all tags associated to the
1315 * image, not additionnal tags.
1316 *
1317 * @param array tag ids
1318 * @param int image id
1319 * @return void
1320 */
1321function set_tags($tags, $image_id)
1322{
[17725]1323  set_tags_of( array($image_id=>$tags) );
[1119]1324}
1325
1326/**
1327 * Add new tags to a set of images.
1328 *
1329 * @param array tag ids
1330 * @param array image ids
1331 * @return void
1332 */
1333function add_tags($tags, $images)
1334{
[5691]1335  if (count($tags) == 0 or count($images) == 0)
[1119]1336  {
1337    return;
1338  }
[1592]1339
[1119]1340  // we can't insert twice the same {image_id,tag_id} so we must first
1341  // delete lines we'll insert later
1342  $query = '
1343DELETE
1344  FROM '.IMAGE_TAG_TABLE.'
1345  WHERE image_id IN ('.implode(',', $images).')
1346    AND tag_id IN ('.implode(',', $tags).')
1347;';
1348  pwg_query($query);
1349
1350  $inserts = array();
1351  foreach ($images as $image_id)
1352  {
[17725]1353    foreach ( array_unique($tags) as $tag_id)
[1119]1354    {
[17725]1355      $inserts[] = array(
[1119]1356          'image_id' => $image_id,
1357          'tag_id' => $tag_id,
1358        );
1359    }
1360  }
1361  mass_inserts(
1362    IMAGE_TAG_TABLE,
1363    array_keys($inserts[0]),
1364    $inserts
1365    );
1366}
1367
[12032]1368/**
1369 *
1370 */
1371function delete_tags($tag_ids)
1372{
1373  if (is_numeric($tag_ids))
1374  {
1375    $tag_ids = array($tag_ids);
1376  }
1377
1378  if (!is_array($tag_ids))
1379  {
1380    return false;
1381  }
[12917]1382
[12032]1383  $query = '
1384DELETE
1385  FROM '.IMAGE_TAG_TABLE.'
1386  WHERE tag_id IN ('.implode(',', $tag_ids).')
1387;';
1388  pwg_query($query);
[12917]1389
[12032]1390  $query = '
1391DELETE
1392  FROM '.TAGS_TABLE.'
1393  WHERE id IN ('.implode(',', $tag_ids).')
1394;';
1395  pwg_query($query);
1396}
1397
[1119]1398function tag_id_from_tag_name($tag_name)
1399{
1400  global $page;
[2478]1401
[2350]1402  $tag_name = trim($tag_name);
[1119]1403  if (isset($page['tag_id_from_tag_name_cache'][$tag_name]))
1404  {
1405    return $page['tag_id_from_tag_name_cache'][$tag_name];
1406  }
[1592]1407
[17725]1408  // search existing by exact name
[1119]1409  $query = '
1410SELECT id
1411  FROM '.TAGS_TABLE.'
1412  WHERE name = \''.$tag_name.'\'
1413;';
[17725]1414  if (count($existing_tags = array_from_query($query, 'id')) == 0)
[1119]1415  {
[17725]1416    // search existing by case insensitive name
1417    $query = '
1418SELECT id
1419  FROM '.TAGS_TABLE.'
1420  WHERE CONVERT(name, CHAR) = \''.$tag_name.'\'
1421;';
1422    if (count($existing_tags = array_from_query($query, 'id')) == 0)
1423    {
1424      $url_name = trigger_event('render_tag_url', $tag_name);
1425      // search existing by url name
1426      $query = '
1427SELECT id
1428  FROM '.TAGS_TABLE.'
1429  WHERE url_name = \''.$url_name.'\'
1430;';
1431      if (count($existing_tags = array_from_query($query, 'id')) == 0)
1432      {
1433        mass_inserts(
1434          TAGS_TABLE,
1435          array('name', 'url_name'),
1436          array(
1437            array(
1438              'name' => $tag_name,
1439              'url_name' => $url_name,
1440              )
1441            )
1442          );
1443        $page['tag_id_from_tag_name_cache'][$tag_name] = pwg_db_insert_id(TAGS_TABLE);
1444        return $page['tag_id_from_tag_name_cache'][$tag_name];
1445      }
1446    }
[1119]1447  }
1448
[17725]1449  $page['tag_id_from_tag_name_cache'][$tag_name] = $existing_tags[0];
[1119]1450  return $page['tag_id_from_tag_name_cache'][$tag_name];
1451}
1452
1453function set_tags_of($tags_of)
1454{
1455  if (count($tags_of) > 0)
1456  {
1457    $query = '
1458DELETE
1459  FROM '.IMAGE_TAG_TABLE.'
1460  WHERE image_id IN ('.implode(',', array_keys($tags_of)).')
1461;';
1462    pwg_query($query);
1463
1464    $inserts = array();
[1592]1465
[1119]1466    foreach ($tags_of as $image_id => $tag_ids)
1467    {
[17725]1468      foreach (array_unique($tag_ids) as $tag_id)
[1119]1469      {
[17725]1470        $inserts[] = array(
[1119]1471            'image_id' => $image_id,
1472            'tag_id' => $tag_id,
1473          );
1474      }
1475    }
1476
[17766]1477    if (count($inserts))
1478    {
1479      mass_inserts(
1480        IMAGE_TAG_TABLE,
1481        array_keys($inserts[0]),
1482        $inserts
1483        );
1484    }
[1119]1485  }
1486}
1487
1488/**
[1121]1489 * Associate a list of images to a list of categories.
1490 *
[17981]1491 * The function will not duplicate links and will preserve ranks
[1121]1492 *
1493 * @param array images
1494 * @param array categories
1495 * @return void
1496 */
1497function associate_images_to_categories($images, $categories)
1498{
1499  if (count($images) == 0
1500      or count($categories) == 0)
1501  {
1502    return false;
1503  }
[17981]1504 
1505  // get existing associations
[1121]1506  $query = '
[17981]1507SELECT
1508    image_id,
1509    category_id
[1121]1510  FROM '.IMAGE_CATEGORY_TABLE.'
1511  WHERE image_id IN ('.implode(',', $images).')
1512    AND category_id IN ('.implode(',', $categories).')
1513;';
[17981]1514  $result = pwg_query($query);
1515 
1516  $existing = array();
1517  while ($row = pwg_db_fetch_assoc($result))
1518  {
1519    $existing[ $row['category_id'] ][] = $row['image_id'];
1520  }
[1121]1521
[17981]1522  // get max rank of each categories
[17001]1523  $query = '
1524SELECT
1525    category_id,
1526    MAX(rank) AS max_rank
1527  FROM '.IMAGE_CATEGORY_TABLE.'
1528  WHERE rank IS NOT NULL
1529    AND category_id IN ('.implode(',', $categories).')
1530  GROUP BY category_id
1531;';
1532
1533  $current_rank_of = simple_hash_from_query(
1534    $query,
1535    'category_id',
1536    'max_rank'
1537    );
1538
[17981]1539  // associate only not already associated images
[1121]1540  $inserts = array();
1541  foreach ($categories as $category_id)
1542  {
[17001]1543    if (!isset($current_rank_of[$category_id]))
1544    {
1545      $current_rank_of[$category_id] = 0;
1546    }
[17981]1547    if (!isset($existing[$category_id]))
1548    {
1549      $existing[$category_id] = array();
1550    }
[17001]1551
[1121]1552    foreach ($images as $image_id)
1553    {
[17981]1554      if (!in_array($image_id, $existing[$category_id]))
1555      {
1556        $rank = ++$current_rank_of[$category_id];
[17001]1557
[17981]1558        array_push(
1559          $inserts,
1560          array(
1561            'image_id' => $image_id,
1562            'category_id' => $category_id,
1563            'rank' => $rank,
1564            )
1565          );
1566      }
[1121]1567    }
1568  }
[1592]1569
[17981]1570  if (count($inserts))
1571  {
1572    mass_inserts(
1573      IMAGE_CATEGORY_TABLE,
1574      array_keys($inserts[0]),
1575      $inserts
1576      );
[1121]1577
[17981]1578    update_category($categories);
1579  }
[1121]1580}
1581
1582/**
[17981]1583 * Dissociate images from all old categories except their storage category and
[13077]1584 * associate to new categories.
1585 *
[17981]1586 * This function will preserve ranks
1587 *
[13077]1588 * @param array images
1589 * @param array categories
1590 * @return void
1591 */
1592function move_images_to_categories($images, $categories)
1593{
1594  if (count($images) == 0)
1595  {
1596    return false;
1597  }
[17295]1598
[17981]1599  // let's first break links with all old albums but their "storage album"
[13077]1600  $query = '
1601DELETE '.IMAGE_CATEGORY_TABLE.'.*
1602  FROM '.IMAGE_CATEGORY_TABLE.'
1603    JOIN '.IMAGES_TABLE.' ON image_id=id
1604  WHERE id IN ('.implode(',', $images).')
[17982]1605';
1606 
1607  if (is_array($categories) and count($categories) > 0)
1608  {
1609    $query.= '
1610    AND category_id NOT IN ('.implode(',', $categories).')
1611';
1612  }
1613
1614  $query.= '
[13077]1615    AND (storage_category_id IS NULL OR storage_category_id != category_id)
1616;';
1617  pwg_query($query);
[17295]1618
[13077]1619  if (is_array($categories) and count($categories) > 0)
1620  {
1621    associate_images_to_categories($images, $categories);
1622  }
1623}
1624
1625/**
[1121]1626 * Associate images associated to a list of source categories to a list of
1627 * destination categories.
1628 *
1629 * @param array sources
1630 * @param array destinations
1631 * @return void
1632 */
1633function associate_categories_to_categories($sources, $destinations)
1634{
1635  if (count($sources) == 0)
1636  {
1637    return false;
1638  }
1639
1640  $query = '
1641SELECT image_id
1642  FROM '.IMAGE_CATEGORY_TABLE.'
1643  WHERE category_id IN ('.implode(',', $sources).')
1644;';
1645  $images = array_from_query($query, 'image_id');
1646
1647  associate_images_to_categories($images, $destinations);
1648}
[1682]1649
1650/**
[2339]1651 * Refer main Piwigo URLs (currently PHPWG_DOMAIN domain)
[1724]1652 *
1653 * @param void
1654 * @return array like $conf['links']
1655 */
1656function pwg_URL()
1657{
1658  $urls = array(
[12875]1659    'HOME'       => PHPWG_URL,
1660    'WIKI'       => PHPWG_URL.'/doc',
1661    'DEMO'       => PHPWG_URL.'/demo',
1662    'FORUM'      => PHPWG_URL.'/forum',
1663    'BUGS'       => PHPWG_URL.'/bugs',
1664    'EXTENSIONS' => PHPWG_URL.'/ext',
[1724]1665    );
1666  return $urls;
1667}
1668
[1978]1669/**
1670 * Invalidates cahed data (permissions and category counts) for all users.
1671 */
[2890]1672function invalidate_user_cache($full = true)
[1978]1673{
[2890]1674  if ($full)
1675  {
1676    $query = '
1677TRUNCATE TABLE '.USER_CACHE_CATEGORIES_TABLE.';';
1678    pwg_query($query);
1679    $query = '
1680TRUNCATE TABLE '.USER_CACHE_TABLE.';';
1681    pwg_query($query);
1682  }
1683  else
1684  {
1685    $query = '
[1978]1686UPDATE '.USER_CACHE_TABLE.'
[2890]1687  SET need_update = \'true\';';
1688    pwg_query($query);
1689  }
[2892]1690  trigger_action('invalidate_user_cache', $full);
[1978]1691}
[2127]1692
1693/**
1694 * adds the caracter set to a create table sql query.
1695 * all CREATE TABLE queries must call this function
1696 * @param string query - the sql query
1697 */
1698function create_table_add_character_set($query)
1699{
[2502]1700  defined('DB_CHARSET') or fatal_error('create_table_add_character_set DB_CHARSET undefined');
[2127]1701  if ('DB_CHARSET'!='')
1702  {
1703    if ( version_compare(mysql_get_server_info(), '4.1.0', '<') )
1704    {
1705      return $query;
1706    }
1707    $charset_collate = " DEFAULT CHARACTER SET ".DB_CHARSET;
[2488]1708    if (DB_COLLATE!='')
[2127]1709    {
1710      $charset_collate .= " COLLATE ".DB_COLLATE;
1711    }
[2488]1712    if ( is_array($query) )
[2127]1713    {
[2488]1714      foreach( $query as $id=>$q)
1715      {
1716        $q=trim($q);
1717        $q=trim($q, ';');
1718        if (preg_match('/^CREATE\s+TABLE/i',$q))
1719        {
1720          $q.=$charset_collate;
1721        }
1722        $q .= ';';
1723        $query[$id] = $q;
1724      }
[2127]1725    }
[2488]1726    else
1727    {
1728      $query=trim($query);
1729      $query=trim($query, ';');
1730      if (preg_match('/^CREATE\s+TABLE/i',$query))
1731      {
1732        $query.=$charset_collate;
1733      }
1734      $query .= ';';
1735    }
[2127]1736  }
1737  return $query;
1738}
[2325]1739
1740/**
1741 * Returns array use on template with html_options method
1742 * @param Min and Max access to use
1743 * @return array of user access level
1744 */
1745function get_user_access_level_html_options($MinLevelAccess = ACCESS_FREE, $MaxLevelAccess = ACCESS_CLOSED)
1746{
1747  $tpl_options = array();
1748  for ($level = $MinLevelAccess; $level <= $MaxLevelAccess; $level++)
1749  {
1750    $tpl_options[$level] = l10n(sprintf('ACCESS_%d', $level));
1751  }
1752  return $tpl_options;
1753}
1754
[2588]1755/**
1756 * returns a list of templates currently available in template-extension
1757 * Each .tpl file is extracted from template-extension.
1758 * @return array
1759 */
1760function get_extents($start='')
1761{
1762  if ($start == '') { $start = './template-extension'; }
1763  $dir = opendir($start);
1764  $extents = array();
1765
1766  while (($file = readdir($dir)) !== false)
1767  {
1768    if ( $file == '.' or $file == '..' or $file == '.svn') continue;
1769    $path = $start . '/' . $file;
1770    if (is_dir($path))
1771    {
1772      $extents = array_merge($extents, get_extents($path));
1773    }
[3145]1774    elseif ( !is_link($path) and file_exists($path)
[2588]1775            and get_extension($path) == 'tpl' )
1776    {
1777      $extents[] = substr($path, 21);
1778    }
1779  }
1780  return $extents;
1781}
1782
[2634]1783function create_tag($tag_name)
1784{
1785  // does the tag already exists?
1786  $query = '
1787SELECT id
1788  FROM '.TAGS_TABLE.'
1789  WHERE name = \''.$tag_name.'\'
1790;';
1791  $existing_tags = array_from_query($query, 'id');
1792
1793  if (count($existing_tags) == 0)
1794  {
1795    mass_inserts(
1796      TAGS_TABLE,
1797      array('name', 'url_name'),
1798      array(
1799        array(
1800          'name' => $tag_name,
[12553]1801          'url_name' => trigger_event('render_tag_url', $tag_name),
[2634]1802          )
1803        )
1804      );
1805
[4892]1806    $inserted_id = pwg_db_insert_id(TAGS_TABLE);
[2634]1807
1808    return array(
1809      'info' => sprintf(
[5036]1810        l10n('Tag "%s" was added'),
[2634]1811        stripslashes($tag_name)
1812        ),
1813      'id' => $inserted_id,
1814      );
1815  }
1816  else
1817  {
1818    return array(
1819      'error' => sprintf(
[5036]1820        l10n('Tag "%s" already exists'),
[2634]1821        stripslashes($tag_name)
1822        )
1823      );
1824  }
1825}
[2777]1826
[11828]1827/**
1828 * Is the category accessible to the (Admin) user ?
1829 *
1830 * Note : if the user is not authorized to see this category, category jump
1831 * will be replaced by admin cat_modify page
1832 *
1833 * @param int category id to verify
1834 * @return bool
1835 */
1836function cat_admin_access($category_id)
1837{
1838  global $user;
[2777]1839
[11828]1840  // $filter['visible_categories'] and $filter['visible_images']
1841  // are not used because it's not necessary (filter <> restriction)
1842  if (in_array($category_id, explode(',', $user['forbidden_categories'])))
1843  {
1844    return false;
1845  }
1846  return true;
1847}
1848
[2880]1849/**
1850 * Retrieve data from external URL
1851 *
1852 * @param string $src: URL
1853 * @param global $dest: can be a file ressource or string
1854 * @return bool
1855 */
[8079]1856function fetchRemote($src, &$dest, $get_data=array(), $post_data=array(), $user_agent='Piwigo', $step=0)
[2880]1857{
[2902]1858  // Try to retrieve data from local file?
1859  if (!url_is_remote($src))
1860  {
1861    $content = @file_get_contents($src);
1862    if ($content !== false)
1863    {
1864      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
1865      return true;
1866    }
1867    else
1868    {
1869      return false;
1870    }
1871  }
1872
[8079]1873  // After 3 redirections, return false
1874  if ($step > 3) return false;
1875
[8080]1876  // Initialization
1877  $method  = empty($post_data) ? 'GET' : 'POST';
1878  $request = empty($post_data) ? '' : http_build_query($post_data, '', '&');
[8090]1879  if (!empty($get_data))
1880  {
1881    $src .= strpos($src, '?') === false ? '?' : '&';
1882    $src .= http_build_query($get_data, '', '&');
1883  }
[8080]1884
[2900]1885  // Initialize $dest
[2880]1886  is_resource($dest) or $dest = '';
1887
1888  // Try curl to read remote file
1889  if (function_exists('curl_init'))
1890  {
1891    $ch = @curl_init();
1892    @curl_setopt($ch, CURLOPT_URL, $src);
[2900]1893    @curl_setopt($ch, CURLOPT_HEADER, 1);
[2880]1894    @curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
[2900]1895    @curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
[8079]1896    if ($method == 'POST')
1897    {
1898      @curl_setopt($ch, CURLOPT_POST, 1);
[8090]1899      @curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
[8079]1900    }
[2880]1901    $content = @curl_exec($ch);
[2900]1902    $header_length = @curl_getinfo($ch, CURLINFO_HEADER_SIZE);
[2902]1903    $status = @curl_getinfo($ch, CURLINFO_HTTP_CODE);
[2880]1904    @curl_close($ch);
[2902]1905    if ($content !== false and $status >= 200 and $status < 400)
[2880]1906    {
[2900]1907      if (preg_match('/Location:\s+?(.+)/', substr($content, 0, $header_length), $m))
1908      {
[8079]1909        return fetchRemote($m[1], $dest, array(), array(), $user_agent, $step+1);
[2900]1910      }
1911      $content = substr($content, $header_length);
1912      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
[2880]1913      return true;
1914    }
1915  }
1916
1917  // Try file_get_contents to read remote file
1918  if (ini_get('allow_url_fopen'))
1919  {
[8079]1920    $opts = array(
1921      'http' => array(
1922        'method' => $method,
1923        'user_agent' => $user_agent,
1924      )
1925    );
[8090]1926    if ($method == 'POST')
1927    {
1928      $opts['http']['content'] = $request;
1929    }
[8079]1930    $context = @stream_context_create($opts);
1931    $content = @file_get_contents($src, false, $context);
[2880]1932    if ($content !== false)
1933    {
1934      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
1935      return true;
1936    }
1937  }
1938
1939  // Try fsockopen to read remote file
1940  $src = parse_url($src);
1941  $host = $src['host'];
1942  $path = isset($src['path']) ? $src['path'] : '/';
1943  $path .= isset($src['query']) ? '?'.$src['query'] : '';
[3145]1944
[2880]1945  if (($s = @fsockopen($host,80,$errno,$errstr,5)) === false)
1946  {
1947    return false;
1948  }
1949
[8079]1950  $http_request  = $method." ".$path." HTTP/1.0\r\n";
1951  $http_request .= "Host: ".$host."\r\n";
[8090]1952  if ($method == 'POST')
1953  {
1954    $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
1955    $http_request .= "Content-Length: ".strlen($request)."\r\n";
1956  }
[8079]1957  $http_request .= "User-Agent: ".$user_agent."\r\n";
1958  $http_request .= "Accept: */*\r\n";
1959  $http_request .= "\r\n";
1960  $http_request .= $request;
[2880]1961
[8079]1962  fwrite($s, $http_request);
1963
[2880]1964  $i = 0;
1965  $in_content = false;
1966  while (!feof($s))
1967  {
1968    $line = fgets($s);
1969
1970    if (rtrim($line,"\r\n") == '' && !$in_content)
1971    {
1972      $in_content = true;
1973      $i++;
1974      continue;
1975    }
1976    if ($i == 0)
1977    {
1978      if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/',rtrim($line,"\r\n"), $m))
1979      {
1980        fclose($s);
1981        return false;
1982      }
1983      $status = (integer) $m[2];
1984      if ($status < 200 || $status >= 400)
1985      {
1986        fclose($s);
1987        return false;
1988      }
1989    }
1990    if (!$in_content)
1991    {
1992      if (preg_match('/Location:\s+?(.+)$/',rtrim($line,"\r\n"),$m))
1993      {
1994        fclose($s);
[8079]1995        return fetchRemote(trim($m[1]),$dest,array(),array(),$user_agent,$step+1);
[2880]1996      }
1997      $i++;
1998      continue;
1999    }
2000    is_resource($dest) ? @fwrite($dest, $line) : $dest .= $line;
2001    $i++;
2002  }
2003  fclose($s);
2004  return true;
2005}
2006
[3145]2007
2008/**
2009 * returns the groupname corresponding to the given group identifier if
2010 * exists
2011 *
2012 * @param int group_id
2013 * @return mixed
2014 */
2015function get_groupname($group_id)
2016{
2017  $query = '
2018SELECT name
2019  FROM '.GROUPS_TABLE.'
2020  WHERE id = '.intval($group_id).'
2021;';
2022  $result = pwg_query($query);
[4325]2023  if (pwg_db_num_rows($result) > 0)
[3145]2024  {
[4325]2025    list($groupname) = pwg_db_fetch_row($result);
[3145]2026  }
2027  else
2028  {
2029    return false;
2030  }
2031
2032  return $groupname;
2033}
2034
2035/**
2036 * returns the username corresponding to the given user identifier if exists
2037 *
2038 * @param int user_id
2039 * @return mixed
2040 */
2041function get_username($user_id)
2042{
2043  global $conf;
2044
2045  $query = '
2046SELECT '.$conf['user_fields']['username'].'
2047  FROM '.USERS_TABLE.'
2048  WHERE '.$conf['user_fields']['id'].' = '.intval($user_id).'
2049;';
2050  $result = pwg_query($query);
[4325]2051  if (pwg_db_num_rows($result) > 0)
[3145]2052  {
[4325]2053    list($username) = pwg_db_fetch_row($result);
[3145]2054  }
2055  else
2056  {
2057    return false;
2058  }
2059
[4304]2060  return stripslashes($username);
[3145]2061}
[3382]2062
2063function get_newsletter_subscribe_base_url($language) {
[12875]2064  return PHPWG_URL.'/announcement/subscribe/';
[3382]2065}
[5173]2066
2067/**
2068 * Accordion menus need to know which section to open by default when
2069 * loading the page
2070 */
2071function get_active_menu($menu_page)
2072{
2073  global $page;
2074
2075  if (isset($page['active_menu']))
2076  {
2077    return $page['active_menu'];
2078  }
2079
2080  switch ($menu_page)
2081  {
[13077]2082    case 'photo':
[5173]2083    case 'photos_add':
2084    case 'rating':
2085    case 'tags':
2086    case 'picture_modify':
[8417]2087    case 'batch_manager':
[5173]2088      return 0;
2089
[13013]2090    case 'album':
[5173]2091    case 'cat_list':
2092    case 'cat_move':
2093    case 'cat_options':
2094    case 'permalinks':
2095      return 1;
[5691]2096
[5173]2097    case 'user_list':
2098    case 'user_perm':
2099    case 'group_list':
2100    case 'group_perm':
2101    case 'notification_by_mail':
2102      return 2;
2103
[10594]2104    case 'plugins':
[5173]2105    case 'plugin':
2106      return 3;
[5691]2107
[6056]2108    case 'site_manager':
2109    case 'site_update':
[5173]2110    case 'stats':
2111    case 'history':
2112    case 'maintenance':
[5997]2113    case 'comments':
[10511]2114    case 'updates':
[5173]2115      return 4;
2116
2117    case 'configuration':
[12820]2118    case 'derivatives':
[5173]2119    case 'extend_for_templates':
2120    case 'menubar':
[10594]2121    case 'themes':
[5448]2122    case 'theme':
[10594]2123    case 'languages':
[5173]2124      return 5;
2125  }
2126  return 0;
2127}
[5188]2128
[12259]2129function get_taglist($query, $only_user_language=true)
[5188]2130{
2131  $result = pwg_query($query);
[12917]2132
[5188]2133  $taglist = array();
[17766]2134  $altlist = array();
[5188]2135  while ($row = pwg_db_fetch_assoc($result))
2136  {
[17766]2137    $raw_name = $row['name'];
2138    $name = trigger_event('render_tag_name', $raw_name);
2139
2140    $taglist[] =  array(
2141        'name' => $name,
2142        'id' => '~~'.$row['id'].'~~',
2143      );
2144
2145    if (!$only_user_language)
[11487]2146    {
[17766]2147      $alt_names = trigger_event('get_tag_alt_names', array(), $raw_name);
2148
2149      // TEMP 2.4
2150      if (count($alt_names)==0 and preg_match_all('#\[lang=(.*?)\](.*?)\[/lang\]#is', $row['name'], $matches))
[11487]2151      {
[17766]2152        foreach ($matches[2] as $alt)
2153        {
2154          $alt_names[] = $alt;
2155        }
2156      }
2157
2158      foreach( array_diff( array_unique($alt_names), array($name) ) as $alt)
2159      {
2160        $altlist[] =  array(
2161            'name' => $alt,
[11853]2162            'id' => '~~'.$row['id'].'~~',
[11487]2163          );
2164      }
2165    }
[17766]2166  }
[12917]2167
[17766]2168  usort($taglist, 'tag_alpha_compare');
2169  if (count($altlist))
2170  {
2171    usort($altlist, 'tag_alpha_compare');
2172    $taglist = array_merge($taglist, $altlist);
[5188]2173  }
[12917]2174
[5188]2175  return $taglist;
2176}
2177
[11853]2178function get_tag_ids($raw_tags, $allow_create=true)
[5188]2179{
2180  // In $raw_tags we receive something like array('~~6~~', '~~59~~', 'New
2181  // tag', 'Another new tag') The ~~34~~ means that it is an existing
2182  // tag. I've added the surrounding ~~ to permit creation of tags like "10"
2183  // or "1234" (numeric characters only)
2184
2185  $tag_ids = array();
[10970]2186  $raw_tags = explode(',',$raw_tags);
[5691]2187
[5188]2188  foreach ($raw_tags as $raw_tag)
2189  {
2190    if (preg_match('/^~~(\d+)~~$/', $raw_tag, $matches))
2191    {
[17725]2192      $tag_ids[] = $matches[1];
[5188]2193    }
[11853]2194    elseif ($allow_create)
[5188]2195    {
2196      // we have to create a new tag
[11853]2197      $tag_ids[] = tag_id_from_tag_name($raw_tag);
[5188]2198    }
2199  }
2200
2201  return $tag_ids;
2202}
[8247]2203
2204/** returns the argument_ids array with new sequenced keys based on related
2205 * names. Sequence is not case sensitive.
2206 * Warning: By definition, this function breaks original keys
2207 */
2208function order_by_name($element_ids,$name)
2209{
2210  $ordered_element_ids = array();
2211  foreach ($element_ids as $k_id => $element_id)
2212  {
2213    $key = strtolower($name[$element_id]) .'-'. $name[$element_id] .'-'. $k_id;
2214    $ordered_element_ids[$key] = $element_id;
2215  }
2216  ksort($ordered_element_ids);
2217  return $ordered_element_ids;
2218}
2219
[11728]2220function add_permission_on_category($category_ids, $user_ids)
2221{
2222  // array-ify categories and users
2223  if (!is_array($category_ids))
2224  {
2225    $category_ids = array($category_ids);
2226  }
2227
2228  if (!is_array($user_ids))
2229  {
2230    $user_ids = array($user_ids);
2231  }
2232
2233  // check for emptiness
2234  if (count($category_ids) == 0 or count($user_ids) == 0)
2235  {
2236    return;
2237  }
[12917]2238
[12019]2239  // make sure categories are private and select uppercats or subcats
2240  $cat_ids = (isset($_POST['apply_on_sub'])) ? implode(',', get_subcat_ids($category_ids)).",".implode(',', get_uppercat_ids($category_ids)) : implode(',', get_uppercat_ids($category_ids));
[11728]2241  $query = '
2242SELECT
2243    id
2244  FROM '.CATEGORIES_TABLE.'
[12019]2245  WHERE id IN ('.$cat_ids.')
[11728]2246    AND status = \'private\'
2247;';
[12019]2248  $private_cats = array_from_query($query, 'id');
[11728]2249
[12019]2250  if (count($private_cats) == 0)
[11728]2251  {
2252    return;
2253  }
[12917]2254
[11728]2255  // We must not reinsert already existing lines in user_access table
2256  $granteds = array();
[12019]2257  foreach ($private_cats as $cat_id)
[11728]2258  {
2259    $granteds[$cat_id] = array();
2260  }
[12917]2261
[11728]2262  $query = '
2263SELECT
2264    user_id,
2265    cat_id
2266  FROM '.USER_ACCESS_TABLE.'
[12019]2267  WHERE cat_id IN ('.implode(',', $private_cats).')
[11728]2268    AND user_id IN ('.implode(',', $user_ids).')
2269;';
2270  $result = pwg_query($query);
2271  while ($row = pwg_db_fetch_assoc($result))
2272  {
2273    array_push($granteds[$row['cat_id']], $row['user_id']);
2274  }
2275
2276  $inserts = array();
[12917]2277
[12019]2278  foreach ($private_cats as $cat_id)
[11728]2279  {
2280    $grant_to_users = array_diff($user_ids, $granteds[$cat_id]);
[12917]2281
[11728]2282    foreach ($grant_to_users as $user_id)
2283    {
2284      array_push(
2285        $inserts,
2286        array(
2287          'user_id' => $user_id,
2288          'cat_id' => $cat_id
2289          )
2290        );
2291    }
2292  }
2293
2294  if (count($inserts) > 0)
2295  {
2296    mass_inserts(USER_ACCESS_TABLE, array_keys($inserts[0]), $inserts);
2297  }
2298}
2299
2300
2301function get_admins($include_webmaster=true)
2302{
2303  $status_list = array('admin');
2304
2305  if ($include_webmaster)
2306  {
2307    $status_list[] = 'webmaster';
2308  }
[12917]2309
[11728]2310  $query = '
2311SELECT
2312    user_id
2313  FROM '.USER_INFOS_TABLE.'
2314  WHERE status in (\''.implode("','", $status_list).'\')
2315;';
2316
2317  return array_from_query($query, 'user_id');
2318}
[12797]2319
[12820]2320/** delete all derivative files for one or several types */
2321function clear_derivative_cache($types='all')
[12797]2322{
[17295]2323  if ($types === 'all')
[12797]2324  {
[12820]2325    $types = ImageStdParams::get_all_types();
2326    $types[] = IMG_CUSTOM;
2327  }
2328  elseif (!is_array($types))
2329  {
2330    $types = array($types);
2331  }
2332
[17295]2333  for ($i=0; $i<count($types); $i++)
[12820]2334  {
[17295]2335    $type = $types[$i];
2336    if ($type == IMG_CUSTOM)
[12797]2337    {
[17295]2338      $type = derivative_to_url($type).'[a-zA-Z0-9]+';
[12797]2339    }
[17295]2340    elseif (in_array($type, ImageStdParams::get_all_types()))
2341    {
2342      $type = derivative_to_url($type);
2343    }
2344    else
2345    {//assume a custom type
2346      $type = derivative_to_url(IMG_CUSTOM).'_'.$type;
2347    }
2348    $types[$i] = $type;
[12797]2349  }
[17295]2350
2351  $pattern='#.*-';
2352  if (count($types)>1)
2353  {
2354    $pattern .= '(' . implode('|',$types) . ')';
2355  }
[12797]2356  else
2357  {
[17295]2358    $pattern .= $types[0];
[12797]2359  }
[17295]2360  $pattern.='\.[a-zA-Z0-9]{3,4}$#';
[12917]2361
[13651]2362  if ($contents = @opendir(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR))
[12797]2363  {
2364    while (($node = readdir($contents)) !== false)
2365    {
2366      if ($node != '.'
2367          and $node != '..'
2368          and is_dir(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR.$node))
2369      {
2370        clear_derivative_cache_rec(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR.$node, $pattern);
2371      }
2372    }
2373    closedir($contents);
2374  }
2375}
2376
2377function clear_derivative_cache_rec($path, $pattern)
2378{
2379  $rmdir = true;
2380  $rm_index = false;
2381
2382  if ($contents = opendir($path))
2383  {
2384    while (($node = readdir($contents)) !== false)
2385    {
2386      if ($node == '.' or $node == '..')
2387        continue;
2388      if (is_dir($path.'/'.$node))
2389      {
2390        $rmdir &= clear_derivative_cache_rec($path.'/'.$node, $pattern);
2391      }
2392      else
2393      {
2394        if (preg_match($pattern, $node))
2395        {
2396          unlink($path.'/'.$node);
2397        }
2398        elseif ($node=='index.htm')
2399        {
2400          $rm_index = true;
2401        }
2402        else
2403        {
2404          $rmdir = false;
2405        }
2406      }
2407    }
2408    closedir($contents);
[12917]2409
[12797]2410    if ($rmdir)
2411    {
2412      if ($rm_index)
2413      {
2414        unlink($path.'/index.htm');
2415      }
2416      clearstatcache();
[12820]2417      @rmdir($path);
[12797]2418    }
2419    return $rmdir;
2420  }
2421}
[12906]2422
[13052]2423function delete_element_derivatives($infos, $type='all')
[12906]2424{
[12917]2425  $path = $infos['path'];
2426  if (!empty($infos['representative_ext']))
[12906]2427  {
[12917]2428    $path = original_to_representative( $path, $infos['representative_ext']);
[12906]2429  }
[12917]2430  if (substr_compare($path, '../', 0, 3)==0)
2431  {
2432    $path = substr($path, 3);
2433  }
[13052]2434  $dot = strrpos($path, '.');
2435  if ($type=='all')
2436  {
2437    $pattern = '-*';
2438  }
2439  else
2440  {
2441    $pattern = '-'.derivative_to_url($type).'*';
2442  }
2443  $path = substr_replace($path, $pattern, $dot, 0);
[16168]2444  if ( ($glob=glob(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR.$path)) !== false)
[12917]2445  {
[16168]2446    foreach( $glob as $file)
2447    {
2448      @unlink($file);
2449    }
[12917]2450  }
[12906]2451}
[8247]2452?>
Note: See TracBrowser for help on using the repository browser.