diff options
Diffstat (limited to '')
-rw-r--r-- | BSF/admin/include/functions.php | 1872 |
1 files changed, 1872 insertions, 0 deletions
diff --git a/BSF/admin/include/functions.php b/BSF/admin/include/functions.php new file mode 100644 index 000000000..328a36ab7 --- /dev/null +++ b/BSF/admin/include/functions.php @@ -0,0 +1,1872 @@ +<?php +// +-----------------------------------------------------------------------+ +// | Piwigo - a PHP based picture gallery | +// +-----------------------------------------------------------------------+ +// | Copyright(C) 2008 Piwigo Team http://piwigo.org | +// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | +// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +include(PHPWG_ROOT_PATH.'admin/include/functions_metadata.php'); + + +// The function delete_site deletes a site and call the function +// delete_categories for each primary category of the site +function delete_site( $id ) +{ + // destruction of the categories of the site + $query = ' +SELECT id + FROM '.CATEGORIES_TABLE.' + WHERE site_id = '.$id.' +;'; + $result = pwg_query($query); + $category_ids = array(); + while ($row = mysql_fetch_array($result)) + { + array_push($category_ids, $row['id']); + } + delete_categories($category_ids); + + // destruction of the site + $query = ' +DELETE FROM '.SITES_TABLE.' + WHERE id = '.$id.' +;'; + pwg_query($query); +} + + +// The function delete_categories deletes the categories identified by the +// (numeric) key of the array $ids. It also deletes (in the database) : +// - all the elements of the category (delete_elements, see further) +// - all the links between elements and this category +// - all the restrictions linked to the category +// The function works recursively. +function delete_categories($ids) +{ + if (count($ids) == 0) + { + return; + } + + // add sub-category ids to the given ids : if a category is deleted, all + // sub-categories must be so + $ids = get_subcat_ids($ids); + + // destruction of all the related elements + $query = ' +SELECT id + FROM '.IMAGES_TABLE.' + WHERE storage_category_id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + $result = pwg_query($query); + $element_ids = array(); + while ($row = mysql_fetch_array($result)) + { + array_push($element_ids, $row['id']); + } + delete_elements($element_ids); + + // destruction of the links between images and this category + $query = ' +DELETE FROM '.IMAGE_CATEGORY_TABLE.' + WHERE category_id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + // destruction of the access linked to the category + $query = ' +DELETE FROM '.USER_ACCESS_TABLE.' + WHERE cat_id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + $query = ' +DELETE FROM '.GROUP_ACCESS_TABLE.' + WHERE cat_id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + // destruction of the category + $query = ' +DELETE FROM '.CATEGORIES_TABLE.' + WHERE id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + $query=' +DELETE FROM '.OLD_PERMALINKS_TABLE.' + WHERE cat_id IN ('.implode(',',$ids).')'; + pwg_query($query); + + trigger_action('delete_categories', $ids); +} + +// The function delete_elements deletes the elements identified by the +// (numeric) values of the array $ids. It also deletes (in the database) : +// - all the comments related to elements +// - all the links between categories and elements +// - all the favorites associated to elements +function delete_elements($ids) +{ + if (count($ids) == 0) + { + return; + } + + // destruction of the comments on the image + $query = ' +DELETE FROM '.COMMENTS_TABLE.' + WHERE image_id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + // destruction of the links between images and this category + $query = ' +DELETE FROM '.IMAGE_CATEGORY_TABLE.' + WHERE image_id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + // destruction of the links between images and tags + $query = ' +DELETE FROM '.IMAGE_TAG_TABLE.' + WHERE image_id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + // destruction of the favorites associated with the picture + $query = ' +DELETE FROM '.FAVORITES_TABLE.' + WHERE image_id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + // destruction of the rates associated to this element + $query = ' +DELETE FROM '.RATE_TABLE.' + WHERE element_id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + // destruction of the rates associated to this element + $query = ' +DELETE FROM '.CADDIE_TABLE.' + WHERE element_id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + // destruction of the image + $query = ' +DELETE FROM '.IMAGES_TABLE.' + WHERE id IN ( +'.wordwrap(implode(', ', $ids), 80, "\n").') +;'; + pwg_query($query); + + trigger_action('delete_elements', $ids); +} + +// The delete_user function delete a user identified by the $user_id +// It also deletes : +// - all the access linked to this user +// - all the links to any group +// - all the favorites linked to this user +// - calculated permissions linked to the user +// - all datas about notifications for the user +function delete_user($user_id) +{ + global $conf; + $tables = array( + // destruction of the access linked to the user + USER_ACCESS_TABLE, + // destruction of data notification by mail for this user + USER_MAIL_NOTIFICATION_TABLE, + // destruction of data RSS notification for this user + USER_FEED_TABLE, + // deletion of calculated permissions linked to the user + USER_CACHE_TABLE, + // deletion of computed cache data linked to the user + USER_CACHE_CATEGORIES_TABLE, + // destruction of the group links for this user + USER_GROUP_TABLE, + // destruction of the favorites associated with the user + FAVORITES_TABLE, + // destruction of the caddie associated with the user + CADDIE_TABLE, + // deletion of piwigo specific informations + USER_INFOS_TABLE, + ); + + foreach ($tables as $table) + { + $query = ' +DELETE FROM '.$table.' + WHERE user_id = '.$user_id.' +;'; + pwg_query($query); + } + + // destruction of the user + $query = ' +DELETE FROM '.SESSIONS_TABLE.' + WHERE data LIKE "pwg_uid|i:'.(int)$user_id.';%" +;'; + pwg_query($query); + + // destruction of the user + $query = ' +DELETE FROM '.USERS_TABLE.' + WHERE '.$conf['user_fields']['id'].' = '.$user_id.' +;'; + pwg_query($query); + + trigger_action('delete_user', $user_id); +} + +/** + * Verifies that the representative picture really exists in the db and + * picks up a random represantive if possible and based on config. + * + * @param mixed category id + * @returns void + */ +function update_category($ids = 'all') +{ + global $conf; + + if ($ids=='all') + { + $where_cats = '1=1'; + } + elseif ( !is_array($ids) ) + { + $where_cats = '%s='.$ids; + } + else + { + if (count($ids) == 0) + { + return false; + } + $where_cats = '%s IN('.wordwrap(implode(', ', $ids), 120, "\n").')'; + } + + // find all categories where the setted representative is not possible : + // the picture does not exist + $query = ' +SELECT DISTINCT c.id + FROM '.CATEGORIES_TABLE.' AS c LEFT JOIN '.IMAGES_TABLE.' AS i + ON c.representative_picture_id = i.id + WHERE representative_picture_id IS NOT NULL + AND '.sprintf($where_cats, 'c.id').' + AND i.id IS NULL +;'; + $wrong_representant = array_from_query($query, 'id'); + + if (count($wrong_representant) > 0) + { + $query = ' +UPDATE '.CATEGORIES_TABLE.' + SET representative_picture_id = NULL + WHERE id IN ('.wordwrap(implode(', ', $wrong_representant), 120, "\n").') +;'; + pwg_query($query); + } + + if (!$conf['allow_random_representative']) + { + // If the random representant is not allowed, we need to find + // categories with elements and with no representant. Those categories + // must be added to the list of categories to set to a random + // representant. + $query = ' +SELECT DISTINCT id + FROM '.CATEGORIES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.' + ON id = category_id + WHERE representative_picture_id IS NULL + AND '.sprintf($where_cats, 'category_id').' +;'; + $to_rand = array_from_query($query, 'id'); + if (count($to_rand) > 0) + { + set_random_representant($to_rand); + } + } +} + +/** + * returns an array containing sub-directories which can be a category, + * recursive by default + * + * directories nammed "thumbnail", "pwg_high" or "pwg_representative" are + * omitted + * + * @param string $basedir + * @return array + */ +function get_fs_directories($path, $recursive = true) +{ + $dirs = array(); + + if (is_dir($path)) + { + if ($contents = opendir($path)) + { + while (($node = readdir($contents)) !== false) + { + if (is_dir($path.'/'.$node) + and $node != '.' + and $node != '..' + and $node != '.svn' + and $node != 'thumbnail' + and $node != 'pwg_high' + and $node != 'pwg_representative') + { + array_push($dirs, $path.'/'.$node); + if ($recursive) + { + $dirs = array_merge($dirs, get_fs_directories($path.'/'.$node)); + } + } + } + } + } + + return $dirs; +} + +/** + * inserts multiple lines in a table + * + * @param string table_name + * @param array dbfields + * @param array inserts + * @return void + */ +function mass_inserts($table_name, $dbfields, $datas) +{ + if (count($datas) != 0) + { + $first = true; + + $query = 'SHOW VARIABLES LIKE \'max_allowed_packet\';'; + list(, $packet_size) = mysql_fetch_row(pwg_query($query)); + $packet_size = $packet_size - 2000; // The last list of values MUST not exceed 2000 character*/ + $query = ''; + + foreach ($datas as $insert) + { + if (strlen($query) >= $packet_size) + { + $query .= ' +;'; + pwg_query($query); + $first = true; + } + + if ($first) + { + $query = ' +INSERT INTO '.$table_name.' + ('.implode(',', $dbfields).') + VALUES'; + $first = false; + } + else + { + $query .= ' + , '; + } + + $query .= '('; + foreach ($dbfields as $field_id => $dbfield) + { + if ($field_id > 0) + { + $query .= ','; + } + + if (!isset($insert[$dbfield]) or $insert[$dbfield] === '') + { + $query .= 'NULL'; + } + else + { + $query .= "'".$insert[$dbfield]."'"; + } + } + $query .= ')'; + } + + $query .= ' +;'; + pwg_query($query); + } +} + +/** + * updates multiple lines in a table + * + * @param string table_name + * @param array dbfields + * @param array datas + * @return void + */ +function mass_updates($tablename, $dbfields, $datas) +{ + if (count($datas) != 0) + { + // depending on the MySQL version, we use the multi table update or N + // update queries + if (count($datas) < 10 or version_compare(mysql_get_server_info(), '4.0.4') < 0) + { + // MySQL is prior to version 4.0.4, multi table update feature is not + // available + foreach ($datas as $data) + { + $query = ' +UPDATE '.$tablename.' + SET '; + $is_first = true; + foreach ($dbfields['update'] as $key) + { + if (!$is_first) + { + $query.= ",\n "; + } + $query.= $key.' = '; + if (isset($data[$key]) and $data[$key] != '') + { + $query.= '\''.$data[$key].'\''; + } + else + { + $query.= 'NULL'; + } + $is_first = false; + } + $query.= ' + WHERE '; + + $is_first = true; + foreach ($dbfields['primary'] as $key) + { + if (!$is_first) + { + $query.= ' AND '; + } + if ( isset($data[$key]) ) + { + $query.= $key.' = \''.$data[$key].'\''; + } + else + { + $query.= $key.' IS NULL'; + } + $is_first = false; + } + $query.= ' +;'; + pwg_query($query); + } + } + else + { + // creation of the temporary table + $query = ' +SHOW FULL COLUMNS FROM '.$tablename.' +;'; + $result = pwg_query($query); + $columns = array(); + $all_fields = array_merge($dbfields['primary'], $dbfields['update']); + while ($row = mysql_fetch_array($result)) + { + if (in_array($row['Field'], $all_fields)) + { + $column = $row['Field']; + $column.= ' '.$row['Type']; + + $nullable = true; + if (!isset($row['Null']) or $row['Null'] == '' or $row['Null']=='NO') + { + $column.= ' NOT NULL'; + $nullable = false; + } + if (isset($row['Default'])) + { + $column.= " default '".$row['Default']."'"; + } + elseif ($nullable) + { + $column.= " default NULL"; + } + if (isset($row['Collation']) and $row['Collation'] != 'NULL') + { + $column.= " collate '".$row['Collation']."'"; + } + array_push($columns, $column); + } + } + + $temporary_tablename = $tablename.'_'.micro_seconds(); + + $query = ' + CREATE TABLE '.$temporary_tablename.' + ( + '.implode(",\n", $columns).', + UNIQUE KEY the_key ('.implode(',', $dbfields['primary']).') + ) +;'; + + pwg_query($query); + mass_inserts($temporary_tablename, $all_fields, $datas); + // update of images table by joining with temporary table + $query = ' +UPDATE '.$tablename.' AS t1, '.$temporary_tablename.' AS t2 + SET '. + implode( + "\n , ", + array_map( + create_function('$s', 'return "t1.$s = t2.$s";'), + $dbfields['update'] + ) + ).' + WHERE '. + implode( + "\n AND ", + array_map( + create_function('$s', 'return "t1.$s = t2.$s";'), + $dbfields['primary'] + ) + ).' + ;'; + pwg_query($query); + $query = ' +DROP TABLE '.$temporary_tablename.' +;'; + pwg_query($query); + } + } +} + +/** + * order categories (update categories.rank and global_rank database fields) + * so that rank field are consecutive integers starting at 1 for each child + * @return void + */ +function update_global_rank() +{ + $query = ' +SELECT id, if(id_uppercat is null,\'\',id_uppercat) AS id_uppercat, uppercats, rank, global_rank + FROM '.CATEGORIES_TABLE.' + ORDER BY id_uppercat,rank,name +;'; + + $cat_map = array(); + + $current_rank = 0; + $current_uppercat = ''; + + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + if ($row['id_uppercat'] != $current_uppercat) + { + $current_rank = 0; + $current_uppercat = $row['id_uppercat']; + } + ++$current_rank; + $cat = + array( + 'rank' => $current_rank, + 'rank_changed' =>$current_rank!=$row['rank'], + 'global_rank' => $row['global_rank'], + 'uppercats' => $row['uppercats'], + ); + $cat_map[ $row['id'] ] = $cat; + } + + $datas = array(); + + foreach( $cat_map as $id=>$cat ) + { + $new_global_rank = preg_replace( + '/(\d+)/e', + "\$cat_map['$1']['rank']", + str_replace(',', '.', $cat['uppercats'] ) + ); + if ( $cat['rank_changed'] + or $new_global_rank!=$cat['global_rank'] + ) + { + $datas[] = array( + 'id' => $id, + 'rank' => $cat['rank'], + 'global_rank' => $new_global_rank, + ); + } + } + + mass_updates( + CATEGORIES_TABLE, + array( + 'primary' => array('id'), + 'update' => array('rank', 'global_rank') + ), + $datas + ); + return count($datas); +} + +/** + * change the visible property on a set of categories + * + * @param array categories + * @param string value + * @return void + */ +function set_cat_visible($categories, $value) +{ + if (!in_array($value, array('true', 'false'))) + { + return false; + } + + // unlocking a category => all its parent categories become unlocked + if ($value == 'true') + { + $uppercats = get_uppercat_ids($categories); + $query = ' +UPDATE '.CATEGORIES_TABLE.' + SET visible = \'true\' + WHERE id IN ('.implode(',', $uppercats).') +;'; + pwg_query($query); + } + // locking a category => all its child categories become locked + if ($value == 'false') + { + $subcats = get_subcat_ids($categories); + $query = ' +UPDATE '.CATEGORIES_TABLE.' + SET visible = \'false\' + WHERE id IN ('.implode(',', $subcats).') +;'; + pwg_query($query); + } +} + +/** + * change the status property on a set of categories : private or public + * + * @param array categories + * @param string value + * @return void + */ +function set_cat_status($categories, $value) +{ + if (!in_array($value, array('public', 'private'))) + { + return false; + } + + // make public a category => all its parent categories become public + if ($value == 'public') + { + $uppercats = get_uppercat_ids($categories); + $query = ' +UPDATE '.CATEGORIES_TABLE.' + SET status = \'public\' + WHERE id IN ('.implode(',', $uppercats).') +;'; + pwg_query($query); + } + // make a category private => all its child categories become private + if ($value == 'private') + { + $subcats = get_subcat_ids($categories); + $query = ' +UPDATE '.CATEGORIES_TABLE.' + SET status = \'private\' + WHERE id IN ('.implode(',', $subcats).') +;'; + pwg_query($query); + } +} + +/** + * returns all uppercats category ids of the given category ids + * + * @param array cat_ids + * @return array + */ +function get_uppercat_ids($cat_ids) +{ + if (!is_array($cat_ids) or count($cat_ids) < 1) + { + return array(); + } + + $uppercats = array(); + + $query = ' +SELECT uppercats + FROM '.CATEGORIES_TABLE.' + WHERE id IN ('.implode(',', $cat_ids).') +;'; + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + $uppercats = array_merge($uppercats, + explode(',', $row['uppercats'])); + } + $uppercats = array_unique($uppercats); + + return $uppercats; +} + +/** + * set a new random representant to the categories + * + * @param array categories + */ +function set_random_representant($categories) +{ + $datas = array(); + foreach ($categories as $category_id) + { + $query = ' +SELECT image_id + FROM '.IMAGE_CATEGORY_TABLE.' + WHERE category_id = '.$category_id.' + ORDER BY RAND() + LIMIT 0,1 +;'; + list($representative) = mysql_fetch_array(pwg_query($query)); + + array_push( + $datas, + array( + 'id' => $category_id, + 'representative_picture_id' => $representative, + ) + ); + } + + mass_updates( + CATEGORIES_TABLE, + array( + 'primary' => array('id'), + 'update' => array('representative_picture_id') + ), + $datas + ); +} + +/** + * returns the fulldir for each given category id + * + * @param array cat_ids + * @return array + */ +function get_fulldirs($cat_ids) +{ + if (count($cat_ids) == 0) + { + return array(); + } + + // caching directories of existing categories + $query = ' +SELECT id, dir + FROM '.CATEGORIES_TABLE.' + WHERE dir IS NOT NULL +;'; + $result = pwg_query($query); + $cat_dirs = array(); + while ($row = mysql_fetch_array($result)) + { + $cat_dirs[$row['id']] = $row['dir']; + } + + // caching galleries_url + $query = ' +SELECT id, galleries_url + FROM '.SITES_TABLE.' +;'; + $result = pwg_query($query); + $galleries_url = array(); + while ($row = mysql_fetch_array($result)) + { + $galleries_url[$row['id']] = $row['galleries_url']; + } + + // categories : id, site_id, uppercats + $categories = array(); + + $query = ' +SELECT id, uppercats, site_id + FROM '.CATEGORIES_TABLE.' + WHERE id IN ( +'.wordwrap(implode(', ', $cat_ids), 80, "\n").') +;'; + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + array_push($categories, $row); + } + + // filling $cat_fulldirs + $cat_fulldirs = array(); + foreach ($categories as $category) + { + $uppercats = str_replace(',', '/', $category['uppercats']); + $cat_fulldirs[$category['id']] = $galleries_url[$category['site_id']]; + $cat_fulldirs[$category['id']].= preg_replace('/(\d+)/e', + "\$cat_dirs['$1']", + $uppercats); + } + + return $cat_fulldirs; +} + +/** + * returns an array with all file system files according to + * $conf['file_ext'] + * + * @param string $path + * @param bool recursive + * @return array + */ +function get_fs($path, $recursive = true) +{ + global $conf; + + // because isset is faster than in_array... + if (!isset($conf['flip_picture_ext'])) + { + $conf['flip_picture_ext'] = array_flip($conf['picture_ext']); + } + if (!isset($conf['flip_file_ext'])) + { + $conf['flip_file_ext'] = array_flip($conf['file_ext']); + } + + $fs['elements'] = array(); + $fs['thumbnails'] = array(); + $fs['representatives'] = array(); + $subdirs = array(); + + if (is_dir($path)) + { + if ($contents = opendir($path)) + { + while (($node = readdir($contents)) !== false) + { + if (is_file($path.'/'.$node)) + { + $extension = get_extension($node); + +// if (in_array($extension, $conf['picture_ext'])) + if (isset($conf['flip_picture_ext'][$extension])) + { + if (basename($path) == 'thumbnail') + { + array_push($fs['thumbnails'], $path.'/'.$node); + } + else if (basename($path) == 'pwg_representative') + { + array_push($fs['representatives'], $path.'/'.$node); + } + else + { + array_push($fs['elements'], $path.'/'.$node); + } + } +// else if (in_array($extension, $conf['file_ext'])) + else if (isset($conf['flip_file_ext'][$extension])) + { + array_push($fs['elements'], $path.'/'.$node); + } + } + else if (is_dir($path.'/'.$node) + and $node != '.' + and $node != '..' + and $node != 'pwg_high' + and $recursive) + { + array_push($subdirs, $node); + } + } + } + closedir($contents); + + foreach ($subdirs as $subdir) + { + $tmp_fs = get_fs($path.'/'.$subdir); + + $fs['elements'] = array_merge($fs['elements'], + $tmp_fs['elements']); + + $fs['thumbnails'] = array_merge($fs['thumbnails'], + $tmp_fs['thumbnails']); + + $fs['representatives'] = array_merge($fs['representatives'], + $tmp_fs['representatives']); + } + } + return $fs; +} + +/** + * stupidly returns the current microsecond since Unix epoch + */ +function micro_seconds() +{ + $t1 = explode(' ', microtime()); + $t2 = explode('.', $t1[0]); + $t2 = $t1[1].substr($t2[1], 0, 6); + return $t2; +} + +/** + * synchronize base users list and related users list + * + * compares and synchronizes base users table (USERS_TABLE) with its child + * tables (USER_INFOS_TABLE, USER_ACCESS, USER_CACHE, USER_GROUP) : each + * base user must be present in child tables, users in child tables not + * present in base table must be deleted. + * + * @return void + */ +function sync_users() +{ + global $conf; + + $query = ' +SELECT '.$conf['user_fields']['id'].' AS id + FROM '.USERS_TABLE.' +;'; + $base_users = array_from_query($query, 'id'); + + $query = ' +SELECT user_id + FROM '.USER_INFOS_TABLE.' +;'; + $infos_users = array_from_query($query, 'user_id'); + + // users present in $base_users and not in $infos_users must be added + $to_create = array_diff($base_users, $infos_users); + + if (count($to_create) > 0) + { + create_user_infos($to_create); + } + + // users present in user related tables must be present in the base user + // table + $tables = array( + USER_MAIL_NOTIFICATION_TABLE, + USER_FEED_TABLE, + USER_INFOS_TABLE, + USER_ACCESS_TABLE, + USER_CACHE_TABLE, + USER_CACHE_CATEGORIES_TABLE, + USER_GROUP_TABLE + ); + + foreach ($tables as $table) + { + $query = ' +SELECT DISTINCT user_id + FROM '.$table.' +;'; + $to_delete = array_diff( + array_from_query($query, 'user_id'), + $base_users + ); + + if (count($to_delete) > 0) + { + $query = ' +DELETE + FROM '.$table.' + WHERE user_id in ('.implode(',', $to_delete).') +;'; + pwg_query($query); + } + } +} + +/** + * updates categories.uppercats field based on categories.id + + * categories.id_uppercat + * + * @return void + */ +function update_uppercats() +{ + $query = ' +SELECT id, id_uppercat, uppercats + FROM '.CATEGORIES_TABLE.' +;'; + $cat_map = hash_from_query($query, 'id'); + + $datas = array(); + foreach ($cat_map as $id => $cat) + { + $upper_list = array(); + + $uppercat = $id; + while ($uppercat) + { + array_push($upper_list, $uppercat); + $uppercat = $cat_map[$uppercat]['id_uppercat']; + } + + $new_uppercats = implode(',', array_reverse($upper_list)); + if ($new_uppercats != $cat['uppercats']) + { + array_push( + $datas, + array( + 'id' => $id, + 'uppercats' => $new_uppercats + ) + ); + } + } + $fields = array('primary' => array('id'), 'update' => array('uppercats')); + mass_updates(CATEGORIES_TABLE, $fields, $datas); +} + +/** + * update images.path field + * + * @return void + */ +function update_path() +{ + $query = ' +SELECT DISTINCT(storage_category_id) + FROM '.IMAGES_TABLE.' +;'; + $cat_ids = array_from_query($query, 'storage_category_id'); + $fulldirs = get_fulldirs($cat_ids); + + foreach ($cat_ids as $cat_id) + { + $query = ' +UPDATE '.IMAGES_TABLE.' + SET path = CONCAT(\''.$fulldirs[$cat_id].'\',\'/\',file) + WHERE storage_category_id = '.$cat_id.' +;'; + pwg_query($query); + } +} + +/** + * update images.average_rate field + * param int $element_id optional, otherwise applies to all + * @return void + */ +function update_average_rate( $element_id=-1 ) +{ + $query = ' +SELECT element_id, + ROUND(AVG(rate),2) AS average_rate + FROM '.RATE_TABLE; + if ( $element_id != -1 ) + { + $query .= ' WHERE element_id=' . $element_id; + } + $query .= ' GROUP BY element_id;'; + + $result = pwg_query($query); + + $datas = array(); + + while ($row = mysql_fetch_array($result)) + { + array_push( + $datas, + array( + 'id' => $row['element_id'], + 'average_rate' => $row['average_rate'] + ) + ); + } + + mass_updates( + IMAGES_TABLE, + array( + 'primary' => array('id'), + 'update' => array('average_rate') + ), + $datas + ); + + $query=' +SELECT id FROM '.IMAGES_TABLE .' + LEFT JOIN '.RATE_TABLE.' ON id=element_id + WHERE element_id IS NULL AND average_rate IS NOT NULL'; + if ( $element_id != -1 ) + { + $query .= ' AND id=' . $element_id; + } + $to_update = array_from_query( $query, 'id'); + + if ( !empty($to_update) ) + { + $query=' +UPDATE '.IMAGES_TABLE .' + SET average_rate=NULL + WHERE id IN (' . implode(',',$to_update) . ')'; + pwg_query($query); + } +} + +/** + * change the parent category of the given categories. The categories are + * supposed virtual. + * + * @param array category identifiers + * @param int parent category identifier + * @return void + */ +function move_categories($category_ids, $new_parent = -1) +{ + global $page; + + if (count($category_ids) == 0) + { + return; + } + + $new_parent = $new_parent < 1 ? 'NULL' : $new_parent; + + $categories = array(); + + $query = ' +SELECT id, id_uppercat, status, uppercats + FROM '.CATEGORIES_TABLE.' + WHERE id IN ('.implode(',', $category_ids).') +;'; + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + $categories[$row['id']] = + array( + 'parent' => empty($row['id_uppercat']) ? 'NULL' : $row['id_uppercat'], + 'status' => $row['status'], + 'uppercats' => $row['uppercats'] + ); + } + + // is the movement possible? The movement is impossible if you try to move + // a category in a sub-category or itself + if ('NULL' != $new_parent) + { + $query = ' +SELECT uppercats + FROM '.CATEGORIES_TABLE.' + WHERE id = '.$new_parent.' +;'; + list($new_parent_uppercats) = mysql_fetch_row(pwg_query($query)); + + foreach ($categories as $category) + { + // technically, you can't move a category with uppercats 12,125,13,14 + // into a new parent category with uppercats 12,125,13,14,24 + if (preg_match('/^'.$category['uppercats'].'/', $new_parent_uppercats)) + { + array_push( + $page['errors'], + l10n('You cannot move a category in its own sub category') + ); + return; + } + } + } + + $tables = + array( + USER_ACCESS_TABLE => 'user_id', + GROUP_ACCESS_TABLE => 'group_id' + ); + + $query = ' +UPDATE '.CATEGORIES_TABLE.' + SET id_uppercat = '.$new_parent.' + WHERE id IN ('.implode(',', $category_ids).') +;'; + pwg_query($query); + + update_uppercats(); + update_global_rank(); + + // status and related permissions management + if ('NULL' == $new_parent) + { + $parent_status = 'public'; + } + else + { + $query = ' +SELECT status + FROM '.CATEGORIES_TABLE.' + WHERE id = '.$new_parent.' +;'; + list($parent_status) = mysql_fetch_row(pwg_query($query)); + } + + if ('private' == $parent_status) + { + foreach ($categories as $cat_id => $category) + { + switch ($category['status']) + { + case 'public' : + { + set_cat_status(array($cat_id), 'private'); + break; + } + case 'private' : + { + $subcats = get_subcat_ids(array($cat_id)); + + foreach ($tables as $table => $field) + { + $query = ' +SELECT '.$field.' + FROM '.$table.' + WHERE cat_id = '.$cat_id.' +;'; + $category_access = array_from_query($query, $field); + + $query = ' +SELECT '.$field.' + FROM '.$table.' + WHERE cat_id = '.$new_parent.' +;'; + $parent_access = array_from_query($query, $field); + + $to_delete = array_diff($parent_access, $category_access); + + if (count($to_delete) > 0) + { + $query = ' +DELETE FROM '.$table.' + WHERE '.$field.' IN ('.implode(',', $to_delete).') + AND cat_id IN ('.implode(',', $subcats).') +;'; + pwg_query($query); + } + } + break; + } + } + } + } + + array_push( + $page['infos'], + l10n_dec( + '%d category moved', '%d categories moved', + count($categories) + ) + ); +} + +/** + * create a virtual category + * + * @param string category name + * @param int parent category id + * @return array with ('info' and 'id') or ('error') key + */ +function create_virtual_category($category_name, $parent_id=null) +{ + global $conf; + + // is the given category name only containing blank spaces ? + if (preg_match('/^\s*$/', $category_name)) + { + return array('error' => l10n('cat_error_name')); + } + + $parent_id = !empty($parent_id) ? $parent_id : 'NULL'; + + $query = ' +SELECT MAX(rank) + FROM '.CATEGORIES_TABLE.' + WHERE id_uppercat '.(is_numeric($parent_id) ? '= '.$parent_id : 'IS NULL').' +;'; + list($current_rank) = mysql_fetch_array(pwg_query($query)); + + $insert = array( + 'name' => $category_name, + 'rank' => ++$current_rank, + 'commentable' => boolean_to_string($conf['newcat_default_commentable']), + 'uploadable' => 'false', + ); + + if ($parent_id != 'NULL') + { + $query = ' +SELECT id, uppercats, global_rank, visible, status + FROM '.CATEGORIES_TABLE.' + WHERE id = '.$parent_id.' +;'; + $parent = mysql_fetch_array(pwg_query($query)); + + $insert{'id_uppercat'} = $parent{'id'}; + $insert{'global_rank'} = $parent{'global_rank'}.'.'.$insert{'rank'}; + + // at creation, must a category be visible or not ? Warning : if the + // parent category is invisible, the category is automatically create + // invisible. (invisible = locked) + if ('false' == $parent['visible']) + { + $insert{'visible'} = 'false'; + } + else + { + $insert{'visible'} = boolean_to_string($conf['newcat_default_visible']); + } + + // at creation, must a category be public or private ? Warning : if the + // parent category is private, the category is automatically create + // private. + if ('private' == $parent['status']) + { + $insert{'status'} = 'private'; + } + else + { + $insert{'status'} = $conf['newcat_default_status']; + } + } + else + { + $insert{'visible'} = boolean_to_string($conf['newcat_default_visible']); + $insert{'status'} = $conf['newcat_default_status']; + $insert{'global_rank'} = $insert{'rank'}; + } + + // we have then to add the virtual category + mass_inserts( + CATEGORIES_TABLE, + array( + 'site_id', 'name', 'id_uppercat', 'rank', 'commentable', + 'uploadable', 'visible', 'status', 'global_rank', + ), + array($insert) + ); + + $inserted_id = mysql_insert_id(); + + $query = ' +UPDATE + '.CATEGORIES_TABLE.' + SET uppercats = \''. + (isset($parent) ? $parent{'uppercats'}.',' : ''). + $inserted_id. + '\' + WHERE id = '.$inserted_id.' +;'; + pwg_query($query); + + return array( + 'info' => l10n('cat_virtual_added'), + 'id' => $inserted_id, + ); +} + +/** + * Set tags to an image. Warning: given tags are all tags associated to the + * image, not additionnal tags. + * + * @param array tag ids + * @param int image id + * @return void + */ +function set_tags($tags, $image_id) +{ + $query = ' +DELETE + FROM '.IMAGE_TAG_TABLE.' + WHERE image_id = '.$image_id.' +;'; + pwg_query($query); + + if (count($tags) > 0) + { + $inserts = array(); + foreach ($tags as $tag_id) + { + array_push( + $inserts, + array( + 'tag_id' => $tag_id, + 'image_id' => $image_id + ) + ); + } + mass_inserts( + IMAGE_TAG_TABLE, + array_keys($inserts[0]), + $inserts + ); + } +} + +/** + * Add new tags to a set of images. + * + * @param array tag ids + * @param array image ids + * @return void + */ +function add_tags($tags, $images) +{ + if (count($tags) == 0 or count($tags) == 0) + { + return; + } + + // we can't insert twice the same {image_id,tag_id} so we must first + // delete lines we'll insert later + $query = ' +DELETE + FROM '.IMAGE_TAG_TABLE.' + WHERE image_id IN ('.implode(',', $images).') + AND tag_id IN ('.implode(',', $tags).') +;'; + pwg_query($query); + + $inserts = array(); + foreach ($images as $image_id) + { + foreach ($tags as $tag_id) + { + array_push( + $inserts, + array( + 'image_id' => $image_id, + 'tag_id' => $tag_id, + ) + ); + } + } + mass_inserts( + IMAGE_TAG_TABLE, + array_keys($inserts[0]), + $inserts + ); +} + +function tag_id_from_tag_name($tag_name) +{ + global $page; + + $tag_name = trim($tag_name); + if (isset($page['tag_id_from_tag_name_cache'][$tag_name])) + { + return $page['tag_id_from_tag_name_cache'][$tag_name]; + } + + // does the tag already exists? + $query = ' +SELECT id + FROM '.TAGS_TABLE.' + WHERE name = \''.$tag_name.'\' +;'; + $existing_tags = array_from_query($query, 'id'); + + if (count($existing_tags) == 0) + { + mass_inserts( + TAGS_TABLE, + array('name', 'url_name'), + array( + array( + 'name' => $tag_name, + 'url_name' => str2url($tag_name), + ) + ) + ); + + $page['tag_id_from_tag_name_cache'][$tag_name] = mysql_insert_id(); + } + else + { + $page['tag_id_from_tag_name_cache'][$tag_name] = $existing_tags[0]; + } + + return $page['tag_id_from_tag_name_cache'][$tag_name]; +} + +function set_tags_of($tags_of) +{ + if (count($tags_of) > 0) + { + $query = ' +DELETE + FROM '.IMAGE_TAG_TABLE.' + WHERE image_id IN ('.implode(',', array_keys($tags_of)).') +;'; + pwg_query($query); + + $inserts = array(); + + foreach ($tags_of as $image_id => $tag_ids) + { + foreach ($tag_ids as $tag_id) + { + array_push( + $inserts, + array( + 'image_id' => $image_id, + 'tag_id' => $tag_id, + ) + ); + } + } + + mass_inserts( + IMAGE_TAG_TABLE, + array_keys($inserts[0]), + $inserts + ); + } +} + +/** + * Do maintenance on all PWG tables + * + * @return nono + */ +function do_maintenance_all_tables() +{ + global $prefixeTable; + + $all_tables = array(); + + // List all tables + $query = 'SHOW TABLES LIKE \''.$prefixeTable.'%\';'; + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + array_push($all_tables, $row[0]); + } + + // Repair all tables + $query = 'REPAIR TABLE '.implode(', ', $all_tables).';'; + pwg_query($query); + + // Re-Order all tables + foreach ($all_tables as $table_name) + { + $all_primary_key = array(); + + $query = 'DESC '.$table_name.';'; + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + if ($row['Key'] == 'PRI') + { + array_push($all_primary_key, $row['Field']); + } + } + + if (count($all_primary_key) != 0) + { + $query = 'ALTER TABLE '.$table_name.' ORDER BY '.implode(', ', $all_primary_key).';'; + pwg_query($query); + } + } + + // Optimize all tables + $query = 'OPTIMIZE TABLE '.implode(', ', $all_tables).';'; + pwg_query($query); + +} + +/** + * Associate a list of images to a list of categories. + * + * The function will not duplicate links + * + * @param array images + * @param array categories + * @return void + */ +function associate_images_to_categories($images, $categories) +{ + if (count($images) == 0 + or count($categories) == 0) + { + return false; + } + + $query = ' +DELETE + FROM '.IMAGE_CATEGORY_TABLE.' + WHERE image_id IN ('.implode(',', $images).') + AND category_id IN ('.implode(',', $categories).') +;'; + pwg_query($query); + + $inserts = array(); + foreach ($categories as $category_id) + { + foreach ($images as $image_id) + { + array_push( + $inserts, + array( + 'image_id' => $image_id, + 'category_id' => $category_id, + ) + ); + } + } + + mass_inserts( + IMAGE_CATEGORY_TABLE, + array_keys($inserts[0]), + $inserts + ); + + update_category($categories); +} + +/** + * Associate images associated to a list of source categories to a list of + * destination categories. + * + * @param array sources + * @param array destinations + * @return void + */ +function associate_categories_to_categories($sources, $destinations) +{ + if (count($sources) == 0) + { + return false; + } + + $query = ' +SELECT image_id + FROM '.IMAGE_CATEGORY_TABLE.' + WHERE category_id IN ('.implode(',', $sources).') +;'; + $images = array_from_query($query, 'image_id'); + + associate_images_to_categories($images, $destinations); +} + +/** + * Create an XML file with Piwigo informations about a list of + * pictures. + * + * The goal of the export feature is to make easier the reading of + * informations related to pictures outside of Piwigo. + * + * @param array image_ids + */ +function export_pwg_data($image_ids) +{ + global $conf; + + if (count($image_ids) == 0) + { + return; + } + + $fp = fopen($conf['export_file'], 'w'); + $xml_string = '<export>'."\n"; + + $query = ' +SELECT tag_id, + image_id + FROM '.IMAGE_TAG_TABLE.' + WHERE image_id IN ('.implode(',', $image_ids).') +;'; + $result = pwg_query($query); + $tags_of = array(); + $all_tag_ids = array(); + $tag_name_of = array(); + + if (mysql_num_rows($result)) + { + while ($row = mysql_fetch_array($result)) + { + array_push($all_tag_ids, $row['tag_id']); + + if (!isset($tags_of[ $row['image_id'] ])) { + $tags_of[ $row['image_id'] ] = array(); + } + + array_push( + $tags_of[ $row['image_id'] ], + $row['tag_id'] + ); + } + + $all_tag_ids = array_unique($all_tag_ids); + + $query = ' +SELECT id, + name + FROM '.TAGS_TABLE.' + WHERE id IN ('.implode(',', $all_tag_ids).') +;'; + $result = pwg_query($query); + + while ($row = mysql_fetch_array($result)) + { + $tag_name_of[ $row['id'] ] = $row['name']; + } + } + + $query = ' +SELECT id, + path + FROM '.IMAGES_TABLE.' + WHERE id IN ('.implode(',', $image_ids).') +;'; + $result = pwg_query($query); + + while ($row = mysql_fetch_array($result)) + { + $xml_string.= " <photo>\n"; + $xml_string.= " <id>".$row['id']."</id>\n"; + $xml_string.= " <path>".$row['path']."</path>\n"; + + foreach ($tags_of[ $row['id'] ] as $tag_id) + { + $xml_string.= " <tag>".$tag_name_of[$tag_id]."</tag>\n"; + } + + $xml_string.= " </photo>\n"; + } + + $xml_string.= '</export>'; + fwrite($fp, $xml_string); + fclose($fp); +} + +/** + * Refer main Piwigo URLs (currently PHPWG_DOMAIN domain) + * + * @param void + * @return array like $conf['links'] + */ +function pwg_URL() +{ + global $lang_info; + $urls = array( + 'WIKI' => 'http://'.PHPWG_DOMAIN.'/doc/', + 'HOME' => 'http://'.PHPWG_DOMAIN.'/', + 'DEMO' => 'http://demo.'.PHPWG_DOMAIN.'/', + 'FORUM' => 'http://forum.'.PHPWG_DOMAIN.'/', + 'BUGS' => 'http://bugs.'.PHPWG_DOMAIN.'/', + 'EXTENSIONS' => 'http://'.PHPWG_DOMAIN.'/ext', + ); + if ( isset($lang_info['code']) and + in_array($lang_info['code'], array('fr','en')) ) + { /* current wiki languages are French or English */ + $urls['WIKI'] .= 'doku.php?id='.$lang_info['code'].':start'; + $urls['HOME'] .= '?lang='.$lang_info['code']; + } + return $urls; +} + +/** + * Invalidates cahed data (permissions and category counts) for all users. + */ +function invalidate_user_cache() +{ + $query = ' +UPDATE '.USER_CACHE_TABLE.' + SET need_update = \'true\' +;'; + pwg_query($query); + trigger_action('invalidate_user_cache'); +} + +/** + * adds the caracter set to a create table sql query. + * all CREATE TABLE queries must call this function + * @param string query - the sql query + */ +function create_table_add_character_set($query) +{ + defined('DB_CHARSET') or die('create_table_add_character_set DB_CHARSET undefined'); + if ('DB_CHARSET'!='') + { + if ( version_compare(mysql_get_server_info(), '4.1.0', '<') ) + { + return $query; + } + $charset_collate = " DEFAULT CHARACTER SET ".DB_CHARSET; + if ('DB_COLLATE'!='') + { + $charset_collate .= " COLLATE ".DB_COLLATE; + } + $query=trim($query); + $query=trim($query, ';'); + if (preg_match('/^CREATE\s+TABLE/i',$query)) + { + $query.=$charset_collate; + } + $query .= ';'; + } + return $query; +} + +/** + * Returns array use on template with html_options method + * @param Min and Max access to use + * @return array of user access level + */ +function get_user_access_level_html_options($MinLevelAccess = ACCESS_FREE, $MaxLevelAccess = ACCESS_CLOSED) +{ + $tpl_options = array(); + for ($level = $MinLevelAccess; $level <= $MaxLevelAccess; $level++) + { + $tpl_options[$level] = l10n(sprintf('ACCESS_%d', $level)); + } + return $tpl_options; +} + +?>
\ No newline at end of file |