system/classes/listfactory.class.php
branchHEAD
changeset 7398 e1700815379b
parent 7391 0bee991937cc
child 7438 af60253641ad
     1.1 --- a/system/classes/listfactory.class.php	Sun Oct 25 22:01:38 2009 +0000
     1.2 +++ b/system/classes/listfactory.class.php	Thu Oct 29 13:01:33 2009 +0100
     1.3 @@ -47,15 +47,15 @@
     1.4      // Set up the fields that will be seen by the user
     1.5      $obj->setField(
     1.6          '#',            // Title of the field
     1.7 -        ROW_NUMBER,     // The field identifier can be either:
     1.8 -                        //   ROW_NUMBER - The number of each row will be displayed
     1.9 -                        //   SQL_TITLE  - The title given the the SQL query will be displayed
    1.10 +        LF_ROW_NUMBER,  // The field identifier can be either:
    1.11 +                        //   LF_ROW_NUMBER - The number of each row will be displayed
    1.12 +                        //   LF_SOURCE_TITLE  - The title given the the SQL query will be displayed
    1.13                          //   <string>   - SQL column name
    1.14          true,           // Enables the field
    1.15          true,           // The field can be sorted
    1.16          '<b>%d.</b>'    // Formats the data
    1.17      );
    1.18 -    $obj->setField('Type', SQL_TITLE, true, true, '<b>%s</b>');
    1.19 +    $obj->setField('Type', LF_SOURCE_TITLE, true, true, '<b>%s</b>');
    1.20      $obj->setField('Title', 'title');
    1.21      $obj->setField('Text', 'text');
    1.22      $obj->setField('Date', 'date');
    1.23 @@ -72,7 +72,7 @@
    1.24      // Set up some queries to execute
    1.25      $sql = 'SELECT sid AS id, title, introtext AS text, date FROM stories';
    1.26      $obj->setQuery(
    1.27 -        'Story', // The name given to the query which will be displayed in the SQL_TITLE field (optional)
    1.28 +        'Story', // The name given to the query which will be displayed in the LF_SOURCE_TITLE field (optional)
    1.29          'story',
    1.30          $sql,    // The SQL string without the LIMIT or ORDER BY clauses. Notice the column names match the field identifiers
    1.31          5        // The rank of the query, 5 highest = more results, 1 lowest = least results
    1.32 @@ -84,7 +84,7 @@
    1.33      // Note: the array must match the field identifier names stated previously
    1.34      $extra_row = array(
    1.35          'id' => -1,
    1.36 -        SQL_TITLE => 'Extra Row',
    1.37 +        LF_SOURCE_TITLE => 'Extra Row',
    1.38          'title' => 'An extra row example',
    1.39          'text' => 'With some really really really long text.....<b>and HTML</b>',
    1.40          'date' => '2008-07-08 03:00:00'
    1.41 @@ -132,7 +132,7 @@
    1.42  
    1.43      // PRIVATE VARIABLES
    1.44      var $_fields = array();
    1.45 -    var $_query_arr = array();
    1.46 +    var $_sources_arr = array();
    1.47      var $_total_rank = 0;
    1.48      var $_sort_arr = array();
    1.49      var $_def_sort_arr = array();
    1.50 @@ -148,7 +148,7 @@
    1.51      * Constructor
    1.52      *
    1.53      * Sets up private url variable and defines the
    1.54 -    * SQL_TITLE, SQL_NAME and ROW_NUMBER constants.
    1.55 +    * LF_SOURCE_TITLE, LF_SOURCE_NAME and LF_ROW_NUMBER constants.
    1.56      *
    1.57      * @access public
    1.58      * @param string $url The URL of the page the table appears on
    1.59 @@ -171,9 +171,9 @@
    1.60              $this->_page_limits = array(10, 15, 20, 25, 30, 35);
    1.61          }
    1.62  
    1.63 -        define('SQL_TITLE', 0);
    1.64 -        define('SQL_NAME', 1);
    1.65 -        define('ROW_NUMBER', 2);
    1.66 +        define('LF_SOURCE_TITLE', 0);
    1.67 +        define('LF_SOURCE_NAME', 1);
    1.68 +        define('LF_ROW_NUMBER', 2);
    1.69      }
    1.70  
    1.71      /**
    1.72 @@ -191,7 +191,7 @@
    1.73      /**
    1.74      * Sets a field in the list.
    1.75      *
    1.76 -    * Note: ROW_NUMBER cannot be sorted
    1.77 +    * Note: LF_ROW_NUMBER cannot be sorted
    1.78      *
    1.79      * @access public
    1.80      * @param string $title The title of the field which is displayed to the user
    1.81 @@ -203,7 +203,7 @@
    1.82      */
    1.83      function setField( $title, $name, $display = true, $sort = true, $format = '%s' )
    1.84      {
    1.85 -        if ($name === ROW_NUMBER) {
    1.86 +        if ($name === LF_ROW_NUMBER) {
    1.87              $sort = false;
    1.88          }
    1.89          $this->_fields[] = array(
    1.90 @@ -227,7 +227,7 @@
    1.91      */
    1.92      function setQuery( $title, $name, $sql, $rank )
    1.93      {
    1.94 -        $this->_query_arr[] = array(
    1.95 +        $this->_sources_arr[] = array(
    1.96              'type' => 'sql',
    1.97              'title' => $title,
    1.98              'name' => $name,
    1.99 @@ -237,13 +237,30 @@
   1.100          $this->_total_rank += $rank;
   1.101      }
   1.102  
   1.103 -    function setCallback( $title, $name, $function, $rank, $total )
   1.104 +    /**
   1.105 +    * Sets a callback function that provides another source for results.
   1.106 +    *
   1.107 +    * The function will be passed two parameters, $offset and $limit,
   1.108 +    * which will determine how many results are requested. The callback
   1.109 +    * function should then return a multidimensional array containing
   1.110 +    * the results. This provides an alternative to the setQuery()
   1.111 +    * function as results can be sourced from anywhere.
   1.112 +    *
   1.113 +    * @access public
   1.114 +    * @param string $title The text that's displayed to the user
   1.115 +    * @param string $name The local name given to the query
   1.116 +    * @param string $function Any callable function, method or lambda
   1.117 +    * @param int $rank The rating that determins how many results will be returned
   1.118 +    * @param int $total The total number of results that are avaliable
   1.119 +    *
   1.120 +    */
   1.121 +    function setCallback( $title, $name, $callback, $rank, $total )
   1.122      {
   1.123 -        $this->_query_arr[] = array(
   1.124 +        $this->_sources_arr[] = array(
   1.125              'type' => 'callback',
   1.126              'title' => $title,
   1.127              'name' => $name,
   1.128 -            'func' => $function,
   1.129 +            'func' => $callback,
   1.130              'rank' => $rank,
   1.131              'total' => $total
   1.132          );
   1.133 @@ -251,7 +268,8 @@
   1.134      }
   1.135  
   1.136      /**
   1.137 -    * Sets the callback function that gets called when formatting a row
   1.138 +    * Sets the callback function thats called on every row for styling
   1.139 +    * or formatting.
   1.140      *
   1.141      * @access public
   1.142      * @param callback $function Any callable function, method or lambda
   1.143 @@ -300,20 +318,21 @@
   1.144      }
   1.145  
   1.146      /**
   1.147 -    * Gets the total number of results from a query
   1.148 +    * Gets the total number of results from source item, either an sql
   1.149 +    * query or a callback function.
   1.150      *
   1.151      * @access private
   1.152 -    * @param string $sql The query
   1.153 +    * @param array $source The source we are currently working with
   1.154      * @return int Total number of rows
   1.155      *
   1.156      */
   1.157 -    function _getTotal( $param )
   1.158 +    function _getTotal( $source )
   1.159      {
   1.160 -        if ($param['type'] == 'callback') {
   1.161 -            return $param['total'];
   1.162 +        if ($source['type'] == 'callback') {
   1.163 +            return $source['total'];
   1.164          }
   1.165          else {
   1.166 -            $sql = $param['sql'];
   1.167 +            $sql = $source['sql'];
   1.168          }
   1.169  
   1.170          if (is_array($sql)) {
   1.171 @@ -382,6 +401,42 @@
   1.172      }
   1.173  
   1.174      /**
   1.175 +    * Applies styling to each row and adds extra meta details that are
   1.176 +    * used else where in the ListFactory.
   1.177 +    *
   1.178 +    * @access private
   1.179 +    * @param array $row_arr A single results row
   1.180 +    * @param array $source The source we are currently working with
   1.181 +    * @return array The row with styling applied and extra meta details
   1.182 +    *
   1.183 +    */
   1.184 +    function _fillrow( $row_arr, $source )
   1.185 +    {
   1.186 +        $col = array();
   1.187 +        $col[LF_SOURCE_TITLE] = $source['title'];
   1.188 +        $col[LF_SOURCE_NAME] = $source['name'];
   1.189 +
   1.190 +        foreach ($this->_fields as $field)
   1.191 +        {
   1.192 +            if (!is_numeric($field['name']) && $field['name'][0] != '_') {
   1.193 +                if (empty($row_arr[ $field['name'] ])) {
   1.194 +                    $col[ $field['name'] ] = 'LF_NULL';
   1.195 +                } else {
   1.196 +                    $col[ $field['name'] ] = $row_arr[ $field['name'] ];
   1.197 +                }
   1.198 +            }
   1.199 +        }
   1.200 +
   1.201 +        // Need to call the format function before and after
   1.202 +        // sorting the results.
   1.203 +        if (is_callable($this->_function)) {
   1.204 +            $col = call_user_func_array($this->_function, array(true, $col));
   1.205 +        }
   1.206 +
   1.207 +        return $col;
   1.208 +    }
   1.209 +
   1.210 +    /**
   1.211      * Executes pre set queries
   1.212      *
   1.213      * @access public
   1.214 @@ -400,7 +455,7 @@
   1.215          if (is_numeric($this->_sort_arr['field']))
   1.216          {
   1.217              $ord = $this->_def_sort_arr['field'];
   1.218 -            $this->_sort_arr['field'] = SQL_TITLE;
   1.219 +            $this->_sort_arr['field'] = LF_SOURCE_TITLE;
   1.220          }
   1.221          else
   1.222          {
   1.223 @@ -424,10 +479,10 @@
   1.224          $num_query_results = $this->_per_page - $this->_total_found;
   1.225          $pp_total = $this->_total_found;
   1.226          $limits = array();
   1.227 -        for ($i = 0; $i < count($this->_query_arr); $i++)
   1.228 +        for ($i = 0; $i < count($this->_sources_arr); $i++)
   1.229          {
   1.230 -            $limits[$i]['total'] = $this->_getTotal($this->_query_arr[$i]);
   1.231 -            $limits[$i]['pp'] = round(($this->_query_arr[$i]['rank'] / $this->_total_rank) * $num_query_results);
   1.232 +            $limits[$i]['total'] = $this->_getTotal($this->_sources_arr[$i]);
   1.233 +            $limits[$i]['pp'] = round(($this->_sources_arr[$i]['rank'] / $this->_total_rank) * $num_query_results);
   1.234              $this->_total_found += $limits[$i]['total'];
   1.235              $pp_total += $limits[$i]['pp'];
   1.236          }
   1.237 @@ -438,45 +493,30 @@
   1.238          }
   1.239          $limits = $this->_getLimits($limits);
   1.240  
   1.241 -        // Execute each query in turn
   1.242 -        for ($i = 0; $i < count($this->_query_arr); $i++)
   1.243 +        // Retrieve the results from each source in turn
   1.244 +        for ($i = 0; $i < count($this->_sources_arr); $i++)
   1.245          {
   1.246              if ($limits[$i]['limit'] <= 0) {
   1.247                  continue;
   1.248              }
   1.249  
   1.250              // This is a callback function
   1.251 -            if ($this->_query_arr[$i]['type'] == 'callback')
   1.252 +            if ($this->_sources_arr[$i]['type'] == 'callback')
   1.253              {
   1.254 -                if (is_callable($this->_query_arr[$i]['func']))
   1.255 +                if (is_callable($this->_sources_arr[$i]['func']))
   1.256                  {
   1.257 -                    $callback_rows = call_user_func_array($this->_query_arr[$i]['func'], array($limits[$i]['offset'], $limits[$i]['limit']));
   1.258 +                    $callback_rows = call_user_func_array(
   1.259 +                        $this->_sources_arr[$i]['func'],
   1.260 +                        array($limits[$i]['offset'],
   1.261 +                        $limits[$i]['limit'])
   1.262 +                    );
   1.263  
   1.264 -                    foreach ($callback_rows as $row)
   1.265 -                    {
   1.266 -                        $col = array();
   1.267 -                        $col[SQL_TITLE] = $this->_query_arr[$i]['title'];
   1.268 -                        $col[SQL_NAME] = $this->_query_arr[$i]['name'];
   1.269 -
   1.270 -                        foreach ($this->_fields as $field)
   1.271 -                        {
   1.272 -                            if (!is_numeric($field['name']) && $field['name'][0] != '_') {
   1.273 -                                if (empty($row[ $field['name'] ])) {
   1.274 -                                    $col[ $field['name'] ] = 'LF_NULL';
   1.275 -                                } else {
   1.276 -                                    $col[ $field['name'] ] = $row[ $field['name'] ];
   1.277 -                                }
   1.278 -                            }
   1.279 -                        }
   1.280 -
   1.281 -                        // Need to call the format function before and after
   1.282 -                        // sorting the results.
   1.283 -                        if (is_callable($this->_function)) {
   1.284 -                            $col = call_user_func_array($this->_function, array(true, $col));
   1.285 -                        }
   1.286 -
   1.287 -                        $rows_arr[] = $col;
   1.288 +                    foreach ($callback_rows as $row) {
   1.289 +                        $rows_arr[] = $this->_fillrow($row, $this->_sources_arr[$i]);
   1.290                      }
   1.291 +                } else {
   1.292 +                    COM_errorLog('ListFactory: A callback function was set for "'.
   1.293 +                        $this->_sources_arr[$i]['name'].'", but it could not be found.');
   1.294                  }
   1.295                  continue;
   1.296              }
   1.297 @@ -484,42 +524,16 @@
   1.298              // This is an SQL query, so execute it and format the results
   1.299              $limit_sql = " LIMIT {$limits[$i]['offset']},{$limits[$i]['limit']}";
   1.300  
   1.301 -            if (is_array($this->_query_arr[$i]['sql']))
   1.302 -            {
   1.303 -                $this->_query_arr[$i]['sql']['mysql'] .= $order_sql . $limit_sql;
   1.304 -                $this->_query_arr[$i]['sql']['mssql'] .= $order_sql . $limit_sql;
   1.305 -            }
   1.306 -            else
   1.307 -            {
   1.308 -                $this->_query_arr[$i]['sql'] .= $order_sql . $limit_sql;
   1.309 +            if (is_array($this->_sources_arr[$i]['sql'])) {
   1.310 +                $this->_sources_arr[$i]['sql']['mysql'] .= $order_sql . $limit_sql;
   1.311 +                $this->_sources_arr[$i]['sql']['mssql'] .= $order_sql . $limit_sql;
   1.312 +            } else {
   1.313 +                $this->_sources_arr[$i]['sql'] .= $order_sql . $limit_sql;
   1.314              }
   1.315  
   1.316 -            $result = DB_query($this->_query_arr[$i]['sql']);
   1.317 -
   1.318 -            while ($A = DB_fetchArray($result))
   1.319 -            {
   1.320 -                $col = array();
   1.321 -                $col[SQL_TITLE] = $this->_query_arr[$i]['title'];
   1.322 -                $col[SQL_NAME] = $this->_query_arr[$i]['name'];
   1.323 -
   1.324 -                foreach ($this->_fields as $field)
   1.325 -                {
   1.326 -                    if (!is_numeric($field['name']) && $field['name'][0] != '_') {
   1.327 -                        if (empty($A[ $field['name'] ])) {
   1.328 -                            $col[ $field['name'] ] = 'LF_NULL';
   1.329 -                        } else {
   1.330 -                            $col[ $field['name'] ] = $A[ $field['name'] ];
   1.331 -                        }
   1.332 -                    }
   1.333 -                }
   1.334 -
   1.335 -                // Need to call the format function before and after
   1.336 -                // sorting the results.
   1.337 -                if (is_callable($this->_function)) {
   1.338 -                    $col = call_user_func_array($this->_function, array(true, $col));
   1.339 -                }
   1.340 -
   1.341 -                $rows_arr[] = $col;
   1.342 +            $result = DB_query($this->_sources_arr[$i]['sql']);
   1.343 +            while ($A = DB_fetchArray($result)) {
   1.344 +                $rows_arr[] = $this->_fillrow($A, $this->_sources_arr[$i]);
   1.345              }
   1.346          }
   1.347  
   1.348 @@ -686,7 +700,7 @@
   1.349                  if ($field['display'] == true)
   1.350                  {
   1.351                      $fieldvalue = '';
   1.352 -                    if ($field['name'] == ROW_NUMBER) {
   1.353 +                    if ($field['name'] == LF_ROW_NUMBER) {
   1.354                          $fieldvalue = $r + $offset;
   1.355                      } else if (!empty($row[ $field['name'] ])) {
   1.356                          $fieldvalue = $row[ $field['name'] ];
   1.357 @@ -710,7 +724,8 @@
   1.358          }
   1.359  
   1.360          // Print page numbers
   1.361 -        $page_url = $this->_page_url . 'order=' . $this->_sort_arr['field'] . '&amp;direction=' . $this->_sort_arr['direction'] . '&amp;results=' . $this->_per_page;
   1.362 +        $page_url = $this->_page_url.'order='.$this->_sort_arr['field'] .
   1.363 +                '&amp;direction='.$this->_sort_arr['direction'].'&amp;results='.$this->_per_page;
   1.364          $num_pages = ceil($this->_total_found / $this->_per_page);
   1.365          if ($num_pages > 1) {
   1.366              $list_templates->set_var('google_paging', COM_printPageNavigation($page_url, $this->_page, $num_pages, 'page=', false, '', ''));