diff --git a/admin/themes/default/js/album_selector.js b/admin/themes/default/js/album_selector.js index 983faa79e..6b9825916 100644 --- a/admin/themes/default/js/album_selector.js +++ b/admin/themes/default/js/album_selector.js @@ -17,15 +17,29 @@ function linked_albums_open() { } function linked_albums_search(searchText) { - $(".linkedAlbumPopInContainer .searching").show(); - $.ajax({ - url: "ws.php?format=json&method=pwg.categories.getAdminList", - type: "POST", - dataType: "json", - data : { + + if (api_method == 'pwg.categories.getList') { + api_params = { + cat_id: 0, + recursive: true, + fullname: true, + } + } else { + api_params = { search: searchText, additional_output: "full_name_with_admin_links", - }, + } + } + + console.log('lalalal'); + console.log(api_method); + + $(".linkedAlbumPopInContainer .searching").show(); + $.ajax({ + url: "ws.php?format=json&method=" + api_method, + type: "POST", + dataType: "json", + data : api_params, before: function () { }, diff --git a/admin/themes/default/template/include/album_selector.inc.tpl b/admin/themes/default/template/include/album_selector.inc.tpl index 45bec48ec..e548ed24c 100644 --- a/admin/themes/default/template/include/album_selector.inc.tpl +++ b/admin/themes/default/template/include/album_selector.inc.tpl @@ -1,6 +1,18 @@ {if empty($load_mode)}{$load_mode='footer'}{/if} {include file='include/colorbox.inc.tpl' load_mode=$load_mode} {combine_script id='albumSelector' load_mode=$load_mode path='admin/themes/default/js/album_selector.js'} +{footer_script} + str_no_search_in_progress = '{'No search in progress'|@translate|escape:javascript}'; + str_albums_found = '{"%d albums found"|translate}'; + str_album_found = '{"1 album found"|translate}'; + + {if isset($api_method)} + api_method = '{$api_method}'; + {else} + api_method = 'pwg.categories.getAdminList'; + {/if} + +{/footer_script}
diff --git a/include/functions_search.inc.php b/include/functions_search.inc.php index 5c4eeb89a..778e9220b 100644 --- a/include/functions_search.inc.php +++ b/include/functions_search.inc.php @@ -65,18 +65,22 @@ function get_sql_search_clause($search) } } - // adds brackets around where clauses - $local_clauses = prepend_append_array_items($local_clauses, '(', ')'); + if (count($local_clauses) > 0) + { + // adds brackets around where clauses + $local_clauses = prepend_append_array_items($local_clauses, '(', ')'); - $clauses[] = implode( - ' '.$search['fields'][$textfield]['mode'].' ', - $local_clauses + $clauses[] = implode( + ' '.$search['fields'][$textfield]['mode'].' ', + $local_clauses ); + } } } - if (isset($search['fields']['allwords']) and count($search['fields']['allwords']['fields']) > 0) + if (isset($search['fields']['allwords']) and !empty($search['fields']['allwords']['words']) and count($search['fields']['allwords']['fields']) > 0) { + // 1) we search in regular fields (ie, the ones in the piwigo_images table) $fields = array('file', 'name', 'comment'); if (isset($search['fields']['allwords']['fields']) and count($search['fields']['allwords']['fields']) > 0) @@ -117,11 +121,48 @@ function get_sql_search_clause($search) $search['fields']['allwords']['mode'] = 'AND'; } + // 2) we search the words in album titles/descriptions + $cat_fields_dictionnary = array( + 'cat-title' => 'name', + 'cat-desc' => 'comment', + ); + $cat_fields = array_intersect(array_keys($cat_fields_dictionnary), $search['fields']['allwords']['fields']); + + if (count($cat_fields) > 0) + { + $cat_word_clauses = array(); + foreach ($search['fields']['allwords']['words'] as $word) + { + $field_clauses = array(); + foreach ($cat_fields as $cat_field) + { + $field_clauses[] = $cat_fields_dictionnary[$cat_field]." LIKE '%".$word."%'"; + } + + // adds brackets around where clauses + $cat_word_clauses[] = implode(' OR ', $field_clauses); + } + + $query = ' +SELECT + id + FROM '.CATEGORIES_TABLE.' + WHERE '.implode(' OR ', $cat_word_clauses).' +;'; + $cat_ids = query2array($query, null, 'id'); + if (count($cat_ids) > 0) + { + $word_clauses[] = 'category_id IN ('.implode(',', $cat_ids).')'; + } + } + $clauses[] = "\n ". implode( "\n ". $search['fields']['allwords']['mode']. "\n ", $word_clauses ); + + // 3) the case of searching among tags is handled by search_in_tags in function get_regular_search_results } foreach (array('date_available', 'date_creation') as $datefield) @@ -145,7 +186,12 @@ function get_sql_search_clause($search) } } - if (isset($search['fields']['cat'])) + if (!empty($search['fields']['added_by'])) + { + $clauses[] = 'added_by IN ('.implode(',', $search['fields']['added_by']).')'; + } + + if (isset($search['fields']['cat']) and !empty($search['fields']['cat']['words'])) { if ($search['fields']['cat']['sub_inc']) { @@ -201,7 +247,15 @@ function get_regular_search_results($search, $images_where='') $items = array(); $tag_items = array(); - if (isset($search['fields']['search_in_tags'])) + // starting with version 14, we no longer have $search['fields']['search_in_tags'] but 'tags' + // in the array $search['fields']['allwords']['fields']. Let's convert, without changing the + // search algorithm + if (!empty($search['fields']['allwords']['fields']) and in_array('tags', $search['fields']['allwords']['fields'])) + { + $search['fields']['search_in_tags'] = true; + } + + if (isset($search['fields']['search_in_tags']) and !empty($search['fields']['allwords']['words'])) { $word_clauses = array(); foreach ($search['fields']['allwords']['words'] as $word) diff --git a/include/ws_functions/pwg.images.php b/include/ws_functions/pwg.images.php index 634f3bb0a..eae6b13d6 100644 --- a/include/ws_functions/pwg.images.php +++ b/include/ws_functions/pwg.images.php @@ -688,6 +688,170 @@ SELECT * ); } +/** + * API method + * Returns a list of elements corresponding to a query search + * @param mixed[] $params + * @option string query + * @option int per_page + * @option int page + * @option string order (optional) + */ +function ws_images_filteredSearch_update($params, $service) +{ + // echo json_encode($params); exit(); + + // * check the search exists + $query = ' +SELECT id + FROM '.SEARCH_TABLE.' + WHERE id = '.$params['search_id'].' +;'; + + if (count(query2array($query)) == 0) + { + return new PwgError(WS_ERR_INVALID_PARAM, 'This search does not exist.'); + } + + $search = array('mode' => 'AND'); + + // TODO we should check that this search is updated by the user who created the search. + + // * check all parameters + if (isset($params['allwords'])) + { + $search['fields']['allwords'] = array(); + + if (!isset($params['allwords_mode'])) + { + $params['allwords_mode'] = 'AND'; + } + if (!preg_match('/^(OR|AND)$/', $params['allwords_mode'])) + { + return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid parameter allwords_mode'); + } + $search['fields']['allwords']['mode'] = $params['allwords_mode']; + + $allwords_fields_available = array('name', 'comment', 'file', 'tags', 'cat-title', 'cat-desc'); + if (!isset($params['allwords_fields'])) + { + $params['allwords_fields'] = $allwords_fields_available; + } + foreach ($params['allwords_fields'] as $field) + { + if (!in_array($field, $allwords_fields_available)) + { + return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid parameter allwords_fields'); + } + } + $search['fields']['allwords']['fields'] = $params['allwords_fields']; + + $search['fields']['allwords']['words'] = null; + if (!preg_match('/^\s*$/', $params['allwords'])) + { + $drop_char_match = array( + '-','^','$',';','#','&','(',')','<','>','`','\'','"','|',',','@','_', + '?','%','~','.','[',']','{','}',':','\\','/','=','\'','!','*' + ); + $drop_char_replace = array( + ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','','',' ',' ',' ',' ','',' ', + ' ',' ',' ',' ',' ',' ',' ',' ','' ,' ',' ',' ',' ',' ' + ); + + // Split words + $search['fields']['allwords']['words'] = array_unique( + preg_split( + '/\s+/', + str_replace( + $drop_char_match, + $drop_char_replace, + $params['allwords'] + ) + ) + ); + } + } + + if (isset($params['tags'])) + { + foreach ($params['tags'] as $tag_id) + { + if (!preg_match('/^\d+$/', $tag_id)) + { + return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid parameter tags'); + } + } + + if (!isset($params['tags_mode'])) + { + $params['tags_mode'] = 'AND'; + } + if (!preg_match('/^(OR|AND)$/', $params['tags_mode'])) + { + return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid parameter tags_mode'); + } + + $search['fields']['tags'] = array( + 'words' => $params['tags'], + 'mode' => $params['tags_mode'], + ); + } + + if (isset($params['categories'])) + { + foreach ($params['categories'] as $cat_id) + { + if (!preg_match('/^\d+$/', $cat_id)) + { + return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid parameter categories'); + } + } + + $search['fields']['cat'] = array( + 'words' => $params['categories'], + 'sub_inc' => $params['categories_withsubs'] ?? false, + ); + } + + if (isset($params['authors'])) + { + $authors = array(); + + foreach ($params['authors'] as $author) + { + $authors[] = strip_tags($author); + } + + $search['fields']['author'] = array( + 'words' => $authors, + 'mode' => 'OR', + ); + } + + if (isset($params['added_by'])) + { + foreach ($params['added_by'] as $user_id) + { + if (!preg_match('/^\d+$/', $user_id)) + { + return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid parameter added_by'); + } + } + + $search['fields']['added_by'] = $params['added_by']; + } + + // register search rules in database, then they will be available on + // thumbnails page and picture page. + $query =' +UPDATE '.SEARCH_TABLE.' + SET rules = \''.pwg_db_real_escape_string(serialize($search)).'\' + , last_seen = NOW() + WHERE id = '.$params['search_id'].' +;'; + pwg_query($query); +} + /** * API method * Sets the level of an image diff --git a/include/ws_functions/pwg.php b/include/ws_functions/pwg.php index 86457c84b..bbb31546e 100644 --- a/include/ws_functions/pwg.php +++ b/include/ws_functions/pwg.php @@ -1068,4 +1068,43 @@ SELECT 'summary' => $search_summary ); } + +function ws_gallery_getSearch($param, &$service) +{ + // return $param; + if (is_null($param['search_id'])) + { + // Créer une recherche + return new PwgError(404, 'Search id is null'); + } + include_once(PHPWG_ROOT_PATH.'include/functions_search.inc.php'); + + if (get_search_array($param['search_id']) == false) + { + return new PwgError(1404, 'Search associated to id '.$param['search_id'].' not found'); + } + + return get_search_array($param['search_id']); +} + +function ws_gallery_updateSearch($param, &$service) +{ + // return $param; + if (is_null($param['search_id'])) + { + // Créer une recherche + return new PwgError(404, 'Search id is null'); + } + include_once(PHPWG_ROOT_PATH.'include/functions_search.inc.php'); + + if (get_search_array($param['search_id']) == false) + { + return new PwgError(404, 'Search associated to id '.$param['search_id'].' not found'); + } + + $tmp = get_search_array($param['search_id']); + + // return 'search #'.$param['search_id'].' updated'; + return $param; +} ?> diff --git a/index.php b/index.php index 84a378937..10dd85e76 100644 --- a/index.php +++ b/index.php @@ -346,6 +346,146 @@ if ( empty($page['is_external']) ) } } + +$available_tags = get_available_tags(); + +if (count($available_tags) > 0) +{ + usort( $available_tags, 'tag_alpha_compare'); + + $template->assign('TAGS', $available_tags); +} + +// authors +$authors = array(); + +$query = ' +SELECT + author, + id + FROM '.IMAGES_TABLE.' AS i + JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON ic.image_id = i.id + '.get_sql_condition_FandF( + array( + 'forbidden_categories' => 'category_id', + 'visible_categories' => 'category_id', + 'visible_images' => 'id' + ), + ' WHERE ' + ).' + AND author IS NOT NULL + GROUP BY author, id + ORDER BY author +;'; +$author_counts = array(); +$result = pwg_query($query); +while ($row = pwg_db_fetch_assoc($result)) +{ + if (!isset($author_counts[ $row['author'] ])) + { + $author_counts[ $row['author'] ] = 0; + } + + $author_counts[ $row['author'] ]++; +} + +foreach ($author_counts as $author => $counter) +{ + $authors[] = array( + 'author' => $author, + 'counter' => $counter, + ); +} + +$template->assign('AUTHORS', $authors); + +// added by +$query = ' +SELECT + id, + username + FROM + '.USERS_TABLE.' +;'; +$username_of = query2array($query, 'id', 'username'); + +$added_by = array(); + +$query = ' +SELECT + count(added_by) as nb_photos, + added_by + FROM '.IMAGES_TABLE.' + GROUP BY + added_by + ORDER BY + nb_photos DESC +;'; + +$result = pwg_query($query); + +while ($row = pwg_db_fetch_assoc($result)) +{ + $added_by[] = array( + 'added_by_id' => $row['added_by'], + 'added_by_name' => $username_of[$row['added_by']], + 'counter' => $row['nb_photos'], + ); +} + +$template->assign('ADDED_BY', $added_by); + +// albums +if (isset($page['search'])) { + $my_search = get_search_array($page['search']); + $template->assign('SEARCH_ID', $page['search']); +} + +if (isset($my_search['fields']['cat']) and !empty($my_search['fields']['cat']['words'])) +{ + $fullname_of = array(); + + $query = ' +SELECT + id, + uppercats + FROM '.CATEGORIES_TABLE.' + WHERE + id + IN ('.implode(", ", array_values($my_search['fields']['cat']['words'])).') + ;'; + + $result = pwg_query($query); + + while ($row = pwg_db_fetch_assoc($result)) + { + $cat_display_name = get_cat_display_name_cache( + $row['uppercats'], + 'admin.php?page=album-' + ); + $row['fullname'] = strip_tags($cat_display_name); + + $fullname_of[$row['id']] = $row['fullname']; + } + + $template->assign('fullname_of', json_encode($fullname_of)); +} + +if (isset($page['search'])) { + if (is_null($page['search'])) + { + $page['errors'][] = l10n('Search id is null'); + } + include_once(PHPWG_ROOT_PATH.'include/functions_search.inc.php'); + + if (get_search_array($page['search']) == false) + { + $page['errors'][] = l10n('Search associated to id '.$page['search'].' not found'); + } + $template->assign('GP', json_encode(get_search_array($page['search']))); +} + + //------------------------------------------------------------ end include(PHPWG_ROOT_PATH.'include/page_header.php'); trigger_notify('loc_end_index'); diff --git a/search.php b/search.php index cd6d8c05c..c59846b21 100644 --- a/search.php +++ b/search.php @@ -17,196 +17,36 @@ check_status(ACCESS_GUEST); trigger_notify('loc_begin_search'); -//------------------------------------------------------------------ form check -$search = array(); -if (isset($_POST['submit'])) +// +-----------------------------------------------------------------------+ +// | Create a default search | +// +-----------------------------------------------------------------------+ + +$search = array( + 'mode' => 'AND', + 'fields' => array( + 'allwords' => array( + 'words' => array(), + 'mode' => 'AND', + 'fields' => array('file', 'name', 'comment', 'tags', 'cat-title', 'cat-desc'), + ), + 'cat' => array( + 'words' => array(), + 'sub_inc' => true, + ), + ), +); + +if (count(get_available_tags()) > 0) { - foreach ($_POST as $post_key => $post_value) - { - if (!is_array($post_value)) - { - $_POST[$post_key] = pwg_db_real_escape_string($post_value); - } - } - - if (isset($_POST['search_allwords']) - and !preg_match('/^\s*$/', $_POST['search_allwords'])) - { - check_input_parameter('mode', $_POST, false, '/^(OR|AND)$/'); - check_input_parameter('fields', $_POST, true, '/^(name|comment|file)$/'); - - $drop_char_match = array( - '-','^','$',';','#','&','(',')','<','>','`','\'','"','|',',','@','_', - '?','%','~','.','[',']','{','}',':','\\','/','=','\'','!','*'); - $drop_char_replace = array( - ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','','',' ',' ',' ',' ','',' ', - ' ',' ',' ',' ',' ',' ',' ',' ','' ,' ',' ',' ',' ',' '); - - // Split words - $search['fields']['allwords'] = array( - 'words' => array_unique( - preg_split( - '/\s+/', - str_replace( - $drop_char_match, - $drop_char_replace, - $_POST['search_allwords'] - ) - ) - ), - 'mode' => $_POST['mode'], - 'fields' => $_POST['fields'], - ); - - if (isset($_POST['search_in_tags'])) - { - $search['fields']['search_in_tags'] = true; - } - } - - if (isset($_POST['tags'])) - { - check_input_parameter('tags', $_POST, true, PATTERN_ID); - check_input_parameter('tag_mode', $_POST, false, '/^(OR|AND)$/'); - - $search['fields']['tags'] = array( - 'words' => $_POST['tags'], - 'mode' => $_POST['tag_mode'], - ); - } - - if (isset($_POST['authors']) and is_array($_POST['authors']) and count($_POST['authors']) > 0) - { - $authors = array(); - - foreach ($_POST['authors'] as $author) - { - $authors[] = strip_tags($author); - } - - $search['fields']['author'] = array( - 'words' => $authors, - 'mode' => 'OR', - ); - } - - if (isset($_POST['cat'])) - { - check_input_parameter('cat', $_POST, true, PATTERN_ID); - - $search['fields']['cat'] = array( - 'words' => $_POST['cat'], - 'sub_inc' => ($_POST['subcats-included'] == 1) ? true : false, - ); - } - - // dates - check_input_parameter('date_type', $_POST, false, '/^date_(creation|available)$/'); - - $type_date = $_POST['date_type']; - - if (!empty($_POST['start_year'])) - { - $search['fields'][$type_date.'-after'] = array( - 'date' => sprintf( - '%d-%02d-%02d 00:00:00', - $_POST['start_year'], - $_POST['start_month'] != 0 ? $_POST['start_month'] : '01', - $_POST['start_day'] != 0 ? $_POST['start_day'] : '01' - ), - 'inc' => true, - ); - } - - if (!empty($_POST['end_year'])) - { - $search['fields'][$type_date.'-before'] = array( - 'date' => sprintf( - '%d-%02d-%02d 23:59:59', - $_POST['end_year'], - $_POST['end_month'] != 0 ? $_POST['end_month'] : '12', - $_POST['end_day'] != 0 ? $_POST['end_day'] : '31' - ), - 'inc' => true, - ); - } - - if (!empty($search)) - { - // default search mode : each clause must be respected - $search['mode'] = 'AND'; - - // register search rules in database, then they will be available on - // thumbnails page and picture page. - $query =' -INSERT INTO '.SEARCH_TABLE.' - (rules, last_seen) - VALUES - (\''.pwg_db_real_escape_string(serialize($search)).'\', NOW()) -;'; - pwg_query($query); - - $search_id = pwg_db_insert_id(SEARCH_TABLE); - } - else - { - $page['errors'][] = l10n('Empty query. No criteria has been entered.'); - } -} -//----------------------------------------------------------------- redirection -if (isset($_POST['submit']) and count($page['errors']) == 0) -{ - redirect( - make_index_url( - array( - 'section' => 'search', - 'search' => $search_id, - ) - ) - ); -} -//----------------------------------------------------- template initialization - -// -// Start output of page -// -$title= l10n('Search'); -$page['body_id'] = 'theSearchPage'; - -$template->set_filename('search' ,'search.tpl' ); - -$month_list = $lang['month']; -$month_list[0]='------------'; -ksort($month_list); - -$template->assign( - array( - 'F_SEARCH_ACTION' => 'search.php', - 'U_HELP' => PHPWG_ROOT_PATH.'popuphelp.php?page=search', - - 'month_list' => $month_list, - 'START_DAY_SELECTED' => @$_POST['start_day'], - 'START_MONTH_SELECTED' => @$_POST['start_month'], - 'END_DAY_SELECTED' => @$_POST['end_day'], - 'END_MONTH_SELECTED' => @$_POST['end_month'], - ) + $search['fields']['tags'] = array( + 'words' => array(), + 'mode' => 'AND', ); - -$available_tags = get_available_tags(); - -if (count($available_tags) > 0) -{ - usort( $available_tags, 'tag_alpha_compare'); - - $template->assign('TAGS', $available_tags); } -// authors -$authors = array(); - +// does this Piwigo has authors for current user? $query = ' SELECT - author, id FROM '.IMAGES_TABLE.' AS i JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON ic.image_id = i.id @@ -219,58 +59,36 @@ SELECT ' WHERE ' ).' AND author IS NOT NULL - GROUP BY author, id - ORDER BY author + LIMIT 1 ;'; -$author_counts = array(); -$result = pwg_query($query); -while ($row = pwg_db_fetch_assoc($result)) +$first_author = query2array($query); + +if (count($first_author) > 0) { - if (!isset($author_counts[ $row['author'] ])) - { - $author_counts[ $row['author'] ] = 0; - } - - $author_counts[ $row['author'] ]++; + $search['fields']['author'] = array( + 'words' => array(), + 'mode' => 'OR', + ); } -foreach ($author_counts as $author => $counter) -{ - $authors[] = array( - 'author' => $author, - 'counter' => $counter, - ); -} +list($dbnow) = pwg_db_fetch_row(pwg_query('SELECT NOW()')); -$template->assign('AUTHORS', $authors); +single_insert( + SEARCH_TABLE, + array( + 'rules' => pwg_db_real_escape_string(serialize($search)), + 'last_seen' => $dbnow, + ) +); -//------------------------------------------------------------- categories form -$query = ' -SELECT id,name,global_rank,uppercats - FROM '.CATEGORIES_TABLE.' -'.get_sql_condition_FandF - ( - array - ( - 'forbidden_categories' => 'id', - 'visible_categories' => 'id' - ), - 'WHERE' - ).' -;'; -display_select_cat_wrapper($query, array(), 'category_options', true); +$search_id = pwg_db_insert_id(SEARCH_TABLE); -// include menubar -$themeconf = $template->get_template_vars('themeconf'); -if (!isset($themeconf['hide_menu_on']) OR !in_array('theSearchPage', $themeconf['hide_menu_on'])) -{ - include( PHPWG_ROOT_PATH.'include/menubar.inc.php'); -} - -//------------------------------------------------------------ html code display -include(PHPWG_ROOT_PATH.'include/page_header.php'); -trigger_notify('loc_end_search'); -flush_page_messages(); -$template->pparse('search'); -include(PHPWG_ROOT_PATH.'include/page_tail.php'); +redirect( + make_index_url( + array( + 'section' => 'search', + 'search' => $search_id, + ) + ) +); ?> diff --git a/themes/default/js/mcs.js b/themes/default/js/mcs.js new file mode 100644 index 000000000..62e52bf0f --- /dev/null +++ b/themes/default/js/mcs.js @@ -0,0 +1,647 @@ +$(document).ready(function () { + related_categories_ids = []; + + $(".linkedAlbumPopInContainer .ClosePopIn").addClass("pwg-icon-cancel"); + $(".filter-validate").on("click", function () { + $(this).find(".loading").css("display", "block"); + $(this).find(".validate-text").hide(); + }); + + $(".filter-form").hover( + function () { + $(this).parent().find(".mcs-icon.remove-filter").css({ + display: 'none', + }); + $(this).parent().find(".mcs-icon.filter-icon").css({ + display: 'block', + }); + }, + function () { + $(this).parent().find(".mcs-icon.remove-filter").css({ + display: 'block', + }); + $(this).parent().find(".mcs-icon.filter-icon").css({ + display: 'none', + }); + }); + + global_params.search_id = search_id; + console.log("Global params after fetch"); + console.log(global_params); + + if (!global_params.fields) { + global_params.fields = {}; + } + + // Declare params sent to pwg.images.filteredSearch.update + PS_params = {}; + PS_params.search_id = search_id; + + // Setup word filter + if (global_params.fields.allwords) { + $(".filter-word").css("display", "flex"); + $(".filter-manager-controller.word").prop("checked", true); + + word_search_str = ""; + word_search_words = global_params.fields.allwords.words != null ? global_params.fields.allwords.words : []; + word_search_words.forEach(word => { + word_search_str += word + " "; + }); + $("#word-search").val(word_search_str.slice(0, -1)); + + if (global_params.fields.allwords.words && global_params.fields.allwords.words.length > 0) { + $(".filter-word").addClass("filter-filled"); + $(".filter-word .search-words").html(word_search_str.slice(0, -1)); + } else { + $(".filter-word .search-words").html(str_word_widget); + } + + word_search_fields = global_params.fields.allwords.fields; + Object.keys(word_search_fields).forEach(field_key => { + $("#"+word_search_fields[field_key]).prop("checked", true); + }); + + word_search_mode = global_params.fields.allwords.mode; + $(".word-search-options input[value=" + word_search_mode + "]").prop("checked", true); + + if (global_params.fields.search_in_tags) { + $("#tags").prop("checked", true); + } + + PS_params.allwords = word_search_str.slice(0, -1); + PS_params.allwords_fields = word_search_fields; + PS_params.allwords_mode = word_search_mode; + } + //Hide filter spinner + $(".filter-spinner").hide(); + + // Setup tag filter + $("#tag-search").each(function() { + $(this).selectize({ + plugins: ['remove_button'], + maxOptions:$(this).find("option").length, + items: global_params.fields.tags ? global_params.fields.tags.words : null, + }); + }); + if (global_params.fields.tags) { + $(".filter-tag").css("display", "flex"); + $(".filter-manager-controller.tags").prop("checked", true); + $(".filter-tag-form .search-params input[value=" + global_params.fields.tags.mode + "]").prop("checked", true); + + tag_search_str = ""; + $("#tag-search")[0].selectize.getValue().forEach(id => { + tag_search_str += $("#tag-search")[0].selectize.getItem(id).text().replace(/\(\d+ \w+\)×/, '').trim() + ", "; + }); + if (global_params.fields.tags.words && global_params.fields.tags.words.length > 0) { + $(".filter-tag").addClass("filter-filled"); + $(".filter.filter-tag .search-words").text(tag_search_str.slice(0, -2)); + } else { + $(".filter.filter-tag .search-words").text("Tags"); + } + + + PS_params.tags = global_params.fields.tags.words.length > 0 ? global_params.fields.tags.words : ''; + PS_params.tags_mode = global_params.fields.tags.mode; + } + + // Setup album filter + if (global_params.fields.cat) { + console.log("there is an album in the search"); + $(".filter-album").css("display", "flex"); + $(".filter-manager-controller.album").prop("checked", true); + + album_widget_value = ""; + global_params.fields.cat.words.forEach(cat_id => { + add_related_category(cat_id, fullname_of_cat[cat_id]); + album_widget_value += fullname_of_cat[cat_id] + ", "; + }); + if (global_params.fields.cat.words && global_params.fields.cat.words.length > 0) { + $(".filter-album").addClass("filter-filled"); + $(".filter-album .search-words").html(album_widget_value.slice(0, -2)); + } else { + $(".filter-album .search-words").html("Album"); + } + + + if (global_params.fields.cat.sub_inc) { + $("#search-sub-cats").prop("checked", true); + } + + PS_params.categories = global_params.fields.cat.words.length > 0 ? global_params.fields.cat.words : ''; + PS_params.categories_withsubs = global_params.fields.cat.sub_inc; + } + + // Setup author filter + $("#authors").each(function() { + $(this).selectize({ + plugins: ['remove_button'], + maxOptions:$(this).find("option").length, + items: global_params.fields.author ? global_params.fields.author.words : null, + }); + if (global_params.fields.author) { + $(".filter-author").css("display", "flex"); + $(".filter-manager-controller.author").prop("checked", true); + + author_search_str = ""; + $("#authors")[0].selectize.getValue().forEach(id => { + author_search_str += $("#authors")[0].selectize.getItem(id).text().replace(/\(\d+ \w+\)×/, '').trim() + ", "; + }); + + if (global_params.fields.author.words && global_params.fields.author.words.length > 0) { + $(".filter-author").addClass("filter-filled"); + $(".filter.filter-author .search-words").text(author_search_str.slice(0, -2)); + } else { + $(".filter.filter-author .search-words").text("Author"); + } + + + PS_params.authors = global_params.fields.author.words.length > 0 ? global_params.fields.author.words : ''; + } + }); + + // Setup added_by filter + $("#added_by").each(function() { + $(this).selectize({ + plugins: ['remove_button'], + maxOptions:$(this).find("option").length, + items: global_params.fields.added_by ? global_params.fields.added_by : null, + }); + if (global_params.fields.added_by) { + $(".filter-added_by").css("display", "flex"); + $(".filter-manager-controller.added_by").prop("checked", true); + + added_search_str = ""; + $("#added_by")[0].selectize.getValue().forEach(id => { + added_search_str += $("#added_by")[0].selectize.getItem(id).text().replace(/\(\d+ \w+\)×/, '').trim() + ", "; + }); + if (global_params.fields.added_by && global_params.fields.added_by.length > 0) { + $(".filter-added_by").addClass("filter-filled"); + $(".filter.filter-added_by .search-words").text(added_search_str.slice(0, -2)); + } else { + $(".filter.filter-added_by .search-words").text("Added by"); + } + + + PS_params.added_by = global_params.fields.added_by.length > 0 ? global_params.fields.added_by : ''; + } + }); + + /** + * Filter Manager + */ + $(".filter-manager").on('click', function () { + $(".filter-manager-popin").show(); + }); + $(document).on('keyup', function (e) { + // 27 is 'Escape' + if(e.keyCode === 27) { + $(".filter-manager-popin").hide(); + } + }); + $(".filter-manager-popin .filter-cancel, .filter-manager-popin .filter-manager-close").on('click', function () { + $(".filter-manager-popin").hide(); + }); + + $(".filter-manager-popin .filter-validate").on('click', function () { + + $(".filter-manager-controller-container input").each(function (e) { + if ($(this).is(':checked')) { + if (!$(".filter.filter-" + $(this).data("wid")).is(':visible')) { + updateFilters($(this).data("wid"), 'add'); + } + } else { + if ($(".filter.filter-" + $(this).data("wid")).is(':visible')) { + updateFilters($(this).data("wid"), 'del'); + } + } + }); + // Set second param to true to trigger reload + performSearch(PS_params ,false); + }) + + /** + * Filter Word + */ + $(".filter-word").on("click", function (e) { + if ($(".filter-form").has(e.target).length != 0 || + $(e.target).hasClass("filter-form") || + $(e.target).hasClass("remove-filter")) { + return; + } + $(".filter-word-form").toggle(0, function () { + + if ($(this).is(':visible')) { + $(".filter-word").addClass("show-filter-dropdown"); + $("#word-search").focus(); + } else { + $(".filter-word").removeClass("show-filter-dropdown"); + + global_params.fields.allwords = {}; + global_params.fields.allwords.words = $("#word-search").val(); + global_params.fields.allwords.mode = $(".word-search-options input:checked").attr('value'); + + PS_params.allwords = $("#word-search").val(); + PS_params.allwords_mode = $(".word-search-options input:checked").attr('value'); + + new_fields = []; + $(".filter-word-form .search-params input:checked").each(function () { + if ($(this).attr("name") == "tags") { + global_params.fields.search_in_tags = true; + } + new_fields.push($(this).attr("name")); + }); + if ($(".filter-word-form .search-params input[name='tags']:checked").length == 0) { + delete global_params.fields.search_in_tags; + } + global_params.fields.allwords.fields = new_fields; + PS_params.allwords_fields = new_fields.length > 0 ? new_fields : ''; + } + }); + }); + $(".filter-word .filter-validate").on("click", function () { + $(".filter-word").trigger("click"); + performSearch(PS_params, true); + }); + $(".filter-word .remove-filter").on("click", function () { + $(this).addClass('pwg-icon-spin6 animate-spin').removeClass('pwg-icon-cancel'); + updateFilters('word', 'del'); + performSearch(PS_params, $(".filter-word").hasClass("filter-filled")); + if (!$(".filter-word").hasClass("filter-filled")) { + $(".filter-word").hide(); + $(".filter-manager-controller.word").prop("checked", false); + } + }); + + /** + * Filter Tag + */ + $(".filter-tag").on("click", function (e) { + if ($(".filter-form").has(e.target).length != 0 || + $(e.target).hasClass("filter-form") || + $(e.target).hasClass("remove") || + $(e.target).hasClass("remove-filter")) { + return; + } + $(".filter-tag-form").toggle(0, function () { + if ($(this).is(':visible')) { + $(".filter-tag").addClass("show-filter-dropdown"); + } else { + $(".filter-tag").removeClass("show-filter-dropdown"); + global_params.fields.tags = {}; + global_params.fields.tags.mode = $(".filter-tag-form .search-params input:checked").val(); + global_params.fields.tags.words = $("#tag-search")[0].selectize.getValue(); + + PS_params.tags = $("#tag-search")[0].selectize.getValue().length > 0 ? $("#tag-search")[0].selectize.getValue() : ''; + PS_params.tags_mode = $(".filter-tag-form .search-params input:checked").val(); + } + }); + }); + $(".filter-tag .filter-validate").on("click", function () { + $(".filter-tag").trigger("click"); + performSearch(PS_params, true); + }); + $(".filter-tag .remove-filter").on("click", function () { + $(this).addClass('pwg-icon-spin6 animate-spin').removeClass('pwg-icon-cancel'); + updateFilters('tag', 'del'); + performSearch(PS_params, $(".filter-tag").hasClass("filter-filled")); + if (!$(".filter-tag").hasClass("filter-filled")) { + $(".filter-tag").hide(); + $(".filter-manager-controller.tags").prop("checked", false); + } + }); + + /** + * Filter Date + */ + $(".filter-date").on("click", function (e) { + if ($(".filter-form").has(e.target).length != 0 || + $(e.target).hasClass("filter-form") || + $(e.target).hasClass("remove-filter")) { + return; + } + $(".filter-date-form").toggle(0, function () { + + if ($(this).is(':visible')) { + $(".filter-date").addClass("show-filter-dropdown"); + } else { + $(".filter-date").removeClass("show-filter-dropdown"); + performSearch(PS_params, true); + } + }); + }); + $(".filter-date .remove-filter").on("click", function () { + $(this).addClass('pwg-icon-spin6 animate-spin').removeClass('pwg-icon-cancel'); + updateFilters('date', 'del'); + performSearch(PS_params, $(".filter-date").hasClass("filter-filled")); + if (!$(".filter-date").hasClass("filter-filled")) { + $(".filter-date").hide(); + $(".filter-manager-controller.date").prop("checked", false); + } + }); + + /** + * Filter Album + */ + $(".filter-album").on("click", function (e) { + if ($(".filter-form").has(e.target).length != 0 || + $(e.target).hasClass("filter-form") || + $(e.target).hasClass("remove-item") || + $(e.target).hasClass("remove-filter")) { + return; + } + $(".filter-album-form").toggle(0, function () { + if ($(this).is(':visible')) { + $(".filter-album").addClass("show-filter-dropdown"); + } else { + $(".filter-album").removeClass("show-filter-dropdown"); + global_params.fields.cat = {}; + global_params.fields.cat.words = related_categories_ids; + // global_params.fields.cat.search_params = $(".filter-form.filter-album-form .search-params input:checked").val().toLowerCase(); + global_params.fields.cat.sub_inc = $("input[name='search-sub-cats']:checked").length != 0; + + PS_params.categories = related_categories_ids.length > 0 ? related_categories_ids : ''; + PS_params.categories_withsubs = $("input[name='search-sub-cats']:checked").length != 0; + } + }); + }); + $(".filter-album .filter-validate").on("click", function () { + $(".filter-album").trigger("click"); + performSearch(PS_params, false); + }); + $(".filter-album .remove-filter").on("click", function () { + $(this).addClass('pwg-icon-spin6 animate-spin').removeClass('pwg-icon-cancel'); + updateFilters('album', 'del'); + performSearch(PS_params, $(".filter-album").hasClass("filter-filled")); + if (!$(".filter-album").hasClass("filter-filled")) { + $(".filter-album").hide(); + $(".filter-manager-controller.album").prop("checked", false); + } + }); + + $(".add-album-button").on("click", function () { + linked_albums_open(); + set_up_popin(); + }); + + $("#linkedAlbumSearch .search-input").on('input', function () { + if ($(this).val() != 0) { + $("#linkedAlbumSearch .search-cancel-linked-album").show(); + } else { + $("#linkedAlbumSearch .search-cancel-linked-album").hide(); + } + + // Search input value length required to start searching + if ($(this).val().length > 0) { + linked_albums_search($(this).val()); + } else { + $(".limitReached").html(str_no_search_in_progress); + $("#searchResult").empty(); + } + }) + + /** + * Author Widget + */ + $(".filter-author").on("click", function (e) { + if ($(".filter-form").has(e.target).length != 0 || + $(e.target).hasClass("filter-form") || + $(e.target).hasClass("remove") || + $(e.target).hasClass("remove-filter")) { + return; + } + $(".filter-author-form").toggle(0, function () { + if ($(this).is(':visible')) { + $(".filter-author").addClass("show-filter-dropdown"); + } else { + $(".filter-author").removeClass("show-filter-dropdown"); + global_params.fields.author = {}; + global_params.fields.author.mode = "OR"; + global_params.fields.author.words = $("#authors")[0].selectize.getValue(); + + PS_params.authors = $("#authors")[0].selectize.getValue().length > 0 ? $("#authors")[0].selectize.getValue() : ''; + } + }); + }); + $(".filter-author .filter-validate").on("click", function () { + $(".filter-author").trigger("click"); + performSearch(PS_params, true); + }); + $(".filter-author .remove-filter").on("click", function () { + $(this).addClass('pwg-icon-spin6 animate-spin').removeClass('pwg-icon-cancel'); + updateFilters('authors', 'del'); + performSearch(PS_params, $(".filter-author").hasClass("filter-filled")); + if (!$(".filter-author").hasClass("filter-filled")) { + $(".filter-author").hide(); + $(".filter-manager-controller.author").prop("checked", false); + } + }); + + /** + * Added by Widget + */ + $(".filter-added_by").on("click", function (e) { + if ($(".filter-form").has(e.target).length != 0 || + $(e.target).hasClass("filter-form") || + $(e.target).hasClass("remove") || + $(e.target).hasClass("remove-filter")) { + return; + } + $(".filter-added_by-form").toggle(0, function () { + if ($(this).is(':visible')) { + $(".filter-added_by").addClass("show-filter-dropdown"); + } else { + $(".filter-added_by").removeClass("show-filter-dropdown"); + global_params.fields.added_by = {}; + global_params.fields.added_by.mode = "OR"; + global_params.fields.added_by.words = $("#added_by")[0].selectize.getValue(); + + PS_params.added_by = $("#added_by")[0].selectize.getValue().length > 0 ? $("#added_by")[0].selectize.getValue() : ''; + } + }); + }); + $(".filter-added_by .filter-validate").on("click", function () { + $(".filter-added_by").trigger("click"); + performSearch(PS_params, true); + }); + $(".filter-added_by .remove-filter").on("click", function () { + $(this).addClass('pwg-icon-spin6 animate-spin').removeClass('pwg-icon-cancel'); + updateFilters('added_by', 'del'); + performSearch(PS_params, $(".filter-added_by").hasClass("filter-filled")); + if (!$(".filter-added_by").hasClass("filter-filled")) { + $(".filter-added_by").hide(); + $(".filter-manager-controller.added_by").prop("checked", false); + } + }); + + /* Close dropdowns if you click on the screen */ + // $(document).mouseup(function (e) { + // e.stopPropagation(); + // let option_is_clicked = false + // $(".mcs-container .filter").each(function () { + // console.log(($(this).hasClass("show-filter-dropdown"))); + // if (!($(this).has(e.target).length === 0)) { + // option_is_clicked = true; + // } + // }) + // if (!option_is_clicked) { + // $(".filter-form").hide(); + // if ($(".show-filter-dropdown").length != 0) { + // $(".show-filter-dropdown").removeClass("show-filter-dropdown"); + // performSearch(); + // } + // } + // }); +}) + +function performSearch(params, reload = false) { + console.log("params sent to updatesearch"); + console.log(params); + $.ajax({ + url: "ws.php?format=json&method=pwg.images.filteredSearch.update", + type:"POST", + dataType: "json", + data: PS_params, + success:function(data) { + console.log("perform search"); + console.log(data); + if (reload) { + reloadPage(); + } + }, + error:function(e) { + console.log(e); + }, + }).done(function () { + console.log('ajax ended'); + $(".filter-validate").find(".validate-text").css("display", "block"); + $(".filter-validate").find(".loading").hide(); + $(".remove-filter").removeClass('pwg-icon-spin6 animate-spin').addClass('pwg-icon-cancel'); + }); +} + +function set_up_popin() { + $(".ClosePopIn").on('click', function () { + linked_albums_close(); + }); + + $("#addLinkedAlbum").on('keyup', function (e) { + // 27 is 'Escape' + if(e.keyCode === 27) { + linked_albums_close(); + } + }) +} + +function linked_albums_close() { + $("#addLinkedAlbum").fadeOut(); +} + +function fill_results(cats) { + $("#searchResult").empty(); + cats.forEach(cat => { + if (!related_categories_ids.includes(cat.id)) { + $("#searchResult").append( + "
" + + "" + cat.name +"" + + "
" + ); + + $(".search-result-item#"+ cat.id).on("click", function () { + add_related_category(cat.id, cat.name); + }); + } + }); +} + +function add_related_category(cat_id, cat_link_path) { + $(".selected-categories-container").append( + "" + ); + + related_categories_ids.push(cat_id); + $(".invisible-related-categories-select").append(""); + + $("#"+ cat_id).on("click", function () { + remove_related_category($(this).attr("id")); + }); + + linked_albums_close(); +} + +function remove_related_category(cat_id) { + $("#" + cat_id).parent().remove(); + + cat_to_remove_index = related_categories_ids.indexOf(parseInt(cat_id)); + if (cat_to_remove_index > -1) { + related_categories_ids.splice(cat_to_remove_index, 1); + } + if (related_categories_ids.length === 0) { + related_categories_ids = ''; + } +} + +function updateFilters(filterName, mode) { + switch (filterName) { + case 'word': + if (mode == 'add') { + global_params.fields.allwords = {}; + + PS_params.allwords = ''; + PS_params.allwords_mode = 'AND'; + PS_params.allwords_fields = []; + } else if (mode == 'del') { + delete global_params.fields.allwords; + + delete PS_params.allwords; + delete PS_params.allwords_mode; + delete PS_params.allwords_fields; + } + break; + + case 'tag': + if (mode == 'add') { + global_params.fields.tags = {}; + + PS_params.tags = ''; + PS_params.tags_mode = 'AND'; + } else if (mode == 'del') { + delete global_params.fields.tags; + + delete PS_params.tags; + delete PS_params.tags_mode; + } + break; + + case 'album': + if (mode == 'add') { + global_params.fields.cat = {}; + + PS_params.categories = ''; + PS_params.categories_withsubs = false; + } else if (mode == 'del') { + delete global_params.fields.cat; + + delete PS_params.categories; + delete PS_params.categories_withsubs; + } + break; + + default: + if (mode == 'add') { + global_params.fields[filterName] = {}; + + PS_params[filterName] = ''; + } else if (mode == 'del') { + delete global_params.fields[filterName]; + + delete PS_params[filterName]; + } + break; + } +} + +function reloadPage(){ + location.reload(true); +} \ No newline at end of file diff --git a/themes/default/template/index.tpl b/themes/default/template/index.tpl index d1411d2f7..7c029d79a 100644 --- a/themes/default/template/index.tpl +++ b/themes/default/template/index.tpl @@ -1,6 +1,25 @@ {combine_script id='core.switchbox' load='async' require='jquery' path='themes/default/js/switchbox.js'} +{combine_script id='jquery.selectize' load='footer' path='themes/default/js/plugins/selectize.min.js'} +{combine_css path="admin/themes/default/fontello/css/animation.css" order=10} {* order 10 is required, see issue 1080 *} + {$MENUBAR} +{footer_script} +{if isset($GP)} + global_params = {$GP}; +{/if} + +{if isset($fullname_of)} +fullname_of_cat = {$fullname_of}; +{/if} + +{if isset($SEARCH_ID)} +search_id = {$SEARCH_ID}; +{/if} + +str_word_widget = "{'Search for words'|@translate}"; + +{/footer_script} {if isset($errors) or isset($infos)}
@@ -171,11 +190,278 @@ {include file='navigation_bar.tpl'|@get_extent:'navbar' navbar=$cats_navbar} {/if} +{if !empty($SEARCH_ID)} +{combine_script id='mcs' load='async' require='jquery' path='themes/default/js/mcs.js'} +{* Recherche multicritère *} +
+
+
+ + +
Filtres
+ +
+ + + + + +
+ +
+
+ Cancel +
+
+ + Validate +
+
+
+
+
+ Filters +
+ + +
+ + + + + +
+
{'Search for words'|@translate}
+ {* Conseils de recherche *} +
+ + +
+ + + Search in : +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + Validate +
+
+
+
+ + + + + +
+
Tags
+
+
+ + +
+
+ + +
+
+ +
+ + Validate +
+
+
+ {*
+ Date: Balloon + +
+ // Still in porgress +
+
+ +
+ + + blavvla + +
+
+
+
+
*} +
+ + + + + +
+
Album
+
+ {*
+ + +
+
+ + +
*} +
+
+
+
+ +
+
+ + +
+
+ + Validate +
+
+
+ {include file='admin/themes/default/template/include/album_selector.inc.tpl' + title={'Search in album'|@translate} + searchPlaceholder={'Search'|@translate} + show_root_btn=false + api_method='pwg.categories.getList' + } +
+ + + + + +
+
Author
+ + +
+ + Validate +
+
+
+ +
+ + + + + +
+
Added by
+ +
+ + Validate +
+
+
+ {*
+ Note div +
+ +
+
+
+ Height div +
+ +
+
+
+ Width div +
+ +
+
+
+ File type div +
+ +
+
+
+ File size div +
+ +
+
*} +
+{/if} + {if !empty($THUMBNAILS)}
+
    {$THUMBNAILS}
+ +{else} +
+
+ No results are available. + You can try to edit your filters and perform a new search. +
+
{/if} {if !empty($thumb_navbar)} {include file='navigation_bar.tpl'|@get_extent:'navbar' navbar=$thumb_navbar} diff --git a/ws.php b/ws.php index cc9368c65..cbb8d683d 100644 --- a/ws.php +++ b/ws.php @@ -1365,6 +1365,54 @@ enabled_high, registration_date, registration_date_string, registration_date_sin
display_thumbnail can be : \'no_display_thumbnail\', \'display_thumbnail_classic\', \'display_thumbnail_hoverbox\'', $ws_functions_root . 'pwg.php' ); + + $service->addMethod( + 'pwg.images.filteredSearch.update', + 'ws_images_filteredSearch_update', + array( + 'search_id' => array( + 'type' => WS_TYPE_ID, + ), + 'allwords' => array( + 'flags' => WS_PARAM_OPTIONAL, + 'info' => 'query to search by words', + ), + 'allwords_mode' => array( + 'flags' => WS_PARAM_OPTIONAL, + 'info' => 'AND (by default) | OR', + ), + 'allwords_fields' => array( + 'flags' => WS_PARAM_OPTIONAL|WS_PARAM_FORCE_ARRAY, + 'info' => 'values among [name, comment, tags, file, cat-title, cat-desc]', + ), + 'tags' => array( + 'flags' => WS_PARAM_OPTIONAL|WS_PARAM_FORCE_ARRAY, + 'type' => WS_TYPE_ID, + ), + 'tags_mode' => array( + 'flags' => WS_PARAM_OPTIONAL, + 'info' => 'AND (by default) | OR', + ), + 'categories' => array( + 'flags' => WS_PARAM_OPTIONAL|WS_PARAM_FORCE_ARRAY, + 'type' => WS_TYPE_ID, + ), + 'categories_withsubs' => array( + 'flags' => WS_PARAM_OPTIONAL, + 'type' => WS_TYPE_BOOL, + 'info' => 'false, by default', + ), + 'authors' => array( + 'flags' => WS_PARAM_OPTIONAL|WS_PARAM_FORCE_ARRAY, + ), + 'added_by' => array( + 'flags' => WS_PARAM_OPTIONAL|WS_PARAM_FORCE_ARRAY, + 'type' => WS_TYPE_ID, + ), + ), + '', + $ws_functions_root . 'pwg.images.php' + ); } ?>