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

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

bug 2716: modifying a photo reset it's rank
modify associate_images_to_categories() and move_images_to_categories() to preserve ranks
please test before 2.4.4 ! :-D

  • Property svn:eol-style set to LF
File size: 54.9 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);
[9191]222      $new_ids[] += $row['id'];
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 */
1199function create_virtual_category($category_name, $parent_id=null)
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  }
[1068]1208
[1064]1209  $parent_id = !empty($parent_id) ? $parent_id : 'NULL';
1210
1211  $insert = array(
1212    'name' => $category_name,
[12763]1213    'rank' => 0,
[1278]1214    'commentable' => boolean_to_string($conf['newcat_default_commentable']),
[1064]1215    );
[1068]1216
[1064]1217  if ($parent_id != 'NULL')
1218  {
1219    $query = '
1220SELECT id, uppercats, global_rank, visible, status
1221  FROM '.CATEGORIES_TABLE.'
1222  WHERE id = '.$parent_id.'
1223;';
[4325]1224    $parent = pwg_db_fetch_assoc(pwg_query($query));
[1064]1225
[4265]1226    $insert['id_uppercat'] = $parent['id'];
1227    $insert['global_rank'] = $parent['global_rank'].'.'.$insert['rank'];
[1068]1228
[1064]1229    // at creation, must a category be visible or not ? Warning : if the
1230    // parent category is invisible, the category is automatically create
1231    // invisible. (invisible = locked)
1232    if ('false' == $parent['visible'])
1233    {
[4265]1234      $insert['visible'] = 'false';
[1064]1235    }
1236    else
1237    {
[4265]1238      $insert['visible'] = boolean_to_string($conf['newcat_default_visible']);
[1064]1239    }
[1068]1240
[1064]1241    // at creation, must a category be public or private ? Warning : if the
1242    // parent category is private, the category is automatically create
1243    // private.
1244    if ('private' == $parent['status'])
1245    {
[4265]1246      $insert['status'] = 'private';
[1064]1247    }
1248    else
1249    {
[4265]1250      $insert['status'] = $conf['newcat_default_status'];
[1064]1251    }
1252  }
1253  else
1254  {
[4265]1255    $insert['visible'] = boolean_to_string($conf['newcat_default_visible']);
1256    $insert['status'] = $conf['newcat_default_status'];
1257    $insert['global_rank'] = $insert['rank'];
[1064]1258  }
1259
1260  // we have then to add the virtual category
1261  mass_inserts(
1262    CATEGORIES_TABLE,
1263    array(
1264      'site_id', 'name', 'id_uppercat', 'rank', 'commentable',
[8734]1265      'visible', 'status', 'global_rank',
[1064]1266      ),
1267    array($insert)
1268    );
1269
[4892]1270  $inserted_id = pwg_db_insert_id(CATEGORIES_TABLE);
[1064]1271
1272  $query = '
1273UPDATE
1274  '.CATEGORIES_TABLE.'
1275  SET uppercats = \''.
1276    (isset($parent) ? $parent{'uppercats'}.',' : '').
1277    $inserted_id.
1278    '\'
1279  WHERE id = '.$inserted_id.'
1280;';
1281  pwg_query($query);
[1068]1282
[12763]1283  update_global_rank();
1284
[11728]1285  if ('private' == $insert['status'])
1286  {
1287    add_permission_on_category($inserted_id, array_unique(array_merge(get_admins(), array($user['id']))));
1288  }
1289
[1064]1290  return array(
[6969]1291    'info' => l10n('Virtual album added'),
[1064]1292    'id'   => $inserted_id,
1293    );
1294}
[1111]1295
1296/**
[1119]1297 * Set tags to an image. Warning: given tags are all tags associated to the
1298 * image, not additionnal tags.
1299 *
1300 * @param array tag ids
1301 * @param int image id
1302 * @return void
1303 */
1304function set_tags($tags, $image_id)
1305{
1306  $query = '
1307DELETE
1308  FROM '.IMAGE_TAG_TABLE.'
1309  WHERE image_id = '.$image_id.'
1310;';
1311  pwg_query($query);
1312
1313  if (count($tags) > 0)
1314  {
1315    $inserts = array();
1316    foreach ($tags as $tag_id)
1317    {
1318      array_push(
1319        $inserts,
1320        array(
1321          'tag_id' => $tag_id,
1322          'image_id' => $image_id
1323          )
1324        );
1325    }
1326    mass_inserts(
1327      IMAGE_TAG_TABLE,
1328      array_keys($inserts[0]),
1329      $inserts
1330      );
1331  }
1332}
1333
1334/**
1335 * Add new tags to a set of images.
1336 *
1337 * @param array tag ids
1338 * @param array image ids
1339 * @return void
1340 */
1341function add_tags($tags, $images)
1342{
[5691]1343  if (count($tags) == 0 or count($images) == 0)
[1119]1344  {
1345    return;
1346  }
[1592]1347
[1119]1348  // we can't insert twice the same {image_id,tag_id} so we must first
1349  // delete lines we'll insert later
1350  $query = '
1351DELETE
1352  FROM '.IMAGE_TAG_TABLE.'
1353  WHERE image_id IN ('.implode(',', $images).')
1354    AND tag_id IN ('.implode(',', $tags).')
1355;';
1356  pwg_query($query);
1357
1358  $inserts = array();
1359  foreach ($images as $image_id)
1360  {
1361    foreach ($tags as $tag_id)
1362    {
1363      array_push(
1364        $inserts,
1365        array(
1366          'image_id' => $image_id,
1367          'tag_id' => $tag_id,
1368          )
1369        );
1370    }
1371  }
1372  mass_inserts(
1373    IMAGE_TAG_TABLE,
1374    array_keys($inserts[0]),
1375    $inserts
1376    );
1377}
1378
[12032]1379/**
1380 *
1381 */
1382function delete_tags($tag_ids)
1383{
1384  if (is_numeric($tag_ids))
1385  {
1386    $tag_ids = array($tag_ids);
1387  }
1388
1389  if (!is_array($tag_ids))
1390  {
1391    return false;
1392  }
[12917]1393
[12032]1394  $query = '
1395DELETE
1396  FROM '.IMAGE_TAG_TABLE.'
1397  WHERE tag_id IN ('.implode(',', $tag_ids).')
1398;';
1399  pwg_query($query);
[12917]1400
[12032]1401  $query = '
1402DELETE
1403  FROM '.TAGS_TABLE.'
1404  WHERE id IN ('.implode(',', $tag_ids).')
1405;';
1406  pwg_query($query);
1407}
1408
[1119]1409function tag_id_from_tag_name($tag_name)
1410{
1411  global $page;
[2478]1412
[2350]1413  $tag_name = trim($tag_name);
[1119]1414  if (isset($page['tag_id_from_tag_name_cache'][$tag_name]))
1415  {
1416    return $page['tag_id_from_tag_name_cache'][$tag_name];
1417  }
[1592]1418
[1452]1419  // does the tag already exists?
[1119]1420  $query = '
1421SELECT id
1422  FROM '.TAGS_TABLE.'
1423  WHERE name = \''.$tag_name.'\'
1424;';
1425  $existing_tags = array_from_query($query, 'id');
1426
1427  if (count($existing_tags) == 0)
1428  {
1429    mass_inserts(
1430      TAGS_TABLE,
1431      array('name', 'url_name'),
1432      array(
1433        array(
1434          'name' => $tag_name,
[12553]1435          'url_name' => trigger_event('render_tag_url', $tag_name),
[1119]1436          )
1437        )
1438      );
1439
[4892]1440    $page['tag_id_from_tag_name_cache'][$tag_name] = pwg_db_insert_id(TAGS_TABLE);
[1119]1441  }
1442  else
1443  {
1444    $page['tag_id_from_tag_name_cache'][$tag_name] = $existing_tags[0];
1445  }
1446
1447  return $page['tag_id_from_tag_name_cache'][$tag_name];
1448}
1449
1450function set_tags_of($tags_of)
1451{
1452  if (count($tags_of) > 0)
1453  {
1454    $query = '
1455DELETE
1456  FROM '.IMAGE_TAG_TABLE.'
1457  WHERE image_id IN ('.implode(',', array_keys($tags_of)).')
1458;';
1459    pwg_query($query);
1460
1461    $inserts = array();
[1592]1462
[1119]1463    foreach ($tags_of as $image_id => $tag_ids)
1464    {
1465      foreach ($tag_ids as $tag_id)
1466      {
1467        array_push(
1468          $inserts,
1469          array(
1470            'image_id' => $image_id,
1471            'tag_id' => $tag_id,
1472            )
1473          );
1474      }
1475    }
1476
1477    mass_inserts(
1478      IMAGE_TAG_TABLE,
1479      array_keys($inserts[0]),
1480      $inserts
1481      );
1482  }
1483}
1484
1485/**
[1121]1486 * Associate a list of images to a list of categories.
1487 *
[17424]1488 * The function will not duplicate links and will preserve ranks
[1121]1489 *
1490 * @param array images
1491 * @param array categories
1492 * @return void
1493 */
1494function associate_images_to_categories($images, $categories)
1495{
1496  if (count($images) == 0
1497      or count($categories) == 0)
1498  {
1499    return false;
1500  }
[17424]1501 
1502  // get existing associations
[1121]1503  $query = '
[17424]1504SELECT
1505    image_id,
1506    category_id
[1121]1507  FROM '.IMAGE_CATEGORY_TABLE.'
1508  WHERE image_id IN ('.implode(',', $images).')
1509    AND category_id IN ('.implode(',', $categories).')
1510;';
[17424]1511  $result = pwg_query($query);
1512 
1513  $existing = array();
1514  while ($row = pwg_db_fetch_assoc($result))
1515  {
1516    $existing[ $row['category_id'] ][] = $row['image_id'];
1517  }
[1121]1518
[17424]1519  // get max rank of each categories
[17002]1520  $query = '
1521SELECT
1522    category_id,
1523    MAX(rank) AS max_rank
1524  FROM '.IMAGE_CATEGORY_TABLE.'
1525  WHERE rank IS NOT NULL
1526    AND category_id IN ('.implode(',', $categories).')
1527  GROUP BY category_id
1528;';
1529
1530  $current_rank_of = simple_hash_from_query(
1531    $query,
1532    'category_id',
1533    'max_rank'
1534    );
1535
[17424]1536  // associate only not already associated images
[1121]1537  $inserts = array();
1538  foreach ($categories as $category_id)
1539  {
[17002]1540    if (!isset($current_rank_of[$category_id]))
1541    {
1542      $current_rank_of[$category_id] = 0;
1543    }
[17424]1544    if (!isset($existing[$category_id]))
1545    {
1546      $existing[$category_id] = array();
1547    }
[17002]1548
[1121]1549    foreach ($images as $image_id)
1550    {
[17424]1551      if (!in_array($image_id, $existing[$category_id]))
1552      {
1553        $rank = ++$current_rank_of[$category_id];
[17002]1554
[17424]1555        array_push(
1556          $inserts,
1557          array(
1558            'image_id' => $image_id,
1559            'category_id' => $category_id,
1560            'rank' => $rank,
1561            )
1562          );
1563      }
[1121]1564    }
1565  }
[1592]1566
[17424]1567  if (count($inserts))
1568  {
1569    mass_inserts(
1570      IMAGE_CATEGORY_TABLE,
1571      array_keys($inserts[0]),
1572      $inserts
1573      );
[1121]1574
[17424]1575    update_category($categories);
1576  }
[1121]1577}
1578
1579/**
[17424]1580 * Dissociate images from all old categories except their storage category and
[13077]1581 * associate to new categories.
1582 *
[17424]1583 * This function will preserve ranks
1584 *
[13077]1585 * @param array images
1586 * @param array categories
1587 * @return void
1588 */
1589function move_images_to_categories($images, $categories)
1590{
1591  if (count($images) == 0)
1592  {
1593    return false;
1594  }
[17302]1595
[17424]1596  // let's first break links with all old albums but their "storage album"
[13077]1597  $query = '
1598DELETE '.IMAGE_CATEGORY_TABLE.'.*
1599  FROM '.IMAGE_CATEGORY_TABLE.'
1600    JOIN '.IMAGES_TABLE.' ON image_id=id
1601  WHERE id IN ('.implode(',', $images).')
[17424]1602    '.((is_array($categories) and count($categories)>0) ? 'AND category_id NOT IN ('.implode(',', $categories).')' : null).'
[13077]1603    AND (storage_category_id IS NULL OR storage_category_id != category_id)
1604;';
1605  pwg_query($query);
[17302]1606
[13077]1607  if (is_array($categories) and count($categories) > 0)
1608  {
1609    associate_images_to_categories($images, $categories);
1610  }
1611}
1612
1613/**
[1121]1614 * Associate images associated to a list of source categories to a list of
1615 * destination categories.
1616 *
1617 * @param array sources
1618 * @param array destinations
1619 * @return void
1620 */
1621function associate_categories_to_categories($sources, $destinations)
1622{
1623  if (count($sources) == 0)
1624  {
1625    return false;
1626  }
1627
1628  $query = '
1629SELECT image_id
1630  FROM '.IMAGE_CATEGORY_TABLE.'
1631  WHERE category_id IN ('.implode(',', $sources).')
1632;';
1633  $images = array_from_query($query, 'image_id');
1634
1635  associate_images_to_categories($images, $destinations);
1636}
[1682]1637
1638/**
[2339]1639 * Refer main Piwigo URLs (currently PHPWG_DOMAIN domain)
[1724]1640 *
1641 * @param void
1642 * @return array like $conf['links']
1643 */
1644function pwg_URL()
1645{
1646  $urls = array(
[12875]1647    'HOME'       => PHPWG_URL,
1648    'WIKI'       => PHPWG_URL.'/doc',
1649    'DEMO'       => PHPWG_URL.'/demo',
1650    'FORUM'      => PHPWG_URL.'/forum',
1651    'BUGS'       => PHPWG_URL.'/bugs',
1652    'EXTENSIONS' => PHPWG_URL.'/ext',
[1724]1653    );
1654  return $urls;
1655}
1656
[1978]1657/**
1658 * Invalidates cahed data (permissions and category counts) for all users.
1659 */
[2890]1660function invalidate_user_cache($full = true)
[1978]1661{
[2890]1662  if ($full)
1663  {
1664    $query = '
1665TRUNCATE TABLE '.USER_CACHE_CATEGORIES_TABLE.';';
1666    pwg_query($query);
1667    $query = '
1668TRUNCATE TABLE '.USER_CACHE_TABLE.';';
1669    pwg_query($query);
1670  }
1671  else
1672  {
1673    $query = '
[1978]1674UPDATE '.USER_CACHE_TABLE.'
[2890]1675  SET need_update = \'true\';';
1676    pwg_query($query);
1677  }
[2892]1678  trigger_action('invalidate_user_cache', $full);
[1978]1679}
[2127]1680
1681/**
1682 * adds the caracter set to a create table sql query.
1683 * all CREATE TABLE queries must call this function
1684 * @param string query - the sql query
1685 */
1686function create_table_add_character_set($query)
1687{
[2502]1688  defined('DB_CHARSET') or fatal_error('create_table_add_character_set DB_CHARSET undefined');
[2127]1689  if ('DB_CHARSET'!='')
1690  {
1691    if ( version_compare(mysql_get_server_info(), '4.1.0', '<') )
1692    {
1693      return $query;
1694    }
1695    $charset_collate = " DEFAULT CHARACTER SET ".DB_CHARSET;
[2488]1696    if (DB_COLLATE!='')
[2127]1697    {
1698      $charset_collate .= " COLLATE ".DB_COLLATE;
1699    }
[2488]1700    if ( is_array($query) )
[2127]1701    {
[2488]1702      foreach( $query as $id=>$q)
1703      {
1704        $q=trim($q);
1705        $q=trim($q, ';');
1706        if (preg_match('/^CREATE\s+TABLE/i',$q))
1707        {
1708          $q.=$charset_collate;
1709        }
1710        $q .= ';';
1711        $query[$id] = $q;
1712      }
[2127]1713    }
[2488]1714    else
1715    {
1716      $query=trim($query);
1717      $query=trim($query, ';');
1718      if (preg_match('/^CREATE\s+TABLE/i',$query))
1719      {
1720        $query.=$charset_collate;
1721      }
1722      $query .= ';';
1723    }
[2127]1724  }
1725  return $query;
1726}
[2325]1727
1728/**
1729 * Returns array use on template with html_options method
1730 * @param Min and Max access to use
1731 * @return array of user access level
1732 */
1733function get_user_access_level_html_options($MinLevelAccess = ACCESS_FREE, $MaxLevelAccess = ACCESS_CLOSED)
1734{
1735  $tpl_options = array();
1736  for ($level = $MinLevelAccess; $level <= $MaxLevelAccess; $level++)
1737  {
1738    $tpl_options[$level] = l10n(sprintf('ACCESS_%d', $level));
1739  }
1740  return $tpl_options;
1741}
1742
[2588]1743/**
1744 * returns a list of templates currently available in template-extension
1745 * Each .tpl file is extracted from template-extension.
1746 * @return array
1747 */
1748function get_extents($start='')
1749{
1750  if ($start == '') { $start = './template-extension'; }
1751  $dir = opendir($start);
1752  $extents = array();
1753
1754  while (($file = readdir($dir)) !== false)
1755  {
1756    if ( $file == '.' or $file == '..' or $file == '.svn') continue;
1757    $path = $start . '/' . $file;
1758    if (is_dir($path))
1759    {
1760      $extents = array_merge($extents, get_extents($path));
1761    }
[3145]1762    elseif ( !is_link($path) and file_exists($path)
[2588]1763            and get_extension($path) == 'tpl' )
1764    {
1765      $extents[] = substr($path, 21);
1766    }
1767  }
1768  return $extents;
1769}
1770
[2634]1771function create_tag($tag_name)
1772{
1773  // does the tag already exists?
1774  $query = '
1775SELECT id
1776  FROM '.TAGS_TABLE.'
1777  WHERE name = \''.$tag_name.'\'
1778;';
1779  $existing_tags = array_from_query($query, 'id');
1780
1781  if (count($existing_tags) == 0)
1782  {
1783    mass_inserts(
1784      TAGS_TABLE,
1785      array('name', 'url_name'),
1786      array(
1787        array(
1788          'name' => $tag_name,
[12553]1789          'url_name' => trigger_event('render_tag_url', $tag_name),
[2634]1790          )
1791        )
1792      );
1793
[4892]1794    $inserted_id = pwg_db_insert_id(TAGS_TABLE);
[2634]1795
1796    return array(
1797      'info' => sprintf(
[5036]1798        l10n('Tag "%s" was added'),
[2634]1799        stripslashes($tag_name)
1800        ),
1801      'id' => $inserted_id,
1802      );
1803  }
1804  else
1805  {
1806    return array(
1807      'error' => sprintf(
[5036]1808        l10n('Tag "%s" already exists'),
[2634]1809        stripslashes($tag_name)
1810        )
1811      );
1812  }
1813}
[2777]1814
[11828]1815/**
1816 * Is the category accessible to the (Admin) user ?
1817 *
1818 * Note : if the user is not authorized to see this category, category jump
1819 * will be replaced by admin cat_modify page
1820 *
1821 * @param int category id to verify
1822 * @return bool
1823 */
1824function cat_admin_access($category_id)
1825{
1826  global $user;
[2777]1827
[11828]1828  // $filter['visible_categories'] and $filter['visible_images']
1829  // are not used because it's not necessary (filter <> restriction)
1830  if (in_array($category_id, explode(',', $user['forbidden_categories'])))
1831  {
1832    return false;
1833  }
1834  return true;
1835}
1836
[2880]1837/**
1838 * Retrieve data from external URL
1839 *
1840 * @param string $src: URL
1841 * @param global $dest: can be a file ressource or string
1842 * @return bool
1843 */
[8079]1844function fetchRemote($src, &$dest, $get_data=array(), $post_data=array(), $user_agent='Piwigo', $step=0)
[2880]1845{
[2902]1846  // Try to retrieve data from local file?
1847  if (!url_is_remote($src))
1848  {
1849    $content = @file_get_contents($src);
1850    if ($content !== false)
1851    {
1852      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
1853      return true;
1854    }
1855    else
1856    {
1857      return false;
1858    }
1859  }
1860
[8079]1861  // After 3 redirections, return false
1862  if ($step > 3) return false;
1863
[8080]1864  // Initialization
1865  $method  = empty($post_data) ? 'GET' : 'POST';
1866  $request = empty($post_data) ? '' : http_build_query($post_data, '', '&');
[8090]1867  if (!empty($get_data))
1868  {
1869    $src .= strpos($src, '?') === false ? '?' : '&';
1870    $src .= http_build_query($get_data, '', '&');
1871  }
[8080]1872
[2900]1873  // Initialize $dest
[2880]1874  is_resource($dest) or $dest = '';
1875
1876  // Try curl to read remote file
1877  if (function_exists('curl_init'))
1878  {
1879    $ch = @curl_init();
1880    @curl_setopt($ch, CURLOPT_URL, $src);
[2900]1881    @curl_setopt($ch, CURLOPT_HEADER, 1);
[2880]1882    @curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
[2900]1883    @curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
[8079]1884    if ($method == 'POST')
1885    {
1886      @curl_setopt($ch, CURLOPT_POST, 1);
[8090]1887      @curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
[8079]1888    }
[2880]1889    $content = @curl_exec($ch);
[2900]1890    $header_length = @curl_getinfo($ch, CURLINFO_HEADER_SIZE);
[2902]1891    $status = @curl_getinfo($ch, CURLINFO_HTTP_CODE);
[2880]1892    @curl_close($ch);
[2902]1893    if ($content !== false and $status >= 200 and $status < 400)
[2880]1894    {
[2900]1895      if (preg_match('/Location:\s+?(.+)/', substr($content, 0, $header_length), $m))
1896      {
[8079]1897        return fetchRemote($m[1], $dest, array(), array(), $user_agent, $step+1);
[2900]1898      }
1899      $content = substr($content, $header_length);
1900      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
[2880]1901      return true;
1902    }
1903  }
1904
1905  // Try file_get_contents to read remote file
1906  if (ini_get('allow_url_fopen'))
1907  {
[8079]1908    $opts = array(
1909      'http' => array(
1910        'method' => $method,
1911        'user_agent' => $user_agent,
1912      )
1913    );
[8090]1914    if ($method == 'POST')
1915    {
1916      $opts['http']['content'] = $request;
1917    }
[8079]1918    $context = @stream_context_create($opts);
1919    $content = @file_get_contents($src, false, $context);
[2880]1920    if ($content !== false)
1921    {
1922      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
1923      return true;
1924    }
1925  }
1926
1927  // Try fsockopen to read remote file
1928  $src = parse_url($src);
1929  $host = $src['host'];
1930  $path = isset($src['path']) ? $src['path'] : '/';
1931  $path .= isset($src['query']) ? '?'.$src['query'] : '';
[3145]1932
[2880]1933  if (($s = @fsockopen($host,80,$errno,$errstr,5)) === false)
1934  {
1935    return false;
1936  }
1937
[8079]1938  $http_request  = $method." ".$path." HTTP/1.0\r\n";
1939  $http_request .= "Host: ".$host."\r\n";
[8090]1940  if ($method == 'POST')
1941  {
1942    $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
1943    $http_request .= "Content-Length: ".strlen($request)."\r\n";
1944  }
[8079]1945  $http_request .= "User-Agent: ".$user_agent."\r\n";
1946  $http_request .= "Accept: */*\r\n";
1947  $http_request .= "\r\n";
1948  $http_request .= $request;
[2880]1949
[8079]1950  fwrite($s, $http_request);
1951
[2880]1952  $i = 0;
1953  $in_content = false;
1954  while (!feof($s))
1955  {
1956    $line = fgets($s);
1957
1958    if (rtrim($line,"\r\n") == '' && !$in_content)
1959    {
1960      $in_content = true;
1961      $i++;
1962      continue;
1963    }
1964    if ($i == 0)
1965    {
1966      if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/',rtrim($line,"\r\n"), $m))
1967      {
1968        fclose($s);
1969        return false;
1970      }
1971      $status = (integer) $m[2];
1972      if ($status < 200 || $status >= 400)
1973      {
1974        fclose($s);
1975        return false;
1976      }
1977    }
1978    if (!$in_content)
1979    {
1980      if (preg_match('/Location:\s+?(.+)$/',rtrim($line,"\r\n"),$m))
1981      {
1982        fclose($s);
[8079]1983        return fetchRemote(trim($m[1]),$dest,array(),array(),$user_agent,$step+1);
[2880]1984      }
1985      $i++;
1986      continue;
1987    }
1988    is_resource($dest) ? @fwrite($dest, $line) : $dest .= $line;
1989    $i++;
1990  }
1991  fclose($s);
1992  return true;
1993}
1994
[3145]1995
1996/**
1997 * returns the groupname corresponding to the given group identifier if
1998 * exists
1999 *
2000 * @param int group_id
2001 * @return mixed
2002 */
2003function get_groupname($group_id)
2004{
2005  $query = '
2006SELECT name
2007  FROM '.GROUPS_TABLE.'
2008  WHERE id = '.intval($group_id).'
2009;';
2010  $result = pwg_query($query);
[4325]2011  if (pwg_db_num_rows($result) > 0)
[3145]2012  {
[4325]2013    list($groupname) = pwg_db_fetch_row($result);
[3145]2014  }
2015  else
2016  {
2017    return false;
2018  }
2019
2020  return $groupname;
2021}
2022
2023/**
2024 * returns the username corresponding to the given user identifier if exists
2025 *
2026 * @param int user_id
2027 * @return mixed
2028 */
2029function get_username($user_id)
2030{
2031  global $conf;
2032
2033  $query = '
2034SELECT '.$conf['user_fields']['username'].'
2035  FROM '.USERS_TABLE.'
2036  WHERE '.$conf['user_fields']['id'].' = '.intval($user_id).'
2037;';
2038  $result = pwg_query($query);
[4325]2039  if (pwg_db_num_rows($result) > 0)
[3145]2040  {
[4325]2041    list($username) = pwg_db_fetch_row($result);
[3145]2042  }
2043  else
2044  {
2045    return false;
2046  }
2047
[4304]2048  return stripslashes($username);
[3145]2049}
[3382]2050
2051function get_newsletter_subscribe_base_url($language) {
[12875]2052  return PHPWG_URL.'/announcement/subscribe/';
[3382]2053}
[5173]2054
2055/**
2056 * Accordion menus need to know which section to open by default when
2057 * loading the page
2058 */
2059function get_active_menu($menu_page)
2060{
2061  global $page;
2062
2063  if (isset($page['active_menu']))
2064  {
2065    return $page['active_menu'];
2066  }
2067
2068  switch ($menu_page)
2069  {
[13077]2070    case 'photo':
[5173]2071    case 'photos_add':
2072    case 'rating':
2073    case 'tags':
2074    case 'picture_modify':
[8417]2075    case 'batch_manager':
[5173]2076      return 0;
2077
[13013]2078    case 'album':
[5173]2079    case 'cat_list':
2080    case 'cat_move':
2081    case 'cat_options':
2082    case 'permalinks':
2083      return 1;
[5691]2084
[5173]2085    case 'user_list':
2086    case 'user_perm':
2087    case 'group_list':
2088    case 'group_perm':
2089    case 'notification_by_mail':
2090      return 2;
2091
[10594]2092    case 'plugins':
[5173]2093    case 'plugin':
2094      return 3;
[5691]2095
[6056]2096    case 'site_manager':
2097    case 'site_update':
[5173]2098    case 'stats':
2099    case 'history':
2100    case 'maintenance':
[5997]2101    case 'comments':
[10511]2102    case 'updates':
[5173]2103      return 4;
2104
2105    case 'configuration':
[12820]2106    case 'derivatives':
[5173]2107    case 'extend_for_templates':
2108    case 'menubar':
[10594]2109    case 'themes':
[5448]2110    case 'theme':
[10594]2111    case 'languages':
[5173]2112      return 5;
2113  }
2114  return 0;
2115}
[5188]2116
[12259]2117function get_taglist($query, $only_user_language=true)
[5188]2118{
2119  $result = pwg_query($query);
[12917]2120
[5188]2121  $taglist = array();
2122  while ($row = pwg_db_fetch_assoc($result))
2123  {
[12259]2124    if (!$only_user_language and preg_match_all('#\[lang=(.*?)\](.*?)\[/lang\]#is', $row['name'], $matches))
[11487]2125    {
2126      foreach ($matches[2] as $tag_name)
2127      {
2128        array_push(
2129          $taglist,
2130          array(
2131            'name' => trigger_event('render_tag_name', $tag_name),
[11853]2132            'id' => '~~'.$row['id'].'~~',
[11487]2133            )
2134          );
2135      }
2136
[12030]2137      $row['name'] = preg_replace('#\[lang=(.*?)\](.*?)\[/lang\]#is', null, $row['name']);
[11487]2138    }
[12917]2139
[11853]2140    if (strlen($row['name']) > 0)
[11487]2141    {
2142      array_push(
2143        $taglist,
2144        array(
[11853]2145          'name' => trigger_event('render_tag_name', $row['name']),
2146          'id' => '~~'.$row['id'].'~~',
[11487]2147          )
2148        );
2149    }
[5188]2150  }
[12917]2151
[11008]2152  $cmp = create_function('$a,$b', 'return strcasecmp($a["name"], $b["name"]);');
2153  usort($taglist, $cmp);
[11487]2154
[5188]2155  return $taglist;
2156}
2157
[11853]2158function get_tag_ids($raw_tags, $allow_create=true)
[5188]2159{
2160  // In $raw_tags we receive something like array('~~6~~', '~~59~~', 'New
2161  // tag', 'Another new tag') The ~~34~~ means that it is an existing
2162  // tag. I've added the surrounding ~~ to permit creation of tags like "10"
2163  // or "1234" (numeric characters only)
2164
2165  $tag_ids = array();
[10970]2166  $raw_tags = explode(',',$raw_tags);
[5691]2167
[5188]2168  foreach ($raw_tags as $raw_tag)
2169  {
2170    if (preg_match('/^~~(\d+)~~$/', $raw_tag, $matches))
2171    {
2172      array_push($tag_ids, $matches[1]);
2173    }
[11853]2174    elseif ($allow_create)
[5188]2175    {
2176      // we have to create a new tag
[11853]2177      $tag_ids[] = tag_id_from_tag_name($raw_tag);
[5188]2178    }
2179  }
2180
2181  return $tag_ids;
2182}
[8247]2183
2184/** returns the argument_ids array with new sequenced keys based on related
2185 * names. Sequence is not case sensitive.
2186 * Warning: By definition, this function breaks original keys
2187 */
2188function order_by_name($element_ids,$name)
2189{
2190  $ordered_element_ids = array();
2191  foreach ($element_ids as $k_id => $element_id)
2192  {
2193    $key = strtolower($name[$element_id]) .'-'. $name[$element_id] .'-'. $k_id;
2194    $ordered_element_ids[$key] = $element_id;
2195  }
2196  ksort($ordered_element_ids);
2197  return $ordered_element_ids;
2198}
2199
[11728]2200function add_permission_on_category($category_ids, $user_ids)
2201{
2202  // array-ify categories and users
2203  if (!is_array($category_ids))
2204  {
2205    $category_ids = array($category_ids);
2206  }
2207
2208  if (!is_array($user_ids))
2209  {
2210    $user_ids = array($user_ids);
2211  }
2212
2213  // check for emptiness
2214  if (count($category_ids) == 0 or count($user_ids) == 0)
2215  {
2216    return;
2217  }
[12917]2218
[12019]2219  // make sure categories are private and select uppercats or subcats
2220  $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]2221  $query = '
2222SELECT
2223    id
2224  FROM '.CATEGORIES_TABLE.'
[12019]2225  WHERE id IN ('.$cat_ids.')
[11728]2226    AND status = \'private\'
2227;';
[12019]2228  $private_cats = array_from_query($query, 'id');
[11728]2229
[12019]2230  if (count($private_cats) == 0)
[11728]2231  {
2232    return;
2233  }
[12917]2234
[11728]2235  // We must not reinsert already existing lines in user_access table
2236  $granteds = array();
[12019]2237  foreach ($private_cats as $cat_id)
[11728]2238  {
2239    $granteds[$cat_id] = array();
2240  }
[12917]2241
[11728]2242  $query = '
2243SELECT
2244    user_id,
2245    cat_id
2246  FROM '.USER_ACCESS_TABLE.'
[12019]2247  WHERE cat_id IN ('.implode(',', $private_cats).')
[11728]2248    AND user_id IN ('.implode(',', $user_ids).')
2249;';
2250  $result = pwg_query($query);
2251  while ($row = pwg_db_fetch_assoc($result))
2252  {
2253    array_push($granteds[$row['cat_id']], $row['user_id']);
2254  }
2255
2256  $inserts = array();
[12917]2257
[12019]2258  foreach ($private_cats as $cat_id)
[11728]2259  {
2260    $grant_to_users = array_diff($user_ids, $granteds[$cat_id]);
[12917]2261
[11728]2262    foreach ($grant_to_users as $user_id)
2263    {
2264      array_push(
2265        $inserts,
2266        array(
2267          'user_id' => $user_id,
2268          'cat_id' => $cat_id
2269          )
2270        );
2271    }
2272  }
2273
2274  if (count($inserts) > 0)
2275  {
2276    mass_inserts(USER_ACCESS_TABLE, array_keys($inserts[0]), $inserts);
2277  }
2278}
2279
2280
2281function get_admins($include_webmaster=true)
2282{
2283  $status_list = array('admin');
2284
2285  if ($include_webmaster)
2286  {
2287    $status_list[] = 'webmaster';
2288  }
[12917]2289
[11728]2290  $query = '
2291SELECT
2292    user_id
2293  FROM '.USER_INFOS_TABLE.'
2294  WHERE status in (\''.implode("','", $status_list).'\')
2295;';
2296
2297  return array_from_query($query, 'user_id');
2298}
[12797]2299
[12820]2300/** delete all derivative files for one or several types */
2301function clear_derivative_cache($types='all')
[12797]2302{
[17302]2303  if ($types === 'all')
[12797]2304  {
[12820]2305    $types = ImageStdParams::get_all_types();
2306    $types[] = IMG_CUSTOM;
2307  }
2308  elseif (!is_array($types))
2309  {
2310    $types = array($types);
2311  }
2312
[17302]2313  for ($i=0; $i<count($types); $i++)
[12820]2314  {
[17302]2315    $type = $types[$i];
2316    if ($type == IMG_CUSTOM)
[12797]2317    {
[17302]2318      $type = derivative_to_url($type).'[a-zA-Z0-9]+';
[12797]2319    }
[17302]2320    elseif (in_array($type, ImageStdParams::get_all_types()))
2321    {
2322      $type = derivative_to_url($type);
2323    }
2324    else
2325    {//assume a custom type
2326      $type = derivative_to_url(IMG_CUSTOM).'_'.$type;
2327    }
2328    $types[$i] = $type;
[12797]2329  }
[17302]2330
2331  $pattern='#.*-';
2332  if (count($types)>1)
2333  {
2334    $pattern .= '(' . implode('|',$types) . ')';
2335  }
[12797]2336  else
2337  {
[17302]2338    $pattern .= $types[0];
[12797]2339  }
[17302]2340  $pattern.='\.[a-zA-Z0-9]{3,4}$#';
[12917]2341
[13651]2342  if ($contents = @opendir(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR))
[12797]2343  {
2344    while (($node = readdir($contents)) !== false)
2345    {
2346      if ($node != '.'
2347          and $node != '..'
2348          and is_dir(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR.$node))
2349      {
2350        clear_derivative_cache_rec(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR.$node, $pattern);
2351      }
2352    }
2353    closedir($contents);
2354  }
2355}
2356
2357function clear_derivative_cache_rec($path, $pattern)
2358{
2359  $rmdir = true;
2360  $rm_index = false;
2361
2362  if ($contents = opendir($path))
2363  {
2364    while (($node = readdir($contents)) !== false)
2365    {
2366      if ($node == '.' or $node == '..')
2367        continue;
2368      if (is_dir($path.'/'.$node))
2369      {
2370        $rmdir &= clear_derivative_cache_rec($path.'/'.$node, $pattern);
2371      }
2372      else
2373      {
2374        if (preg_match($pattern, $node))
2375        {
2376          unlink($path.'/'.$node);
2377        }
2378        elseif ($node=='index.htm')
2379        {
2380          $rm_index = true;
2381        }
2382        else
2383        {
2384          $rmdir = false;
2385        }
2386      }
2387    }
2388    closedir($contents);
[12917]2389
[12797]2390    if ($rmdir)
2391    {
2392      if ($rm_index)
2393      {
2394        unlink($path.'/index.htm');
2395      }
2396      clearstatcache();
[12820]2397      @rmdir($path);
[12797]2398    }
2399    return $rmdir;
2400  }
2401}
[12906]2402
[13052]2403function delete_element_derivatives($infos, $type='all')
[12906]2404{
[12917]2405  $path = $infos['path'];
2406  if (!empty($infos['representative_ext']))
[12906]2407  {
[12917]2408    $path = original_to_representative( $path, $infos['representative_ext']);
[12906]2409  }
[12917]2410  if (substr_compare($path, '../', 0, 3)==0)
2411  {
2412    $path = substr($path, 3);
2413  }
[13052]2414  $dot = strrpos($path, '.');
2415  if ($type=='all')
2416  {
2417    $pattern = '-*';
2418  }
2419  else
2420  {
2421    $pattern = '-'.derivative_to_url($type).'*';
2422  }
2423  $path = substr_replace($path, $pattern, $dot, 0);
[16167]2424  if ( ($glob=glob(PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR.$path)) !== false)
[12917]2425  {
[16167]2426    foreach( $glob as $file)
2427    {
2428      @unlink($file);
2429    }
[12917]2430  }
[12906]2431}
[8247]2432?>
Note: See TracBrowser for help on using the repository browser.