11
christian
Re: Xoops Search - A Better Implementation?
  • 2007/7/30 16:22

  • christian

  • Just can't stay away

  • Posts: 401

  • Since: 2002/2/24


Thank, Your text was added in the FAQ

12
rlankford
Re: Xoops Search - A Better Implementation?
  • 2007/7/30 16:34

  • rlankford

  • Not too shy to talk

  • Posts: 158

  • Since: 2004/8/27


Great! Thanks.

13
giba
Re: Implementation
  • 2007/7/30 20:58

  • giba

  • Just can't stay away

  • Posts: 638

  • Since: 2003/4/26


Hi rlankford, exelent step by step, 1st World

Thanks for your work. I go to translated for brazilian user in soon.
[]s

[Edited for myself]

Temporary in portuguese by Google here.

14
Burning
Re: Implementation
  • 2007/7/30 21:37

  • Burning

  • Theme Designer

  • Posts: 1163

  • Since: 2006/8/22


Hi !

Many thanks rlankford (and Christian who has linked this hack to frxoops).

It work's fine (example)

@+
Still learning CSS and... english

15
giba
Re: Implementation
  • 2007/7/31 8:59

  • giba

  • Just can't stay away

  • Posts: 638

  • Since: 2003/4/26


Quote:

Burning wrote:
Hi !

Many thanks rlankford (and Christian who has linked this hack to frxoops).

It work's fine (example)

@+


Yes my friend Burning, exelent

[img]http://img528.imageshack.us/img528/1347/inst065zw2.gif[/img]

16
rlankford
Re: Implementation
  • 2007/8/7 19:42

  • rlankford

  • Not too shy to talk

  • Posts: 158

  • Since: 2004/8/27


As an added twist, I've updated the search page and the template page. I've also added some graphics in.

PLEASE NOTE: This new search template performs *full* searching across all modules so that totals and page navs can be determined accurately. This can (and will) slow down searching for sites with weak hardware and lots of data.

The results now look something like this:

Resized Image

Notice in the above shot that you immediately know how many hits were returned for each module. Furthermore, the 'more results' button is prominently displayed and it's only visible on modules that generate more than 5 results.

Resized Image

On this page we can still see how many hits were generated and can easily navigate through the hits using the standard page nav.

Here's the new search.php:

<?php
// $Id: search.php 506 2006-05-26 23:10:37Z skalpa $
//  ------------------------------------------------------------------------ //
//                XOOPS - PHP Content Management System                      //
//                    Copyright (c) 2000 XOOPS.org                           //
//                       <https://xoops.org/>                             //
//  ------------------------------------------------------------------------ //
//  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; either version 2 of the License, or        //
//  (at your option) any later version.                                      //
//                                                                           //
//  You may not change or alter any portion of this comment or credits       //
//  of supporting developers from this source code or any supporting         //
//  source code which is considered copyrighted (c) material of the          //
//  original comment or credit authors.                                      //
//                                                                           //
//  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 //
//  ------------------------------------------------------------------------ //

$xoopsOption['pagetype'] = "search";

include 
'mainfile.php';

$xoopsOption['template_main'] = 'system_search.html';

$config_handler =& xoops_gethandler('config');
$xoopsConfigSearch =& $config_handler->getConfigsByCat(XOOPS_CONF_SEARCH);

if (
$xoopsConfigSearch['enable_search'] != 1) {
    
header('Location: '.XOOPS_URL.'/index.php');
    exit();
}

include 
XOOPS_ROOT_PATH.'/header.php';

$action "search";
if (!empty(
$_GET['action'])) {
  
$action $_GET['action'];
} elseif (!empty(
$_POST['action'])) {
  
$action $_POST['action'];
}
$query "";
if (!empty(
$_GET['query'])) {
  
$query $_GET['query'];
} elseif (!empty(
$_POST['query'])) {
  
$query $_POST['query'];
}
$andor "AND";
if (!empty(
$_GET['andor'])) {
  
$andor $_GET['andor'];
} elseif (!empty(
$_POST['andor'])) {
  
$andor $_POST['andor'];
}
$mid $uid $start 0;
if ( !empty(
$_GET['mid']) ) {
  
$mid intval($_GET['mid']);
} elseif ( !empty(
$_POST['mid']) ) {
  
$mid intval($_POST['mid']);
}
if (!empty(
$_GET['uid'])) {
  
$uid intval($_GET['uid']);
} elseif (!empty(
$_POST['uid'])) {
  
$uid intval($_POST['uid']);
}
if (!empty(
$_GET['start'])) {
  
$start intval($_GET['start']);
} elseif (!empty(
$_POST['start'])) {
  
$start intval($_POST['start']);
}

