Added callback function to search API (feature request #0000985) HEAD
authorSami Barakat
Sun Oct 25 22:01:38 2009 +0000 (3 months ago)
branchHEAD
changeset 73910bee991937cc
parent 73902b5aac1d58f8
child 73923872f0c040e4
Added callback function to search API (feature request #0000985)
system/classes/listfactory.class.php
system/classes/search.class.php
system/classes/searchcriteria.class.php
     1.1 --- a/system/classes/listfactory.class.php	Tue Oct 20 22:53:07 2009 +0100
     1.2 +++ b/system/classes/listfactory.class.php	Sun Oct 25 22:01:38 2009 +0000
     1.3 @@ -206,7 +206,13 @@
     1.4          if ($name === ROW_NUMBER) {
     1.5              $sort = false;
     1.6          }
     1.7 -        $this->_fields[] = array('title' => $title, 'name' => $name, 'display' => $display, 'sort' => $sort, 'format' => $format);
     1.8 +        $this->_fields[] = array(
     1.9 +            'title' => $title,
    1.10 +            'name' => $name,
    1.11 +            'display' => $display,
    1.12 +            'sort' => $sort,
    1.13 +            'format' => $format
    1.14 +        );
    1.15      }
    1.16  
    1.17      /**
    1.18 @@ -221,7 +227,26 @@
    1.19      */
    1.20      function setQuery( $title, $name, $sql, $rank )
    1.21      {
    1.22 -        $this->_query_arr[] = array('title' => $title, 'name' => $name, 'sql' => $sql, 'rank' => $rank);
    1.23 +        $this->_query_arr[] = array(
    1.24 +            'type' => 'sql',
    1.25 +            'title' => $title,
    1.26 +            'name' => $name,
    1.27 +            'sql' => $sql,
    1.28 +            'rank' => $rank
    1.29 +        );
    1.30 +        $this->_total_rank += $rank;
    1.31 +    }
    1.32 +
    1.33 +    function setCallback( $title, $name, $function, $rank, $total )
    1.34 +    {
    1.35 +        $this->_query_arr[] = array(
    1.36 +            'type' => 'callback',
    1.37 +            'title' => $title,
    1.38 +            'name' => $name,
    1.39 +            'func' => $function,
    1.40 +            'rank' => $rank,
    1.41 +            'total' => $total
    1.42 +        );
    1.43          $this->_total_rank += $rank;
    1.44      }
    1.45  
    1.46 @@ -282,21 +307,25 @@
    1.47      * @return int Total number of rows
    1.48      *
    1.49      */
    1.50 -    function _numRows( $sql )
    1.51 +    function _getTotal( $param )
    1.52      {
    1.53 -        if (is_array($sql))
    1.54 -        {
    1.55 +        if ($param['type'] == 'callback') {
    1.56 +            return $param['total'];
    1.57 +        }
    1.58 +        else {
    1.59 +            $sql = $param['sql'];
    1.60 +        }
    1.61 +
    1.62 +        if (is_array($sql)) {
    1.63              $sql['mysql'] = preg_replace('/SELECT.*FROM/is', 'SELECT COUNT(*) FROM', $sql['mysql']);
    1.64              $sql['mssql'] = preg_replace('/SELECT.*FROM/is', 'SELECT COUNT(*) FROM', $sql['mssql']);
    1.65          }
    1.66 -        else
    1.67 -        {
    1.68 +        else {
    1.69              $sql = preg_replace('/SELECT.*FROM/is', 'SELECT COUNT(*) FROM', $sql);
    1.70          }
    1.71          $result = DB_query($sql);
    1.72          $num_rows = DB_numRows($result);
    1.73 -        if ($num_rows <= 1)
    1.74 -        {
    1.75 +        if ($num_rows <= 1) {
    1.76              $B = DB_fetchArray($result, true);
    1.77              $num_rows = $B[0];
    1.78          }
    1.79 @@ -397,7 +426,7 @@
    1.80          $limits = array();
    1.81          for ($i = 0; $i < count($this->_query_arr); $i++)
    1.82          {
    1.83 -            $limits[$i]['total'] = $this->_numRows($this->_query_arr[$i]['sql']);
    1.84 +            $limits[$i]['total'] = $this->_getTotal($this->_query_arr[$i]);
    1.85              $limits[$i]['pp'] = round(($this->_query_arr[$i]['rank'] / $this->_total_rank) * $num_query_results);
    1.86              $this->_total_found += $limits[$i]['total'];
    1.87              $pp_total += $limits[$i]['pp'];
    1.88 @@ -415,6 +444,44 @@
    1.89              if ($limits[$i]['limit'] <= 0) {
    1.90                  continue;
    1.91              }
    1.92 +
    1.93 +            // This is a callback function
    1.94 +            if ($this->_query_arr[$i]['type'] == 'callback')
    1.95 +            {
    1.96 +                if (is_callable($this->_query_arr[$i]['func']))
    1.97 +                {
    1.98 +                    $callback_rows = call_user_func_array($this->_query_arr[$i]['func'], array($limits[$i]['offset'], $limits[$i]['limit']));
    1.99 +
   1.100 +                    foreach ($callback_rows as $row)
   1.101 +                    {
   1.102 +                        $col = array();
   1.103 +                        $col[SQL_TITLE] = $this->_query_arr[$i]['title'];
   1.104 +                        $col[SQL_NAME] = $this->_query_arr[$i]['name'];
   1.105 +
   1.106 +                        foreach ($this->_fields as $field)
   1.107 +                        {
   1.108 +                            if (!is_numeric($field['name']) && $field['name'][0] != '_') {
   1.109 +                                if (empty($row[ $field['name'] ])) {
   1.110 +                                    $col[ $field['name'] ] = 'LF_NULL';
   1.111 +                                } else {
   1.112 +                                    $col[ $field['name'] ] = $row[ $field['name'] ];
   1.113 +                                }
   1.114 +                            }
   1.115 +                        }
   1.116 +
   1.117 +                        // Need to call the format function before and after
   1.118 +                        // sorting the results.
   1.119 +                        if (is_callable($this->_function)) {
   1.120 +                            $col = call_user_func_array($this->_function, array(true, $col));
   1.121 +                        }
   1.122 +
   1.123 +                        $rows_arr[] = $col;
   1.124 +                    }
   1.125 +                }
   1.126 +                continue;
   1.127 +            }
   1.128 +
   1.129 +            // This is an SQL query, so execute it and format the results
   1.130              $limit_sql = " LIMIT {$limits[$i]['offset']},{$limits[$i]['limit']}";
   1.131  
   1.132              if (is_array($this->_query_arr[$i]['sql']))
     2.1 --- a/system/classes/search.class.php	Tue Oct 20 22:53:07 2009 +0100
     2.2 +++ b/system/classes/search.class.php	Sun Oct 25 22:01:38 2009 +0000
     2.3 @@ -2,7 +2,7 @@
     2.4  
     2.5  /* Reminder: always indent with 4 spaces (no tabs). */
     2.6  // +---------------------------------------------------------------------------+
     2.7 -// | Geeklog 1.6                                                               |
     2.8 +// | Geeklog 1.6.1                                                             |
     2.9  // +---------------------------------------------------------------------------+
    2.10  // | search.class.php                                                          |
    2.11  // |                                                                           |
    2.12 @@ -342,8 +342,6 @@
    2.13      /**
    2.14      * Performs search on all stories
    2.15      *
    2.16 -    * @author Tony Bibbs, tony AT geeklog DOT net
    2.17 -    * @author Sami Barakat, s.m.barakat AT gmail DOT com
    2.18      * @access private
    2.19      * @return object plugin object
    2.20      *
    2.21 @@ -425,7 +423,6 @@
    2.22      * in this function to allow legacy support to plugins using
    2.23      * the old API calls defined versions prior to Geeklog 1.5.1
    2.24      *
    2.25 -    * @author Sami Barakat, s.m.barakat AT gmail DOT com
    2.26      * @access public
    2.27      * @return string HTML output for search results
    2.28      *
    2.29 @@ -460,7 +457,7 @@
    2.30  
    2.31          $url = "{$this->_searchURL}&amp;type={$this->_type}&amp;mode=";
    2.32          $obj = new ListFactory($url.'search', $_CONF['search_limits'], $_CONF['num_search_results']);
    2.33 -        $obj->setRowFunction(array($this, 'searchFormatCallBack'));
    2.34 +        $obj->setRowFunction(array($this, 'searchFormatCallback'));
    2.35          $obj->setField('ID', 'id', false);
    2.36          $obj->setField('URL', 'url', false);
    2.37  
    2.38 @@ -520,51 +517,62 @@
    2.39          {
    2.40              if (is_a($result, 'SearchCriteria'))
    2.41              {
    2.42 +                $debug_info = $result->getName() . " using APIv2";
    2.43 +
    2.44                  if ($this->_type != 'all' && $this->_type != $result->getName())
    2.45                  {
    2.46                      if ($this->_verbose) {
    2.47 -                        COM_errorLog($result->getName() . " using APIv2. Skipped as type is not " . $this->_type);
    2.48 +                        $new_api++;
    2.49 +                        COM_errorLog("$debug_info. Skipped as type is not " . $this->_type);
    2.50                      }
    2.51                      continue;
    2.52                  }
    2.53  
    2.54 -                $debug_info = $result->getName() . " using APIv2 with ";
    2.55 -
    2.56 -                if ($_CONF['search_use_fulltext'] == true && $result->getFTSQL() != '')
    2.57 -                {
    2.58 -                    $debug_info .= "FULLTEXT. ";
    2.59 -                    $sql = $result->getFTSQL();
    2.60 -                }
    2.61 -                else
    2.62 -                {
    2.63 -                    $debug_info .= "LIKE. ";
    2.64 -                    $sql = $result->getSQL();
    2.65 -                }
    2.66 -
    2.67 -                $sql = $this->_convertsql($sql);
    2.68 -
    2.69 -                $debug_info .= "SQL = " . print_r($sql,1);
    2.70 -                if ($this->_verbose) {
    2.71 -                    COM_errorLog($debug_info);
    2.72 -                }
    2.73 -
    2.74                  $api_results = $result->getResults();
    2.75                  if (!empty($api_results)) {
    2.76                      $obj->addResultArray($api_results);
    2.77                  }
    2.78  
    2.79 -                $obj->setQuery($result->getLabel(), $result->getName(), $sql, $result->getRank());
    2.80 +                $api_callback_func = $result->getCallback();
    2.81 +                if (!empty($api_callback_func))
    2.82 +                {
    2.83 +                    $debug_info .= " with Callback Function " . $api_callback_func;
    2.84 +                    $obj->setCallback($result->getLabel(), $result->getName(), $api_callback_func, $result->getRank(), $result->getTotal());
    2.85 +                }
    2.86 +                else
    2.87 +                {
    2.88 +                    if ($_CONF['search_use_fulltext'] == true && $result->getFTSQL() != '')
    2.89 +                    {
    2.90 +                        $debug_info .= " with SQL FULLTEXT. ";
    2.91 +                        $sql = $result->getFTSQL();
    2.92 +                    }
    2.93 +                    else
    2.94 +                    {
    2.95 +                        $debug_info .= " with SQL LIKE. ";
    2.96 +                        $sql = $result->getSQL();
    2.97 +                    }
    2.98 +
    2.99 +                    $sql = $this->_convertsql($sql);
   2.100 +                    $debug_info .= "SQL = " . print_r($sql,1);
   2.101 +                    $obj->setQuery($result->getLabel(), $result->getName(), $sql, $result->getRank());
   2.102 +                }
   2.103 +
   2.104                  $this->_url_rewrite[ $result->getName() ] = $result->UrlRewriteEnable();
   2.105                  $this->_append_query[ $result->getName() ] = $result->AppendQueryEnable();
   2.106 -                $new_api++;
   2.107 +
   2.108 +                if ($this->_verbose) {
   2.109 +                    $new_api++;
   2.110 +                    COM_errorLog($debug_info);
   2.111 +                }
   2.112              }
   2.113              else if (is_a($result, 'Plugin') && $result->num_searchresults != 0)
   2.114              {
   2.115                  // Some backwards compatibility
   2.116 -                $debug_info = $result->plugin_name . " using APIv1 with backwards compatibility.";
   2.117 -                $debug_info .= " Count: " . $result->num_searchresults;
   2.118 -                $debug_info .= " Headings: " . implode(",", $result->searchheading);
   2.119                  if ($this->_verbose) {
   2.120 +                    $old_api++;
   2.121 +                    $debug_info = $result->plugin_name . " using APIv1 with backwards compatibility.";
   2.122 +                    $debug_info .= " Count: " . $result->num_searchresults;
   2.123 +                    $debug_info .= " Headings: " . implode(",", $result->searchheading);
   2.124                      COM_errorLog($debug_info);
   2.125                  }
   2.126  
   2.127 @@ -617,7 +625,6 @@
   2.128  
   2.129                      $obj->addResult($api_results);
   2.130                  }
   2.131 -                $old_api++;
   2.132              }
   2.133          }
   2.134  
   2.135 @@ -673,19 +680,18 @@
   2.136      }
   2.137  
   2.138      /**
   2.139 -    * CallBack function for the ListFactory class
   2.140 +    * Callback function for the ListFactory class
   2.141      *
   2.142      * This function gets called by the ListFactory class and formats
   2.143      * each row accordingly for example pulling usernames from the
   2.144      * users table and displaying a link to their profile.
   2.145      *
   2.146 -    * @author Sami Barakat, s.m.barakat AT gmail DOT com
   2.147      * @access public
   2.148      * @param array $row An array of plain data to format
   2.149      * @return array A reformatted version of the input array
   2.150      *
   2.151      */
   2.152 -    function searchFormatCallBack( $preSort, $row )
   2.153 +    function searchFormatCallback( $preSort, $row )
   2.154      {
   2.155          global $_CONF, $LANG09;
   2.156  
   2.157 @@ -756,7 +762,6 @@
   2.158      * version depending where the text was cut. Works on a
   2.159      * word basis, so long words wont get cut.
   2.160      *
   2.161 -    * @author Sami Barakat, s.m.barakat AT gmail DOT com
   2.162      * @access private
   2.163      * @param string $keyword The word to centre around
   2.164      * @param string $text The complete text string
   2.165 @@ -879,7 +884,6 @@
   2.166      * number of similar heading names. Used for backwards
   2.167      * compatibility in the doSearch() function.
   2.168      *
   2.169 -    * @author Sami Barakat, s.m.barakat AT gmail DOT com
   2.170      * @access private
   2.171      * @param array $headings All the headings
   2.172      * @param array $find An array of alternative headings to find
   2.173 @@ -907,7 +911,6 @@
   2.174      /**
   2.175      * Converts the MySQL CONCAT function to the MSSQL equivalent
   2.176      *
   2.177 -    * @author Sami Barakat, s.m.barakat AT gmail DOT com
   2.178      * @access private
   2.179      * @param string $sql The SQL to convert
   2.180      * @return string MSSQL friendly SQL
     3.1 --- a/system/classes/searchcriteria.class.php	Tue Oct 20 22:53:07 2009 +0100
     3.2 +++ b/system/classes/searchcriteria.class.php	Sun Oct 25 22:01:38 2009 +0000
     3.3 @@ -2,7 +2,7 @@
     3.4  
     3.5  /* Reminder: always indent with 4 spaces (no tabs). */
     3.6  // +---------------------------------------------------------------------------+
     3.7 -// | Geeklog 1.6                                                               |
     3.8 +// | Geeklog 1.6.1                                                             |
     3.9  // +---------------------------------------------------------------------------+
    3.10  // | searchcriteria.class.php                                                  |
    3.11  // |                                                                           |
    3.12 @@ -41,7 +41,10 @@
    3.13      var $_url_rewrite;
    3.14      var $_append_query;
    3.15      var $_results = array();
    3.16 +    var $_callback_func = '';
    3.17 +    var $_total_results = 0;
    3.18  
    3.19 +    // CONSTRUCTOR
    3.20      function SearchCriteria( $pluginName, $pluginLabel )
    3.21      {
    3.22          $this->_pluginName = $pluginName;
    3.23 @@ -49,16 +52,18 @@
    3.24          $this->_rank = 3;
    3.25          $this->_url_rewrite = false;
    3.26          $this->_append_query = true;
    3.27 +        $this->_total_results = 0;
    3.28      }
    3.29  
    3.30 -    function setSQL( $sql )
    3.31 +    // GENERAL METHODS
    3.32 +    function getName()
    3.33      {
    3.34 -        $this->_sql = $sql;
    3.35 +        return $this->_pluginName;
    3.36      }
    3.37  
    3.38 -    function setFTSQL( $ftsql )
    3.39 +    function getLabel()
    3.40      {
    3.41 -        $this->_ftsql = $ftsql;
    3.42 +        return $this->_pluginLabel;
    3.43      }
    3.44  
    3.45      function setRank( $rank )
    3.46 @@ -81,33 +86,6 @@
    3.47          $this->_results = $result_arr;
    3.48      }
    3.49  
    3.50 -    function getSQL()
    3.51 -    {
    3.52 -        return $this->_sql;
    3.53 -    }
    3.54 -
    3.55 -    function getFTSQL()
    3.56 -    {
    3.57 -        global $_DB_dbms;
    3.58 -
    3.59 -        // When only one SQL statment is set we assume it is for MySQL
    3.60 -        if ($this->_ftsql != '' && (is_string($this->_ftsql) && $_DB_dbms == 'mysql') || is_array($this->_ftsql)) {
    3.61 -            return $this->_ftsql;
    3.62 -        } else {
    3.63 -            return '';
    3.64 -        }
    3.65 -    }
    3.66 -
    3.67 -    function getName()
    3.68 -    {
    3.69 -        return $this->_pluginName;
    3.70 -    }
    3.71 -
    3.72 -    function getLabel()
    3.73 -    {
    3.74 -        return $this->_pluginLabel;
    3.75 -    }
    3.76 -
    3.77      function getRank()
    3.78      {
    3.79          return $this->_rank;
    3.80 @@ -128,6 +106,55 @@
    3.81          return $this->_results;
    3.82      }
    3.83  
    3.84 +    // CALLBACK METHODS
    3.85 +    function setCallback( $func )
    3.86 +    {
    3.87 +        $this->_callback_func = $func;
    3.88 +    }
    3.89 +
    3.90 +    function getCallback()
    3.91 +    {
    3.92 +        return $this->_callback_func;
    3.93 +    }
    3.94 +
    3.95 +    function setTotal( $total_results )
    3.96 +    {
    3.97 +        $this->_total_results = $total_results;
    3.98 +    }
    3.99 +
   3.100 +    function getTotal()
   3.101 +    {
   3.102 +        return $this->_total_results;
   3.103 +    }
   3.104 +
   3.105 +    // SQL METHODS
   3.106 +    function setSQL( $sql )
   3.107 +    {
   3.108 +        $this->_sql = $sql;
   3.109 +    }
   3.110 +
   3.111 +    function setFTSQL( $ftsql )
   3.112 +    {
   3.113 +        $this->_ftsql = $ftsql;
   3.114 +    }
   3.115 +
   3.116 +    function getSQL()
   3.117 +    {
   3.118 +        return $this->_sql;
   3.119 +    }
   3.120 +
   3.121 +    function getFTSQL()
   3.122 +    {
   3.123 +        global $_DB_dbms;
   3.124 +
   3.125 +        // When only one SQL statment is set we assume it is for MySQL
   3.126 +        if ($this->_ftsql != '' && (is_string($this->_ftsql) && $_DB_dbms == 'mysql') || is_array($this->_ftsql)) {
   3.127 +            return $this->_ftsql;
   3.128 +        } else {
   3.129 +            return '';
   3.130 +        }
   3.131 +    }
   3.132 +
   3.133      function buildSearchSQL( $keyType, $query, $columns, $sql = '' )
   3.134      {
   3.135          if ($keyType == 'all')
   3.136 @@ -208,7 +235,7 @@
   3.137              }
   3.138          }
   3.139  
   3.140 -        return "";
   3.141 +        return '';
   3.142      }
   3.143  }
   3.144