PageRenderTime 84ms CodeModel.GetById 40ms app.highlight 11ms RepoModel.GetById 29ms app.codeStats 0ms

/libraries/joomla/application/component/modellist.php

https://bitbucket.org/izubizarreta/https-bitbucket.org-bityvip
PHP | 373 lines | 163 code | 48 blank | 162 comment | 20 complexity | a9b91139fbe8c2c26bbd4db448610d37 MD5 | raw file
  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
 10defined('JPATH_PLATFORM') or die;
 11
 12jimport('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 */
 21class 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 / $limit) - 1) * $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'), 'uint');
301			$limit = $value;
302			$this->setState('list.limit', $limit);
303
304			$value = $app->getUserStateFromRequest($this->context . '.limitstart', 'limitstart', 0);
305			$limitstart = ($limit != 0 ? (floor($value / $limit) * $limit) : 0);
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($request, null, '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}