$xoopsTpl->assign("start"$start 1);

$queries = array();

if (
$action == "recoosults") {
    if (
$query == "") {
         
redirect_header("search.php",1,_SR_PLZENTER);
        exit();
    }
} elseif (
$action == "showall") {
    if (
$query == "" || empty($mid)) {
        
redirect_header("search.php",1,_SR_PLZENTER);
        exit();
    }
} elseif (
$action == "showallbyuser") {
    if (empty(
$mid) || empty($uid)) {
        
redirect_header("search.php",1,_SR_PLZENTER);
        exit();
    }
}

global 
$xoopsUser;
$groups is_object($xoopsUser) ? $xoopsUser -> getGroups() : XOOPS_GROUP_ANONYMOUS;
$gperm_handler = & xoops_gethandler'groupperm' );
$available_modules $gperm_handler->getItemIds('module_read'$groups);

$xoopsTpl->assign('basic_search'false);
if (
$action == 'search') {
    
// This area seems to handle the 'just display the advanced search page' part.
   
$search_form = include 'include/searchform.php';
   
$xoopsTpl->assign('search_form'$search_form);
   
$xoopsTpl->assign('basic_search'true);
    include 
XOOPS_ROOT_PATH.'/footer.php';
    exit();
}

if ( 
$andor != "OR" && $andor != "exact" && $andor != "AND" ) {
    
$andor "AND";
}
$xoopsTpl->assign("search_type"$andor);

$myts =& MyTextSanitizer::getInstance();
if (
$action != 'showallbyuser') {
    if ( 
$andor != "exact" ) {
        
$ignored_queries = array(); // holds kewords that are shorter than allowed minmum length
        
$temp_queries preg_split('/[s,]+/'$query);
        foreach (
$temp_queries as $q) {
            
$q trim($q);
            if (
strlen($q) >= $xoopsConfigSearch['keyword_min']) {
                
$queries[] = $myts->addSlashes($q);
            } else {
                
$ignored_queries[] = $myts->addSlashes($q);
            }
        }
        if (
count($queries) == 0) {
            
redirect_header('search.php'2sprintf(_SR_KEYTOOSHORT$xoopsConfigSearch['keyword_min']));
            exit();
        }
    } else {
        
$query trim($query);
        if (
strlen($query) < $xoopsConfigSearch['keyword_min']) {
            
redirect_header('search.php'2sprintf(_SR_KEYTOOSHORT$xoopsConfigSearch['keyword_min']));
            exit();
        }
        
$queries = array($myts->addSlashes($query));
    }
}
$xoopsTpl->assign("label_search_results"_SR_SEARCHRESULTS);

// Keywords section.
$xoopsTpl->assign("label_keywords"_SR_KEYWORDS ':');
$keywords = array();
$ignored_keywords = array();
foreach (
$queries as $q) {
    
$keywords[] = htmlspecialchars(stripslashes($q));
}
if (!empty(
$ignored_queries)) {
     
$xoopsTpl->assign("label_ignored_keywords"sprintf(_SR_IGNOREDWORDS$xoopsConfigSearch['keyword_min']));
    foreach (
$ignored_queries as $q) {
        
$ignored_keywords[] = htmlspecialchars(stripslashes($q));
    }
    
$xoopsTpl->assign("ignored_keywords"$ignored_keywords);
}
$xoopsTpl->assign("searched_keywords"$keywords);

