PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

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

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