diff options
44 files changed, 1848 insertions, 353 deletions
@@ -92,6 +92,7 @@ $template->assign_vars( 'U_COMMENTS'=> $link_start.'comments', 'U_RATING'=> $link_start.'rating', 'U_CADDIE'=> $link_start.'element_set&cat=caddie', + 'U_TAGS'=> $link_start.'tags', 'U_THUMBNAILS'=> $link_start.'thumbnail', 'U_USERS'=> $link_start.'user_list', 'U_GROUPS'=> $link_start.'group_list', diff --git a/admin/element_set_global.php b/admin/element_set_global.php index 61ef2d6ee..f4b8aae2b 100644 --- a/admin/element_set_global.php +++ b/admin/element_set_global.php @@ -44,40 +44,6 @@ include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); check_status(ACCESS_ADMINISTRATOR); // +-----------------------------------------------------------------------+ -// | functions | -// +-----------------------------------------------------------------------+ - -/** - * returns the list of uniq keywords among given elements - * - * @param array element_ids - */ -function get_elements_keywords($element_ids) -{ - if (0 == count($element_ids)) - { - return array(); - } - - $keywords = array(); - - $query = ' -SELECT keywords - FROM '.IMAGES_TABLE.' - WHERE id IN ('.implode(',', $element_ids).') -;'; - $result = pwg_query($query); - while ($row = mysql_fetch_array($result)) - { - if (isset($row['keywords']) and !empty($row['keywords'])) - { - $keywords = array_merge($keywords, explode(',', $row['keywords'])); - } - } - return array_unique($keywords); -} - -// +-----------------------------------------------------------------------+ // | global mode form submission | // +-----------------------------------------------------------------------+ @@ -111,6 +77,22 @@ if (isset($_POST['submit'])) } } + if (isset($_POST['add_tags']) and count($collection) > 0) + { + add_tags($_POST['add_tags'], $collection); + } + + if (isset($_POST['del_tags']) and count($collection) > 0) + { + $query = ' +DELETE + FROM '.IMAGE_TAG_TABLE.' + WHERE image_id IN ('.implode(',', $collection).') + AND tag_id IN ('.implode(',', $_POST['del_tags']).') +;'; + pwg_query($query); + } + if ($_POST['associate'] != 0 and count($collection) > 0) { $datas = array(); @@ -192,11 +174,6 @@ DELETE $datas = array(); $dbfields = array('primary' => array('id'), 'update' => array()); - if (!empty($_POST['add_keywords']) or $_POST['remove_keyword'] != '0') - { - array_push($dbfields['update'], 'keywords'); - } - $formfields = array('author', 'name', 'date_creation'); foreach ($formfields as $formfield) { @@ -210,7 +187,7 @@ DELETE if (count($dbfields['update']) > 0 and count($collection) > 0) { $query = ' -SELECT id, keywords +SELECT id FROM '.IMAGES_TABLE.' WHERE id IN ('.implode(',', $collection).') ;'; @@ -221,44 +198,6 @@ SELECT id, keywords $data = array(); $data['id'] = $row['id']; - if (!empty($_POST['add_keywords'])) - { - $data['keywords'] = - implode( - ',', - array_unique( - array_merge( - get_keywords(empty($row['keywords']) ? '' : $row['keywords']), - get_keywords($_POST['add_keywords']) - ) - ) - ); - } - - if ($_POST['remove_keyword'] != '0') - { - if (!isset($data['keywords'])) - { - $data['keywords'] = empty($row['keywords']) ? '' : $row['keywords']; - } - - $data['keywords'] = - implode( - ',', - array_unique( - array_diff( - get_keywords($data['keywords']), - array($_POST['remove_keyword']) - ) - ) - ); - - if ($data['keywords'] == '') - { - unset($data['keywords']); - } - } - if ('set' == $_POST['author_action']) { $data['author'] = $_POST['author']; @@ -384,25 +323,36 @@ SELECT DISTINCT(category_id) AS id, c.name, uppercats, global_rank display_select_cat_wrapper($query, array(), $blockname, true); } -$blockname = 'remove_keyword_option'; - -$template->assign_block_vars( - $blockname, - array('VALUE'=> 0, - 'OPTION' => '------------' - )); +// add tags +$template->assign_vars( + array( + 'ADD_TAG_SELECTION' => get_html_tag_selection(get_all_tags(), 'add_tags'), + ) + ); -$keywords = get_elements_keywords($page['cat_elements_id']); +// remove tags +$query = ' +SELECT tag_id, name, url_name, count(*) counter + FROM '.IMAGE_TAG_TABLE.' + INNER JOIN '.TAGS_TABLE.' ON tag_id = id + WHERE image_id IN ('.implode(',', $page['cat_elements_id']).') + GROUP BY tag_id + ORDER BY name ASC +;'; +$result = pwg_query($query); -foreach ($keywords as $keyword) +$tags = array(); +while($row = mysql_fetch_array($result)) { - $template->assign_block_vars( - $blockname, - array('VALUE'=> $keyword, - 'OPTION' => $keyword - )); + array_push($tags, $row); } +$template->assign_vars( + 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']; diff --git a/admin/element_set_unit.php b/admin/element_set_unit.php index c43522894..f6800f399 100644 --- a/admin/element_set_unit.php +++ b/admin/element_set_unit.php @@ -103,25 +103,21 @@ SELECT id, date_creation { $data{'date_creation'} = $row['date_creation']; } + + array_push($datas, $data); - $keywords = get_keywords($_POST['keywords-'.$row['id']]); - if (count($keywords) > 0) - { - $data{'keywords'} = implode(',', $keywords); - } - else + // tags management + if (isset($_POST[ 'tags-'.$row['id'] ])) { - $data{'keywords'} = ''; + set_tags($_POST[ 'tags-'.$row['id'] ], $row['id']); } - - array_push($datas, $data); } mass_updates( IMAGES_TABLE, array( 'primary' => array('id'), - 'update' => array('name','author','comment','date_creation','keywords') + 'update' => array('name','author','comment','date_creation') ), $datas ); @@ -192,11 +188,13 @@ if (count($page['cat_elements_id']) > 0) ); $template->assign_vars(array('NAV_BAR' => $nav_bar)); + // tags + $all_tags = get_all_tags(); $element_ids = array(); $query = ' -SELECT id,path,tn_ext,name,date_creation,comment,keywords,author,file +SELECT id,path,tn_ext,name,date_creation,comment,author,file FROM '.IMAGES_TABLE.' WHERE id IN ('.implode(',', $page['cat_elements_id']).') '.$conf['order_by'].' @@ -210,6 +208,13 @@ SELECT id,path,tn_ext,name,date_creation,comment,keywords,author,file array_push($element_ids, $row['id']); $src = get_thumbnail_src($row['path'], @$row['tn_ext']); + + $query = ' +SELECT tag_id + FROM '.IMAGE_TAG_TABLE.' + WHERE image_id = '.$row['id'].' +;'; + $selected_tags = array_from_query($query, 'tag_id'); // creation date if (!empty($row['date_creation'])) @@ -237,7 +242,12 @@ SELECT id,path,tn_ext,name,date_creation,comment,keywords,author,file 'AUTHOR' => @$row['author'], 'DESCRIPTION' => @$row['comment'], 'DATE_CREATION_YEAR' => $year, - 'KEYWORDS' => @$row['keywords'] + + 'TAG_SELECTION' => get_html_tag_selection( + $all_tags, + 'tags-'.$row['id'], + $selected_tags + ), ) ); diff --git a/admin/include/functions.php b/admin/include/functions.php index dc477f6d1..3a8c6b506 100644 --- a/admin/include/functions.php +++ b/admin/include/functions.php @@ -269,6 +269,14 @@ DELETE FROM '.IMAGE_CATEGORY_TABLE.' ;'; 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.' @@ -577,25 +585,6 @@ function date_convert_back( $date ) } /** - * returns an array with relevant keywords found in the given string. - * - * Keywords must be separated by comma or space characters. - * - * @param string keywords_string - * @return array - */ -function get_keywords($keywords_string) -{ - return - array_unique( - preg_split( - '/[\s,]+/', - $keywords_string - ) - ); -} - -/** * returns an array containing sub-directories which can be a category, * recursive by default * @@ -2094,6 +2083,173 @@ UPDATE } /** + * 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; + + if (isset($page['tag_id_from_tag_name_cache'][$tag_name])) + { + return $page['tag_id_from_tag_name_cache'][$tag_name]; + } + + if (function_exists('mysql_real_escape_string')) + { + $tag_name = mysql_real_escape_string($tag_name); + } + else + { + $tag_name = mysql_escape_string($tag_name); + } + + // does the tag already exist? + $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 @@ -2143,6 +2299,4 @@ function do_maintenance_all_tables() pwg_query($query); } - - ?> diff --git a/admin/include/functions_metadata.php b/admin/include/functions_metadata.php index 337019b2e..21897c2cd 100644 --- a/admin/include/functions_metadata.php +++ b/admin/include/functions_metadata.php @@ -50,10 +50,7 @@ function get_sync_iptc_data($file) if (isset($iptc['keywords'])) { - // keywords separator is the comma, nothing else. Allowed characters in - // keywords : [A-Za-z0-9], "-" and "_". All other characters will be - // considered as separators - $iptc['keywords'] = preg_replace('/[^\w-]+/', ',', $iptc['keywords']); + // keywords separator is the comma $iptc['keywords'] = preg_replace('/^,+|,+$/', '', $iptc['keywords']); } @@ -90,6 +87,7 @@ function update_metadata($files) } $datas = array(); + $tags_of = array(); foreach ($files as $id => $file) { @@ -123,7 +121,25 @@ function update_metadata($files) { foreach (array_keys($iptc) as $key) { - $data[$key] = addslashes($iptc[$key]); + if ($key == 'keywords' or $key == 'tags') + { + if (!isset($tags_of[$id])) + { + $tags_of[$id] = array(); + } + + foreach (explode(',', $iptc[$key]) as $tag_name) + { + array_push( + $tags_of[$id], + tag_id_from_tag_name($tag_name) + ); + } + } + else + { + $data[$key] = addslashes($iptc[$key]); + } } } } @@ -157,7 +173,10 @@ function update_metadata($files) $update_fields = array_merge( $update_fields, - array_keys($conf['use_iptc_mapping']) + array_diff( + array_keys($conf['use_iptc_mapping']), + array('tags', 'keywords') + ) ); } @@ -166,8 +185,11 @@ function update_metadata($files) 'primary' => array('id'), 'update' => array_unique($update_fields) ); + echo '<pre>'; print_r($datas); echo '</pre>'; mass_updates(IMAGES_TABLE, $fields, $datas); } + + set_tags_of(tags_of); } /** diff --git a/admin/picture_modify.php b/admin/picture_modify.php index be7497a07..83bf09a23 100644 --- a/admin/picture_modify.php +++ b/admin/picture_modify.php @@ -100,16 +100,6 @@ if (isset($_POST['submit']) and count($page['errors']) == 0) } } - $keywords = get_keywords($_POST['keywords']); - if (count($keywords) > 0) - { - $data{'keywords'} = implode(',', $keywords); - } - else - { - $data{'keywords'} = ''; - } - mass_updates( IMAGES_TABLE, array( @@ -119,6 +109,11 @@ if (isset($_POST['submit']) and count($page['errors']) == 0) array($data) ); + set_tags( + isset($_POST['tags']) ? $_POST['tags'] : array(), + $_GET['image_id'] + ); + array_push($page['infos'], l10n('Picture informations updated')); } // associate the element to other categories than its storage category @@ -215,6 +210,14 @@ $row = mysql_fetch_array(pwg_query($query)); $storage_category_id = $row['category_id']; $image_file = $row['file']; +// tags +$query = ' +SELECT tag_id + FROM '.IMAGE_TAG_TABLE.' + WHERE image_id = '.$_GET['image_id'].' +;'; +$selected_tags = array_from_query($query, 'tag_id'); + // Navigation path $date = isset($_POST['date_creation']) && empty($page['errors']) @@ -257,9 +260,11 @@ $template->assign_vars( 'CREATION_DATE' => $date, - 'KEYWORDS' => - isset($_POST['keywords']) ? - stripslashes($_POST['keywords']) : @$row['keywords'], + 'TAG_SELECTION' => get_html_tag_selection( + get_all_tags(), + 'tags', + $selected_tags + ), 'DESCRIPTION' => isset($_POST['description']) ? diff --git a/admin/site_update.php b/admin/site_update.php index b68ce2b28..c7c31106c 100644 --- a/admin/site_update.php +++ b/admin/site_update.php @@ -715,6 +715,7 @@ if (isset($_POST['submit']) and preg_match('/^metadata/', $_POST['sync']) $start = get_moment(); $datas = array(); + $tags_of = array(); foreach ( $files as $id=>$file ) { $data = $site_reader->get_element_update_attributes($file); @@ -723,23 +724,55 @@ if (isset($_POST['submit']) and preg_match('/^metadata/', $_POST['sync']) $data['date_metadata_update'] = CURRENT_DATE; $data['id']=$id; array_push($datas, $data); + + foreach (array('keywords', 'tags') as $key) + { + if (isset($data[$key])) + { + if (!isset($tags_of[$id])) + { + $tags_of[$id] = array(); + } + + foreach (explode(',', $data[$key]) as $tag_name) + { + array_push( + $tags_of[$id], + tag_id_from_tag_name($tag_name) + ); + } + } + } } else { array_push($errors, array('path' => $file, 'type' => 'PWG-ERROR-NO-FS')); } } - $update_fields = $site_reader->get_update_attributes(); - $update_fields = array_merge($update_fields, array('date_metadata_update')); - $fields = - array( - 'primary' => array('id'), - 'update' => array_unique($update_fields) - ); - //print_r($datas); - if (!$simulate and count($datas)>0 ) + + if (!$simulate) { - mass_updates(IMAGES_TABLE, $fields, $datas); + if (count($datas) > 0) + { + mass_updates( + IMAGES_TABLE, + // fields + array( + 'primary' => array('id'), + 'update' => array_unique( + array_merge( + array_diff( + $site_reader->get_update_attributes(), + // keywords and tags fields are managed separately + array('keywords', 'tags') + ), + array('date_metadata_update')) + ) + ), + $datas + ); + } + set_tags_of($tags_of); } echo '<!-- metadata update : '; diff --git a/admin/tags.php b/admin/tags.php new file mode 100644 index 000000000..7ff29727c --- /dev/null +++ b/admin/tags.php @@ -0,0 +1,265 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net | +// | Copyright (C) 2003-2005 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $RCSfile$ +// | last update : $Date: 2006-03-09 23:46:28 +0100 (jeu, 09 mar 2006) $ +// | last modifier : $Author: rub $ +// | revision : $Revision: 1072 $ +// +-----------------------------------------------------------------------+ +// | 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. | +// +-----------------------------------------------------------------------+ + +if( !defined("PHPWG_ROOT_PATH") ) +{ + die ("Hacking attempt!"); +} + +include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); +check_status(ACCESS_ADMINISTRATOR); + +// +-----------------------------------------------------------------------+ +// | edit tags | +// +-----------------------------------------------------------------------+ + +if (isset($_POST['submit'])) +{ + $query = ' +SELECT name + FROM '.TAGS_TABLE.' +;'; + $existing_names = array_from_query($query, 'name'); + + + $current_name_of = array(); + $query = ' +SELECT id, name + FROM '.TAGS_TABLE.' + WHERE id IN ('.$_POST['edit_list'].') +;'; + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + $current_name_of[ $row['id'] ] = $row['name']; + } + + $updates = array(); + // we must not rename tag with an already existing name + foreach (explode(',', $_POST['edit_list']) as $tag_id) + { + if (function_exists('mysql_real_escape_string')) + { + $tag_name = mysql_real_escape_string($_POST['tag_name-'.$tag_id]); + } + else + { + $tag_name = mysql_escape_string($_POST['tag_name-'.$tag_id]); + } + + if ($tag_name != $current_name_of[$tag_id]) + { + if (in_array($tag_name, $existing_names)) + { + array_push( + $page['errors'], + sprintf( + l10n('Tag "%s" already exist'), + $tag_name + ) + ); + } + else if (!empty($tag_name)) + { + array_push( + $updates, + array( + 'id' => $tag_id, + 'name' => $tag_name, + 'url_name' => str2url($tag_name), + ) + ); + } + } + } + mass_updates( + TAGS_TABLE, + array( + 'primary' => array('id'), + 'update' => array('name', 'url_name'), + ), + $updates + ); +} + +// +-----------------------------------------------------------------------+ +// | delete tags | +// +-----------------------------------------------------------------------+ + +if (isset($_POST['delete']) and isset($_POST['tags'])) +{ + $query = ' +SELECT name + FROM '.TAGS_TABLE.' + WHERE id IN ('.implode(',', $_POST['tags']).') +;'; + $tag_names = array_from_query($query, 'name'); + + $query = ' +DELETE + FROM '.IMAGE_TAG_TABLE.' + WHERE tag_id IN ('.implode(',', $_POST['tags']).') +;'; + pwg_query($query); + + $query = ' +DELETE + FROM '.TAGS_TABLE.' + WHERE id IN ('.implode(',', $_POST['tags']).') +;'; + pwg_query($query); + + array_push( + $page['infos'], + sprintf( + l10n('The %d following tags were deleted : %s'), + count($tag_names), + implode(', ', $tag_names) + ) + ); +} + +// +-----------------------------------------------------------------------+ +// | add a tag | +// +-----------------------------------------------------------------------+ + +if (isset($_POST['add_tag']) and !empty($_POST['add_tag'])) +{ + if (function_exists('mysql_real_escape_string')) + { + $tag_name = mysql_real_escape_string($_POST['add_tag']); + } + else + { + $tag_name = mysql_escape_string($_POST['add_tag']); + } + + // does the tag already exist? + $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), + ) + ) + ); + + array_push( + $page['infos'], + sprintf( + l10n('Tag "%s" was added'), + $tag_name + ) + ); + } + else + { + array_push( + $page['errors'], + sprintf( + l10n('Tag "%s" already exist'), + $tag_name + ) + ); + } +} + +// +-----------------------------------------------------------------------+ +// | template init | +// +-----------------------------------------------------------------------+ + +$template->set_filenames(array('tags' => 'admin/tags.tpl')); + +$template->assign_vars( + array( + 'F_ACTION' => PHPWG_ROOT_PATH.'admin.php?page=tags' + ) + ); + +// +-----------------------------------------------------------------------+ +// | form creation | +// +-----------------------------------------------------------------------+ + +$template->assign_vars( + array( + 'TAG_SELECTION' => get_html_tag_selection( + get_all_tags(), + 'tags' + ), + ) + ); + +if (isset($_POST['edit']) and isset($_POST['tags'])) +{ + $template->assign_block_vars( + 'edit_tags', + array( + 'LIST' => implode(',', $_POST['tags']), + ) + ); + + $query = ' +SELECT id, name + FROM '.TAGS_TABLE.' + WHERE id IN ('.implode(',', $_POST['tags']).') +;'; + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + $name_of[ $row['id'] ] = $row['name']; + } + + foreach ($_POST['tags'] as $tag_id) + { + $template->assign_block_vars( + 'edit_tags.tag', + array( + 'ID' => $tag_id, + 'NAME' => $name_of[$tag_id], + ) + ); + } +} + +// +-----------------------------------------------------------------------+ +// | sending html code | +// +-----------------------------------------------------------------------+ + +$template->assign_var_from_handle('ADMIN_CONTENT', 'tags'); + +?> diff --git a/include/category_default.inc.php b/include/category_default.inc.php index 31d40ed90..6c909647a 100644 --- a/include/category_default.inc.php +++ b/include/category_default.inc.php @@ -79,7 +79,7 @@ foreach ($pictures as $row) { $thumbnail_title .= ' : '.$row['filesize'].' KB'; } - + // link on picture.php page $url = duplicate_picture_url( array( diff --git a/include/common.inc.php b/include/common.inc.php index 42697353e..f66d1ee7f 100644 --- a/include/common.inc.php +++ b/include/common.inc.php @@ -148,6 +148,7 @@ SELECT id if (count(array_diff($existing, $applied)) > 0) { ob_start();// buffer output so that cookies work + echo '<p>' .'Some database upgrades are missing, ' diff --git a/include/config_default.inc.php b/include/config_default.inc.php index 3675f2ed6..57a4520c3 100644 --- a/include/config_default.inc.php +++ b/include/config_default.inc.php @@ -439,6 +439,18 @@ $conf['picture_url_style'] = 'id'; $conf['php_extension_in_urls'] = true; // +-----------------------------------------------------------------------+ +// | tags | +// +-----------------------------------------------------------------------+ + +// full_tag_cloud_items_number: number of tags to show in the full tag +// cloud. Only the most represented tags will be shown +$conf['full_tag_cloud_items_number'] = 200; + +// tags_levels: number of levels to use for display. Each level is bind to a +// CSS class tagLevelX. +$conf['tags_levels'] = 10; + +// +-----------------------------------------------------------------------+ // | Notification by mail | // +-----------------------------------------------------------------------+ @@ -455,5 +467,4 @@ $conf['nbm_list_all_enabled_users_to_send'] = false; // Max mails sended on one pass $conf['nbm_max_mails_send'] = 35; - ?> diff --git a/include/constants.php b/include/constants.php index 089e3b65d..02b352cc3 100644 --- a/include/constants.php +++ b/include/constants.php @@ -70,4 +70,6 @@ define('UPGRADE_TABLE', $prefixeTable.'upgrade'); define('SEARCH_TABLE', $prefixeTable.'search'); define('USER_MAIL_NOTIFICATION_TABLE', $prefixeTable.'user_mail_notification'); define('CATEGORIES_LINK_TABLE', $prefixeTable.'categories_link'); +define('TAGS_TABLE', $prefixeTable.'tags'); +define('IMAGE_TAG_TABLE', $prefixeTable.'image_tag'); ?> diff --git a/include/functions.inc.php b/include/functions.inc.php index 981da55c4..d8b86743f 100644 --- a/include/functions.inc.php +++ b/include/functions.inc.php @@ -31,6 +31,7 @@ include_once( PHPWG_ROOT_PATH .'include/functions_category.inc.php' ); include_once( PHPWG_ROOT_PATH .'include/functions_xml.inc.php' ); include_once( PHPWG_ROOT_PATH .'include/functions_group.inc.php' ); include_once( PHPWG_ROOT_PATH .'include/functions_html.inc.php' ); +include_once( PHPWG_ROOT_PATH .'include/functions_tag.inc.php' ); include_once( PHPWG_ROOT_PATH .'include/functions_url.inc.php' ); //----------------------------------------------------------- generic functions @@ -267,6 +268,35 @@ function get_picture_size( $original_width, $original_height, $picture_size[1] = $height; return $picture_size; } + +/** + * simplify a string to insert it into an URL + * + * based on str2url function from Dotclear + * + * @param string + * @return string + */ +function str2url($str) +{ + $str = strtr( + $str, + 'ÀÁÂÃÄÅàáâãäåÇçÒÓÔÕÖØòóôõöøÈÉÊËèéêëÌÍÎÏìíîïÙÚÛÜùúûü¾ÝÿýÑñ', + 'AAAAAAaaaaaaCcOOOOOOooooooEEEEeeeeIIIIiiiiUUUUuuuuYYyyNn' + ); + + $str = str_replace('Æ', 'AE', $str); + $str = str_replace('æ', 'ae', $str); + $str = str_replace('¼', 'OE', $str); + $str = str_replace('½', 'oe', $str); + + $str = preg_replace('/[^a-z0-9_\s\'\:\/\[\]-]/','',strtolower($str)); + $str = preg_replace('/[\s\'\:\/\[\]-]+/',' ',trim($str)); + $res = str_replace(' ','_',$str); + + return $res; +} + //-------------------------------------------- PhpWebGallery specific functions /** @@ -829,5 +859,4 @@ function get_available_upgrade_ids() return $available_upgrade_ids; } - -?>
\ No newline at end of file +?> diff --git a/include/functions_html.inc.php b/include/functions_html.inc.php index 7e7df7c41..13c3dc206 100644 --- a/include/functions_html.inc.php +++ b/include/functions_html.inc.php @@ -5,7 +5,6 @@ // | Copyright (C) 2003-2005 PhpWebGallery Team - http://phpwebgallery.net | // +-----------------------------------------------------------------------+ // | branch : BSF (Best So Far) -// | file : $Id$ // | last update : $Date$ // | last modifier : $Author$ // | revision : $Revision$ @@ -495,6 +494,56 @@ function get_cat_display_name_from_id($cat_id, } /** + * Returns an HTML list of tags. It can be a multi select field or a list of + * checkboxes. + * + * @param string HTML field name + * @param array selected tag ids + * @return array + */ +function get_html_tag_selection( + $tags, + $fieldname, + $selecteds = array(), + $forbidden_categories = null + ) +{ + global $conf; + + $output = '<ul class="tagSelection">'; + foreach ($tags as $tag) + { + $output.= + '<li>' + .'<label>' + .'<input type="checkbox" name="'.$fieldname.'[]"' + .' value="'.$tag['tag_id'].'"' + ; + + if (in_array($tag['tag_id'], $selecteds)) + { + $output.= ' checked="checked"'; + } + + $output.= + ' />' + .' '.$tag['name'] + .'</label>' + .'</li>' + ."\n" + ; + } + $output.= '</ul>'; + + return $output; +} + +function name_compare($a, $b) +{ + return strcmp($a['name'], $b['name']); +} + +/** * exits the current script (either exit or redirect) */ function access_denied() @@ -519,4 +568,4 @@ function access_denied() redirect($login_url); } } -?>
\ No newline at end of file +?> diff --git a/include/functions_search.inc.php b/include/functions_search.inc.php index 2ca87969e..7e55160c8 100644 --- a/include/functions_search.inc.php +++ b/include/functions_search.inc.php @@ -84,7 +84,7 @@ function get_sql_search_clause($search_id) // construction $clauses = array(); - foreach (array('file','name','comment','keywords','author') as $textfield) + foreach (array('file','name','comment','author') as $textfield) { if (isset($search['fields'][$textfield])) { @@ -109,7 +109,7 @@ function get_sql_search_clause($search_id) if (isset($search['fields']['allwords'])) { - $fields = array('file', 'name', 'comment', 'keywords', 'author'); + $fields = array('file', 'name', 'comment', 'author'); // in the OR mode, request bust be : // ((field1 LIKE '%word1%' OR field2 LIKE '%word1%') // OR (field1 LIKE '%word2%' OR field2 LIKE '%word2%')) @@ -208,12 +208,68 @@ function get_sql_search_clause($search_id) $search_clause = $where_separator; - if (isset($forbidden)) + return $search_clause; +} + +/** + * returns the list of items corresponding to the search id + * + * @param int search id + * @return array + */ +function get_search_items($search_id) +{ + $items = array(); + + $search_clause = get_sql_search_clause($search_id); + + if (!empty($search_clause)) { - $search_clause.= "\n AND ".$forbidden; + $query = ' +SELECT DISTINCT(id) + FROM '.IMAGES_TABLE.' + INNER JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON id = ic.image_id + WHERE '.$search_clause.' +;'; + $items = array_from_query($query, 'id'); } - return $search_clause; -} + $search = get_search_array($search_id); + if (isset($search['fields']['tags'])) + { + $tag_items = get_image_ids_for_tags( + $search['fields']['tags']['words'], + $search['fields']['tags']['mode'] + ); + + switch ($search['mode']) + { + case 'AND': + { + if (empty($search_clause)) + { + $items = $tag_items; + } + else + { + $items = array_intersect($items, $tag_items); + } + break; + } + case 'OR': + { + $items = array_unique( + array_merge( + $items, + $tag_items + ) + ); + break; + } + } + } + + return $items; +} ?>
\ No newline at end of file diff --git a/include/functions_tag.inc.php b/include/functions_tag.inc.php new file mode 100644 index 000000000..5dd4884f4 --- /dev/null +++ b/include/functions_tag.inc.php @@ -0,0 +1,218 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net | +// | Copyright (C) 2003-2006 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $RCSfile$ +// | last update : $Date: 2006-03-16 23:58:16 +0100 (jeu, 16 mar 2006) $ +// | last modifier : $Author: rub $ +// | revision : $Revision: 1085 $ +// | revision : $Revision: 1085 $ +// +-----------------------------------------------------------------------+ +// | 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. | +// +-----------------------------------------------------------------------+ + + +/** + * Tags available. Each return tag is represented as an array with its id, + * its name, its weight (count), its url name. Tags are not sorted. + * + * The returned list can be a subset of all existing tags due to + * permissions, only if a list of forbidden categories is provided + * + * @param array forbidden categories + * @return array + */ +function get_available_tags($forbidden_categories = null) +{ + // we can find top fatter tags among reachable images + $tags_query = ' +SELECT tag_id, name, url_name, count(*) counter + FROM '.IMAGE_TAG_TABLE.' + INNER JOIN '.TAGS_TABLE.' ON tag_id = id'; + + if (!is_null($forbidden_categories)) + { + // first we need all reachable image ids + $images_query = ' +SELECT DISTINCT image_id + FROM '.IMAGE_CATEGORY_TABLE.' + WHERE category_id NOT IN ('.implode(',', $forbidden_categories).') +;'; + $image_ids = array_from_query($images_query, 'image_id'); + + $tags_query.= ' + WHERE image_id IN ('. + wordwrap( + implode(', ', $image_ids), + 80, + "\n" + ).')'; + } + + $tags_query.= ' + GROUP BY tag_id +;'; + + $result = pwg_query($tags_query); + + $tags = array(); + + while ($row = mysql_fetch_array($result)) + { + array_push($tags, $row); + } + + return $tags; +} + +/** + * All tags, even tags associated to no image. + * + * @return array + */ +function get_all_tags() +{ + $query = ' +SELECT id AS tag_id, name, url_name + FROM '.TAGS_TABLE.' + ORDER BY name +;'; + $result = pwg_query($query); + + $tags = array(); + + while ($row = mysql_fetch_array($result)) + { + array_push($tags, $row); + } + + return $tags; +} + +/** + * Giving a set of tags with a counter for each one, calculate the display + * level of each tag. + * + * The level of each tag depends on the average count of tags. This + * calcylation method avoid having very different levels for tags having + * nearly the same count when set are small. + * + * @param array tags + * @return array + */ +function add_level_to_tags($tags) +{ + global $conf; + + if (count($tags) == 0) + { + return $tags; + } + + $total_count = 0; + + foreach ($tags as $tag) + { + $total_count+= $tag['counter']; + } + + // average count of available tags will determine the level of each tag + $tag_average_count = $total_count / count($tags); + + // tag levels threshold calculation: a tag with an average rate must have + // the middle level. + for ($i = 1; $i < $conf['tags_levels']; $i++) + { + $threshold_of_level[$i] = + 2 * $i * $tag_average_count / $conf['tags_levels']; + } + + // display sorted tags + foreach (array_keys($tags) as $k) + { + $tags[$k]['level'] = 1; + + // based on threshold, determine current tag level + for ($i = $conf['tags_levels'] - 1; $i >= 1; $i--) + { + if ($tags[$k]['counter'] > $threshold_of_level[$i]) + { + $tags[$k]['level'] = $i + 1; + break; + } + } + } + + return $tags; +} + +/** + * return the list of image ids corresponding to given tags. AND & OR mode + * supported. + * + * @param array tag ids + * @param string mode + * @return array + */ +function get_image_ids_for_tags($tag_ids, $mode = 'AND') +{ + switch ($mode) + { + case 'AND': + { + // strategy is to list images associated to each tag + $tag_images = array(); + + foreach ($tag_ids as $tag_id) + { + $query = ' +SELECT image_id + FROM '.IMAGE_TAG_TABLE.' + WHERE tag_id = '.$tag_id.' +;'; + $tag_images[$tag_id] = array_from_query($query, 'image_id'); + } + + // then we calculate the intersection, the images that are associated to + // every tags + $items = array_shift($tag_images); + foreach ($tag_images as $images) + { + $items = array_intersect($items, $images); + } + + return array_unique($items); + break; + } + case 'OR': + { + $query = ' +SELECT DISTINCT image_id + FROM '.IMAGE_TAG_TABLE.' + WHERE tag_id IN ('.implode(',', $tag_ids).') +;'; + return array_from_query($query, 'image_id'); + break; + } + default: + { + die('get_image_ids_for_tags: unknown mode, only AND & OR are supported'); + } + } +} +?>
\ No newline at end of file diff --git a/include/functions_url.inc.php b/include/functions_url.inc.php index 0e0583872..a50f789c8 100644 --- a/include/functions_url.inc.php +++ b/include/functions_url.inc.php @@ -258,23 +258,18 @@ function make_section_in_URL($params) { $section_string = ''; - if (!isset($params['section'])) + $section_of = array( + 'category' => 'categories', + 'tags' => 'tags', + 'list' => 'list', + 'search' => 'search', + ); + + foreach ($section_of as $param => $section) { - if (isset($params['category'])) - { - $params['section'] = 'categories'; - } - else if (isset($params['tags'])) - { - $params['section'] = 'tags'; - } - else if (isset($params['list'])) - { - $params['section'] = 'list'; - } - else if (isset($params['search'])) + if (isset($params[$param])) { - $params['section'] = 'search'; + $params['section'] = $section; } } @@ -289,7 +284,7 @@ function make_section_in_URL($params) { if (!isset($params['category'])) { - //$section_string.= '/categories'; + $section_string.= '/categories'; } else { @@ -309,7 +304,12 @@ function make_section_in_URL($params) foreach ($params['tags'] as $tag) { - $section_string.= '/'.$tag; + $section_string.= '/'.$tag['id']; + + if (isset($tag['url_name'])) + { + $section_string.= '-'.$tag['url_name']; + } } break; diff --git a/include/functions_user.inc.php b/include/functions_user.inc.php index cfa4d53aa..c5efa98ad 100644 --- a/include/functions_user.inc.php +++ b/include/functions_user.inc.php @@ -633,5 +633,4 @@ function is_adviser() return ($user['adviser'] == 'true'); } - ?>
\ No newline at end of file diff --git a/include/section_init.inc.php b/include/section_init.inc.php index cc7c074c2..e2ed07b42 100644 --- a/include/section_init.inc.php +++ b/include/section_init.inc.php @@ -145,15 +145,11 @@ else if (0 === strpos($tokens[$next_token], 'tag')) $page['tags'] = array(); $next_token++; + $i = $next_token; - for ($i = $next_token; ; $i++) + while (isset($tokens[$i])) { - if (!isset($tokens[$i])) - { - break; - } - - preg_match('/^(\d+)/', $tokens[$i], $matches); + preg_match('/^(\d+)(?:-(.*))?/', $tokens[$i], $matches); if (!isset($matches[1])) { if (0 == count($page['tags'])) @@ -165,7 +161,16 @@ else if (0 === strpos($tokens[$next_token], 'tag')) break; } } - array_push($page['tags'], $matches[1]); + + array_push( + $page['tags'], + array( + 'id' => $matches[1], + 'url_name' => isset($matches[2]) ? $matches[2] : '', + ) + ); + + $i++; } $next_token = $i; @@ -225,13 +230,10 @@ else if ('list' == $tokens[$next_token]) $next_token++; } -for ($i = $next_token; ; $i++) -{ - if (!isset($tokens[$i])) - { - break; - } +$i = $next_token; +while (isset($tokens[$i])) +{ if (preg_match('/^start-(\d+)/', $tokens[$i], $matches)) { $page['start'] = $matches[1]; @@ -240,9 +242,12 @@ for ($i = $next_token; ; $i++) if (preg_match('/^posted|created/', $tokens[$i] )) { $chronology_tokens = explode('-', $tokens[$i] ); + $page['chronology_field'] = $chronology_tokens[0]; + array_shift($chronology_tokens); $page['chronology_style'] = $chronology_tokens[0]; + array_shift($chronology_tokens); if ( count($chronology_tokens)>0 ) { @@ -255,6 +260,8 @@ for ($i = $next_token; ; $i++) $page['chronology_date'] = $chronology_tokens; } } + + $i++; } @@ -338,19 +345,97 @@ else $forbidden = ' 1 = 1'; } // +-----------------------------------------------------------------------+ +// | tags section | +// +-----------------------------------------------------------------------+ + if ($page['section'] == 'tags') + { + $page['tag_ids'] = array(); + foreach ($page['tags'] as $tag) + { + array_push($page['tag_ids'], $tag['id']); + } + + $items = get_image_ids_for_tags($page['tag_ids']); + + // permissions depends on category, so to only keep images that are + // reachable to the connected user, we need to check category + // associations + if (!empty($user['forbidden_categories'])) + { + $query = ' +SELECT image_id + FROM '.IMAGE_CATEGORY_TABLE.' + WHERE image_id IN ('.implode(',', $items).') + AND '.$forbidden.' +;'; + $items = array_unique( + array_from_query($query, 'image_id') + ); + } + + // tag names + $query = ' +SELECT name, url_name, id + FROM '.TAGS_TABLE.' + WHERE id IN ('.implode(',', $page['tag_ids']).') +;'; + $result = pwg_query($query); + $tag_infos = array(); + + while ($row = mysql_fetch_array($result)) + { + $tag_infos[ $row['id'] ]['name'] = $row['name']; + $tag_infos[ $row['id'] ]['url_name'] = $row['url_name']; + } + + $title = count($page['tags']) > 1 ? l10n('Tags') : l10n('Tag'); + $title.= ' '; + + $tag_num = 1; + foreach ($page['tag_ids'] as $tag_id) + { + $title.= + ($tag_num++ > 1 ? ' + ' : '') + .'<a href="' + .make_index_url( + array( + 'tags' => array( + array( + 'id' => $tag_id, + 'url_name' => $tag_infos[$tag_id]['url_name'], + ), + ) + ) + ) + .'">' + .$tag_infos[$tag_id]['name'] + .'</a>'; + } + + $page = array_merge( + $page, + array( + 'title' => $title, + 'items' => array_values($items), + 'thumbnails_include' => 'include/category_default.inc.php', + ) + ); + } +// +-----------------------------------------------------------------------+ // | search section | // +-----------------------------------------------------------------------+ if ($page['section'] == 'search') { include_once( PHPWG_ROOT_PATH .'include/functions_search.inc.php' ); + $query = ' SELECT DISTINCT(id) FROM '.IMAGES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON id = ic.image_id - WHERE '.get_sql_search_clause($page['search']).' + WHERE id IN ('.implode(',', get_search_items($page['search'])).') AND '.$forbidden.' '.$conf['order_by'].' -;'; +;'; $page = array_merge( $page, @@ -221,6 +221,76 @@ if (count($conf['links']) > 0) ); } } +//------------------------------------------------------------------------ tags +if ('tags' == $page['section']) +{ + $template->assign_block_vars('tags', array()); + + // display tags associated to currently tagged items, less current tags + $query = ' +SELECT tag_id, name, url_name, count(*) counter + FROM '.IMAGE_TAG_TABLE.' + INNER JOIN '.TAGS_TABLE.' ON tag_id = id + WHERE image_id IN ('.implode(',', $items).') + AND tag_id NOT IN ('.implode(',', $page['tag_ids']).') + GROUP BY tag_id + ORDER BY name ASC +;'; + $result = pwg_query($query); + + $tags = array(); + + while($row = mysql_fetch_array($result)) + { + array_push($tags, $row); + } + + $tags = add_level_to_tags($tags); + + foreach ($tags as $tag) + { + $template->assign_block_vars( + 'tags.tag', + array( + 'URL_ADD' => make_index_URL( + array( + 'tags' => array_merge( + $page['tags'], + array( + array( + 'id' => $tag['tag_id'], + 'url_name' => $tag['url_name'], + ), + ) + ) + ) + ), + + 'URL' => make_index_URL( + array( + 'tags' => array( + array( + 'id' => $tag['tag_id'], + 'url_name' => $tag['url_name'], + ), + ) + ) + ), + + 'NAME' => $tag['name'], + + 'TITLE' => l10n('See pictures linked to this tag only'), + + 'TITLE_ADD' => sprintf( + l10n('%d pictures are also linked to current tags'), + $tag['counter'] + ), + + 'CLASS' => 'tagLevel'.$tag['level'] + ) + ); + } +} //---------------------------------------------------------- special categories // favorites categories if ( !$user['is_the_guest'] ) @@ -332,6 +402,16 @@ else } } +// tags link +$template->assign_block_vars( + 'summary', + array( + 'TITLE' => l10n('See available tags'), + 'NAME' => l10n('Tags'), + 'U_SUMMARY'=> get_root_url().'tags.php', + ) + ); + // search link $template->assign_block_vars( 'summary', diff --git a/install/db/19-database.php b/install/db/19-database.php new file mode 100644 index 000000000..035aff95a --- /dev/null +++ b/install/db/19-database.php @@ -0,0 +1,151 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net | +// | Copyright (C) 2003-2005 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $RCSfile$ +// | last update : $Date: 2005-09-21 00:04:57 +0200 (mer, 21 sep 2005) $ +// | last modifier : $Author: plg $ +// | revision : $Revision: 870 $ +// +-----------------------------------------------------------------------+ +// | 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. | +// +-----------------------------------------------------------------------+ + +if (!defined('PHPWG_ROOT_PATH')) +{ + die('Hacking attempt!'); +} + +$upgrade_description = '#images.keywords moved to new table #tags'; + +// +-----------------------------------------------------------------------+ +// | New tables | +// +-----------------------------------------------------------------------+ + +$query = ' +CREATE TABLE '.PREFIX_TABLE.'tags ( + id smallint(5) UNSIGNED NOT NULL auto_increment, + name varchar(255) BINARY NOT NULL, + url_name varchar(255) BINARY NOT NULL, + PRIMARY KEY (id) +) TYPE=MyISAM +;'; +pwg_query($query); + +$query = ' +CREATE TABLE '.PREFIX_TABLE.'image_tag ( + image_id mediumint(8) UNSIGNED NOT NULL, + tag_id smallint(5) UNSIGNED NOT NULL, + PRIMARY KEY (image_id,tag_id) +) TYPE=MyISAM +;'; +pwg_query($query); + +// +-----------------------------------------------------------------------+ +// | Move keywords to tags | +// +-----------------------------------------------------------------------+ + +// each tag label is associated to a numeric identifier +$tag_id = array(); +// to each tag id (key) a list of image ids (value) is associated +$tag_images = array(); + +$current_id = 1; + +$query = ' +SELECT id, keywords + FROM '.PREFIX_TABLE.'images + WHERE keywords IS NOT NULL +;'; +$result = pwg_query($query); +while ($row = mysql_fetch_array($result)) +{ + foreach(preg_split('/[,]+/', $row['keywords']) as $keyword) + { + if (!isset($tag_id[$keyword])) + { + $tag_id[$keyword] = $current_id++; + } + + if (!isset($tag_images[ $tag_id[$keyword] ])) + { + $tag_images[ $tag_id[$keyword] ] = array(); + } + + array_push($tag_images[ $tag_id[$keyword] ], $row['id']); + } +} + +$datas = array(); +foreach ($tag_id as $tag_name => $tag_id) +{ + array_push( + $datas, + array( + 'id' => $tag_id, + 'name' => $tag_name, + 'url_name' => str2url($tag_name), + ) + ); +} +mass_inserts( + PREFIX_TABLE.'tags', + array_keys($datas[0]), + $datas + ); + +$datas = array(); +foreach ($tag_images as $tag_id => $images) +{ + foreach (array_unique($images) as $image_id) + { + array_push( + $datas, + array( + 'tag_id' => $tag_id, + 'image_id' => $image_id, + ) + ); + } +} + +mass_inserts( + PREFIX_TABLE.'image_tag', + array_keys($datas[0]), + $datas + ); + +// +-----------------------------------------------------------------------+ +// | Delete images.keywords | +// +-----------------------------------------------------------------------+ + +$query = ' +ALTER TABLE '.PREFIX_TABLE.'images DROP COLUMN keywords +;'; +pwg_query($query); + +// +-----------------------------------------------------------------------+ +// | End notification | +// +-----------------------------------------------------------------------+ + +echo +"\n" +.'Table '.PREFIX_TABLE.'tags created and filled'."\n" +.'Table '.PREFIX_TABLE.'image_tag created and filled'."\n" +.'Column '.PREFIX_TABLE.'images.keywords dropped'."\n" +; +?> diff --git a/install/phpwebgallery_structure.sql b/install/phpwebgallery_structure.sql index 4c682d738..db614f40d 100644 --- a/install/phpwebgallery_structure.sql +++ b/install/phpwebgallery_structure.sql @@ -1,5 +1,4 @@ -- MySQL dump 9.11 --- MySQL dump 9.11 -- -- Host: localhost Database: pwg-bsf -- ------------------------------------------------------ @@ -146,6 +145,17 @@ CREATE TABLE `phpwebgallery_image_category` ( ) TYPE=MyISAM; -- +-- Table structure for table `phpwebgallery_image_tag` +-- + +DROP TABLE IF EXISTS `phpwebgallery_image_tag`; +CREATE TABLE `phpwebgallery_image_tag` ( + `image_id` mediumint(8) unsigned NOT NULL default '0', + `tag_id` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`image_id`,`tag_id`) +) TYPE=MyISAM; + +-- -- Table structure for table `phpwebgallery_images` -- @@ -163,8 +173,6 @@ CREATE TABLE `phpwebgallery_images` ( `filesize` mediumint(9) unsigned default NULL, `width` smallint(9) unsigned default NULL, `height` smallint(9) unsigned default NULL, - `keywords` varchar(255) default NULL, - `storage_category_id` smallint(5) unsigned default NULL, `representative_ext` varchar(4) default NULL, `date_metadata_update` date default NULL, `average_rate` float(5,2) unsigned default NULL, @@ -172,7 +180,6 @@ CREATE TABLE `phpwebgallery_images` ( `path` varchar(255) NOT NULL default '', PRIMARY KEY (`id`), KEY `images_i2` (`date_available`), - KEY `images_i1` (`storage_category_id`), KEY `images_i3` (`average_rate`), KEY `images_i4` (`hit`), KEY `images_i5` (`date_creation`) @@ -229,6 +236,18 @@ CREATE TABLE `phpwebgallery_sites` ( ) TYPE=MyISAM; -- +-- Table structure for table `phpwebgallery_tags` +-- + +DROP TABLE IF EXISTS `phpwebgallery_tags`; +CREATE TABLE `phpwebgallery_tags` ( + `id` smallint(5) unsigned NOT NULL auto_increment, + `name` varchar(255) binary NOT NULL default '', + `url_name` varchar(255) binary NOT NULL default '', + PRIMARY KEY (`id`) +) TYPE=MyISAM; + +-- -- Table structure for table `phpwebgallery_upgrade` -- @@ -260,7 +279,7 @@ CREATE TABLE `phpwebgallery_user_cache` ( `user_id` smallint(5) NOT NULL default '0', `need_update` enum('true','false') NOT NULL default 'true', `forbidden_categories` text, - `nb_total_images` mediumint(8) unsigned, + `nb_total_images` mediumint(8) unsigned default NULL, PRIMARY KEY (`user_id`) ) TYPE=MyISAM; @@ -296,7 +315,7 @@ CREATE TABLE `phpwebgallery_user_infos` ( `user_id` smallint(5) NOT NULL default '0', `nb_image_line` tinyint(1) unsigned NOT NULL default '5', `nb_line_page` tinyint(3) unsigned NOT NULL default '3', - `status` enum('webmaster', 'admin', 'normal', 'generic', 'guest') NOT NULL default 'guest', + `status` enum('webmaster','admin','normal','generic','guest') NOT NULL default 'guest', `adviser` enum('true','false') NOT NULL default 'false', `language` varchar(50) NOT NULL default 'english', `maxwidth` smallint(6) default NULL, diff --git a/language/en_UK.iso-8859-1/admin.lang.php b/language/en_UK.iso-8859-1/admin.lang.php index 81b1aeb20..abfd89a85 100644 --- a/language/en_UK.iso-8859-1/admin.lang.php +++ b/language/en_UK.iso-8859-1/admin.lang.php @@ -40,6 +40,7 @@ $lang['%d waiting pictures rejected'] = '%d waiting pictures rejected'; $lang['%d waiting pictures validated'] = '%d waiting pictures validated'; $lang['A new version of PhpWebGallery is available.'] = 'A new version of PhpWebGallery is available.'; $lang['Actions'] = 'Actions'; +$lang['Add a tag'] = 'Add a tag'; $lang['Add a user'] = 'Add a user'; $lang['Add group'] = 'Add group'; $lang['Add selected elements to caddie'] = 'Add selected elements to caddie'; @@ -58,8 +59,10 @@ $lang['Check for upgrade'] = 'Check for upgrade'; $lang['Comments for all'] = 'Comments for all'; $lang['Controversy'] = 'Controversy'; $lang['Creation date'] = 'Creation date'; +$lang['Current name'] = 'Current name'; $lang['Database'] = 'Database'; $lang['Delete Representant'] = 'Delete Representant'; +$lang['Delete selected tags'] = 'Delete selected tags'; $lang['Delete selected users'] = 'Delete selected users'; $lang['Deletions'] = 'Deletions'; $lang['Deny selected groups'] = 'Deny selected groups'; @@ -69,6 +72,8 @@ $lang['Display options'] = 'Display options'; $lang['Dissociated'] = 'Dissociated'; $lang['Does not represent'] = 'Does not represent'; $lang['Edit all picture informations'] = 'Edit all picture informations'; +$lang['Edit selected tags'] = 'Edit selected tags'; +$lang['Edit tags'] = 'Edit tags'; $lang['Elements'] = 'Elements'; $lang['Empty caddie'] = 'Empty caddie'; $lang['Environment'] = 'Environment'; @@ -91,6 +96,7 @@ $lang['Maintenance'] = 'Maintenance'; $lang['Manage permissions for a category'] = 'Manage permissions for a category'; $lang['Manage permissions for group "%s"'] = 'Manage permissions for group "%s"'; $lang['Manage permissions for user "%s"'] = 'Manage permissions for user "%s"'; +$lang['Manage tags'] = 'Manage tags'; $lang['Maximum height of the pictures'] = 'Maximum height of the pictures'; $lang['Maximum width of the pictures'] = 'Maximum width of the pictures'; $lang['Members'] = 'Members'; @@ -98,7 +104,9 @@ $lang['Metadata synchronized from file'] = 'Metadata synchronized from file'; $lang['Move categories'] = 'Move categories'; $lang['Move'] = 'Move'; $lang['Name'] = 'Name'; +$lang['New name'] = 'New name'; $lang['New parent category'] = 'New parent category'; +$lang['New tag'] = 'New tag'; $lang['No'] = 'No'; $lang['Number of comments per page'] = 'Number of comments per page'; $lang['Number of images per row'] = 'Number of images per row'; @@ -111,6 +119,7 @@ $lang['Options'] = 'Options'; $lang['Order alphanumerically'] = 'Order alphanumerically'; $lang['Order by'] = 'Order by'; $lang['Other private categories'] = 'Other private categories'; +$lang['Page banner'] = 'Page banner'; $lang['Parent category'] = 'Parent category'; $lang['Path'] = 'Path'; $lang['Permission denied'] = 'Permission denied'; @@ -118,7 +127,6 @@ $lang['Permission granted thanks to a group'] = 'Permission granted thanks to a $lang['Permission granted'] = 'Permission granted'; $lang['PhpWebGallery Administration'] = 'PhpWebGallery Administration'; $lang['PhpWebGallery version'] = 'PhpWebGallery version'; -$lang['Page banner'] = 'Page banner'; $lang['Picture informations updated'] = 'Picture informations updated'; $lang['Position'] = 'Position'; $lang['Preferences'] = 'Preferences'; @@ -146,6 +154,7 @@ $lang['Status'] = 'Status'; $lang['Storage category'] = 'Storage category'; $lang['Submit'] = 'Submit'; $lang['Sum of rates'] = 'Sum of rates'; +$lang['Tag selection'] = 'Tag selection'; $lang['Take selected elements out of caddie'] = 'Take selected elements out of caddie'; $lang['Unable to check for upgrade since allow_url_fopen is disabled.'] = 'Unable to check for upgrade since allow_url_fopen is disabled.'; $lang['User comments validation'] = 'User comments validation'; @@ -162,12 +171,9 @@ $lang['You are running the latest version of PhpWebGallery.'] = 'You are running $lang['You cannot move a category in its own sub category'] = 'You cannot move a category in its own sub category'; $lang['You need to confirm deletion'] = 'You need to confirm deletion'; $lang['actions'] = 'Actions'; -$lang['properties'] = 'Properties'; -$lang['is_high_enabled'] = 'High definition'; -$lang['is_high_disabled'] = ''; -$lang['enabled_high'] = 'High definition enabled'; -$lang['adviser'] = 'Adviser'; $lang['add keywords'] = 'add keywords'; +$lang['add tags'] = 'add tags'; +$lang['adviser'] = 'Adviser'; $lang['associate to category'] = 'associate to category'; $lang['associate to group'] = 'associate to group'; $lang['author'] = 'author'; @@ -208,6 +214,7 @@ $lang['editcat_uploadable'] = 'Authorize upload'; $lang['elements per line'] = 'elements per line'; $lang['elements per page'] = 'elements per page'; $lang['elements'] = 'elements'; +$lang['enabled_high'] = 'High definition enabled'; $lang['file'] = 'file'; $lang['filesize'] = 'filesize'; $lang['first element added on %s'] = 'first element added on %s'; @@ -224,6 +231,8 @@ $lang['group_id URL parameter is missing'] = 'group_id URL parameter is missing' $lang['groups'] = 'Groups'; $lang['history'] = 'History'; $lang['instructions'] = 'Instructions'; +$lang['is_high_disabled'] = ''; +$lang['is_high_enabled'] = 'High definition'; $lang['jump to category'] = 'jump to category'; $lang['jump to image'] = 'jump to image'; $lang['jump to'] = 'jump to'; @@ -239,62 +248,62 @@ $lang['metadata_exif'] = 'EXIF'; $lang['metadata_iptc'] = 'IPTC'; $lang['name'] = 'name'; $lang['nbm_break_list_user'] = 'List of users to send mail is limited to %d. Others users are not listed.'; -$lang['nbm_nbm_break_send_mail'] = 'Sent mail is limited to %d send by pass. Others mails are skipped.'; -$lang['nbm_msg_no_mail_to_send'] = '%d mails were not sent.'; -$lang['nbm_msg_n_mails_sent'] = '%d mails were sent.'; -$lang['nbm_msg_error_sending_email_to'] = 'Error when sending email to %s [%s].'; -$lang['nbm_msg_mail_sent_to'] = 'Mail sent to %s [%s].'; -$lang['nbm_object_news'] = 'New elements added'; -$lang['nbm_object_subcribe'] = 'Subcribe of notification by mail'; -$lang['nbm_object_unsubcribe'] = 'Unsubcribe of notification by mail'; +$lang['nbm_col_check_user_send_mail'] = 'To send ?'; +$lang['nbm_col_last_send'] = 'Last send'; +$lang['nbm_col_mail'] = 'email'; +$lang['nbm_col_user'] = 'User'; +$lang['nbm_complementary_mail_content'] = 'Complementary mail content'; +$lang['nbm_content_byebye'] = 'See you soon'; +$lang['nbm_content_goto'] = 'Go to %s %s.'; $lang['nbm_content_hello'] = 'Hello %s'; -$lang['nbm_content_new_elements_between'] = 'New elements were added between %s and %s'; $lang['nbm_content_new_elements'] = 'New elements were added on %s'; -$lang['nbm_content_goto'] = 'Go to %s %s.'; +$lang['nbm_content_new_elements_between'] = 'New elements were added between %s and %s'; $lang['nbm_content_subscribe_by_admin'] = 'You are subcribed by webmaster for the notification by mail'; -$lang['nbm_content_unsubscribe_by_admin'] = 'You are unsubcribed by webmaster for the notification by mail'; $lang['nbm_content_subscribe_by_himself'] = 'You are subcribed for the notification by mail'; -$lang['nbm_content_unsubscribe_by_himself'] = 'You are unsubcribed for the notification by mail'; -$lang['nbm_content_byebye'] = 'See you soon'; -$lang['nbm_content_unsubscribe_link'] = 'To unsubscribe, click on %s .'; $lang['nbm_content_subscribe_link'] = 'To subscribe, click on %s .'; $lang['nbm_content_subscribe_unsubscribe_contact'] = 'On problems or questions, send a message to %s.'; +$lang['nbm_content_unsubscribe_by_admin'] = 'You are unsubcribed by webmaster for the notification by mail'; +$lang['nbm_content_unsubscribe_by_himself'] = 'You are unsubcribed for the notification by mail'; +$lang['nbm_content_unsubscribe_link'] = 'To unsubscribe, click on %s .'; +$lang['nbm_info_send_mail_as'] = 'With blank value, gallery title will be used'; +$lang['nbm_item_notification'] = 'Notification'; +$lang['nbm_msg_error_sending_email_to'] = 'Error when sending email to %s [%s].'; +$lang['nbm_msg_mail_sent_to'] = 'Mail sent to %s [%s].'; +$lang['nbm_msg_n_mails_sent'] = '%d mails were sent.'; +$lang['nbm_msg_no_mail_to_send'] = '%d mails were not sent.'; +$lang['nbm_nbm_break_send_mail'] = 'Sent mail is limited to %d send by pass. Others mails are skipped.'; $lang['nbm_no_mail_to_send'] = 'No mail to send.'; +$lang['nbm_no_user_available_to_send_L1'] = 'No user are available in order to send mail.'; +$lang['nbm_no_user_available_to_send_L2'] = 'A user is available, if the are news elements to notify'; $lang['nbm_no_user_to send_notifications_by_mail'] = 'No user to send notifications by mail.'; -$lang['nbm_send_mail_to_users'] = 'Send mail to users'; -$lang['nbm_user_x_added'] = 'User %s [%s] added.'; -$lang['nbm_item_notification'] = 'Notification'; +$lang['nbm_object_news'] = 'New elements added'; +$lang['nbm_object_subcribe'] = 'Subcribe of notification by mail'; +$lang['nbm_object_unsubcribe'] = 'Unsubcribe of notification by mail'; $lang['nbm_param_mode'] = 'Parameter'; -$lang['nbm_subscribe_mode'] = 'Subscribe'; -$lang['nbm_send_mode'] = 'Send'; -$lang['nbm_title_param'] = 'Parameters'; -$lang['nbm_updated_param_count'] = '%d parameters are updated.'; -$lang['nbm_send_mail_as'] = 'Send mail as'; -$lang['nbm_info_send_mail_as'] = 'With blank value, gallery title will be used'; +$lang['nbm_send_check_all'] = 'Check All'; +$lang['nbm_send_complementary_mail_content'] = 'Complementary mail content'; $lang['nbm_send_detailed_content'] = 'Send detailed content'; -$lang['nbm_complementary_mail_content'] = 'Complementary mail content'; -$lang['nbm_title_subscribe'] = 'Subscribe/unscribe users'; -$lang['nbm_warning_subscribe_unsubcribe'] = 'Warning, subscribe or unscribe send mails to users'; -$lang['nbm_subscribe_col'] = 'Subscribed'; -$lang['nbm_unsubscribe_col'] = 'Unsubcribed'; -$lang['nbm_no_user_available_to_send_L1'] = 'No user are available in order to send mail.'; -$lang['nbm_no_user_available_to_send_L2'] = 'A user is available, if the are news elements to notify'; -$lang['nbm_title_send'] = 'Select sendings'; -$lang['nbm_col_user'] = 'User'; -$lang['nbm_col_mail'] = 'email'; -$lang['nbm_col_last_send'] = 'Last send'; -$lang['nbm_col_check_user_send_mail'] = 'To send ?'; +$lang['nbm_send_mail_as'] = 'Send mail as'; +$lang['nbm_send_mail_to_users'] = 'Send mail to users'; +$lang['nbm_send_mode'] = 'Send'; $lang['nbm_send_options'] = 'Options'; -$lang['nbm_send_complementary_mail_content'] = 'Complementary mail content'; $lang['nbm_send_submit'] = 'Send'; -$lang['nbm_send_check_all'] = 'Check All'; $lang['nbm_send_uncheck_all'] = 'Uncheck All'; -$lang['nbm_user_change_enabled_true'] = 'User %s [%s] added to subscribe list.'; +$lang['nbm_subscribe_col'] = 'Subscribed'; +$lang['nbm_subscribe_mode'] = 'Subscribe'; +$lang['nbm_title_param'] = 'Parameters'; +$lang['nbm_title_send'] = 'Select sendings'; +$lang['nbm_title_subscribe'] = 'Subscribe/unscribe users'; +$lang['nbm_unsubscribe_col'] = 'Unsubcribed'; +$lang['nbm_updated_param_count'] = '%d parameters are updated.'; +$lang['nbm_user_change_enabled_error_on_updated_data_count'] = '%d user(s) are not updated.'; $lang['nbm_user_change_enabled_false'] = 'User %s [%s] removed of subscribe list.'; -$lang['nbm_user_not_change_enabled_true'] = 'User %s [%s] not added to subscribe list.'; -$lang['nbm_user_not_change_enabled_false'] = 'User %s [%s] not removed of subscribe list.'; +$lang['nbm_user_change_enabled_true'] = 'User %s [%s] added to subscribe list.'; $lang['nbm_user_change_enabled_updated_data_count'] = '%d user(s) are updated.'; -$lang['nbm_user_change_enabled_error_on_updated_data_count'] = '%d user(s) are not updated.'; +$lang['nbm_user_not_change_enabled_false'] = 'User %s [%s] not removed of subscribe list.'; +$lang['nbm_user_not_change_enabled_true'] = 'User %s [%s] not added to subscribe list.'; +$lang['nbm_user_x_added'] = 'User %s [%s] added.'; +$lang['nbm_warning_subscribe_unsubcribe'] = 'Warning, subscribe or unscribe send mails to users'; $lang['no_write_access'] = 'no write access'; $lang['order_by'] = 'order by'; $lang['path'] = 'path'; @@ -303,10 +312,10 @@ $lang['permuser_info'] = 'Only private categories are listed. Private/Public cat $lang['permuser_only_private'] = 'Only private categories are shown'; $lang['pictures'] = 'pictures'; $lang['private'] = 'private'; +$lang['properties'] = 'Properties'; $lang['public'] = 'public'; $lang['purge history'] = 'purge history'; $lang['purge never used notification feeds'] = 'purge never used notification feeds'; -$lang['repair and optimize database'] = 'repair and optimize database'; $lang['purge sessions'] = 'purge sessions'; $lang['randomly represented'] = 'randomly represented'; $lang['registration_date'] = 'registration date'; @@ -322,6 +331,8 @@ $lang['remote_site_test'] = 'test'; $lang['remote_site_test_hint'] = 'test this remote site'; $lang['remote_site_uncorrect_url'] = 'Remote site url must start by http or https and must only contain characters among "/", "a-zA-Z0-9", "-" or "_"'; $lang['remove keyword'] = 'remove keyword'; +$lang['remove tags'] = 'remove tags'; +$lang['repair and optimize database'] = 'repair and optimize database'; $lang['selection'] = 'selection'; $lang['set to'] = 'set to'; $lang['singly represented'] = 'singly represented'; @@ -442,11 +453,11 @@ $lang['user_delete'] = 'Delete user'; $lang['user_delete_hint'] = 'Click here to delete this user. Warning! This operation cannot be undone!'; $lang['user_id URL parameter is missing'] = 'user_id URL parameter is missing'; $lang['user_status'] = 'User status'; -$lang['user_status_webmaster'] = 'Webmaster'; $lang['user_status_admin'] = 'Administrator'; -$lang['user_status_normal'] = 'User'; $lang['user_status_generic'] = 'Generic'; $lang['user_status_guest'] = 'Guest'; +$lang['user_status_normal'] = 'User'; +$lang['user_status_webmaster'] = 'Webmaster'; $lang['username'] = 'username'; $lang['users'] = 'Users'; $lang['visitors'] = 'Visitors'; diff --git a/language/en_UK.iso-8859-1/common.lang.php b/language/en_UK.iso-8859-1/common.lang.php index abe3bc29b..5fffbff9a 100644 --- a/language/en_UK.iso-8859-1/common.lang.php +++ b/language/en_UK.iso-8859-1/common.lang.php @@ -39,9 +39,14 @@ $lang['%d comments to validate'] = '%d comments to validate'; $lang['%d new comments'] = '%d new comments'; $lang['%d new elements'] = '%d new elements'; $lang['%d new users'] = '%d new users'; +$lang['%d pictures are also linked to current tags'] = '%d pictures are also linked to current tags'; $lang['%d waiting elements'] = '%d waiting elements'; $lang['About'] = 'About'; +$lang['All tags must match'] = 'All tags must match'; +$lang['All tags'] = 'All tags'; +$lang['Any tag'] = 'Any tag'; $lang['At least one listed rule must be satisfied.'] = 'At least one listed rule must be satisfied.'; +$lang['At least one tag must match'] = 'At least one tag must match'; $lang['Author'] = 'Author'; $lang['Average rate'] = 'Average rate'; $lang['Categories'] = 'Categories'; @@ -62,8 +67,8 @@ $lang['Email address is missing'] = 'Email address is missing'; $lang['Email address'] = 'Email address'; $lang['Enter your personnal informations'] = 'Enter your personnal informations'; $lang['Error sending email'] = 'Error sending email'; -$lang['File'] = 'File'; $lang['File name'] = 'File name'; +$lang['File'] = 'File'; $lang['Filesize'] = 'Filesize'; $lang['Filter and display'] = 'Filter and display'; $lang['Filter'] = 'Filter'; @@ -91,21 +96,26 @@ $lang['Post date'] = 'Post date'; $lang['Posted on'] = 'Posted on'; $lang['Profile'] = 'Profile'; $lang['Quick connect'] = 'Quick connect'; -$lang['Rate'] = 'Rate'; $lang['RSS feed'] = 'RSS feed'; +$lang['Rate'] = 'Rate'; $lang['Register'] = 'Register'; $lang['Registration'] = 'Registration'; +$lang['Related tags'] = 'Related tags'; $lang['Reset'] = 'Reset'; $lang['Retrieve password'] = 'Retrieve password'; $lang['Search rules'] = 'Search rules'; +$lang['Search tags'] = 'Search tags'; $lang['Search'] = 'Search'; +$lang['See available tags'] = 'See available tags'; +$lang['See pictures linked to this tag only'] = 'See pictures linked to this tag only'; $lang['Send new password'] = 'Send new password'; $lang['Since'] = 'Since'; $lang['Sort by'] = 'Sort by'; $lang['Sort order'] = 'Sort order'; +$lang['Tag'] = 'Tag'; +$lang['Tags'] = 'Tags'; $lang['The RSS notification feed provides notification on news from this website : new pictures, updated categories, new comments. Use a RSS feed reader.'] = 'The RSS notification feed provides notification on news from this website : new pictures, updated categories, new comments. Use a RSS feed reader.'; $lang['Unknown feed identifier'] = 'Unknown feed identifier'; -$lang['nbm_unknown_identifier'] = 'Unknown identifier'; $lang['User comments'] = 'User comments'; $lang['Username'] = 'Username'; $lang['Visits'] = 'Visits'; @@ -117,6 +127,7 @@ $lang['add to caddie'] = 'add to caddie'; $lang['add_favorites_alt'] = 'Add to favorites'; $lang['add_favorites_hint'] = 'Add this picture to your favorites'; $lang['admin'] = 'Administration'; +$lang['adviser_mode_enabled'] = 'Adviser mode enabled'; $lang['all'] = 'all'; $lang['all_categories'] = 'all categories'; $lang['already_rated'] = 'You\'ve already rated this item'; @@ -135,8 +146,8 @@ $lang['calendar_any'] = 'All'; $lang['calendar_hint'] = 'displays each day with pictures, month per month'; $lang['calendar_picture_hint'] = 'displays pictures added on '; $lang['calendar_view'] = 'View'; -$lang['chronology_monthly_list'] = 'Monthly list'; $lang['chronology_monthly_calendar'] = 'Monthly calendar'; +$lang['chronology_monthly_list'] = 'Monthly list'; $lang['chronology_weekly_list'] = 'Weekly list'; $lang['click_to_redirect'] = 'Click here if your browser does not automatically forward you'; $lang['comment date'] = 'comment date'; @@ -211,8 +222,8 @@ $lang['maxheight'] = 'Maximum height of the pictures'; $lang['maxheight_error'] = 'Maximum height must be a number superior to 50'; $lang['maxwidth'] = 'Maximum width of the pictures'; $lang['maxwidth_error'] = 'Maximum width must be a number superior to 50'; -$lang['mode_normal_hint'] = 'return to normal view mode'; $lang['mode_created_hint'] = 'displays a calendar by creation date'; +$lang['mode_normal_hint'] = 'return to normal view mode'; $lang['mode_posted_hint'] = 'displays a calendar by date posted'; $lang['month'][10] = 'October'; $lang['month'][11] = 'November'; @@ -228,10 +239,11 @@ $lang['month'][8] = 'August'; $lang['month'][9] = 'September'; $lang['most_visited_cat'] = 'Most visited'; $lang['most_visited_cat_hint'] = 'displays most visited pictures'; -$lang['nb_image_per_row'] = 'Number of images per row'; $lang['nb_image_line_error'] = 'The number of images per row must be a not null scalar'; -$lang['nb_row_per_page'] = 'Number of rows per page'; +$lang['nb_image_per_row'] = 'Number of images per row'; $lang['nb_line_page_error'] = 'The number of rows per page must be a not null scalar'; +$lang['nb_row_per_page'] = 'Number of rows per page'; +$lang['nbm_unknown_identifier'] = 'Unknown identifier'; $lang['never_rated'] = 'You\'ve never rated this item'; $lang['new_password'] = 'New password'; $lang['new_password_hint'] = 'You only have to give a password if you wish to change it.'; @@ -332,5 +344,4 @@ $lang['upload_username'] = 'Username'; $lang['useful when password forgotten'] = 'useful when password forgotten'; $lang['w_month'] = 'Month'; $lang['yes'] = 'Yes'; -$lang['adviser_mode_enabled'] = 'Adviser mode enabled'; ?> diff --git a/language/fr_FR.iso-8859-1/admin.lang.php b/language/fr_FR.iso-8859-1/admin.lang.php index 69a7c3523..114f1b07f 100644 --- a/language/fr_FR.iso-8859-1/admin.lang.php +++ b/language/fr_FR.iso-8859-1/admin.lang.php @@ -25,6 +25,7 @@ // | USA. | // +-----------------------------------------------------------------------+ + $lang['%d categories including %d physical and %d virtual'] = '%d catégories dont %d physiques et %d virtuelles'; $lang['%d categories moved'] = '%d catégories déplacées'; $lang['%d comments'] = '%d commentaires utilisateur'; @@ -40,6 +41,7 @@ $lang['%d waiting pictures rejected'] = '%d images en attente rejetées'; $lang['%d waiting pictures validated'] = '%d images en attente validées'; $lang['A new version of PhpWebGallery is available.'] = 'Une nouvelle version de PhpWebGallery est disponible.'; $lang['Actions'] = 'Actions'; +$lang['Add a tag'] = 'Ajouter un tag'; $lang['Add a user'] = 'Ajouter un utilisateur'; $lang['Add group'] = 'Ajouter un groupe'; $lang['Add selected elements to caddie'] = 'Ajouter les éléments sélectionnés au panier'; @@ -58,8 +60,10 @@ $lang['Check for upgrade'] = 'Dernière version ?'; $lang['Comments for all'] = 'Commentaires utilisateur pour tous'; $lang['Controversy'] = 'Controverse'; $lang['Creation date'] = 'Date de création'; +$lang['Current name'] = 'Nom courant'; $lang['Database'] = 'Base de données'; $lang['Delete Representant'] = 'Supprimer le représentant'; +$lang['Delete selected tags'] = 'Supprimer les tags sélectionnés'; $lang['Delete selected users'] = 'Supprimer les utilisateurs sélectionnés'; $lang['Deletions'] = 'Suppressions'; $lang['Deny selected groups'] = 'Interdire l\'accès aux groupes sélectionnés'; @@ -69,6 +73,8 @@ $lang['Display options'] = 'Options d\'affichage'; $lang['Dissociated'] = 'Dissociée de'; $lang['Does not represent'] = 'Ne représente pas'; $lang['Edit all picture informations'] = 'Modifier toutes les informations liées à cette image'; +$lang['Edit selected tags'] = 'Editer les tags sélectionnés'; +$lang['Edit tags'] = 'Editer les tags'; $lang['Elements'] = 'Éléments'; $lang['Empty caddie'] = 'Vider le panier'; $lang['Environment'] = 'Environnement'; @@ -91,6 +97,7 @@ $lang['Maintenance'] = 'Maintenance'; $lang['Manage permissions for a category'] = 'Gérer les permissions pour une catégorie'; $lang['Manage permissions for group "%s"'] = 'Gérer les permissions pour le groupe "%s"'; $lang['Manage permissions for user "%s"'] = 'Gérer les permissions pour l\'utilisateur "%s"'; +$lang['Manage tags'] = 'Gérer les tags'; $lang['Maximum height of the pictures'] = 'Hauteur maximum des images'; $lang['Maximum width of the pictures'] = 'Largeur maximum des images'; $lang['Members'] = 'Membres'; @@ -98,7 +105,9 @@ $lang['Metadata synchronized from file'] = 'Meta-données synchronisées à partir $lang['Move categories'] = 'Déplacer les catégories'; $lang['Move'] = 'Déplacer'; $lang['Name'] = 'Nom'; +$lang['New name'] = 'Nouveau nom'; $lang['New parent category'] = 'Nouvelle catégorie parente'; +$lang['New tag'] = 'Nouveau tag'; $lang['No'] = 'Non'; $lang['Number of comments per page'] = 'Nombre de commentaires utilisateur par page'; $lang['Number of images per row'] = 'Nombre de miniatures par ligne'; @@ -146,6 +155,7 @@ $lang['Status'] = 'Statut'; $lang['Storage category'] = 'Catégorie de stockage'; $lang['Submit'] = 'Valider'; $lang['Sum of rates'] = 'Somme des notes'; +$lang['Tag selection'] = 'Sélection de tags'; $lang['Take selected elements out of caddie'] = 'Sortir les éléments sélectionnés du panier'; $lang['Unable to check for upgrade since allow_url_fopen is disabled.'] = 'Impossible de connaître la dernière version cat la fonction allow_url_fopen est désactivée.'; $lang['User comments validation'] = 'Validation des commentaires utilisateur'; @@ -162,12 +172,9 @@ $lang['You are running the latest version of PhpWebGallery.'] = 'Vous utilisez l $lang['You cannot move a category in its own sub category'] = 'Vous ne pouvez pas déplacer une catégorie dans sa propre sous-catégorie'; $lang['You need to confirm deletion'] = 'Vous devez confirmer la suppression'; $lang['actions'] = 'Actions'; -$lang['properties'] = 'Propriétés'; -$lang['is_high_enabled'] = 'Haute définition'; -$lang['is_high_disabled'] = ''; -$lang['enabled_high'] = 'Haute définition actif'; -$lang['adviser'] = 'Conseiller'; $lang['add keywords'] = 'ajouter des mots-clef'; +$lang['add tags'] = 'ajouter les tags'; +$lang['adviser'] = 'Conseiller'; $lang['associate to category'] = 'associer à la catégorie'; $lang['associate to group'] = 'associer au groupe'; $lang['author'] = 'auteur'; @@ -208,6 +215,7 @@ $lang['editcat_uploadable'] = 'Autoriser l\'ajout d\'images'; $lang['elements per line'] = 'éléments par ligne'; $lang['elements per page'] = 'éléments par page'; $lang['elements'] = 'éléments'; +$lang['enabled_high'] = 'Haute définition actif'; $lang['file'] = 'fichier'; $lang['filesize'] = 'poids'; $lang['first element added on %s'] = 'premier élément ajouté le %s'; @@ -224,6 +232,8 @@ $lang['group_id URL parameter is missing'] = 'Le paramètre d\'URL "group_id" est $lang['groups'] = 'Groupes'; $lang['history'] = 'Historique'; $lang['instructions'] = 'Instructions'; +$lang['is_high_disabled'] = ''; +$lang['is_high_enabled'] = 'Haute définition'; $lang['jump to category'] = 'se rendre dans la catégorie'; $lang['jump to image'] = 'se rendre à l\'image'; $lang['jump to'] = 's\'y rendre'; @@ -239,62 +249,62 @@ $lang['metadata_exif'] = 'EXIF'; $lang['metadata_iptc'] = 'IPTC'; $lang['name'] = 'nom'; $lang['nbm_break_list_user'] = 'La liste des utilisateurs pour l\'envoi est limitéé à %d. Les autres utilisateurs ne sont pas listés.'; -$lang['nbm_nbm_break_send_mail'] = 'Les mails envoyés sont limités à %d envois d\'une seule passe. Les autres envois de mail ont été ignorés.'; -$lang['nbm_msg_no_mail_to_send'] = '%s mails n\'ont pas été envoyés.'; -$lang['nbm_msg_n_mails_sent'] = '%s mails ont été envoyés.'; -$lang['nbm_msg_error_sending_email_to'] = 'Erreur lors de l\'envoi du mail à %s [%s].'; -$lang['nbm_msg_mail_sent_to'] = 'Mail envoyé à %s [%s].'; -$lang['nbm_object_news'] = 'Nouveaux éléments ajoutés'; -$lang['nbm_object_subcribe'] = 'Inscription à la notification par mail'; -$lang['nbm_object_unsubcribe'] = 'Désinscription à la notification par mail'; +$lang['nbm_col_check_user_send_mail'] = 'A envoyer ?'; +$lang['nbm_col_last_send'] = 'Dernier envoi'; +$lang['nbm_col_mail'] = 'email'; +$lang['nbm_col_user'] = 'Utilisateur'; +$lang['nbm_complementary_mail_content'] = 'Contenu complémentaire au mail'; +$lang['nbm_content_byebye'] = 'A bientôt'; +$lang['nbm_content_goto'] = 'Rendez-vous sur %s %s.'; $lang['nbm_content_hello'] = 'Bonjour %s'; -$lang['nbm_content_new_elements_between'] = 'Des nouveaux éléments ont été ajoutés entre le %s et le %s'; $lang['nbm_content_new_elements'] = 'Des nouveaux éléments ont été ajoutés le %s'; -$lang['nbm_content_goto'] = 'Rendez-vous sur %s %s.'; +$lang['nbm_content_new_elements_between'] = 'Des nouveaux éléments ont été ajoutés entre le %s et le %s'; $lang['nbm_content_subscribe_by_admin'] = 'Vous venez d\'être inscrit par le webmestre du site pour revevoir la notification par mail.'; -$lang['nbm_content_unsubscribe_by_admin'] = 'Vous venez d\'être désinscrit par le webmestre du site pour revevoir la notification par mail.'; $lang['nbm_content_subscribe_by_himself'] = 'Vous venez de vous inscrire pour revevoir la notification par mail.'; -$lang['nbm_content_unsubscribe_by_himself'] = 'Vous venez de vous désinscrire pour revevoir la notification par mail.'; -$lang['nbm_content_byebye'] = 'A bientôt'; -$lang['nbm_content_unsubscribe_link'] = 'Pour vous désinscrire, cliquez sur %s .'; $lang['nbm_content_subscribe_link'] = 'Pour vous inscrire, cliquez sur %s .'; $lang['nbm_content_subscribe_unsubscribe_contact'] = 'En cas de problèmes ou de questions, envoyer un mail à %s.'; +$lang['nbm_content_unsubscribe_by_admin'] = 'Vous venez d\'être désinscrit par le webmestre du site pour revevoir la notification par mail.'; +$lang['nbm_content_unsubscribe_by_himself'] = 'Vous venez de vous désinscrire pour revevoir la notification par mail.'; +$lang['nbm_content_unsubscribe_link'] = 'Pour vous désinscrire, cliquez sur %s .'; +$lang['nbm_info_send_mail_as'] = 'Sans valeur, le titre de la galerie sera utilisé'; +$lang['nbm_item_notification'] = 'Notification'; +$lang['nbm_msg_error_sending_email_to'] = 'Erreur lors de l\'envoi du mail à %s [%s].'; +$lang['nbm_msg_mail_sent_to'] = 'Mail envoyé à %s [%s].'; +$lang['nbm_msg_n_mails_sent'] = '%s mails ont été envoyés.'; +$lang['nbm_msg_no_mail_to_send'] = '%s mails n\'ont pas été envoyés.'; +$lang['nbm_nbm_break_send_mail'] = 'Les mails envoyés sont limités à %d envois d\'une seule passe. Les autres envois de mail ont été ignorés.'; $lang['nbm_no_mail_to_send'] = 'Pas de mail à envoyer.'; +$lang['nbm_no_user_available_to_send_L1'] = 'Il n\'y a pas d\'utilisateur à notifier par mail.'; +$lang['nbm_no_user_available_to_send_L2'] = 'Un utilisateur est à notifier si de nouveaux éléments sont disponibles pour cet utilisateur.'; $lang['nbm_no_user_to send_notifications_by_mail'] = 'Pas d\'utilisateur pour envoyer des notifications par mails.'; -$lang['nbm_send_mail_to_users'] = 'Envoi de mail aux utilisateurs'; -$lang['nbm_user_x_added'] = 'Utilisateur %s [%s] ajouté.'; -$lang['nbm_item_notification'] = 'Notification'; +$lang['nbm_object_news'] = 'Nouveaux éléments ajoutés'; +$lang['nbm_object_subcribe'] = 'Inscription à la notification par mail'; +$lang['nbm_object_unsubcribe'] = 'Désinscription à la notification par mail'; $lang['nbm_param_mode'] = 'Paramètrage'; -$lang['nbm_subscribe_mode'] = 'Inscription'; -$lang['nbm_send_mode'] = 'Envoi'; -$lang['nbm_title_param'] = 'Paramètres'; -$lang['nbm_updated_param_count'] = '%d paramètres ont été mis à jour.'; -$lang['nbm_send_mail_as'] = 'Envoyer le mail en tant que'; -$lang['nbm_info_send_mail_as'] = 'Sans valeur, le titre de la galerie sera utilisé'; +$lang['nbm_send_check_all'] = 'Tout cocher'; +$lang['nbm_send_complementary_mail_content'] = 'Contenu complémentaire du mail'; $lang['nbm_send_detailed_content'] = 'Envoi d\'un contenu détaillé'; -$lang['nbm_complementary_mail_content'] = 'Contenu complémentaire au mail'; -$lang['nbm_title_subscribe'] = 'Inscrire/desinscrire les utilisateurs'; -$lang['nbm_warning_subscribe_unsubcribe'] = 'Attention, l\'inscription ou la desincription entraine l\'envoi de mails aux utilisateurs concernés'; -$lang['nbm_subscribe_col'] = 'Inscrits'; -$lang['nbm_unsubscribe_col'] = 'Non Inscrits'; -$lang['nbm_no_user_available_to_send_L1'] = 'Il n\'y a pas d\'utilisateur à notifier par mail.'; -$lang['nbm_no_user_available_to_send_L2'] = 'Un utilisateur est à notifier si de nouveaux éléments sont disponibles pour cet utilisateur.'; -$lang['nbm_title_send'] = 'Sélection des envois'; -$lang['nbm_col_user'] = 'Utilisateur'; -$lang['nbm_col_mail'] = 'email'; -$lang['nbm_col_last_send'] = 'Dernier envoi'; -$lang['nbm_col_check_user_send_mail'] = 'A envoyer ?'; +$lang['nbm_send_mail_as'] = 'Envoyer le mail en tant que'; +$lang['nbm_send_mail_to_users'] = 'Envoi de mail aux utilisateurs'; +$lang['nbm_send_mode'] = 'Envoi'; $lang['nbm_send_options'] = 'Options'; -$lang['nbm_send_complementary_mail_content'] = 'Contenu complémentaire du mail'; $lang['nbm_send_submit'] = 'Envoyer'; -$lang['nbm_send_check_all'] = 'Tout cocher'; $lang['nbm_send_uncheck_all'] = 'Tout décocher'; -$lang['nbm_user_change_enabled_true'] = 'L\'utilisateur %s [%s] a été ajouté à la liste des inscrits.'; +$lang['nbm_subscribe_col'] = 'Inscrits'; +$lang['nbm_subscribe_mode'] = 'Inscription'; +$lang['nbm_title_param'] = 'Paramètres'; +$lang['nbm_title_send'] = 'Sélection des envois'; +$lang['nbm_title_subscribe'] = 'Inscrire/desinscrire les utilisateurs'; +$lang['nbm_unsubscribe_col'] = 'Non Inscrits'; +$lang['nbm_updated_param_count'] = '%d paramètres ont été mis à jour.'; +$lang['nbm_user_change_enabled_error_on_updated_data_count'] = '%d utilisateurs n\'ont pas été mis à jour.'; $lang['nbm_user_change_enabled_false'] = 'L\'utilisateur %s [%s] a été supprimé de la liste des inscrits.'; -$lang['nbm_user_not_change_enabled_true'] = 'L\'utilisateur %s [%s] n\'a pas été ajouté à la liste des inscrits.'; -$lang['nbm_user_not_change_enabled_false'] = 'L\'utilisateur %s [%s] n\'a pas été supprimé de la liste des inscrits.'; +$lang['nbm_user_change_enabled_true'] = 'L\'utilisateur %s [%s] a été ajouté à la liste des inscrits.'; $lang['nbm_user_change_enabled_updated_data_count'] = '%d utilisateurs ont été mis à jour.'; -$lang['nbm_user_change_enabled_error_on_updated_data_count'] = '%d utilisateurs n\'ont pas été mis à jour.'; +$lang['nbm_user_not_change_enabled_false'] = 'L\'utilisateur %s [%s] n\'a pas été supprimé de la liste des inscrits.'; +$lang['nbm_user_not_change_enabled_true'] = 'L\'utilisateur %s [%s] n\'a pas été ajouté à la liste des inscrits.'; +$lang['nbm_user_x_added'] = 'Utilisateur %s [%s] ajouté.'; +$lang['nbm_warning_subscribe_unsubcribe'] = 'Attention, l\'inscription ou la desincription entraine l\'envoi de mails aux utilisateurs concernés'; $lang['no_write_access'] = 'pas d\'accès en écriture'; $lang['order_by'] = 'trier selon'; $lang['path'] = 'chemin'; @@ -303,10 +313,10 @@ $lang['permuser_info'] = 'Seules les catégories privées sont listées.'; $lang['permuser_only_private'] = 'Seules les catégories privées sont listées.'; $lang['pictures'] = 'images'; $lang['private'] = 'privée'; +$lang['properties'] = 'Propriétés'; $lang['public'] = 'publique'; $lang['purge history'] = 'purger l\'historique'; $lang['purge never used notification feeds'] = 'purger les flux de notification jamais utilisés'; -$lang['repair and optimize database'] = 'réparer et optimiser la base de données'; $lang['purge sessions'] = 'purger les sessions'; $lang['randomly represented'] = 'représentant au hasard'; $lang['registration_date'] = 'date d\'enregistrement'; @@ -322,6 +332,8 @@ $lang['remote_site_test'] = 'tester'; $lang['remote_site_test_hint'] = 'tester ce site distant'; $lang['remote_site_uncorrect_url'] = 'L\'URL d\'un site distant doit commencer par "http" ou "https" et ne doit contenir des caractères que parmi "/", "a-zA-Z0-9", "-" ou "_"'; $lang['remove keyword'] = 'supprimer mot-clef'; +$lang['remove tags'] = 'supprimer les tags'; +$lang['repair and optimize database'] = 'réparer et optimiser la base de données'; $lang['selection'] = 'sélection'; $lang['set to'] = 'changer en'; $lang['singly represented'] = 'représentant fixe'; @@ -442,11 +454,11 @@ $lang['user_delete'] = 'Supprimer utilisateur'; $lang['user_delete_hint'] = 'Cliquer ici pour supprimer cet utilisateur. Attention : cette opération ne peut pas être annulée !'; $lang['user_id URL parameter is missing'] = 'le paramètre d\'URL "user_id" manque'; $lang['user_status'] = 'Statut de l\'utilisateur'; -$lang['user_status_webmaster'] = 'Webmestre'; $lang['user_status_admin'] = 'Administrateur'; -$lang['user_status_normal'] = 'Visiteur'; $lang['user_status_generic'] = 'Générique'; $lang['user_status_guest'] = 'Invité'; +$lang['user_status_normal'] = 'Visiteur'; +$lang['user_status_webmaster'] = 'Webmestre'; $lang['username'] = 'nom utilisateur'; $lang['users'] = 'Utilisateurs'; $lang['visitors'] = 'Visiteurs'; diff --git a/language/fr_FR.iso-8859-1/common.lang.php b/language/fr_FR.iso-8859-1/common.lang.php index 5a4ea1ac4..45e00ad2c 100644 --- a/language/fr_FR.iso-8859-1/common.lang.php +++ b/language/fr_FR.iso-8859-1/common.lang.php @@ -39,8 +39,13 @@ $lang['%d comments to validate'] = '%d commentaires utilisateur à valider'; $lang['%d new comments'] = '%d nouveaux commentaires utilisateur'; $lang['%d new elements'] = '%d nouveaux éléments'; $lang['%d new users'] = '%d nouveaux utilisateurs'; +$lang['%d pictures are also linked to current tags'] = '%d images sont également liées aux tags courants'; $lang['About'] = 'À propos'; +$lang['All tags must match'] = 'Tous les tags doivent correspondre'; +$lang['All tags'] = 'Tous les tags'; +$lang['Any tag'] = 'N\'importe quel tag'; $lang['At least one listed rule must be satisfied.'] = 'Au moins un des critères doit être satisfait.'; +$lang['At least one tag must match'] = 'Au moins un tag doit correspondre'; $lang['Author'] = 'Auteur'; $lang['Average rate'] = 'Note moyenne'; $lang['Categories'] = 'Catégories'; @@ -61,8 +66,8 @@ $lang['Email address is missing'] = 'L\'adresse e-mail manque'; $lang['Email address'] = 'Adresse e-mail'; $lang['Enter your personnal informations'] = 'Entrer vos informations personnelles'; $lang['Error sending email'] = 'Erreur à l\'envoi du mail'; -$lang['File'] = 'Fichier'; $lang['File name'] = 'Nom du fichier'; +$lang['File'] = 'Fichier'; $lang['Filesize'] = 'Poids'; $lang['Filter and display'] = 'Filtrer et afficher'; $lang['Filter'] = 'Filtre'; @@ -90,21 +95,26 @@ $lang['Post date'] = 'Date d\'ajout'; $lang['Posted on'] = 'Ajoutée le'; $lang['Profile'] = 'Profil'; $lang['Quick connect'] = 'Connexion rapide'; -$lang['Rate'] = 'Note'; $lang['RSS feed'] = 'flux RSS'; +$lang['Rate'] = 'Note'; $lang['Register'] = 'S\'enregistrer'; $lang['Registration'] = 'Enregistrement'; +$lang['Related tags'] = 'Tags liés'; $lang['Reset'] = 'Annuler'; $lang['Retrieve password'] = 'Récupérer un mot de passe'; $lang['Search rules'] = 'Critères de recherche'; +$lang['Search tags'] = 'Rechercher les tags'; $lang['Search'] = 'Rechercher'; +$lang['See available tags'] = 'Voir les tags disponibles'; +$lang['See pictures linked to this tag only'] = 'Voir les images liées uniquement à ce tag'; $lang['Send new password'] = 'Envoyer le nouveau mot de passe'; $lang['Since'] = 'Depuis'; $lang['Sort by'] = 'Trier selon'; $lang['Sort order'] = 'Ordre de tri'; +$lang['Tag'] = 'Tag'; +$lang['Tags'] = 'Tags'; $lang['The RSS notification feed provides notification on news from this website : new pictures, updated categories, new comments. Use a RSS feed reader.'] = 'Le flux RSS notifie les événements de la galerie : nouvelles images, catégories mises à jour, nouveaux commentaires utilisateur. À utiliser avec un lecteur de flux RSS.'; $lang['Unknown feed identifier'] = 'Identifiant de flux inconnu'; -$lang['nbm_unknown_identifier'] = 'Identifiants inconnus'; $lang['User comments'] = 'Commentaires utilisateur'; $lang['Username'] = 'Nom d\'utilisateur'; $lang['Visits'] = 'Visites'; @@ -116,6 +126,7 @@ $lang['add to caddie'] = 'ajouter au panier'; $lang['add_favorites_alt'] = 'Ajouter aux favoris'; $lang['add_favorites_hint'] = 'Ajouter cette image à vos favoris'; $lang['admin'] = 'Administration'; +$lang['adviser_mode_enabled'] = 'Mode conseiller actif'; $lang['all'] = 'tout'; $lang['all_categories'] = 'toutes les catégories'; $lang['already_rated'] = 'Vous avez déjà voté pour cette image'; @@ -134,8 +145,8 @@ $lang['calendar_any'] = 'Tout'; $lang['calendar_hint'] = 'affichage année par année, mois par mois, jour par jour'; $lang['calendar_picture_hint'] = 'afficher les images du '; $lang['calendar_view'] = 'Vue'; -$lang['chronology_monthly_list'] = 'Liste mensuelle'; $lang['chronology_monthly_calendar'] = 'Calendrier mensuel'; +$lang['chronology_monthly_list'] = 'Liste mensuelle'; $lang['chronology_weekly_list'] = 'Liste hebdomadaire'; $lang['click_to_redirect'] = 'Cliquez ici si votre navigateur ne vous redirige pas.'; $lang['comment date'] = 'date du commentaire'; @@ -210,8 +221,8 @@ $lang['maxheight'] = 'Hauteur maximum des images'; $lang['maxheight_error'] = 'La hauteur maximum des images doit être supérieure à 50'; $lang['maxwidth'] = 'Largeur maximum des images'; $lang['maxwidth_error'] = 'La largeur des images doit être supérieure à 50'; -$lang['mode_normal_hint'] = 'retourne à la vue normale'; $lang['mode_created_hint'] = 'afficher un calendrier par date de création'; +$lang['mode_normal_hint'] = 'retourne à la vue normale'; $lang['mode_posted_hint'] = 'afficher un calendrier par date d\'ajout'; $lang['month'][10] = 'Octobre'; $lang['month'][11] = 'Novembre'; @@ -227,10 +238,11 @@ $lang['month'][8] = 'Août'; $lang['month'][9] = 'Septembre'; $lang['most_visited_cat'] = 'Plus vues'; $lang['most_visited_cat_hint'] = 'afficher les images les plus vues'; -$lang['nb_image_per_row'] = 'Nombre de miniatures par ligne'; $lang['nb_image_line_error'] = 'Le nombre d\'images par ligne doit être un entier non nul'; -$lang['nb_row_per_page'] = 'Nombre de lignes par page'; +$lang['nb_image_per_row'] = 'Nombre de miniatures par ligne'; $lang['nb_line_page_error'] = 'Le nombre de lignes par page doit être un entier non nul'; +$lang['nb_row_per_page'] = 'Nombre de lignes par page'; +$lang['nbm_unknown_identifier'] = 'Identifiants inconnus'; $lang['never_rated'] = 'Vous n\'avez jamais voté pour cette image'; $lang['new_password'] = 'Nouveau mot de passe'; $lang['new_password_hint'] = 'Vous n\'avez à confirmer votre mot de passe que si vous désirez en changer.'; @@ -332,5 +344,4 @@ $lang['upload_username'] = 'Nom d\'utilisateur'; $lang['useful when password forgotten'] = 'utile en cas d\'oubli de mot de passe'; $lang['w_month'] = 'Mois'; $lang['yes'] = 'Oui'; -$lang['adviser_mode_enabled'] = 'Mode conseiller actif'; ?>
\ No newline at end of file diff --git a/picture.php b/picture.php index 91a944bc9..bb4f8ead7 100644 --- a/picture.php +++ b/picture.php @@ -698,25 +698,43 @@ $infos['INFO_VISITS'] = $picture['current']['hit']; // file $infos['INFO_FILE'] = $picture['current']['file']; -// keywords -if (!empty($picture['current']['keywords'])) +// tags +$query = ' +SELECT id, name, url_name + FROM '.IMAGE_TAG_TABLE.' + INNER JOIN '.TAGS_TABLE.' ON tag_id = id + WHERE image_id = '.$page['image_id'].' +;'; +$result = pwg_query($query); + +if (mysql_num_rows($result) > 0) { - $infos['INFO_KEYWORDS'] = - // FIXME because of search engine partial rewrite, giving the author - // name threw GET is not supported anymore. This feature should come - // back later, with a better design (tag classification). -// preg_replace( -// '/([^,]+)/', -// '<a href="'. -// PHPWG_ROOT_PATH.'category.php?cat=search&search=keywords:$1' -// .'">$1</a>', -// $picture['current']['keywords'] -// ); - $picture['current']['keywords']; + $tags = array(); + + while ($row = mysql_fetch_array($result)) + { + array_push( + $tags, + '<a href="' + .make_index_URL( + array( + 'tags' => array( + array( + 'id' => $row['id'], + 'url_name' => $row['url_name'], + ), + ) + ) + ) + .'">'.$row['name'].'</a>' + ); + } + + $infos['INFO_TAGS'] = implode(', ', $tags); } else { - $infos['INFO_KEYWORDS'] = l10n('N/A'); + $infos['INFO_TAGS'] = l10n('N/A'); } $template->assign_vars($infos); diff --git a/search.php b/search.php index 09131320e..2d6ce0c8f 100644 --- a/search.php +++ b/search.php @@ -65,6 +65,14 @@ if (isset($_POST['submit'])) ); } + if (isset($_POST['tags'])) + { + $search['fields']['tags'] = array( + 'words' => $_POST['tags'], + 'mode' => $_POST['tag_mode'], + ); + } + if ($_POST['search_author']) { $search['fields']['author'] = array( @@ -200,6 +208,16 @@ $template->assign_vars(array( 'S_SEARCH_ACTION' => 'search.php', 'U_HELP' => PHPWG_ROOT_PATH.'/popuphelp.php?page=search', 'U_HOME' => make_index_url(), + + 'TAG_SELECTION' => get_html_tag_selection( + get_available_tags( + isset($user['forbidden_categories']) + ? explode(',', $user['forbidden_categories']) + : null + ), + 'tags', + isset($_POST['tags']) ? $_POST['tags'] : array() + ), ) ); diff --git a/search_rules.php b/search_rules.php index 6e6900e90..51ccaf2c0 100644 --- a/search_rules.php +++ b/search_rules.php @@ -83,6 +83,34 @@ if (isset($search['fields']['allwords'])) ); } +if (isset($search['fields']['tags'])) +{ + $template->assign_block_vars( + 'tags', + array( + 'LIST_INTRO' => ($search['fields']['tags']['mode'] == 'AND') + ? l10n('All tags must match') + : l10n('At least one tag must match') + ) + ); + + $query = ' +SELECT name + FROM '.TAGS_TABLE.' + WHERE id IN ('.implode(',', $search['fields']['tags']['words']).') +;'; + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + $template->assign_block_vars( + 'tags.tag', + array( + 'NAME' => $row['name'], + ) + ); + } +} + if (isset($search['fields']['author'])) { $template->assign_block_vars( diff --git a/tags.php b/tags.php new file mode 100644 index 000000000..e61ee1f24 --- /dev/null +++ b/tags.php @@ -0,0 +1,120 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net | +// | Copyright (C) 2003-2005 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $RCSfile$ +// | last update : $Date: 2006-03-22 02:01:47 +0100 (mer, 22 mar 2006) $ +// | last modifier : $Author: rvelices $ +// | revision : $Revision: 1092 $ +// +-----------------------------------------------------------------------+ +// | 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. | +// +-----------------------------------------------------------------------+ + +// +-----------------------------------------------------------------------+ +// | functions | +// +-----------------------------------------------------------------------+ + +function counter_compare($a, $b) +{ + if ($a['counter'] == $b['counter']) + { + return tag_id_compare($a, $b); + } + + return ($a['counter'] < $b['counter']) ? -1 : 1; +} + +function tag_id_compare($a, $b) +{ + return ($a['tag_id'] < $b['tag_id']) ? -1 : 1; +} + +// +-----------------------------------------------------------------------+ +// | initialization | +// +-----------------------------------------------------------------------+ + +define('PHPWG_ROOT_PATH','./'); +include_once(PHPWG_ROOT_PATH.'include/common.inc.php'); + +check_status(ACCESS_GUEST); + +// +-----------------------------------------------------------------------+ +// | page header and options | +// +-----------------------------------------------------------------------+ + +$title= l10n('Tags'); +$page['body_id'] = 'theTagsPage'; +include(PHPWG_ROOT_PATH.'include/page_header.php'); + +$template->set_filenames(array('tags'=>'tags.tpl')); +$template->assign_vars( + array( + 'U_HOME' => make_index_url(), + ) + ); + +// +-----------------------------------------------------------------------+ +// | tag cloud construction | +// +-----------------------------------------------------------------------+ + +// find all tags available for the current user +$tags = get_available_tags(explode(',', $user['forbidden_categories'])); + +// we want only the first most represented tags, so we sort them by counter +// and take the first tags +usort($tags, 'counter_compare'); +$tags = array_slice($tags, 0, $conf['full_tag_cloud_items_number']); + +// depending on its counter and the other tags counter, each tag has a level +$tags = add_level_to_tags($tags); + +// we want tags diplayed in alphabetic order +usort($tags, 'name_compare'); + +// display sorted tags +foreach ($tags as $tag) +{ + $template->assign_block_vars( + 'tag', + array( + 'URL' => make_index_url( + array( + 'tags' => array( + array( + 'id' => $tag['tag_id'], + 'url_name' => $tag['url_name'], + ), + ), + ) + ), + + 'NAME' => $tag['name'], + 'TITLE' => $tag['counter'], + 'CLASS' => 'tagLevel'.$tag['level'], + ) + ); +} + +// +-----------------------------------------------------------------------+ +// | html code display | +// +-----------------------------------------------------------------------+ + +$template->assign_block_vars('title',array()); +$template->parse('tags'); +include(PHPWG_ROOT_PATH.'include/page_tail.php'); +?>
\ No newline at end of file diff --git a/template/yoga/admin.tpl b/template/yoga/admin.tpl index 785e312d9..6f0a58789 100644 --- a/template/yoga/admin.tpl +++ b/template/yoga/admin.tpl @@ -54,6 +54,7 @@ <li><a href="{U_COMMENTS}">{lang:comments}</a></li> <li><a href="{U_RATING}">{lang:Rating}</a></li> <li><a href="{U_CADDIE}">{lang:Caddie}</a></li> + <li><a href="{U_TAGS}">{lang:Tags}</a></li> </ul> </dd> diff --git a/template/yoga/admin/element_set_global.tpl b/template/yoga/admin/element_set_global.tpl index 53c956d40..a4e46508c 100644 --- a/template/yoga/admin/element_set_global.tpl +++ b/template/yoga/admin/element_set_global.tpl @@ -83,21 +83,15 @@ </tr> <tr> - <td>{lang:add keywords}</td> - <td><input type="text" name="add_keywords" value="" /></td> + <td>{lang:add tags}</td> + <td>{ADD_TAG_SELECTION}</td> </tr> <tr> - <td>{lang:remove keyword}</td> - <td> - <select name="remove_keyword"> - <!-- BEGIN remove_keyword_option --> - <option value="{remove_keyword_option.VALUE}">{remove_keyword_option.OPTION}</option> - <!-- END remove_keyword_option --> - </select> - </td> + <td>{lang:remove tags}</td> + <td>{DEL_TAG_SELECTION}</td> </tr> - + <tr> <td>{lang:author}</td> <td> diff --git a/template/yoga/admin/element_set_unit.tpl b/template/yoga/admin/element_set_unit.tpl index a5e718012..63b7fa5b6 100644 --- a/template/yoga/admin/element_set_unit.tpl +++ b/template/yoga/admin/element_set_unit.tpl @@ -69,8 +69,8 @@ </tr> <tr> - <td><strong>{lang:Keywords}</strong></td> - <td><input type="text" name="keywords-{element.ID}" value="{element.KEYWORDS}" size="50" /></td> + <td><strong>{lang:Tags}</strong></td> + <td>{element.TAG_SELECTION}</td> </tr> <tr> diff --git a/template/yoga/admin/picture_modify.tpl b/template/yoga/admin/picture_modify.tpl index 2be4547dd..c10e7744e 100644 --- a/template/yoga/admin/picture_modify.tpl +++ b/template/yoga/admin/picture_modify.tpl @@ -99,10 +99,11 @@ </tr> <tr> - <td><strong>{lang:Keywords}</strong></td> - <td><input type="text" name="keywords" value="{KEYWORDS}" size="50" /></td> + <td><strong>{lang:Tags}</strong></td> + <td>{TAG_SELECTION}</td> </tr> + <tr> <td><strong>{lang:Description}</strong></td> <td><textarea name="description" class="description">{DESCRIPTION}</textarea></td> diff --git a/template/yoga/admin/tags.tpl b/template/yoga/admin/tags.tpl new file mode 100644 index 000000000..c39181580 --- /dev/null +++ b/template/yoga/admin/tags.tpl @@ -0,0 +1,55 @@ +<div class="titrePage"> + <h2>{lang:Manage tags}</h2> +</div> + +<form action="{F_ACTION}" method="post"> + + <!-- BEGIN edit_tags --> + <input type="hidden" name="edit_list" value="{edit_tags.LIST}" /> + + <fieldset> + <legend>{lang:Edit tags}</legend> + + <table class="table2"> + <tr class="throw"> + <th>{lang:Current name}</th> + <th>{lang:New name}</th> + </tr> + <!-- BEGIN tag --> + <tr> + <td>{edit_tags.tag.NAME}</td> + <td><input type="text" name="tag_name-{edit_tags.tag.ID}" value="{edit_tags.tag.NAME}" /></td> + </tr> + <!-- END tag --> + </table> + + <p> + <input type="submit" name="submit" value="{lang:Submit}" {TAG_INPUT_ENABLED} /> + <input type="reset" value="{lang:Reset}" /> + </p> + </fieldset> + <!-- END edit_tags --> + + <fieldset> + <legend>{lang:Add a tag}</legend> + + <label> + {lang:New tag} + <input type="text" name="add_tag" /> + </label> + + <p><input type="submit" name="add" value="{lang:Submit}" {TAG_INPUT_ENABLED}/></p> + </fieldset> + + <fieldset> + <legend>{lang:Tag selection}</legend> + + {TAG_SELECTION} + + <p> + <input type="submit" name="edit" value="{lang:Edit selected tags}" {TAG_INPUT_ENABLED}/> + <input type="submit" name="delete" value="{lang:Delete selected tags}" {TAG_INPUT_ENABLED}/> + </p> + </fieldset> + +</form> diff --git a/template/yoga/content.css b/template/yoga/content.css index 2054efd78..56599ec93 100644 --- a/template/yoga/content.css +++ b/template/yoga/content.css @@ -13,6 +13,7 @@ BODY#theAboutPage #content, BODY#thePopuphelpPage #content, BODY#thePasswordPage #content, BODY#theNotificationPage #content, +BODY#theTagsPage #content, BODY#theNBMPage #content { margin: 1em; diff --git a/template/yoga/default-layout.css b/template/yoga/default-layout.css index d8aab0732..a5637c17e 100644 --- a/template/yoga/default-layout.css +++ b/template/yoga/default-layout.css @@ -261,3 +261,12 @@ UL.actions A { border: none; } +UL.tagSelection { + width: 500px; + padding: 0; +} + +UL.tagSelection LI { + display: inline; + white-space: nowrap; +}
\ No newline at end of file diff --git a/template/yoga/icon/add_tag.png b/template/yoga/icon/add_tag.png Binary files differnew file mode 100644 index 000000000..5c5e235de --- /dev/null +++ b/template/yoga/icon/add_tag.png diff --git a/template/yoga/index.tpl b/template/yoga/index.tpl index df6e4d249..494d2059b 100644 --- a/template/yoga/index.tpl +++ b/template/yoga/index.tpl @@ -19,6 +19,23 @@ <p class="totalImages">{NB_PICTURE} {lang:total}</p> </dd> </dl> + +<!-- BEGIN tags --> +<dl> + <dt>{lang:Related tags}</dt> + <dd> + <ul id="menuTagCloud"> + <!-- BEGIN tag --> + <li> + <a href="{tags.tag.URL_ADD}" title="{tags.tag.TITLE_ADD}"><img src="{pwg_root}{themeconf:icon_dir}/add_tag.png" alt="+"></a> + <a href="{tags.tag.URL}" class="{tags.tag.CLASS}" title="{tags.tag.TITLE}">{tags.tag.NAME}</a> + </li> + <!-- END tag --> + </ul> + </dd> +</dl> +<!-- END tags --> + <dl> <dt>{lang:special_categories}</dt> <dd> diff --git a/template/yoga/menubar.css b/template/yoga/menubar.css index b1a768aa9..c965d0753 100644 --- a/template/yoga/menubar.css +++ b/template/yoga/menubar.css @@ -95,3 +95,12 @@ FORM#quickconnect LABEL { margin: 0 0.5em 0 0.5em; } +#menubar #menuTagCloud { + text-align: center; + margin: 5px 0; +} + +#menubar #menuTagCloud LI +{ + display: inline; +}
\ No newline at end of file diff --git a/template/yoga/picture.tpl b/template/yoga/picture.tpl index 50fcf5f5f..82260bc96 100644 --- a/template/yoga/picture.tpl +++ b/template/yoga/picture.tpl @@ -107,8 +107,8 @@ <td class="value">{INFO_FILESIZE}</td> </tr> <tr> - <td class="label">{lang:Keywords}</td> - <td class="value">{INFO_KEYWORDS}</td> + <td class="label">{lang:Tags}</td> + <td class="value">{INFO_TAGS}</td> </tr> <tr> <td class="label">{lang:Categories}</td> diff --git a/template/yoga/search.tpl b/template/yoga/search.tpl index ca7e8346b..6a3fb9f1e 100644 --- a/template/yoga/search.tpl +++ b/template/yoga/search.tpl @@ -35,6 +35,16 @@ <input type="text" style="width: 300px" name="search_author" size="30" /> </td> </tr> + + <tr> + <td colspan="2"><b>{lang:Search tags} :</b></td> + <td colspan="2" valign="middle"> + {TAG_SELECTION} + <br /><label><input type="radio" name="tag_mode" value="AND" checked="checked" /> {lang:All tags}</label> + <br /><label><input type="radio" name="tag_mode" value="OR" /> {lang:Any tag}</label> + </td> + </tr> + <tr> <td colspan="2"><b>{L_SEARCH_DATE} :</b> <td colspan="2" valign="middle"> diff --git a/template/yoga/search_rules.tpl b/template/yoga/search_rules.tpl index aac2586fe..921df4a12 100644 --- a/template/yoga/search_rules.tpl +++ b/template/yoga/search_rules.tpl @@ -9,6 +9,18 @@ <li>{words.CONTENT}</li> <!-- END words --> + <!-- BEGIN tags --> + <li> + <p>{tags.LIST_INTRO}</p> + + <ul> + <!-- BEGIN tag --> + <li>{tags.tag.NAME}</li> + <!-- END tag --> + </ul> + </li> + <!-- END tags --> + <!-- BEGIN author --> <li>{author.CONTENT}</li> <!-- END author --> diff --git a/template/yoga/tags.tpl b/template/yoga/tags.tpl new file mode 100644 index 000000000..33f69ca69 --- /dev/null +++ b/template/yoga/tags.tpl @@ -0,0 +1,17 @@ +<!-- $Id: comments.tpl 960 2005-12-03 17:33:38Z chrisaga $ --> +<div id="content"> + + <div class="titrePage"> + <ul class="categoryActions"> + <li><a href="{U_HOME}" title="{lang:return to homepage}"><img src="{themeconf:icon_dir}/home.png" class="button" alt="{lang:home}"/></a></li> + </ul> + <h2>{lang:Tags}</h2> + </div> + + <ul id="fullTagCloud"> + <!-- BEGIN tag --> + <li><a href="{tag.URL}" class="{tag.CLASS}" title="{tag.TITLE}">{tag.NAME}</a></li> + <!-- END tag --> + </ul> + +</div> <!-- content --> |