$all_results = array();
$all_results_counts = array();
switch (
$action) {
    case 
"results":
        
$max_results_per_page 5;
        
$module_handler =& xoops_gethandler('module');
        
$criteria = new CriteriaCompo(new Criteria('hassearch'1));
        
$criteria->add(new Criteria('isactive'1));
        
$criteria->add(new Criteria('mid'"(".implode(','$available_modules).")"'IN'));
        
$modules =& $module_handler->getObjects($criteriatrue);
        
$mids = isset($_REQUEST['mids']) ? $_REQUEST['mids'] : array();
        if (empty(
$mids) || !is_array($mids)) {
            unset(
$mids);
            
$mids array_keys($modules);
        }
    
        foreach (
$mids as $mid) {
            
$mid intval($mid);
            if ( 
in_array($mid$available_modules) ) {
                
$module =& $modules[$mid];
                
$results =& $module->search($queries$andor00);
                
$xoopsTpl->assign("showing"sprintf(_SR_SHOWING1$max_results_per_page));
                
$count count($results);
                
$all_results_counts[$module->getVar('name')] = $count;

                if (!
is_array($results) || $count == 0) {
                    
$all_results[$module->getVar('name')] = array();
                } else {
                                ((
$count $start) > $max_results_per_page)? $num_show_this_page $max_results_per_page$num_show_this_page $count $start;
                                for (
$i 0$i $num_show_this_page$i++) {
                          
$results[$i]['processed_image_alt_text'] = $myts->makeTboxData4Show($module->getVar('name')) . ": ";
                        if (isset(
$results[$i]['image']) && $results[$i]['image'] != "") {
                              
$results[$i]['processed_image_url'] = "modules/" $module->getVar('dirname') . "/" $results[$i]['image'];
                        } else {
                              
$results[$i]['processed_image_url'] = "images/icons/posticon2.gif";
                        }
                        if (!
preg_match("/^http[s]*:///i"$results[$i]['link'])) {
                            
$results[$i]['link'] = "modules/".$module->getVar('dirname')."/".$results[$i]['link'];
                        }
                        
$results[$i]['processed_title'] = $myts->makeTboxData4Show($results[$i]['title']);
                        
$results[$i]['uid'] = @intval($results[$i]['uid']);
                        if ( !empty(
$results[$i]['uid']) ) {
                            
$uname XoopsUser::getUnameFromId($results[$i]['uid']);
                            
$results[$i]['processed_user_name'] = $uname;
                            
$results[$i]['processed_user_url'] = XOOPS_URL."/userinfo.php?uid=".$results[$i]['uid'];
                        }
                        
$results[$i]['processed_time'] = !empty($results[$i]['time']) ? " ("formatTimestamp(intval($results[$i]['time'])).")" "";
                    }
                    if ( 
$count $max_results_per_page ) {
                        
$search_url XOOPS_URL.'/search.php?query='.urlencode(stripslashes(implode(' '$queries)));
                        
$search_url .= "&mid=$mid&action=showall&andor=$andor";
                    } else {
                        
$search_url "";
                    }
                    
$all_results[$module->getVar('name')] = array("search_more_title" => _SR_SHOWALLR
                                                                
"search_more_url" => htmlspecialchars($search_url), 
                                                                
"results" => array_slice($results0$num_show_this_page));
                }
            }
            unset(
$results);
            unset(
$module);
        }
        break;
    case 
"showall":
    case 
'showallbyuser':
        
$max_results_per_page 20;
        
$module_handler =& xoops_gethandler('module');
        
$module =& $module_handler->get($mid);
        
$results =& $module->search($queries$andor0$start$uid);
      
//$xoopsTpl->assign("showing", sprintf(_SR_SHOWING, $start + 1, $start + 20));
        
$count count($results);
        
$all_results_counts[$module->getVar('name')] = $count;
        if (
is_array($results) && $count 0) {
                    ((
$count $start) > $max_results_per_page)? $num_show_this_page $max_results_per_page$num_show_this_page $count $start;
            for (
$i 0$i $num_show_this_page$i++) {
                  
$results[$i]['processed_image_alt_text'] = $myts->makeTboxData4Show($module->getVar('name')) . ": ";
                if (isset(
$results[$i]['image']) && $results[$i]['image'] != "") {
                      
$results[$i]['processed_image_url'] = "modules/" $module->getVar('dirname') . "/" $results[$i]['image'];
                } else {
                      
$results[$i]['processed_image_url'] = "images/icons/posticon2.gif";
                }
                if (!
preg_match("/^http[s]*:///i"$results[$i]['link'])) {
                    
$results[$i]['link'] = "modules/".$module->getVar('dirname')."/".$results[$i]['link'];
                }
                
$results[$i]['processed_title'] = $myts->makeTboxData4Show($results[$i]['title']);
                
$results[$i]['uid'] = @intval($results[$i]['uid']);
                if ( !empty(
$results[$i]['uid']) ) {
                    
$uname XoopsUser::getUnameFromId($results[$i]['uid']);
                    
$results[$i]['processed_user_name'] = $uname;
                    
$results[$i]['processed_user_url'] = XOOPS_URL."/userinfo.php?uid=".$results[$i]['uid'];
                }
                
$results[$i]['processed_time'] = !empty($results[$i]['time']) ? " ("formatTimestamp(intval($results[$i]['time'])).")" "";
            }
            
                        
$search_url_prev "";
                        
$search_url_next "";
                        
                        
$search_url_base "XOOPS_URL.'/search.php?";
                        
$search_url_get_params 'query=' urlencode(stripslashes(implode(' '$queries)));
                
$search_url_get_params .= "&mid=$mid&action=$action&andor=$andor";
                if (
$action=='showallbyuser') {
                    
$search_url_get_params .= "&uid=$uid";
                }
                        
$search_url $search_url_base $search_url_get_params;
                        
        include_once 
XOOPS_ROOT_PATH.'/class/pagenav.php';
        
$pagenav = new XoopsPageNav($count$max_results_per_page$start"start"$search_url_get_params);
        
$all_results[$module->getVar('name')] = array("results" =>array_slice($results0$num_show_this_page),
                                                      
"page_nav" => $pagenav->renderNav());
        } else {
            echo 
'<p>'._SR_NOMATCH.'</p>';
        }
        break;
}
arsort($all_results_counts);
$xoopsTpl->assign("module_sort_order"$all_results_counts);
$xoopsTpl->assign("search_results"$all_results);

