From 48c6d7e8a4d5b44a6c5c6fa919267d098ed28ee7 Mon Sep 17 00:00:00 2001 From: rvelices Date: Tue, 15 Aug 2006 02:06:06 +0000 Subject: feature 519: quick search (first version) git-svn-id: http://piwigo.org/svn/trunk@1537 68402e56-0260-453c-a942-63ccdbb3a9ee --- include/config_default.inc.php | 12 ++- include/functions_search.inc.php | 194 ++++++++++++++++++++++++++++++++++++--- include/functions_tag.inc.php | 43 +++++++++ include/menubar.inc.php | 17 +--- include/section_init.inc.php | 8 +- index.php | 35 +++++++ qsearch.php | 56 +++++++++++ search_rules.php | 28 ++++-- template/yoga/default-layout.css | 16 +++- template/yoga/index.tpl | 10 ++ template/yoga/menubar.css | 7 +- template/yoga/menubar.tpl | 4 + 12 files changed, 388 insertions(+), 42 deletions(-) create mode 100644 qsearch.php diff --git a/include/config_default.inc.php b/include/config_default.inc.php index 2f573cc5a..e906fca06 100644 --- a/include/config_default.inc.php +++ b/include/config_default.inc.php @@ -206,7 +206,7 @@ $conf['mail_options'] = false; $conf['send_bcc_mail_webmaster'] = false; // enabled_format_email: -// on true email will be formatted with name and address +// on true email will be formatted with name and address // on false email will be only address // There are webhosting wich not allow email formatted (Lycos, ...) $conf['enabled_format_email'] = true; @@ -473,6 +473,14 @@ $conf['tag_url_style'] = 'id-tag'; // cloud. Only the most represented tags will be shown $conf['full_tag_cloud_items_number'] = 200; +// menubar_tag_cloud_items_number: number of tags to show in the tag +// cloud in the menubar. Only the most represented tags will be shown +$conf['menubar_tag_cloud_items_number'] = 100; + +// content_tag_cloud_items_number: number of tags to show in the tag +// cloud on the content page. Only the most represented tags will be shown +$conf['content_tag_cloud_items_number'] = 12; + // tags_levels: number of levels to use for display. Each level is bind to a // CSS class tagLevelX. $conf['tags_levels'] = 5; @@ -505,7 +513,7 @@ $conf['nbm_treatment_timeout_default'] = 20; // Step 1, default_admin_layout is not defined // null value, user_layout is used for admin layout // defined value, this value are used for admin layout -// Next on step 2, default_admin_layout will be used +// Next on step 2, default_admin_layout will be used // if there are not checked like admin layout // stored on user informations //$conf['default_admin_layout']='yoga/dark'; diff --git a/include/functions_search.inc.php b/include/functions_search.inc.php index 7e55160c8..ce2e6115b 100644 --- a/include/functions_search.inc.php +++ b/include/functions_search.inc.php @@ -73,13 +73,11 @@ SELECT rules * Search rules are stored in search table as a serialized array. This array * need to be transformed into an SQL clause to be used in queries. * - * @param int search_id + * @param array search * @return string */ -function get_sql_search_clause($search_id) +function get_sql_search_clause($search) { - $search = get_search_array($search_id); - // SQL where clauses are stored in $clauses array during query // construction $clauses = array(); @@ -212,17 +210,17 @@ function get_sql_search_clause($search_id) } /** - * returns the list of items corresponding to the search id + * returns the list of items corresponding to the advanced search array * - * @param int search id + * @param array search * @return array */ -function get_search_items($search_id) +function get_regular_search_results($search) { $items = array(); - - $search_clause = get_sql_search_clause($search_id); - + + $search_clause = get_sql_search_clause($search); + if (!empty($search_clause)) { $query = ' @@ -269,7 +267,181 @@ SELECT DISTINCT(id) } } } - + return $items; } + + +if (!function_exists('array_intersect_key')) { + function array_intersect_key() + { + $arrs = func_get_args(); + $result = array_shift($arrs); + foreach ($arrs as $array) { + foreach ($result as $key => $v) { + if (!array_key_exists($key, $array)) { + unset($result[$key]); + } + } + } + return $result; + } +} + + +function get_qsearch_like_clause($q, $field) +{ + $tokens = preg_split('/[\s,.;!\?]+/', $q); + for ($i=0; $i]/',$tokens[$i]) ) + $tokens[$i]=substr($tokens[$i], 1); + else if (substr($tokens[$i], 0, 1)=='-') + { + unset($tokens[$i]); + $i--; + } + } + + if (!empty($tokens)) + { + $query = '('; + for ($i=0; $i0) $query .= 'OR '; + $query .= ' '.$field.' LIKE "%'.$tokens[$i].'%" '; + } + $query .= ')'; + return $query; + } + return null; +} + + +/** + * returns the search results corresponding to a quick search + * + * @param string q + * @return array + */ +function get_quick_search_results($q) +{ + global $user, $page; + $search_results = array(); + + $q_like_clause = get_qsearch_like_clause($q, 'CONVERT(name, CHAR)' ); + $by_tag_weights=array(); + if (!empty($q_like_clause)) + { + $query = ' +SELECT id + FROM '.TAGS_TABLE.' + WHERE '.$q_like_clause; + $tag_ids = array_from_query( $query, 'id'); + if (!empty($tag_ids)) + { + $query = ' +SELECT image_id, COUNT(tag_id) AS q + FROM '.IMAGE_TAG_TABLE.' + WHERE tag_id IN ('.implode(',',$tag_ids).') + GROUP BY image_id'; + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + $by_tag_weights[(int)$row['image_id']] = $row['q']; + } + } + } + + $query = ' +SELECT + i.id, i.file, CAST( CONCAT_WS(" ", + IFNULL(i.name,""), + IFNULL(i.comment,""), + IFNULL(GROUP_CONCAT(DISTINCT co.content),""), + IFNULL(GROUP_CONCAT(DISTINCT c.dir),""), + IFNULL(GROUP_CONCAT(DISTINCT c.name),""), + IFNULL(GROUP_CONCAT(DISTINCT c.comment),"") ) AS CHAR) AS ft +FROM ( + ( + '.IMAGES_TABLE.' i LEFT JOIN '.COMMENTS_TABLE.' co on i.id=co.image_id + ) + INNER JOIN + '.IMAGE_CATEGORY_TABLE.' ic on ic.image_id=i.id + ) + INNER JOIN + '.CATEGORIES_TABLE.' c on c.id=ic.category_id +WHERE category_id NOT IN ('.$user['forbidden_categories'].') +GROUP BY i.id'; + + $query = 'SELECT id, MATCH(ft) AGAINST( "'.$q.'" IN BOOLEAN MODE) AS q FROM ('.$query.') AS Y +WHERE MATCH(ft) AGAINST( "'.$q.'" IN BOOLEAN MODE)'; + + $q_like_clause = get_qsearch_like_clause($q, 'file' ); + if (! empty($q_like_clause) ) + { + $query .= ' OR '.$q_like_clause; + } + + $by_weights=array(); + $result = pwg_query($query); + while ($row = mysql_fetch_array($result)) + { + $by_weights[(int)$row['id']] = $row['q'] ? $row['q'] : 0; + } + + foreach ( $by_weights as $image=>$w ) + { + $by_tag_weights[$image] = 2*$w+ (isset($by_tag_weights[$image])?$by_tag_weights[$image]:0); + } + + if ( empty($by_tag_weights) or isset($page['super_order_by']) ) + { + if (! isset($page['super_order_by']) ) + { + arsort($by_tag_weights, SORT_NUMERIC); + $search_results['as_is']=1; + } + $search_results['items'] = array_keys($by_tag_weights); + } + else + { + $query = ' +SELECT DISTINCT(id) + FROM '.IMAGES_TABLE.' + INNER JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON id = ic.image_id + WHERE id IN ('.implode(',', array_keys($by_tag_weights) ).') + AND category_id NOT IN ('.$user['forbidden_categories'].')'; + + $allowed_image_ids = array_from_query( $query, 'id'); + $by_tag_weights = array_intersect_key($by_tag_weights, array_flip($allowed_image_ids)); + arsort($by_tag_weights, SORT_NUMERIC); + $search_results = array( + 'items'=>array_keys($by_tag_weights), + 'as_is'=>1 + ); + } + return $search_results; +} + +/** + * returns an array of 'items' corresponding to the search id + * + * @param int search id + * @return array + */ +function get_search_results($search_id) +{ + $search = get_search_array($search_id); + if ( !isset($search['q']) ) + { + $result['items'] = get_regular_search_results($search); + return $result; + } + else + { + return get_quick_search_results($search['q']); + } +} ?> \ No newline at end of file diff --git a/include/functions_tag.inc.php b/include/functions_tag.inc.php index 046eb6bb1..b330041ca 100644 --- a/include/functions_tag.inc.php +++ b/include/functions_tag.inc.php @@ -221,4 +221,47 @@ SELECT DISTINCT image_id } } } + +/** + * return a list of tags corresponding to given items. + * + * @param array items + * @param array max_tags + * @param array excluded_tag_ids + * @return array + */ +function get_common_tags($items, $max_tags, $excluded_tag_ids=null) +{ + if (empty($items)) + { + return array(); + } + $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).')'; + if (!empty($excluded_tag_ids)) + { + $query.=' + AND tag_id NOT IN ('.implode(',', $excluded_tag_ids).')'; + } + $query .=' + GROUP BY tag_id + ORDER BY counter DESC'; + if ($max_tags>0) + { + $query .= ' + LIMIT 0,'.$max_tags; + } + + $result = pwg_query($query); + $tags = array(); + while($row = mysql_fetch_array($result)) + { + array_push($tags, $row); + } + usort($tags, 'name_compare'); + return $tags; +} ?> \ No newline at end of file diff --git a/include/menubar.inc.php b/include/menubar.inc.php index 822f19fec..971b32782 100755 --- a/include/menubar.inc.php +++ b/include/menubar.inc.php @@ -76,20 +76,8 @@ if ('tags' == $page['section']) if ( !empty($page['items']) ) { - $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); - while($row = mysql_fetch_array($result)) - { - array_push($tags, $row); - } + $tags = get_common_tags($page['items'], + $conf['menubar_tag_cloud_items_number'], $page['tag_ids']); } $tags = add_level_to_tags($tags); @@ -269,6 +257,7 @@ $template->assign_block_vars( 'REL'=> 'rel="search"' ) ); +$template->assign_block_vars( 'summary.quick_search', array() ); // comments link $template->assign_block_vars( diff --git a/include/section_init.inc.php b/include/section_init.inc.php index 1aa58516c..d451c3781 100644 --- a/include/section_init.inc.php +++ b/include/section_init.inc.php @@ -450,14 +450,14 @@ SELECT image_id { include_once( PHPWG_ROOT_PATH .'include/functions_search.inc.php' ); - $search_items = get_search_items($page['search']); - if ( !empty($search_items) ) + $search_result = get_search_results($page['search']); + if ( !empty($search_result['items']) and !isset($search_result['as_is']) ) { $query = ' SELECT DISTINCT(id) FROM '.IMAGES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON id = ic.image_id - WHERE id IN ('.implode(',', $search_items).') + WHERE id IN ('.implode(',', $search_result['items']).') AND '.$forbidden.' '.$conf['order_by'].' ;'; @@ -465,7 +465,7 @@ SELECT DISTINCT(id) } else { - $page['items'] = array(); + $page['items'] = $search_result['items']; } $page = array_merge( diff --git a/index.php b/index.php index cf3d9e434..5b6d011c4 100644 --- a/index.php +++ b/index.php @@ -198,6 +198,41 @@ if (is_admin() and !empty($page['items']) ) ); } +if ( $page['section']=='search' and $page['start']==0 ) +{ + $tags = get_common_tags($page['items'], + $conf['content_tag_cloud_items_number'], null); + if ( count($tags)>1 ) + { + $template->assign_block_vars('related_tags', array() ); + + $tags = add_level_to_tags($tags); + foreach ($tags as $tag) + { + $template->assign_block_vars( + 'related_tags.tag', array( + 'URL' => make_index_url( + array( + 'tags' => array( + array( + 'id' => $tag['tag_id'], + 'url_name' => $tag['url_name'], + ), + ) + ) + ), + 'NAME' => $tag['name'], + 'TITLE' => sprintf( + l10n('%d pictures are also linked to current tags'), + $tag['counter'] + ), + 'CLASS' => 'tagLevel'.$tag['level'] + ) + ); + } + } +} + //------------------------------------------------------ main part : thumbnails if (isset($page['thumbnails_include'])) { diff --git a/qsearch.php b/qsearch.php new file mode 100644 index 000000000..c993d4386 --- /dev/null +++ b/qsearch.php @@ -0,0 +1,56 @@ + 'search', + 'search' => $search_id, + ) + ) + ); +?> \ No newline at end of file diff --git a/search_rules.php b/search_rules.php index 51ccaf2c0..d9f0635a5 100644 --- a/search_rules.php +++ b/search_rules.php @@ -61,14 +61,26 @@ $template->set_filenames(array('search_rules' => 'search_rules.tpl')); $search = get_search_array($_GET['search_id']); -$template->assign_vars( - array( - 'INTRODUCTION' - => 'OR' == $search['mode'] - ? l10n('At least one listed rule must be satisfied.') - : l10n('Each listed rule must be satisfied.'), - ) - ); +if (isset($search['q'])) +{ + $template->assign_block_vars( + 'words', + array( + 'CONTENT' => $search['q'] + ) + ); +} +else +{ + $template->assign_vars( + array( + 'INTRODUCTION' + => 'OR' == $search['mode'] + ? l10n('At least one listed rule must be satisfied.') + : l10n('Each listed rule must be satisfied.'), + ) + ); +} if (isset($search['fields']['allwords'])) { diff --git a/template/yoga/default-layout.css b/template/yoga/default-layout.css index 17f0a23cc..afe4cf525 100644 --- a/template/yoga/default-layout.css +++ b/template/yoga/default-layout.css @@ -237,9 +237,21 @@ UL.tagSelection LI { white-space: nowrap; } -#fullTagCloud { font-size: 140%; } +#fullTagCloud { + font-size: 140%; + text-align: justify; + padding: 0; + margin: 1em 2em 1em 2em; +} -#fullTagCloud LI { display: inline; } +#fullTagCloud LI { + display: inline; + white-space: nowrap; +} + +#content #fullTagCloud { + font-size: 120%; +} .tagLevel5 { font-size: 150%; } .tagLevel4 { font-size: 140%; } diff --git a/template/yoga/index.tpl b/template/yoga/index.tpl index 85b91d1de..0eb4baa8e 100644 --- a/template/yoga/index.tpl +++ b/template/yoga/index.tpl @@ -90,4 +90,14 @@ + + + + + diff --git a/template/yoga/menubar.css b/template/yoga/menubar.css index 696e9b128..4a687b9d5 100644 --- a/template/yoga/menubar.css +++ b/template/yoga/menubar.css @@ -57,7 +57,7 @@ } /* quickconnect form */ -FORM#quickconnect { +FORM#quickconnect { margin: 0; padding: 5px; } @@ -114,6 +114,11 @@ FORM#quickconnect INPUT.password { width: 95%; }*/ +FORM#quicksearch { + margin-top: 4px; + margin-bottom: 1px; +} + #menubar #menuTagCloud { text-align: center; margin: 5px 0; diff --git a/template/yoga/menubar.tpl b/template/yoga/menubar.tpl index 1bcbbec24..983260d13 100644 --- a/template/yoga/menubar.tpl +++ b/template/yoga/menubar.tpl @@ -51,6 +51,10 @@
    + +
    + +
  • {summary.NAME}
  • -- cgit v1.2.3