Update Xoops 2.0.x Search Page to Support the Template Engine
Overview Xoops has a template engine that allows you to separate page generation (php code) from page layout and presentation (HTML + CSS). Xoops also supports a theme engine. This level of customization exists “above” data generation + layout and is outside the scope of this article. Templates are HTML documents written to make use of Smarty tags. Smarty is an additional language/layer that you must learn in order layout your Xoops generated HTML. Basically, though, the paradigm is one of adding in tags throughout your HTML that act as placeholders for incoming variables that were set up by the corresponding PHP page. By default, the search page for Xoops is found at the root of your Xoops directory and is called search.php. This page (unlike most) actually generates the HTML necessary to carry out it's assigned task directly inside the PHP code with a series of 'echo' statements. This makes the process of updating the look and feel of the Xoops search page more difficult since you now have to deal with the functionality of Xoop's search engine too. This 'How To' documents the process for stripping out layout from function with regards to search.php. At the end of this tutorial, your Xoops system will have a new system-level template that is associated with your search page. You'll be able to update the look and feel of your search page by manipulating this Smarty template rather than the search.php file directly. Furthermore, the search.php page will now have an interface (or contract) between itself and the corresponding template page that consists of various tags and their meanings. This means that you can tweak search.php whenever you like to change how the search engine works without necessarily affecting the look and feel of the search page itself (unless, of course, your changes necessitate a change to the interface with the template). Back Up Everything – Use a Test Site – Yadda, Yadda, Yadda As with anything, be sure to back up your valuable data first before attempting the changes in this document. Make these changes on test site first (if you can). Although nothing here is too invasive, it's important to be sure that you can recover if something goes wrong. searchform.php In the “include” folder, there exists a file called searchform.php. This file is responsible for generating the 'advanced search' form that you see at the bottom of every search page. Before we do anything else, we need to make a small change to this form in order to make it compatible with our new search template. At the very bottom of the file, simply add the following line:
$search_form->addElement(new XoopsFormButton("", "submit", _SR_SEARCH, "submit"));
return $search_form->render(); // Added by Lankford on 2007/7/26.
?>
$modversion['templates'][15]['description'] = 'Dummy template for custom blocks or blocks without templates';
$modversion['templates'][16]['file'] = 'system_search.html';
$modversion['templates'][16]['description'] = 'Smarty template for Xoops' search page.';
// Blocks
<h3>"<{$search_type}>" <{$label_search_results}>: <{$showing}>h3>
<{$label_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}> <{/if}>
<{/section}>
strong>
<br />
<{$label_ignored_keywords}>
<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}> <{/if}>
<{/section}>
strong>
<br />
<{*
This section generates a search results that mimic Xoops' original search.php results.
Note: The results are sorted. Modules with higher hit counts are located on the page
above modules with lower hit counts.
*}>
<{* This section has been commented out in favor of the 'table' version located below...
<{foreach from=$module_sort_order key=sort_key item=sort_value}>
<{$sort_key}>: (<{$sort_value}> hits returned)
<{section name=cur_result loop=$search_results[$sort_key].results}>
<{if $smarty.section.cur_result.index > 0}>
<{/if}>
" src="<{$search_results[$sort_key].results[cur_result].processed_image_url}>" />
<{$search_results[$sort_key].results[cur_result].processed_image_tag}>
"><{$search_results[$sort_key].results[cur_result].processed_title}>
"><{$search_results[$sort_key].results[cur_result].processed_user_name}> <{$search_results[$sort_key].results[cur_result].processed_time}>
<{/section}>
"><{$search_results[$sort_key].search_more_title}>
<{/foreach}>
*}>
<{*
This section generates a search results and places them into tables using the standard
Xoops style tags for table formatting.
Note: The results are sorted. Modules with higher hit counts are located on the page
above modules with lower hit counts.
*}>
<{foreach from=$module_sort_order key=sort_key item=sort_value}>
<{$sort_key}>: (<{$sort_value}> hits returned)
<{if ($search_results[$sort_key].search_more_title == '') and ($sort_value > 0)}>
"><{$search_results[$sort_key].search_prev_title}>
"><{$search_results[$sort_key].search_next_title}>
<{/if}>
<{section name=cur_result loop=$search_results[$sort_key].results}>
<{math equation="x + y" x=$smarty.section.cur_result.index y=$start}>
" width="100%">
" src="<{$search_results[$sort_key].results[cur_result].processed_image_url}>" />
<{$search_results[$sort_key].results[cur_result].processed_image_tag}>
"><{$search_results[$sort_key].results[cur_result].processed_title}>
"><{$search_results[$sort_key].results[cur_result].processed_user_name}> <{$search_results[$sort_key].results[cur_result].processed_time}>
<{/section}>
<{if $sort_value > 0 }>
<{if $search_results[$sort_key].search_more_title == ''}>
"><{$search_results[$sort_key].search_prev_title}>
"><{$search_results[$sort_key].search_next_title}>
<{else}>
<{if $search_results[$sort_key].search_more_url != ''}>
"><{$search_results[$sort_key].search_more_title}>
<{/if}>
<{/if}>
<{/if}>
<{/foreach}>
<{$search_form}>
// $Id: search.php 506 2006-05-26 23:10:37Z skalpa $
// ------------------------------------------------------------------------ //
// XOOPS - PHP Content Management System //
// Copyright (c) 2000 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();
}
}
$groups = is_object($xoopsUser) ? $xoopsUser -> getGroups() : XOOPS_GROUP_ANONYMOUS;
$gperm_handler = & xoops_gethandler( 'groupperm' );
$available_modules = $gperm_handler->getItemIds('module_read', $groups);
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);
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', 2, sprintf(_SR_KEYTOOSHORT, $xoopsConfigSearch['keyword_min']));
exit();
}
} else {
$query = trim($query);
if (strlen($query) < $xoopsConfigSearch['keyword_min']) {
redirect_header('search.php', 2, sprintf(_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":
$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($criteria, true);
$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, $andor, 5, 0);
$xoopsTpl->assign("showing", sprintf(_SR_SHOWING, 1, 5));
$count = count($results);
$all_results_counts[$module->getVar('name')] = $count;
if (!is_array($results) || $count == 0) {
$all_results[$module->getVar('name')] = array();
} else {
for ($i = 0; $i < $count; $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 >= 5 ) {
$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),
"search_next_title" => "",
"search_next_url" => "",
"search_prev_title" => "",
"search_prev_url" => "",
"results" =>$results);
}
}
unset($results);
unset($module);
}
break;
case "showall":
case 'showallbyuser':
$module_handler =& xoops_gethandler('module');
$module =& $module_handler->get($mid);
$results =& $module->search($queries, $andor, 20, $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) {
$next_results =& $module->search($queries, $andor, 1, $start + 20, $uid);
$next_count = count($next_results);
$has_next = false;
if (is_array($next_results) && $next_count == 1) {
$has_next = true;
}
for ($i = 0; $i < $count; $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 = XOOPS_URL.'/search.php?query='.urlencode(stripslashes(implode(' ', $queries)));
$search_url .= "&mid=$mid&action=$action&andor=$andor";
if ($action=='showallbyuser') {
$search_url .= "&uid=$uid";
}
if ( $start > 0 ) {
$prev = $start - 20;
$search_url_prev = $search_url."&start=$prev";
}
if (false != $has_next) {
$next = $start + 20;
$search_url_next = $search_url."&start=$next";
}
$all_results[$module->getVar('name')] = array("search_more_title" => "",
"search_more_url" => "",
"search_next_title" => _SR_NEXT,
"search_next_url" => htmlspecialchars($search_url_next),
"search_prev_title" => _SR_PREVIOUS,
"search_prev_url" => htmlspecialchars($search_url_prev),
"results" =>$results);
} else {
echo ''
._SR_NOMATCH.'';
}
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";
?>
Template system_search.html inserted to the database. Template system_search.html recompiled.
This Q&A was found on XOOPS Web Application System : https://xoops.org/modules/smartfaq/faq.php?faqid=678