Joomla! Platform 12.1

Source code for file /libraries/joomla/application/component/modellist.php

Documentation is available at modellist.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Platform
  4.  * @subpackage  Application
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('JPATH_PLATFORM'or die;
  11.  
  12. jimport('joomla.application.component.model');
  13.  
  14. /**
  15.  * Model class for handling lists of items.
  16.  *
  17.  * @package     Joomla.Platform
  18.  * @subpackage  Application
  19.  * @since       11.1
  20.  */
  21. class JModelList extends JModel
  22. {
  23.     /**
  24.      * Internal memory based cache array of data.
  25.      *
  26.      * @var    array 
  27.      * @since  11.1
  28.      */
  29.     protected $cache = array();
  30.  
  31.     /**
  32.      * Context string for the model type.  This is used to handle uniqueness
  33.      * when dealing with the getStoreId() method and caching data structures.
  34.      *
  35.      * @var    string 
  36.      * @since  11.1
  37.      */
  38.     protected $context = null;
  39.  
  40.     /**
  41.      * Valid filter fields or ordering.
  42.      *
  43.      * @var    array 
  44.      * @since  11.1
  45.      */
  46.     protected $filter_fields = array();
  47.  
  48.     /**
  49.      * An internal cache for the last query used.
  50.      *
  51.      * @var    JDatabaseQuery 
  52.      * @since  11.1
  53.      */
  54.     protected $query = array();
  55.  
  56.     /**
  57.      * Constructor.
  58.      *
  59.      * @param   array  $config  An optional associative array of configuration settings.
  60.      *
  61.      * @see     JController
  62.      * @since   11.1
  63.      */
  64.     public function __construct($config array())
  65.     {
  66.         parent::__construct($config);
  67.  
  68.         // Add the ordering filtering fields white list.
  69.         if (isset($config['filter_fields']))
  70.         {
  71.             $this->filter_fields = $config['filter_fields'];
  72.         }
  73.  
  74.         // Guess the context as Option.ModelName.
  75.         if (empty($this->context))
  76.         {
  77.             $this->context = strtolower($this->option . '.' $this->getName());
  78.         }
  79.     }
  80.  
  81.     /**
  82.      * Method to cache the last query constructed.
  83.      *
  84.      * This method ensures that the query is constructed only once for a given state of the model.
  85.      *
  86.      * @return  JDatabaseQuery  A JDatabaseQuery object
  87.      *
  88.      * @since   11.1
  89.      */
  90.     protected function _getListQuery()
  91.     {
  92.         // Capture the last store id used.
  93.         static $lastStoreId;
  94.  
  95.         // Compute the current store id.
  96.         $currentStoreId $this->getStoreId();
  97.  
  98.         // If the last store id is different from the current, refresh the query.
  99.         if ($lastStoreId != $currentStoreId || empty($this->query))
  100.         {
  101.             $lastStoreId $currentStoreId;
  102.             $this->query = $this->getListQuery();
  103.         }
  104.  
  105.         return $this->query;
  106.     }
  107.  
  108.     /**
  109.      * Method to get an array of data items.
  110.      *
  111.      * @return  mixed  An array of data items on success, false on failure.
  112.      *
  113.      * @since   11.1
  114.      */
  115.     public function getItems()
  116.     {
  117.         // Get a storage key.
  118.         $store $this->getStoreId();
  119.  
  120.         // Try to load the data from internal storage.
  121.         if (isset($this->cache[$store]))
  122.         {
  123.             return $this->cache[$store];
  124.         }
  125.  
  126.         // Load the list items.
  127.         $query $this->_getListQuery();
  128.         $items $this->_getList($query$this->getStart()$this->getState('list.limit'));
  129.  
  130.         // Check for a database error.
  131.         if ($this->_db->getErrorNum())
  132.         {
  133.             $this->setError($this->_db->getErrorMsg());
  134.             return false;
  135.         }
  136.  
  137.         // Add the items to the internal cache.
  138.         $this->cache[$store$items;
  139.  
  140.         return $this->cache[$store];
  141.     }
  142.  
  143.     /**
  144.      * Method to get a JDatabaseQuery object for retrieving the data set from a database.
  145.      *
  146.      * @return  JDatabaseQuery   A JDatabaseQuery object to retrieve the data set.
  147.      *
  148.      * @since   11.1
  149.      */
  150.     protected function getListQuery()
  151.     {
  152.         $db $this->getDbo();
  153.         $query $db->getQuery(true);
  154.  
  155.         return $query;
  156.     }
  157.  
  158.     /**
  159.      * Method to get a JPagination object for the data set.
  160.      *
  161.      * @return  JPagination  A JPagination object for the data set.
  162.      *
  163.      * @since   11.1
  164.      */
  165.     public function getPagination()
  166.     {
  167.         // Get a storage key.
  168.         $store $this->getStoreId('getPagination');
  169.  
  170.         // Try to load the data from internal storage.
  171.         if (isset($this->cache[$store]))
  172.         {
  173.             return $this->cache[$store];
  174.         }
  175.  
  176.         // Create the pagination object.
  177.         jimport('joomla.html.pagination');
  178.         $limit = (int) $this->getState('list.limit'- (int) $this->getState('list.links');
  179.         $page new JPagination($this->getTotal()$this->getStart()$limit);
  180.  
  181.         // Add the object to the internal cache.
  182.         $this->cache[$store$page;
  183.  
  184.         return $this->cache[$store];
  185.     }
  186.  
  187.     /**
  188.      * Method to get a store id based on the model configuration state.
  189.      *
  190.      * This is necessary because the model is used by the component and
  191.      * different modules that might need different sets of data or different
  192.      * ordering requirements.
  193.      *
  194.      * @param   string  $id  An identifier string to generate the store id.
  195.      *
  196.      * @return  string  A store id.
  197.      *
  198.      * @since   11.1
  199.      */
  200.     protected function getStoreId($id '')
  201.     {
  202.         // Add the list state to the store id.
  203.         $id .= ':' $this->getState('list.start');
  204.         $id .= ':' $this->getState('list.limit');
  205.         $id .= ':' $this->getState('list.ordering');
  206.         $id .= ':' $this->getState('list.direction');
  207.  
  208.         return md5($this->context . ':' $id);
  209.     }
  210.  
  211.     /**
  212.      * Method to get the total number of items for the data set.
  213.      *
  214.      * @return  integer  The total number of items available in the data set.
  215.      *
  216.      * @since   11.1
  217.      */
  218.     public function getTotal()
  219.     {
  220.         // Get a storage key.
  221.         $store $this->getStoreId('getTotal');
  222.  
  223.         // Try to load the data from internal storage.
  224.         if (isset($this->cache[$store]))
  225.         {
  226.             return $this->cache[$store];
  227.         }
  228.  
  229.         // Load the total.
  230.         $query $this->_getListQuery();
  231.         $total = (int) $this->_getListCount($query);
  232.  
  233.         // Check for a database error.
  234.         if ($this->_db->getErrorNum())
  235.         {
  236.             $this->setError($this->_db->getErrorMsg());
  237.             return false;
  238.         }
  239.  
  240.         // Add the total to the internal cache.
  241.         $this->cache[$store$total;
  242.  
  243.         return $this->cache[$store];
  244.     }
  245.  
  246.     /**
  247.      * Method to get the starting number of items for the data set.
  248.      *
  249.      * @return  integer  The starting number of items available in the data set.
  250.      *
  251.      * @since   11.1
  252.      */
  253.     public function getStart()
  254.     {
  255.         $store $this->getStoreId('getstart');
  256.  
  257.         // Try to load the data from internal storage.
  258.         if (isset($this->cache[$store]))
  259.         {
  260.             return $this->cache[$store];
  261.         }
  262.  
  263.         $start $this->getState('list.start');
  264.         $limit $this->getState('list.limit');
  265.         $total $this->getTotal();
  266.         if ($start $total $limit)
  267.         {
  268.             $start max(0(int) (ceil($total $limit1$limit);
  269.         }
  270.  
  271.         // Add the total to the internal cache.
  272.         $this->cache[$store$start;
  273.  
  274.         return $this->cache[$store];
  275.     }
  276.  
  277.     /**
  278.      * Method to auto-populate the model state.
  279.      *
  280.      * This method should only be called once per instantiation and is designed
  281.      * to be called on the first call to the getState() method unless the model
  282.      * configuration flag to ignore the request is set.
  283.      *
  284.      * Note. Calling getState in this method will result in recursion.
  285.      *
  286.      * @param   string  $ordering   An optional ordering field.
  287.      * @param   string  $direction  An optional direction (asc|desc).
  288.      *
  289.      * @return  void 
  290.      *
  291.      * @since   11.1
  292.      */
  293.     protected function populateState($ordering null$direction null)
  294.     {
  295.         // If the context is set, assume that stateful lists are used.
  296.         if ($this->context)
  297.         {
  298.             $app JFactory::getApplication();
  299.  
  300.             $value $app->getUserStateFromRequest('global.list.limit''limit'$app->getCfg('list_limit'));
  301.             $limit $value;
  302.             $this->setState('list.limit'$limit);
  303.  
  304.             $value $app->getUserStateFromRequest($this->context . '.limitstart''limitstart'0);
  305.             $limitstart ($limit != (floor($value $limit$limit0);
  306.             $this->setState('list.start'$limitstart);
  307.  
  308.             // Check if the ordering field is in the white list, otherwise use the incoming value.
  309.             $value $app->getUserStateFromRequest($this->context . '.ordercol''filter_order'$ordering);
  310.             if (!in_array($value$this->filter_fields))
  311.             {
  312.                 $value $ordering;
  313.                 $app->setUserState($this->context . '.ordercol'$value);
  314.             }
  315.             $this->setState('list.ordering'$value);
  316.  
  317.             // Check if the ordering direction is valid, otherwise use the incoming value.
  318.             $value $app->getUserStateFromRequest($this->context . '.orderdirn''filter_order_Dir'$direction);
  319.             if (!in_array(strtoupper($value)array('ASC''DESC''')))
  320.             {
  321.                 $value $direction;
  322.                 $app->setUserState($this->context . '.orderdirn'$value);
  323.             }
  324.             $this->setState('list.direction'$value);
  325.         }
  326.         else
  327.         {
  328.             $this->setState('list.start'0);
  329.             $this->state->set('list.limit'0);
  330.         }
  331.     }
  332.  
  333.     /**
  334.      * Gets the value of a user state variable and sets it in the session
  335.      *
  336.      * This is the same as the method in JApplication except that this also can optionally
  337.      * force you back to the first page when a filter has changed
  338.      *
  339.      * @param   string   $key        The key of the user state variable.
  340.      * @param   string   $request    The name of the variable passed in a request.
  341.      * @param   string   $default    The default value for the variable if not found. Optional.
  342.      * @param   string   $type       Filter for the variable, for valid values see {@link JFilterInput::clean()}. Optional.
  343.      * @param   boolean  $resetPage  If true, the limitstart in request is set to zero
  344.      *
  345.      * @return  The request user state.
  346.      *
  347.      * @since   11.1
  348.      */
  349.     public function getUserStateFromRequest($key$request$default null$type 'none'$resetPage true)
  350.     {
  351.         $app JFactory::getApplication();
  352.         $old_state $app->getUserState($key);
  353.         $cur_state (!is_null($old_state)) $old_state $default;
  354.         $new_state JRequest::getVar($requestnull'default'$type);
  355.  
  356.         if (($cur_state != $new_state&& ($resetPage))
  357.         {
  358.             JRequest::setVar('limitstart'0);
  359.         }
  360.  
  361.         // Save the new value only if it is set in this request.
  362.         if ($new_state !== null)
  363.         {
  364.             $app->setUserState($key$new_state);
  365.         }
  366.         else
  367.         {
  368.             $new_state $cur_state;
  369.         }
  370.  
  371.         return $new_state;
  372.     }
  373. }
/html>