Zikula_System_Modules
[ class tree: Zikula_System_Modules ] [ index: Zikula_System_Modules ] [ all elements ]

Source for file pnuser.php

Documentation is available at pnuser.php

  1. <?php
  2. /**
  3.  * Zikula Application Framework
  4.  *
  5.  * @copyright (c) 2002, Zikula Development Team
  6.  * @link http://www.zikula.org
  7.  * @version $Id: pnuser.php 24353 2008-06-08 10:41:06Z jornlind $
  8.  * @license GNU/GPL - http://www.gnu.org/copyleft/gpl.html
  9.  * @package Zikula_System_Modules
  10.  * @subpackage Search
  11.  * @author Patrick Kellum
  12.  * @author Stefano Garuti (ported to pnAPI)
  13.  */
  14.  
  15. /**
  16. * Main user function
  17. *
  18. * This function is the default function. Call the function to show the search form.
  19. *
  20. @author Stefano Garuti
  21. @return string HTML string templated
  22. */
  23. function search_user_main()
  24. {
  25.     // Security check
  26.     if (!SecurityUtil::checkPermission('Search::''::'ACCESS_READ)) {
  27.         return LogUtil::registerPermissionError();
  28.     }
  29.  
  30.     // Create output object
  31.     $pnRender pnRender::getInstance('Search');
  32.  
  33.     // Return the output that has been generated by this function
  34.     return $pnRender->fetch('search_user_main.htm');
  35. }
  36.  
  37. /*
  38. * Splits the query string into words suitable for a mysql query
  39. *
  40. * This function is ported 'as is' from the old, nonAPI, module
  41. * it is called from each plugin so we can't delete it or change it's name
  42. *
  43. * @author Patrick Kellum
  44. * @param string $q the string to parse and split
  45. * @param string $dbwildcard wrap each word in a DB wildcard character (%)
  46. * @return array an array of words optionally surrounded by '%'
  47. */
  48. function search_split_query($q$dbwildcard true)
  49. {
  50.     if (!isset($q)) {
  51.         return;
  52.     }
  53.  
  54.     $w array();
  55.     $stripped DataUtil::formatForStore($q);
  56.     $qwords preg_split('/ /'$stripped-1PREG_SPLIT_NO_EMPTY);
  57.  
  58.     foreach($qwords as $word{
  59.         if ($dbwildcard{
  60.             $w['%' $word '%';
  61.         else {
  62.             $w[$word;
  63.         }
  64.     }
  65.  
  66.     return $w;
  67. }
  68.  
  69. /*
  70. * Contruct part of a where clause out of the supplied search parameters
  71. *
  72. */
  73. function search_construct_where($args$fields$mlfield null)
  74. {
  75.     $where '';
  76.  
  77.     if (!isset($args|| empty($args|| !isset($fields|| empty($fields)) {
  78.         return $where;
  79.     }
  80.  
  81.     if (!empty($args['q'])) {
  82.         $q DataUtil::formatForStore($args['q']);
  83.         $q str_replace('%''\\%'$q);  // Don't allow user input % as wildcard
  84.         $where .= ' (';
  85.         if ($args['searchtype'!== 'EXACT'{
  86.             $searchwords search_split_query($q);
  87.             $connector $args['searchtype'== 'AND' ' AND ' ' OR ';
  88.         else {
  89.             $searchwords array("%{$q}%");
  90.         }
  91.         $start true;
  92.         foreach($searchwords as $word{
  93.             $where .= (!$start $connector ''' (';
  94.             // I'm not sure if "LIKE" is the best solution in terms of DB portability (PC)
  95.             foreach ($fields as $field{
  96.                 $where .= "{$field} LIKE '$word' OR ";
  97.             }
  98.             $where substr($where-4);
  99.             $where .= ')';
  100.             $start false;
  101.         }
  102.         $where .= ') ';
  103.     }
  104.  
  105.     // Check if we're in a multilingual setup
  106.     if (isset($mlfield&& pnConfigGetVar('multilingual'== 1{
  107.         $currentlang pnUserGetLang();
  108.         $where .= "AND ({$mlfield} = '$currentlang' OR {$mlfield} = '')";
  109.     }
  110.  
  111.     return $where;
  112. }
  113.  
  114. /**
  115. * Generate complete search form
  116. *
  117. * Generate the whole search form, including the various plugins options.
  118. * It uses the Search API's getallplugins() function to find plugins.
  119. *
  120. @author Patrick Kellum
  121. @author Stefano Garuti
  122. *
  123. @return string HTML string templated
  124. */
  125. function search_user_form($vars)
  126. {
  127.     // Security check
  128.     if (!SecurityUtil::checkPermission('Search::''::'ACCESS_READ)) {
  129.         return LogUtil::registerPermissionError();
  130.     }
  131.  
  132.     // get parameter from input
  133.     $vars['q'strip_tags(FormUtil::getPassedValue('q''''REQUEST'));
  134.     $vars['searchtype'FormUtil::getPassedValue('searchtype'SessionUtil::getVar('searchtype')'REQUEST');
  135.     $vars['searchorder'FormUtil::getPassedValue('searchorder'SessionUtil::getVar('searchorder')'REQUEST');
  136.     $vars['numlimit'pnModGetVar('Search''itemsperpage'25);
  137.     // this var allows the headers to not be displayed
  138.     if (!isset($vars['titles']))
  139.       $vars['titles'true;
  140.  
  141.     // set some defaults
  142.     if (!isset($vars['searchtype']|| empty($vars['searchtype'])) {
  143.         $vars['searchtype''AND';
  144.     }
  145.     if (!isset($vars['searchorder']|| empty($vars['searchorder'])) {
  146.         $vars['searchorder''newest';
  147.     }
  148.  
  149.     // reset the session vars for a new search
  150.     SessionUtil::delVar('searchtype');
  151.     SessionUtil::delVar('searchorder');
  152.     SessionUtil::delVar('searchactive');
  153.     SessionUtil::delVar('searchmodvar');
  154.  
  155.     // get all the search plugins
  156.     $search_modules pnModAPIFunc('Search''user''getallplugins');
  157.  
  158.     if (count($search_modules0{
  159.         $plugin_options array();
  160.         foreach($search_modules as $mods{
  161.             // as every search plugins return a formatted html string
  162.             // we assign it to a generic holder named 'plugin_options'
  163.             // maybe in future this will change
  164.             // we should retrieve from the plugins an array of values
  165.             // and formatting it here according with the module's template
  166.             // we have also to provide some trick to assure the 'backward compatibility'
  167.  
  168.             $plugin_options[$mods['title']] pnModAPIFunc($mods['title']'search''options'$vars);
  169.         }
  170.         // Create output object
  171.         $pnRender pnRender::getInstance('Search');
  172.         // add content to template
  173.         $pnRender->assign($vars);
  174.         $pnRender->assign('plugin_options'$plugin_options);
  175.  
  176.         // Return the output that has been generated by this function
  177.         return $pnRender->fetch('search_user_form.htm');
  178.     else {
  179.         // Create output object
  180.         $pnRender pnRender::getInstance('Search');
  181.         // Return the output that has been generated by this function
  182.         return $pnRender->fetch('search_user_noplugins.htm');
  183.     }
  184. }
  185.  
  186.  
  187. /** Class for doing module based access check and URL creation of search result
  188.  *
  189.  * - The module based access is somewhat deprecated (it still works but is not
  190.  *   used since it makes it impossible to count the number of search result).
  191.  * - The URL for each found item is created here. By doing this we only create
  192.  *   URLs for results the user actually view and save some time this way.
  193.  * @package Zikula_System_Modules
  194.  * @subpackage Search
  195.  */
  196. {
  197.     // This variable contains a table of all search plugins (indexed by module name)
  198.     var $search_modules = array();
  199.  
  200.  
  201.     function search_result_checker($search_modules)
  202.     {
  203.         $this->search_modules = $search_modules;
  204.     }
  205.  
  206.  
  207.     // This method is called by DBUtil::selectObjectArrayFilter() for each and every search result.
  208.     // A return value of true means "keep result" - false means "discard".
  209.     // The decision is delegated to the search plugin (module) that generated the result
  210.     function checkResult(&$datarow)
  211.     {
  212.         // Get module name
  213.         $module $datarow['module'];
  214.  
  215.         // Get plugin information
  216.         $mod $this->search_modules[$module];
  217.  
  218.         $ok true;
  219.  
  220.         if (isset($mod['functions'])) {
  221.             foreach ($mod['functions'as $contenttype => $function{
  222.                 // Delegate check to search plugin
  223.                 // (also allow plugin to write 'url' => ... into $datarow by passing it by reference)
  224.                 $ok $ok && pnModAPIFunc($mod['title']'search'$function.'_check',
  225.                                           array('datarow'     => &$datarow,
  226.                                                 'contenttype' => $contenttype));
  227.             }
  228.         }
  229.  
  230.         return $ok;
  231.     }
  232. }
  233.  
  234. /**
  235. * Perform the search then show the results
  236. *
  237. * This function includes all the search plugins, then call every one passing
  238. * an array that contains the string to search for, the boolean operators.
  239. *
  240. @author Patrick Kellum
  241. @author Stefano Garuti
  242. @author Mark West
  243. @author Jorn Wildt
  244. *
  245. @return string HTML string templated
  246. */
  247. function search_user_search()
  248. {
  249.     // Security check
  250.     if (!SecurityUtil::checkPermission('Search::''::'ACCESS_READ)) {
  251.         return LogUtil::registerPermissionError();
  252.     }
  253.  
  254.     // get parameter from HTTP input
  255.     $vars array();
  256.     $vars['q'strip_tags(FormUtil::getPassedValue('q''''REQUEST'));
  257.     $vars['searchtype'FormUtil::getPassedValue('searchtype'SessionUtil::getVar('searchtype')'REQUEST');
  258.     $vars['searchorder'FormUtil::getPassedValue('searchorder'SessionUtil::getVar('searchorder')'REQUEST');
  259.     $vars['numlimit'pnModGetVar('Search''itemsperpage'25);
  260.     $vars['page'= (int)FormUtil::getPassedValue('page'1'REQUEST');
  261.  
  262.     // $firstpage is used to identify the very first result page 
  263.     // - and to disable calls to plugins on the following pages
  264.     $firstPage !isset($_REQUEST['page']);
  265.  
  266.     // The modulename exists in this array as key, if the checkbox was filled
  267.     $active FormUtil::getPassedValue('active'SessionUtil::getVar('searchactive')'REQUEST');
  268.  
  269.     // All formular data from the modules search plugins is contained in:
  270.     $modvar FormUtil::getPassedValue('modvar'SessionUtil::getVar('searchmodvar')'REQUEST');
  271.  
  272.     // set some defaults
  273.     if (!isset($vars['searchtype']|| empty($vars['searchtype'])) {
  274.         $vars['searchtype''AND';
  275.     else {
  276.         SessionUtil::setVar('searchtype'$vars['searchtype']);
  277.     }
  278.     if (!isset($vars['searchorder']|| empty($vars['searchorder'])) {
  279.         $vars['searchorder''newest';
  280.     else {
  281.         SessionUtil::setVar('searchorder'$vars['searchorder']);
  282.     }
  283.     if (!isset($active|| !is_array($active|| empty($active)) {
  284.         $active array();
  285.     else {
  286.         SessionUtil::setVar('searchactive'$active);
  287.     }
  288.     if (!isset($modvar|| !is_array($modvar|| empty($modvar)) {
  289.         $modvar array();
  290.     else {
  291.         SessionUtil::setVar('searchmodvar'$modvar);
  292.     }
  293.  
  294.     // work out row index from page number
  295.     $vars['startnum'(($vars['page'1$vars['numlimit']1;
  296.  
  297.     if (empty($vars['q'])) {
  298.         return pnRedirect(pnModUrl('Search''user''main'));
  299.     }
  300.  
  301.     // get all the search plugins
  302.     $search_modules pnModAPIFunc('Search''user''getallplugins');
  303.  
  304.     // Create output object and check caching
  305.     $pnRender pnRender::getInstance('Search');
  306.     $pnRender->cache_id md5($vars['q'$vars['searchtype'$vars['searchorder'pnUserGetVar('uid')) $vars['page'];
  307.     // check if the contents are cached.
  308.     if ($pnRender->is_cached('search_user_results.htm')) {
  309.         return $pnRender->fetch('search_user_results.htm');
  310.     }
  311.  
  312.     // load the extra language file
  313.     pnModLangLoad('Search''search');
  314.  
  315.     // Load database stuff
  316.     pnModDBInfoLoad('Search');
  317.     $pntable      pnDBGetTables();
  318.     $userId       = (int)pnUserGetVar('uid');
  319.     $searchTable  $pntable['search_result'];
  320.     $searchColumn $pntable['search_result_column'];
  321.  
  322.     // Create restriction on result table (so user only sees own results)
  323.     $userResultWhere "$searchColumn[session] = 'session_id("'";
  324.  
  325.     // Do all the heavy database stuff on the first page only
  326.     if ($firstPage)
  327.     {
  328.         // Clear current search result for current user - before showing the first page
  329.         // Clear also older searches from other users.
  330.         $dbType DBConnectionStack::getConnectionDBType();
  331.         $where  $userResultWhere;
  332.     if ($dbType=='postgres'{
  333.             $where .= " OR $searchColumn[found] + INTERVAL '8 HOUR' < NOW();
  334.         else {
  335.             $where .= " OR DATE_ADD($searchColumn[found], INTERVAL 8 HOUR) < NOW();
  336.         }
  337.         
  338.         DBUtil::deleteWhere ('search_result'$where);
  339.  
  340.         // Ask active modules to find their items and put them into $searchTable for the current user
  341.         // At the same time convert modules list from numeric index to modname index
  342.  
  343.         $searchModulesByName array();
  344.         foreach($search_modules as $mod{
  345.             // check we've a valid search plugin
  346.             if (isset($mod['functions']&& (empty($active|| isset($active[$mod['title']]))) {
  347.                 foreach ($mod['functions'as $contenttype => $function{
  348.                     if (isset($modvar[$mod['title']])) {
  349.                         $param array_merge($vars$modvar[$mod['title']]);
  350.                     else {
  351.                         $param $vars;
  352.                     }
  353.                     $searchModulesByName[$mod['name']] $mod;
  354.                     $ok pnModAPIFunc($mod['title']'search'$function$param);
  355.                     if (!$ok{
  356.                         LogUtil::registerError ("Internal error: module $mod[title] returned false in search function '$function'");
  357.                         return pnRedirect(pnModUrl('Search''user''main'));
  358.                     }
  359.                 }
  360.             }
  361.         }
  362.  
  363.     // Count number of found results
  364.     $resultCount DBUtil::selectObjectCount ('search_result'$userResultWhere);
  365.         SessionUtil::setVar('searchResultCount'$resultCount);
  366.         SessionUtil::setVar('searchModulesByName'$searchModulesByName);
  367.     }
  368.     else
  369.     {
  370.         $resultCount SessionUtil::getVar('searchResultCount');
  371.         $searchModulesByName SessionUtil::getVar('searchModulesByName');
  372.     }
  373.  
  374.     // Fetch search result - do sorting and paging in database
  375.  
  376.     // Figure out what to sort by
  377.     switch ($vars['searchorder']{
  378.         case 'alphabetical':
  379.             $sort 'title';
  380.             break;
  381.         case 'oldest':
  382.             $sort 'created';
  383.             break;
  384.         case 'newest':
  385.             $sort 'created DESC';
  386.             break;
  387.         default:
  388.             $sort 'title';
  389.             break;
  390.     }
  391.  
  392.     // Get next N results from the current user's result set
  393.     // The "checker" object is used to:
  394.     // 1) do secondary access control (deprecated more or less)
  395.     // 2) let the modules add "url" to the found (and viewed) items
  396.     $checker new search_result_checker($searchModulesByName);
  397.     $sqlResult DBUtil::selectObjectArrayFilter('search_result'$userResultWhere$sort,  
  398.                                                  $vars['startnum']-1$vars['numlimit']'',
  399.                                                  $checkernull);
  400.  
  401.     // Get number of chars to display in search summaries
  402.     $limitsummary pnModGetVar('Search''limitsummary');
  403.     if (empty($limitsummary)) {
  404.         $limitsummary 200;
  405.     }
  406.  
  407.     $pnRender->assign('resultcount'$resultCount);
  408.     $pnRender->assign('results'$sqlResult);
  409.     $pnRender->assign(pnModGetVar('Search'));
  410.     $pnRender->assign($vars);
  411.     $pnRender->assign('limitsummary'$limitsummary)
  412.  
  413.     // log the search
  414.     pnModAPIFunc('Search''user''log'$vars);
  415.  
  416.     // Return the output that has been generated by this function
  417.     return $pnRender->fetch('search_user_results.htm');
  418. }
  419.  
  420.  
  421. /**
  422.  * display a list of recent searches
  423.  *
  424.  * @author Jorg Napp
  425.  */
  426. function Search_user_recent()
  427. {
  428.     // security check
  429.     if (!SecurityUtil::checkPermission('Search::''::'ACCESS_READ)) {
  430.         return LogUtil::registerPermissionError();
  431.     }
  432.  
  433.     // Get parameters from whatever input we need.
  434.     $startnum = (int)FormUtil::getPassedValue('startnum'null'GET');
  435.  
  436.     // we need this value multiple times, so we keep it
  437.     $itemsperpage pnModGetVar('Search''itemsperpage');
  438.  
  439.     // get the
  440.     $items pnModApiFunc('Search''user''getall'array('startnum' => $startnum'numitems' => $itemsperpage'sortorder' => 'date'));
  441.  
  442.     // Create output object - this object will store all of our output so that
  443.     // we can return it easily when required
  444.     $pnRender pnRender::getInstance('Search');
  445.  
  446.     // assign the results to the template
  447.     $pnRender->assign('recentsearches'$items);
  448.  
  449.     // assign the values for the smarty plugin to produce a pager in case of there
  450.     // being many items to display.
  451.     $pnRender->assign('pager'array('numitems'     => pnModAPIFunc('Search''user''countitems'),
  452.                                      'itemsperpage' => $itemsperpage));
  453.  
  454.     // Return the output that has been generated by this function
  455.     return $pnRender->fetch('search_user_recent.htm');
  456. }

Documentation generated on Fri, 18 Jul 2008 21:54:59 +0200 by phpDocumentor 1.4.1