diff options
-rw-r--r-- | admin.php | 1 | ||||
-rw-r--r-- | admin/batch_manager.php | 335 | ||||
-rw-r--r-- | admin/batch_manager_global.php | 575 | ||||
-rw-r--r-- | admin/themes/default/template/admin.tpl | 1 | ||||
-rw-r--r-- | admin/themes/default/template/batch_manager_global.tpl | 580 |
5 files changed, 1492 insertions, 0 deletions
@@ -129,6 +129,7 @@ $template->assign( 'U_RATING'=> $link_start.'rating', 'U_CADDIE'=> $link_start.'element_set&cat=caddie', 'U_RECENT_SET'=> $link_start.'element_set&cat=recent', + 'U_BATCH'=> $link_start.'batch_manager', 'U_TAGS'=> $link_start.'tags', 'U_THUMBNAILS'=> $link_start.'thumbnail', 'U_USERS'=> $link_start.'user_list', diff --git a/admin/batch_manager.php b/admin/batch_manager.php new file mode 100644 index 000000000..3fe4c3ce4 --- /dev/null +++ b/admin/batch_manager.php @@ -0,0 +1,335 @@ +<?php +// +-----------------------------------------------------------------------+ +// | Piwigo - a PHP based picture gallery | +// +-----------------------------------------------------------------------+ +// | Copyright(C) 2008-2010 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. | +// +-----------------------------------------------------------------------+ + +/** + * Management of elements set. Elements can belong to a category or to the + * user caddie. + * + */ + +if (!defined('PHPWG_ROOT_PATH')) +{ + die('Hacking attempt!'); +} + +include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); + +// +-----------------------------------------------------------------------+ +// | Check Access and exit when user status is not ok | +// +-----------------------------------------------------------------------+ + +check_status(ACCESS_ADMINISTRATOR); + +check_input_parameter('selection', $_POST, true, PATTERN_ID); + +// +-----------------------------------------------------------------------+ +// | initialize current set | +// +-----------------------------------------------------------------------+ + +if (isset($_POST['submitFilter'])) +{ + // echo '<pre>'; print_r($_POST); echo '</pre>'; + + $_SESSION['bulk_manager_filter'] = array(); + + if (isset($_POST['filter_prefilter_use'])) + { + $prefilters = array('caddie', 'last import', 'with no album', 'with no tag'); + if (in_array($_POST['filter_prefilter'], $prefilters)) + { + $_SESSION['bulk_manager_filter']['prefilter'] = $_POST['filter_prefilter']; + } + } + + if (isset($_POST['filter_category_use'])) + { + $_SESSION['bulk_manager_filter']['category'] = $_POST['filter_category']; + + if (isset($_POST['filter_category_recursive'])) + { + $_SESSION['bulk_manager_filter']['category_recursive'] = true; + } + } + + if (isset($_POST['filter_level_use'])) + { + if (in_array($_POST['filter_level'], $conf['available_permission_levels'])) + { + $_SESSION['bulk_manager_filter']['level'] = $_POST['filter_level']; + } + } +} + +if (isset($_GET['cat'])) +{ + if ('caddie' == $_GET['cat']) + { + $_SESSION['bulk_manager_filter'] = array( + 'prefilter' => 'caddie' + ); + } + + if (is_numeric($_GET['cat'])) + { + $_SESSION['bulk_manager_filter'] = array( + 'category' => $_GET['cat'] + ); + } +} + +if (!isset($_SESSION['bulk_manager_filter'])) +{ + $_SESSION['bulk_manager_filter'] = array( + 'prefilter' => 'caddie' + ); +} + +// echo '<pre>'; print_r($_SESSION['bulk_manager_filter']); echo '</pre>'; + +// depending on the current filter (in session), we find the appropriate +// photos +$filter_sets = array(); +if (isset($_SESSION['bulk_manager_filter']['prefilter'])) +{ + if ('caddie' == $_SESSION['bulk_manager_filter']['prefilter']) + { + $query = ' +SELECT element_id + FROM '.CADDIE_TABLE.' + WHERE user_id = '.$user['id'].' +;'; + array_push( + $filter_sets, + array_from_query($query, 'element_id') + ); + } + + if ('last import'== $_SESSION['bulk_manager_filter']['prefilter']) + { + $query = ' +SELECT MAX(date_available) AS date + FROM '.IMAGES_TABLE.' +;'; + $row = pwg_db_fetch_assoc(pwg_query($query)); + if (!empty($row['date'])) + { + $query = ' +SELECT id + FROM '.IMAGES_TABLE.' + WHERE date_available BETWEEN '.pwg_db_get_recent_period_expression(1, $row['date']).' AND \''.$row['date'].'\' +;'; + array_push( + $filter_sets, + array_from_query($query, 'id') + ); + } + } +} + +if (isset($_SESSION['bulk_manager_filter']['category'])) +{ + $categories = array(); + + if (isset($_SESSION['bulk_manager_filter']['category_recursive'])) + { + $categories = get_subcat_ids(array($_SESSION['bulk_manager_filter']['category'])); + } + else + { + $categories = array($_SESSION['bulk_manager_filter']['category']); + } + + $query = ' + SELECT DISTINCT(image_id) + FROM '.IMAGE_CATEGORY_TABLE.' + WHERE category_id IN ('.implode(',', $categories).') + ;'; + array_push( + $filter_sets, + array_from_query($query, 'image_id') + ); +} + +if (isset($_SESSION['bulk_manager_filter']['level'])) +{ + $query = ' +SELECT id + FROM '.IMAGES_TABLE.' + WHERE level >= '.$_SESSION['bulk_manager_filter']['level'].' +;'; + array_push( + $filter_sets, + array_from_query($query, 'id') + ); +} + +$current_set = array_shift($filter_sets); +foreach ($filter_sets as $set) +{ + $current_set = array_intersect($current_set, $set); +} +$page['cat_elements_id'] = $current_set; + +// // To element_set_(global|unit).php, we must provide the elements id of the +// // managed category in $page['cat_elements_id'] array. +// $page['cat_elements_id'] = array(); +// if (is_numeric($_GET['cat'])) +// { +// $page['title'] = +// get_cat_display_name_from_id( +// $_GET['cat'], +// PHPWG_ROOT_PATH.'admin.php?page=cat_modify&cat_id=', +// false +// ); +// +// $query = ' +// SELECT image_id +// FROM '.IMAGE_CATEGORY_TABLE.' +// WHERE category_id = '.$_GET['cat'].' +// ;'; +// $page['cat_elements_id'] = array_from_query($query, 'image_id'); +// } +// else if ('caddie' == $_GET['cat']) +// { +// $page['title'] = l10n('caddie'); +// +// $query = ' +// SELECT element_id +// FROM '.CADDIE_TABLE.' +// WHERE user_id = '.$user['id'].' +// ;'; +// $page['cat_elements_id'] = array_from_query($query, 'element_id'); +// } +// else if ('not_linked' == $_GET['cat']) +// { +// $page['title'] = l10n('Not linked elements'); +// $template->assign(array('U_ACTIVE_MENU' => 5 )); +// +// // we are searching elements not linked to any virtual category +// $query = ' +// SELECT id +// FROM '.IMAGES_TABLE.' +// ;'; +// $all_elements = array_from_query($query, 'id'); +// +// $linked_to_virtual = array(); +// +// $query = ' +// SELECT id +// FROM '.CATEGORIES_TABLE.' +// WHERE dir IS NULL +// ;'; +// $virtual_categories = array_from_query($query, 'id'); +// if (!empty($virtual_categories)) +// { +// $query = ' +// SELECT DISTINCT(image_id) +// FROM '.IMAGE_CATEGORY_TABLE.' +// WHERE category_id IN ('.implode(',', $virtual_categories).') +// ;'; +// $linked_to_virtual = array_from_query($query, 'image_id'); +// } +// +// $page['cat_elements_id'] = array_diff($all_elements, $linked_to_virtual); +// } +// else if ('duplicates' == $_GET['cat']) +// { +// $page['title'] = l10n('Files with same name in more than one physical category'); +// $template->assign(array('U_ACTIVE_MENU' => 5 )); +// +// // we are searching related elements twice or more to physical categories +// // 1 - Retrieve Files +// $query = ' +// SELECT DISTINCT(file) +// FROM '.IMAGES_TABLE.' +// GROUP BY file +// HAVING COUNT(DISTINCT storage_category_id) > 1 +// ;'; +// +// $duplicate_files = array_from_query($query, 'file'); +// $duplicate_files[]='Nofiles'; +// // 2 - Retrives related picture ids +// $query = ' +// SELECT id, file +// FROM '.IMAGES_TABLE.' +// WHERE file IN (\''.implode("','", $duplicate_files).'\') +// ORDER BY file, id +// ;'; +// +// $page['cat_elements_id'] = array_from_query($query, 'id'); +// } +// elseif ('recent'== $_GET['cat']) +// { +// $page['title'] = l10n('Recent pictures'); +// $query = 'SELECT MAX(date_available) AS date +// FROM '.IMAGES_TABLE; +// $row = pwg_db_fetch_assoc(pwg_query($query)); +// if (!empty($row['date'])) +// { +// $query = 'SELECT id +// FROM '.IMAGES_TABLE.' +// WHERE date_available BETWEEN '.pwg_db_get_recent_period_expression(1, $row['date']).' AND \''.$row['date'].'\''; +// $page['cat_elements_id'] = array_from_query($query, 'id'); +// } +// } + +// +-----------------------------------------------------------------------+ +// | first element to display | +// +-----------------------------------------------------------------------+ + +// $page['start'] contains the number of the first element in its +// category. For exampe, $page['start'] = 12 means we must show elements #12 +// and $page['nb_images'] next elements + +if (!isset($_GET['start']) + or !is_numeric($_GET['start']) + or $_GET['start'] < 0 + or (isset($_GET['display']) and 'all' == $_GET['display'])) +{ + $page['start'] = 0; +} +else +{ + $page['start'] = $_GET['start']; +} + +// +-----------------------------------------------------------------------+ +// | open specific mode | +// +-----------------------------------------------------------------------+ + +$_GET['mode'] = !empty($_GET['mode']) ? $_GET['mode'] : 'global'; + +switch ($_GET['mode']) +{ + case 'global' : + { + include(dirname(__FILE__).'/batch_manager_global.php'); + break; + } + case 'unit' : + { + include(PHPWG_ROOT_PATH.'admin/element_set_unit.php'); + break; + } +} +?> diff --git a/admin/batch_manager_global.php b/admin/batch_manager_global.php new file mode 100644 index 000000000..b78ec1d43 --- /dev/null +++ b/admin/batch_manager_global.php @@ -0,0 +1,575 @@ +<?php +// +-----------------------------------------------------------------------+ +// | Piwigo - a PHP based picture gallery | +// +-----------------------------------------------------------------------+ +// | Copyright(C) 2008-2010 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. | +// +-----------------------------------------------------------------------+ + +/** + * Management of elements set. Elements can belong to a category or to the + * user caddie. + * + */ + +if (!defined('PHPWG_ROOT_PATH')) +{ + die('Hacking attempt!'); +} + +include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); + +// +-----------------------------------------------------------------------+ +// | Check Access and exit when user status is not ok | +// +-----------------------------------------------------------------------+ + +check_status(ACCESS_ADMINISTRATOR); + +trigger_action('loc_begin_element_set_global'); + +// the $_POST['selection'] was already checked in element_set.php +check_input_parameter('del_tags', $_POST, true, PATTERN_ID); +check_input_parameter('associate', $_POST, false, PATTERN_ID); +check_input_parameter('dissociate', $_POST, false, PATTERN_ID); + +// +-----------------------------------------------------------------------+ +// | current selection | +// +-----------------------------------------------------------------------+ + +$collection = array(); +if (isset($_POST['setSelected'])) +{ + $collection = $page['cat_elements_id']; +} +else if (isset($_POST['selection'])) +{ + $collection = $_POST['selection']; +} + +// +-----------------------------------------------------------------------+ +// | global mode form submission | +// +-----------------------------------------------------------------------+ + +if (isset($_POST['submit'])) +{ + // if the user tries to apply an action, it means that there is at least 1 + // photo in the selection + if (count($collection) == 0) + { + array_push($page['errors'], l10n('Select at least one picture')); + } + + $action = $_POST['selectAction']; + + if ('remove_from_caddie' == $action) + { + $query = ' +DELETE + FROM '.CADDIE_TABLE.' + WHERE element_id IN ('.implode(',', $collection).') + AND user_id = '.$user['id'].' +;'; + pwg_query($query); + + // if we are here in the code, it means that the user is currently + // displaying the caddie content, so we have to remove the current + // selection from the current set + $page['cat_elements_id'] = array_diff($page['cat_elements_id'], $collection); + } + + if ('add_tags' == $action) + { + $tag_ids = get_fckb_tag_ids($_POST['add_tags']); + add_tags($tag_ids, $collection); + } + + if ('del_tags' == $action) + { + if (count($_POST['del_tags']) == 0) + { + array_push($page['errors'], l10n('Select at least one tag')); + } + + $query = ' +DELETE + FROM '.IMAGE_TAG_TABLE.' + WHERE image_id IN ('.implode(',', $collection).') + AND tag_id IN ('.implode(',', $_POST['del_tags']).') +;'; + pwg_query($query); + } + + if ('associate' == $action) + { + associate_images_to_categories( + $collection, + array($_POST['associate']) + ); + } + + if ('dissociate' == $action) + { + // physical links must not be broken, so we must first retrieve image_id + // which create virtual links with the category to "dissociate from". + $query = ' +SELECT id + FROM '.IMAGE_CATEGORY_TABLE.' + INNER JOIN '.IMAGES_TABLE.' ON image_id = id + WHERE category_id = '.$_POST['dissociate'].' + AND id IN ('.implode(',', $collection).') + AND ( + category_id != storage_category_id + OR storage_category_id IS NULL + ) +;'; + $dissociables = array_from_query($query, 'id'); + + if (!empty($dissociables)) + { + $query = ' +DELETE + FROM '.IMAGE_CATEGORY_TABLE.' + WHERE category_id = '.$_POST['dissociate'].' + AND image_id IN ('.implode(',', $dissociables).') +'; + pwg_query($query); + + // we remove the dissociated images if we are currently displaying the + // category to dissociate from. + if (is_numeric($_GET['cat']) and $_POST['dissociate'] == $_GET['cat']) + { + $page['cat_elements_id'] = array_diff( + $page['cat_elements_id'], + $dissociables + ); + } + } + + update_category($_POST['dissociate']); + } + + // author + if ('author' == $action) + { + $datas = array(); + foreach ($collection as $image_id) + { + array_push( + $datas, + array( + 'id' => $image_id, + 'author' => $_POST['author'] + ) + ); + } + + mass_updates( + IMAGES_TABLE, + array('primary' => array('id'), 'update' => array('author')), + $datas + ); + } + + // name + if ('name' == $action) + { + $datas = array(); + foreach ($collection as $image_id) + { + array_push( + $datas, + array( + 'id' => $image_id, + 'name' => $_POST['name'] + ) + ); + } + + mass_updates( + IMAGES_TABLE, + array('primary' => array('id'), 'update' => array('name')), + $datas + ); + } + + // date_creation + if ('date_creation' == $action) + { + $date_creation = sprintf( + '%u-%u-%u', + $_POST['date_creation_year'], + $_POST['date_creation_month'], + $_POST['date_creation_day'] + ); + + $datas = array(); + foreach ($collection as $image_id) + { + array_push( + $datas, + array( + 'id' => $image_id, + 'date_creation' => $date_creation + ) + ); + } + + mass_updates( + IMAGES_TABLE, + array('primary' => array('id'), 'update' => array('date_creation')), + $datas + ); + } + + // privacy_level + if ('level' == $action) + { + $datas = array(); + foreach ($collection as $image_id) + { + array_push( + $datas, + array( + 'id' => $image_id, + 'level' => $_POST['level'] + ) + ); + } + + mass_updates( + IMAGES_TABLE, + array('primary' => array('id'), 'update' => array('level')), + $datas + ); + } + + // add_to_caddie + if ('add_to_caddie' == $action) + { + fill_caddie($collection); + } + + // delete + if ('delete' == $action) + { + if (isset($_POST['confirm_deletion']) and 1 == $_POST['confirm_deletion']) + { + // filter selection on photos that have no storage_category_id (ie + // that were added via pLoader) + $query = ' +SELECT id + FROM '.IMAGES_TABLE.' + WHERE id IN ('.implode(',', $collection).') + AND storage_category_id IS NULL +;'; + $deletables = array_from_query($query, 'id'); + + if (count($deletables) > 0) + { + $physical_deletion = true; + delete_elements($deletables, $physical_deletion); + + array_push( + $page['infos'], + sprintf( + l10n_dec( + '%d photo was deleted', + '%d photos were deleted', + count($deletables) + ), + count($deletables) + ) + ); + + // we have to remove the deleted photos from the current set + $page['cat_elements_id'] = array_diff($page['cat_elements_id'], $deletables); + } + else + { + array_push($page['errors'], l10n('No photo can be deleted')); + } + } + else + { + array_push($page['errors'], l10n('You need to confirm deletion')); + } + } +} + +// +-----------------------------------------------------------------------+ +// | template init | +// +-----------------------------------------------------------------------+ +$template->set_filenames(array('batch_manager_global' => 'batch_manager_global.tpl')); + +$base_url = get_root_url().'admin.php'; + +$template->assign( + array( + 'filter' => $_SESSION['bulk_manager_filter'], + + 'selection' => $collection, + + 'U_DISPLAY'=>$base_url.get_query_string_diff(array('display')), + + 'U_UNIT_MODE' + => + $base_url + .get_query_string_diff(array('mode','display')) + .'&mode=unit', + + 'F_ACTION'=>$base_url.get_query_string_diff(array('cat')), + ) + ); + +// +-----------------------------------------------------------------------+ +// | caddie options | +// +-----------------------------------------------------------------------+ + +$in_caddie = false; +if (isset($_SESSION['bulk_manager_filter']['prefilter']) + and 'caddie' == $_SESSION['bulk_manager_filter']['prefilter']) +{ + $in_caddie = true; +} +$template->assign('IN_CADDIE', $in_caddie); + +// +-----------------------------------------------------------------------+ +// | deletion form | +// +-----------------------------------------------------------------------+ + +// we can only remove photos that have no storage_category_id, in other +// word, it currently (Butterfly) means that the photo was added with +// pLoader +if (count($page['cat_elements_id']) > 0) +{ + $query = ' +SELECT + COUNT(*) + FROM '.IMAGES_TABLE.' + WHERE id IN ('.implode(',', $page['cat_elements_id']).') + AND storage_category_id IS NULL +;'; + list($counter) = pwg_db_fetch_row(pwg_query($query)); + + if ($counter > 0) + { + $template->assign('show_delete_form', true); + } +} + +// +-----------------------------------------------------------------------+ +// | global mode form | +// +-----------------------------------------------------------------------+ + +// privacy level +$template->assign( + array( + 'filter_level_options'=> get_privacy_level_options(), + 'filter_level_options_selected' => isset($_SESSION['bulk_manager_filter']['level']) + ? $_SESSION['bulk_manager_filter']['level'] + : 0, + ) + ); + +// Virtualy associate a picture to a category +$query = ' +SELECT id,name,uppercats,global_rank + FROM '.CATEGORIES_TABLE.' +;'; +display_select_cat_wrapper($query, array(), 'associate_options', true); + +// in the filter box, which category to select by default +$selected_category = array(); + +if (isset($_SESSION['bulk_manager_filter']['category'])) +{ + $selected_category = array($_SESSION['bulk_manager_filter']['category']); +} +else +{ + // we need to know the category in which the last photo was added + $selected_category = array(); + + $query = ' +SELECT + category_id, + id_uppercat + FROM '.IMAGES_TABLE.' AS i + JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON image_id = i.id + JOIN '.CATEGORIES_TABLE.' AS c ON category_id = c.id + ORDER BY i.id DESC + LIMIT 1 +;'; + $result = pwg_query($query); + if (pwg_db_num_rows($result) > 0) + { + $row = pwg_db_fetch_assoc($result); + + $selected_category = array($row['category_id']); + } +} + +$query = ' +SELECT id,name,uppercats,global_rank + FROM '.CATEGORIES_TABLE.' +;'; +display_select_cat_wrapper($query, $selected_category, 'filter_category_options', true); + +// Dissociate from a category : categories listed for dissociation can +// only represent virtual links. Links to physical categories can't be +// broken +if (count($page['cat_elements_id']) > 0) +{ + $query = ' +SELECT + DISTINCT(category_id) AS id, + c.name, + c.uppercats, + c.global_rank + FROM '.IMAGE_CATEGORY_TABLE.' AS ic + JOIN '.CATEGORIES_TABLE.' AS c ON c.id = ic.category_id + JOIN '.IMAGES_TABLE.' AS i ON i.id = ic.image_id + WHERE ic.image_id IN ('.implode(',', $page['cat_elements_id']).') + AND ( + ic.category_id != i.storage_category_id + OR i.storage_category_id IS NULL + ) +;'; + display_select_cat_wrapper($query, array(), 'dissociate_options', true); +} + +if (count($page['cat_elements_id']) > 0) +{ + // remove tags + $tags = get_common_tags($page['cat_elements_id'], -1); + + $template->assign( + array( + 'DEL_TAG_SELECTION' => get_html_tag_selection($tags, 'del_tags'), + ) + ); +} + +// creation date +$day = +empty($_POST['date_creation_day']) ? date('j') : $_POST['date_creation_day']; + +$month = +empty($_POST['date_creation_month']) ? date('n') : $_POST['date_creation_month']; + +$year = +empty($_POST['date_creation_year']) ? date('Y') : $_POST['date_creation_year']; + +$month_list = $lang['month']; +$month_list[0]='------------'; +ksort($month_list); +$template->assign( array( + 'month_list' => $month_list, + 'DATE_CREATION_DAY' => (int)$day, + 'DATE_CREATION_MONTH'=> (int)$month, + 'DATE_CREATION_YEAR' => (int)$year, + ) + ); + +// image level options +$template->assign( + array( + 'level_options'=> get_privacy_level_options(), + 'level_options_selected' => 0, + ) + ); + +// +-----------------------------------------------------------------------+ +// | global mode thumbnails | +// +-----------------------------------------------------------------------+ + +// how many items to display on this page +if (!empty($_GET['display'])) +{ + if ('all' == $_GET['display']) + { + $page['nb_images'] = count($page['cat_elements_id']); + } + else + { + $page['nb_images'] = intval($_GET['display']); + } +} +else +{ + $page['nb_images'] = 20; +} + +$nb_thumbs_page = 0; + +if (count($page['cat_elements_id']) > 0) +{ + $nav_bar = create_navigation_bar( + $base_url.get_query_string_diff(array('start')), + count($page['cat_elements_id']), + $page['start'], + $page['nb_images'] + ); + $template->assign('navbar', $nav_bar); + + $query = ' +SELECT id,path,tn_ext,file,filesize,level,name + FROM '.IMAGES_TABLE.' + WHERE id IN ('.implode(',', $page['cat_elements_id']).') + '.$conf['order_by'].' + LIMIT '.$page['nb_images'].' OFFSET '.$page['start'].' +;'; + $result = pwg_query($query); + + // template thumbnail initialization + while ($row = pwg_db_fetch_assoc($result)) + { + $nb_thumbs_page++; + $src = get_thumbnail_url($row); + + $title = $row['name']; + if (empty($title)) + { + $title = get_name_from_file($row['file']); + } + + $template->append( + 'thumbnails', + array( + 'ID' => $row['id'], + 'TN_SRC' => $src, + 'FILE' => $row['file'], + 'TITLE' => $title, + 'LEVEL' => $row['level'] + ) + ); + } +} + +$template->assign( + array( + 'nb_thumbs_page' => $nb_thumbs_page, + 'nb_thumbs_set' => count($page['cat_elements_id']), + ) + ); + +trigger_action('loc_end_element_set_global'); + +//----------------------------------------------------------- sending html code +$template->assign_var_from_handle('ADMIN_CONTENT', 'batch_manager_global'); +?> diff --git a/admin/themes/default/template/admin.tpl b/admin/themes/default/template/admin.tpl index bd6636323..415fbe3ee 100644 --- a/admin/themes/default/template/admin.tpl +++ b/admin/themes/default/template/admin.tpl @@ -25,6 +25,7 @@ jQuery(document).ready(function(){ldelim} <li><a href="{$U_TAGS}">{'Tags'|@translate}</a></li> <li><a href="{$U_CADDIE}">{'Caddie'|@translate}</a></li> <li><a href="{$U_RECENT_SET}">{'Recent pictures'|@translate}</a></li> + <li><a href="{$U_BATCH}">{'Batch Manager'|@translate}</a></li> </ul> </dd> </dl> diff --git a/admin/themes/default/template/batch_manager_global.tpl b/admin/themes/default/template/batch_manager_global.tpl new file mode 100644 index 000000000..7f33c0297 --- /dev/null +++ b/admin/themes/default/template/batch_manager_global.tpl @@ -0,0 +1,580 @@ +{include file='include/tag_selection.inc.tpl'} +{include file='include/datepicker.inc.tpl'} + +{footer_script}{literal} + pwg_initialization_datepicker("#date_creation_day", "#date_creation_month", "#date_creation_year", "#date_creation_linked_date", "#date_creation_action_set"); +{/literal}{/footer_script} + +{combine_script id='jquery.fcbkcomplete' load='footer' require='jquery' path='themes/default/js/plugins/jquery.fcbkcomplete.js'} + +{footer_script require='jquery.fcbkcomplete'}{literal} +jQuery(document).ready(function() { + jQuery("#tags").fcbkcomplete({ + json_url: "admin.php?fckb_tags=1", + cache: false, + filter_case: false, + filter_hide: true, + firstselected: true, + filter_selected: true, + maxitems: 100, + newel: true + }); +}); +{/literal}{/footer_script} + +{footer_script} +var nb_thumbs_page = {$nb_thumbs_page}; +var nb_thumbs_set = {$nb_thumbs_set}; +var applyOnDetails_pattern = "{'on the %d selected photos'|@translate}"; + +var selectedMessage_pattern = "{'%d of %d photos selected'|@translate}"; +var selectedMessage_none = "{'No photo selected, %d photos in current set'|@translate}"; +var selectedMessage_all = "{'All %d photos are selected'|@translate}"; +{literal} +function str_repeat(i, m) { + for (var o = []; m > 0; o[--m] = i); + return o.join(''); +} + +function sprintf() { + var i = 0, a, f = arguments[i++], o = [], m, p, c, x, s = ''; + while (f) { + if (m = /^[^\x25]+/.exec(f)) { + o.push(m[0]); + } + else if (m = /^\x25{2}/.exec(f)) { + o.push('%'); + } + else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) { + if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) { + throw('Too few arguments.'); + } + if (/[^s]/.test(m[7]) && (typeof(a) != 'number')) { + throw('Expecting number but found ' + typeof(a)); + } + switch (m[7]) { + case 'b': a = a.toString(2); break; + case 'c': a = String.fromCharCode(a); break; + case 'd': a = parseInt(a); break; + case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break; + case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break; + case 'o': a = a.toString(8); break; + case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break; + case 'u': a = Math.abs(a); break; + case 'x': a = a.toString(16); break; + case 'X': a = a.toString(16).toUpperCase(); break; + } + a = (/[def]/.test(m[7]) && m[2] && a >= 0 ? '+'+ a : a); + c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' '; + x = m[5] - String(a).length - s.length; + p = m[5] ? str_repeat(c, x) : ''; + o.push(s + (m[4] ? a + p : p + a)); + } + else { + throw('Huh ?!'); + } + f = f.substring(m[0].length); + } + return o.join(''); +} + +$(document).ready(function() { + function checkPermitAction() { + var nbSelected = 0; + if ($("input[name=setSelected]").is(':checked')) { + nbSelected = nb_thumbs_set; + } + else { + $(".thumbnails input[type=checkbox]").each(function() { + if ($(this).is(':checked')) { + nbSelected++; + } + }); + } + + if (nbSelected == 0) { + $("#permitAction").hide(); + $("#forbidAction").show(); + } + else { + $("#permitAction").show(); + $("#forbidAction").hide(); + } + + $("#applyOnDetails").text( + sprintf( + applyOnDetails_pattern, + nbSelected + ) + ); + + // display the number of currently selected photos in the "Selection" fieldset + if (nbSelected == 0) { + $("#selectedMessage").text( + sprintf( + selectedMessage_none, + nb_thumbs_set + ) + ); + } + else if (nbSelected == nb_thumbs_set) { + $("#selectedMessage").text( + sprintf( + selectedMessage_all, + nb_thumbs_set + ) + ); + } + else { + $("#selectedMessage").text( + sprintf( + selectedMessage_pattern, + nbSelected, + nb_thumbs_set + ) + ); + } + } + + $('img.thumbnail').tipTip({ + 'delay' : 0, + 'fadeIn' : 200, + 'fadeOut' : 200, + }); + + $("[id^=action_]").hide(); + + $("select[name=selectAction]").click(function () { + $("[id^=action_]").hide(); + $("#action_"+$(this).attr("value")).show(); + }); + + $(".wrap1 label").click(function () { + $("input[name=setSelected]").attr('checked', false); + + var wrap2 = $(this).children(".wrap2"); + var checkbox = $(this).children("input[type=checkbox]"); + + if ($(checkbox).is(':checked')) { + $(wrap2).addClass("thumbSelected"); + } + else { + $(wrap2).removeClass('thumbSelected'); + } + + checkPermitAction(); + }); + + $("#selectAll").click(function () { + $(".thumbnails label").each(function() { + var wrap2 = $(this).children(".wrap2"); + var checkbox = $(this).children("input[type=checkbox]"); + + $(checkbox).attr('checked', true); + $(wrap2).addClass("thumbSelected"); + }); + + if (nb_thumbs_page < nb_thumbs_set) { + $("#selectSetMessage").show(); + } + + checkPermitAction(); + + return false; + }); + + $("#selectNone").click(function () { + $("input[name=setSelected]").attr('checked', false); + + $(".thumbnails label").each(function() { + var wrap2 = $(this).children(".wrap2"); + var checkbox = $(this).children("input[type=checkbox]"); + + $(checkbox).attr('checked', false); + $(wrap2).removeClass("thumbSelected"); + }); + checkPermitAction(); + return false; + }); + + $("#selectInvert").click(function () { + $("#selectSetMessage").hide(); + $("input[name=setSelected]").attr('checked', false); + + $(".thumbnails label").each(function() { + var wrap2 = $(this).children(".wrap2"); + var checkbox = $(this).children("input[type=checkbox]"); + + $(checkbox).attr('checked', !$(checkbox).is(':checked')); + + if ($(checkbox).is(':checked')) { + $(wrap2).addClass("thumbSelected"); + } + else { + $(wrap2).removeClass('thumbSelected'); + } + }); + checkPermitAction(); + return false; + }); + + $("#selectSet").click(function () { + $("input[name=setSelected]").attr('checked', true); + checkPermitAction(); + return false; + }); + + $("input[name=remove_author]").click(function () { + if ($(this).is(':checked')) { + $("input[name=author]").hide(); + } + else { + $("input[name=author]").show(); + } + }); + + $("input[name=remove_name]").click(function () { + if ($(this).is(':checked')) { + $("input[name=name]").hide(); + } + else { + $("input[name=name]").show(); + } + }); + + $("input[name=remove_date_creation]").click(function () { + if ($(this).is(':checked')) { + $("#set_date_creation").hide(); + } + else { + $("#set_date_creation").show(); + } + }); + + $("select[name=selectAction]").change(function() { + if ($(this).val() != -1) { + $("#applyActionBlock").show(); + } + else { + $("#applyActionBlock").hide(); + } + }); + + $(".removeFilter").click(function () { + var filter = $(this).parent('li').attr("id"); + filter_disable(filter); + + return false; + }); + + function filter_enable(filter) { + /* show the filter*/ + $("#"+filter).show(); + + /* check the checkbox to declare we use this filter */ + $("input[type=checkbox][name="+filter+"_use]").attr("checked", true); + + /* forbid to select this filter in the addFilter list */ + $("#addFilter").children("option[value="+filter+"]").attr("disabled", "disabled"); + } + + $("#addFilter").change(function () { + var filter = $(this).attr("value"); + filter_enable(filter); + $(this).attr("value", -1); + }); + + function filter_disable(filter) { + /* hide the filter line */ + $("#"+filter).hide(); + + /* uncheck the checkbox to declare we do not use this filter */ + $("input[name="+filter+"_use]").removeAttr("checked"); + + /* give the possibility to show it again */ + $("#addFilter").children("option[value="+filter+"]").removeAttr("disabled"); + } + + $("#removeFilters").click(function() { + $("#filterList li").each(function() { + var filter = $(this).attr("id"); + filter_disable(filter); + }); + return false; + }); + + checkPermitAction() +}); +{/literal}{/footer_script} + +{literal} +<style> +#action p {text-align:left;} +.bulkAction {text-align:left;margin:15px 0;padding:0;} +#action_del_tags ul.tagSelection {margin:0 !important; width:620px;} +#selectAction {} +#checkActions {text-align:left; margin:0 0 20px 0;} +.content ul.thumbnails span.wrap1 {margin:5px} +.content ul.thumbnails span.wrap2 {border:0;background-color:#ddd;} +.content ul.thumbnails span.wrap2:hover {background-color:#7CBA0F;} +.thumbSelected {background-color:#C2F5C2 !important} + +#selectedMessage {background-color:#C2F5C2; padding:5px; -moz-border-radius:5px;} +#selectSet a {border-bottom:1px dotted} +#applyOnDetails {font-style:italic;} + +.actionButtons {text-align:left;} +#filterList {padding-left:5px;} +#filterList li {margin-bottom:5px; list-style-type:none;} +a.removeFilter {background: url(plugins/bulk_manager/remove_filter.png) no-repeat top left;width:7px;height:7px;display:inline-block} +a.removeFilter:hover {background: url(plugins/bulk_manager/remove_filter_hover.png); border:none;} +.removeFilter span {display:none} +#applyFilterBlock {margin-top:20px;} +.useFilterCheckbox {display:none} +</style> +{/literal} + + <p style="float:left; font-size:90%;margin:5px 0 0 0;padding:0;"> + <a href="{$U_UNIT_MODE}">Switch to unit mode</a> + </p> + +<h2>{'Batch manager'|@translate}</h2> + + <form action="{$F_ACTION}" method="post"> + + <fieldset> + <legend>{'Filter'|@translate}</legend> + + <ul id="filterList"> + <li id="filter_prefilter" {if !isset($filter.prefilter)}style="display:none"{/if}> + <a href="#" class="removeFilter" title="remove this filter"><span>[x]</span></a> + <input type="checkbox" name="filter_prefilter_use" class="useFilterCheckbox" {if isset($filter.prefilter)}checked="checked"{/if}> + predefined filter + <select name="filter_prefilter"> + <option value="caddie" {if $filter.prefilter eq 'caddie'}selected="selected"{/if}>caddie</option> + <option value="last import" {if $filter.prefilter eq 'last import'}selected="selected"{/if}>last import</option> +<!-- <option value="with no album">with no album</option> --> +<!-- <option value="with no virtual album">with no virtual album</option> --> +<!-- <option value="with no tag">with no tag</option> --> + </select> + </li> + <li id="filter_category" {if !isset($filter.category)}style="display:none"{/if}> + <a href="#" class="removeFilter" title="remove this filter"><span>[x]</span></a> + <input type="checkbox" name="filter_category_use" class="useFilterCheckbox" {if isset($filter.category)}checked="checked"{/if}> + album + <select style="width:400px" name="filter_category" size="1"> + {html_options options=$filter_category_options selected=$filter_category_options_selected} + </select> + <label><input type="checkbox" name="filter_category_recursive" {if isset($filter.category_recursive)}checked="checked"{/if}> {'include child albums'|@translate}</label> + </li> + <li id="filter_level" {if !isset($filter.level)}style="display:none"{/if}> + <a href="#" class="removeFilter" title="remove this filter"><span>[x]</span></a> + <input type="checkbox" name="filter_level_use" class="useFilterCheckbox" {if isset($filter.level)}checked="checked"{/if}> + {'Who can see these photos?'|@translate} + <select name="filter_level" size="1"> + {html_options options=$filter_level_options selected=$filter_level_options_selected} + </select> + </li> + </ul> + + <p class="actionButtons" style=""> + <select id="addFilter"> + <option value="-1">Add a filter</option> + <option disabled="disabled">------------------</option> + <option value="filter_prefilter">predefined filter</option> + <option value="filter_category">album</option> + <option value="filter_level">{'Who can see these photos?'|@translate}</option> + </select> +<!-- <input id="removeFilters" class="submit" type="submit" value="Remove all filters" name="removeFilters"> --> + <a id="removeFilters" href="">Remove all filters</a> + </p> + + <p class="actionButtons" id="applyFilterBlock"> + <input id="applyFilter" class="submit" type="submit" value="Refresh photo set" name="submitFilter"> + </p> + + </fieldset> + + <fieldset> + + <legend>{'Selection'|@translate}</legend> + + {if !empty($thumbnails)} + <p id="checkActions"> + {'Select:'|@translate} + <a href="#" id="selectAll">{'All'|@translate}</a> + (<a href="#" id="selectSet">or the whole set</a>), + <a href="#" id="selectNone">{'None'|@translate}</a>, + <a href="#" id="selectInvert">{'Invert'|@translate}</a> + + <span id="selectedMessage"></span> + + <input type="checkbox" name="setSelected" style="display:none" {if count($selection) == $nb_thumbs_set}checked="checked"{/if}> + </p> + + <ul class="thumbnails"> + {foreach from=$thumbnails item=thumbnail} + {if in_array($thumbnail.ID, $selection)} + {assign var='isSelected' value=true} + {else} + {assign var='isSelected' value=false} + {/if} + + <li><span class="wrap1"> + <label> + <span class="wrap2{if $isSelected} thumbSelected{/if}"> + {if $thumbnail.LEVEL > 0} + <em class="levelIndicatorB">{$pwg->l10n($pwg->sprintf('Level %d',$thumbnail.LEVEL))}</em> + <em class="levelIndicatorF" title="{'Who can see these photos?'|@translate} : ">{$pwg->l10n($pwg->sprintf('Level %d',$thumbnail.LEVEL))}</em> + {/if} + <span> + <img src="{$thumbnail.TN_SRC}" + alt="{$thumbnail.FILE}" + title="{$thumbnail.TITLE|@escape:'html'}" + class="thumbnail"> + </span></span> + <input type="checkbox" name="selection[]" value="{$thumbnail.ID}" {if $isSelected}checked="checked"{/if}> + </label> + </span> + </li> + {/foreach} + </ul> + + {if !empty($navbar) } + <div style="clear:both;"> + + <div style="float:left"> + {include file='navigation_bar.tpl'|@get_extent:'navbar'} + </div> + + <div style="float:right;margin-top:10px;">{'display'|@translate} + <a href="{$U_DISPLAY}&display=20">20</a> + · <a href="{$U_DISPLAY}&display=50">50</a> + · <a href="{$U_DISPLAY}&display=100">100</a> + · <a href="{$U_DISPLAY}&display=all">{'all'|@translate}</a> + thumbnails per page + </div> + </div> + {/if} + + {else} + <div>No photo in the current set.</div> + {/if} + </fieldset> + + <fieldset id="action"> + + <legend>{'Action'|@translate}</legend> + <div id="forbidAction"{if count($selection) != 0}style="display:none"{/if}>No photo selected, no action possible.</div> + <div id="permitAction"{if count($selection) == 0}style="display:none"{/if}> + + <select name="selectAction"> + <option value="-1">Choose an action</option> + <option disabled="disabled">------------------</option> + {if isset($show_delete_form) } + <option value="delete">{'Delete selected photos'|@translate}</option> + {/if} + <option value="associate">{'associate to category'|@translate}</option> + {if !empty($dissociate_options)} + <option value="dissociate">{'dissociate from category'|@translate}</option> + {/if} + <option value="add_tags">{'add tags'|@translate}</option> + {if !empty($DEL_TAG_SELECTION)} + <option value="del_tags">{'remove tags'|@translate}</option> + {/if} + <option value="author">{'Set author'|@translate}</option> + <option value="name">{'Set title'|@translate}</option> + <option value="date_creation">{'Set creation date'|@translate}</option> + <option value="level">{'Who can see these photos?'|@translate}</option> + {if ($IN_CADDIE)} + <option value="remove_from_caddie">{'Remove from caddie'|@translate}</option> + {else} + <option value="add_to_caddie">{'Add to caddie'|@translate}</option> + {/if} + </select> + + <!-- delete --> + <div id="action_delete" class="bulkAction"> +{if $ENABLE_SYNCHRONIZATION} + <p style="font-style:italic;width:500px;">{'Note: photo deletion does not apply to photos added by synchronization. For photos added by synchronization, remove them from the filesystem and then perform another synchronization.'|@translate}</p> +{/if} + <p><label><input type="checkbox" name="confirm_deletion" value="1"> {'Are you sure?'|@translate}</label></p> + </div> + + <!-- associate --> + <div id="action_associate" class="bulkAction"> + <select style="width:400px" name="associate" size="1"> + {html_options options=$associate_options } + </select> + </div> + + <!-- dissociate --> + <div id="action_dissociate" class="bulkAction"> + <select style="width:400px" name="dissociate" size="1"> + {if !empty($dissociate_options)}{html_options options=$dissociate_options }{/if} + </select> + </div> + + + <!-- add_tags --> + <div id="action_add_tags" class="bulkAction"> +<select id="tags" name="add_tags"> +</select> + </div> + + <!-- del_tags --> + <div id="action_del_tags" class="bulkAction"> +{$DEL_TAG_SELECTION} + </div> + + <!-- author --> + <div id="action_author" class="bulkAction"> + <label><input type="checkbox" name="remove_author"> remove author</label><br> + {assign var='authorDefaultValue' value='Type here the author name'} +<input type="text" class="large" name="author" value="{$authorDefaultValue}" onfocus="this.value=(this.value=='{$authorDefaultValue}') ? '' : this.value;" onblur="this.value=(this.value=='') ? '{$authorDefaultValue}' : this.value;"> + </div> + + <!-- name --> + <div id="action_name" class="bulkAction"> + <label><input type="checkbox" name="remove_name"> remove name</label><br> + {assign var='nameDefaultValue' value='Type here the name name'} +<input type="text" class="large" name="name" value="{$nameDefaultValue}" onfocus="this.value=(this.value=='{$nameDefaultValue}') ? '' : this.value;" onblur="this.value=(this.value=='') ? '{$nameDefaultValue}' : this.value;"> + </div> + + <!-- date_creation --> + <div id="action_date_creation" class="bulkAction"> + <label><input type="checkbox" name="remove_date_creation"> remove creation date</label><br> + <div id="set_date_creation"> + <select id="date_creation_day" name="date_creation_day"> + <option value="0">--</option> + {section name=day start=1 loop=32} + <option value="{$smarty.section.day.index}" {if $smarty.section.day.index==$DATE_CREATION_DAY}selected="selected"{/if}>{$smarty.section.day.index}</option> + {/section} + </select> + <select id="date_creation_month" name="date_creation_month"> + {html_options options=$month_list selected=$DATE_CREATION_MONTH} + </select> + <input id="date_creation_year" + name="date_creation_year" + type="text" + size="4" + maxlength="4" + value="{$DATE_CREATION_YEAR}"> + <input id="date_creation_linked_date" name="date_creation_linked_date" type="hidden" size="10" disabled="disabled"> + </div> + </div> + + <!-- level --> + <div id="action_level" class="bulkAction"> + <select name="level" size="1"> + {html_options options=$level_options selected=$level_options_selected} + </select> + </div> + + <p id="applyActionBlock" style="display:none" class="actionButtons"> + <input id="applyAction" class="submit" type="submit" value="{'Apply action'|@translate}" name="submit" {$TAG_INPUT_ENABLED}> <span id="applyOnDetails"></span></p> + + </div> <!-- #permitAction --> + </fieldset> + + </form> |