source: branches/2.0/admin/include/functions.php @ 4213

Last change on this file since 4213 was 4213, checked in by plg, 14 years ago

feature 1231: subscribe to cn.piwigo.org/announcement when current language is
zh_CN

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