$search_form = include 'include/searchform.php';
$xoopsTpl->assign('search_form'$search_form);

include 
XOOPS_ROOT_PATH."/footer.php";
?>


Here's the new template file:

<{if $basic_search == false }>
<
strong>Search Type:</strong> <{$search_type}><br />
<
strong>Keywords: </strong>
        <{* 
This section generates a space separated list of keywords that were searched. *}>
        <{
section name=cur_kw_searched loop=$searched_keywords}>
              <{
$searched_keywords[cur_kw_searched]}><{if $smarty.section.cur_kw_searched.index <> $smarty.section.cur_kw_searched.total}>&nbsp;<{/if}>
        <{/
section}>
<
br /><br />
<
table cellpadding="0" cellspacing="0" width="100%" height="33" border="0">
 <
tr height="33">
  <
td width="3"><img src="images/search/header.left.gif" /></td>
  <
td style="background-image: url(images/search/header.background.gif); vertical-align: middle">
   <
table cellpadding="0" cellspacing="0" border="0">
    <
tr>
     <
td colspan="2" style="font-family: sans-serif; font-size: large; font-weight: bold; padding-left: 3px;"><{$label_search_results}>: <{$showing}></td>
    </
tr>
   </
table>
  </
td>
  <
td width="3"><img src="images/search/header.right.gif" /></td>
 </
tr>
</
table>

<
table cellpadding="0" cellspacing="0" width="100%" border="0">
<{foreach 
from=$module_sort_order key=sort_key item=sort_value}>
<
tr>
 <
td><img src="images/search/articleHeader.left.gif" /></td>
 <
td style="background-image: url(images/search/articleHeader.background.gif);">
     <
div style="font-size: large; padding-top: 5px; padding-bottom: 5px;"><b><{$sort_key}></b>: (<{$sort_value}> hits returned)</div>
    <{if 
$search_results[$sort_key].search_more_url != ''}>
      <
div style="padding-bottom: 5px;"><a href="<{$search_results[$sort_key].search_more_url}>"><img src="images/search/search.more_results.gif" alt="<{$search_results[$sort_key].search_more_title}>" /></a></div>
    <{/if}>
    <{if 
$search_results[$sort_key].page_nav != ''}>
        <
div style="padding-bottom: 5px; text-align: right"><{$search_results[$sort_key].page_nav}></div>
    <{/if}>
 </
td>
 <
td><img src="images/search/articleHeader.right.gif" /></td>
</
tr>
<
tr style="background-color: #FDFDFD;">
 <
td width="16" style="background-image: url(images/search/article.left.gif)"></td>
 <
td style="padding: 15px">
    <
table class="outer" cellpadding="4" cellspacing="1" width="100%">
        <{
section name=cur_result loop=$search_results[$sort_key].results}>
        <
tr>
            <
td class="head"><{math equation="x + y" x=$smarty.section.cur_result.index y=$start}></td>
            <
td align="left" class="<{cycle values="even,odd"}>" width="100%">
                <
img alt="<{$search_results[$sort_key].results[cur_result].processed_image_alt_text}>" src="<{$search_results[$sort_key].results[cur_result].processed_image_url}>" />
                <{
$search_results[$sort_key].results[cur_result].processed_image_tag}>&nbsp;
                <
b><a href="<{$search_results[$sort_key].results[cur_result].link}>"><{$search_results[$sort_key].results[cur_result].processed_title}></a>                        </b>
                <
br /><small>&nbsp;&nbsp;<a href="<{$search_results[$sort_key].results[cur_result].processed_user_url}>"><{$search_results[$sort_key].results[cur_result].processed_user_name}></a> <{$search_results[$sort_key].results[cur_result].processed_time}></small>
                 </
td>
        </
tr>
        <{/
section}>
    </
table>
    <{if 
$search_results[$sort_key].page_nav != ''}>
        <
div style="padding-bottom: 5px; text-align: right"><{$search_results[$sort_key].page_nav}></div>
    <{/if}>
 </
td>
 <
td width="19" style="background-image: url(images/search/article.right.gif)"></td>
</
tr>
<{/foreach}>

    <
tr>
     <
td><img src="images/search/footer.left.gif" /></td>
     <
td style="background-image: url(images/search/footer.background.gif);"></td>
     <
td><img src="images/search/footer.right.gif" /></td>
    </
tr>
</
table>
<
br /><br />
<{
$label_ignored_keywords}>&nbsp;
    <
strong>
    <{* 
This section generates a space separated list of keywords that were NOT searched. *}>
     <{
section name=cur_kw_not_searched loop=$ignored_keywords}>
          <{
$ignored_keywords[cur_kw_not_searched]}><{if $smarty.section.cur_kw_not_searched.index <> $smarty.section.cur_kw_not_searched.total}>&nbsp;<{/if}>
    <{/
section}>
    </
strong>
<
br /><br />
<{/if}>
<{
$search_form}>


You can get these files and the images that are referenced by the template by clicking here.

So far, this seems to be getting a good reception with my users. If you can handle the performance hit with this latest change, then you might be able to make good use of it too!

17
marcan
Re: Xoops Search - A Better Implementation?
  • 2007/8/14 13:17

  • marcan

  • Just can't stay away

  • Posts: 824

  • Since: 2003/10/8


Hi rlankford,

This is very interesting and very well documented. I would like to have a better look at the code to perhaps be implemented in a future XOOPS release.

I have created a patch item on SourceForge for this. Could I ask you to create a package containing the modified files and upload it on this patch item.

Looking forward to test this !

Thanks !
.:: marcan (aka mal aka Marc-André) ::.
.:: Open Source :: The SmartFactory ::.
.:: XOOPS Professional Services :: INBOX International ::.

18
rlankford
Re: Xoops Search - A Better Implementation?
  • 2007/8/14 14:45

  • rlankford

  • Not too shy to talk

  • Posts: 158

  • Since: 2004/8/27


OK, let me mull it over a little more over the next couple of days. I probably need to 'hack in' a preference setting in the admin panel that lets the XOOPS user choose whether or not they want the main search page to support 'deep' searches or not. That way, large sites can default back to only searching x (where x is 5 at the moment) at a time on the initial search results page.

I'll get back to you...

19
kurak_bu
Re: Xoops Search - A Better Implementation?
  • 2007/8/14 15:46

  • kurak_bu

  • Quite a regular

  • Posts: 342

  • Since: 2005/9/5 1


great job, hope we will see this in XOOPS as soon as possible

20
rlankford
Re: Xoops Search - A Better Implementation?
  • 2007/8/16 2:14

  • rlankford

  • Not too shy to talk

  • Posts: 158

  • Since: 2004/8/27


I've posted the patch. Let me know if you have any trouble with it!

Login

Who's Online

218 user(s) are online (117 user(s) are browsing Support Forums)


Members: 0


Guests: 218


more...

Donat-O-Meter

Stats
Goal: $100.00
Due Date: Mar 31
Gross Amount: $0.00
Net Balance: $0.00
Left to go: $100.00
Make donations with PayPal!

Latest GitHub Commits