filter_fields = $config['filter_fields']; } // Guess the context as Option.ModelName. if (empty($this->context)) { $this->context = strtolower($this->option . '.' . $this->getName()); } } /** * Method to cache the last query constructed. * * This method ensures that the query is constructed only once for a given state of the model. * * @return JDatabaseQuery A JDatabaseQuery object * * @since 12.2 */ protected function _getListQuery() { // Capture the last store id used. static $lastStoreId; // Compute the current store id. $currentStoreId = $this->getStoreId(); // If the last store id is different from the current, refresh the query. if ($lastStoreId != $currentStoreId || empty($this->query)) { $lastStoreId = $currentStoreId; $this->query = $this->getListQuery(); } return $this->query; } /** * Method to get an array of data items. * * @return mixed An array of data items on success, false on failure. * * @since 12.2 */ public function getItems() { // Get a storage key. $store = $this->getStoreId(); // Try to load the data from internal storage. if (isset($this->cache[$store])) { return $this->cache[$store]; } // Load the list items. $query = $this->_getListQuery(); try { $items = $this->_getList($query, $this->getStart(), $this->getState('list.limit')); } catch (RuntimeException $e) { $this->setError($e->getMessage()); return false; } // Add the items to the internal cache. $this->cache[$store] = $items; return $this->cache[$store]; } /** * Method to get a JDatabaseQuery object for retrieving the data set from a database. * * @return JDatabaseQuery A JDatabaseQuery object to retrieve the data set. * * @since 12.2 */ protected function getListQuery() { $db = $this->getDbo(); $query = $db->getQuery(true); return $query; } /** * Method to get a JPagination object for the data set. * * @return JPagination A JPagination object for the data set. * * @since 12.2 */ public function getPagination() { // Get a storage key. $store = $this->getStoreId('getPagination'); // Try to load the data from internal storage. if (isset($this->cache[$store])) { return $this->cache[$store]; } // Create the pagination object. $limit = (int) $this->getState('list.limit') - (int) $this->getState('list.links'); $page = new JPagination($this->getTotal(), $this->getStart(), $limit); // Add the object to the internal cache. $this->cache[$store] = $page; return $this->cache[$store]; } /** * Method to get a store id based on the model configuration state. * * This is necessary because the model is used by the component and * different modules that might need different sets of data or different * ordering requirements. * * @param string $id An identifier string to generate the store id. * * @return string A store id. * * @since 12.2 */ protected function getStoreId($id = '') { // Add the list state to the store id. $id .= ':' . $this->getState('list.start'); $id .= ':' . $this->getState('list.limit'); $id .= ':' . $this->getState('list.ordering'); $id .= ':' . $this->getState('list.direction'); return md5($this->context . ':' . $id); } /** * Method to get the total number of items for the data set. * * @return integer The total number of items available in the data set. * * @since 12.2 */ public function getTotal() { // Get a storage key. $store = $this->getStoreId('getTotal'); // Try to load the data from internal storage. if (isset($this->cache[$store])) { return $this->cache[$store]; } // Load the total. $query = $this->_getListQuery(); try { $total = (int) $this->_getListCount($query); } catch (RuntimeException $e) { $this->setError($e->getMessage()); return false; } // Add the total to the internal cache. $this->cache[$store] = $total; return $this->cache[$store]; } /** * Method to get the starting number of items for the data set. * * @return integer The starting number of items available in the data set. * * @since 12.2 */ public function getStart() { $store = $this->getStoreId('getstart'); // Try to load the data from internal storage. if (isset($this->cache[$store])) { return $this->cache[$store]; } $start = $this->getState('list.start'); $limit = $this->getState('list.limit'); $total = $this->getTotal(); if ($start > $total - $limit) { $start = max(0, (int) (ceil($total / $limit) - 1) * $limit); } // Add the total to the internal cache. $this->cache[$store] = $start; return $this->cache[$store]; } /** * Method to auto-populate the model state. * * This method should only be called once per instantiation and is designed * to be called on the first call to the getState() method unless the model * configuration flag to ignore the request is set. * * Note. Calling getState in this method will result in recursion. * * @param string $ordering An optional ordering field. * @param string $direction An optional direction (asc|desc). * * @return void * * @since 12.2 */ protected function populateState($ordering = null, $direction = null) { // If the context is set, assume that stateful lists are used. if ($this->context) { $app = JFactory::getApplication(); $value = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->getCfg('list_limit'), 'uint'); $limit = $value; $this->setState('list.limit', $limit); $value = $app->getUserStateFromRequest($this->context . '.limitstart', 'limitstart', 0); $limitstart = ($limit != 0 ? (floor($value / $limit) * $limit) : 0); $this->setState('list.start', $limitstart); // Check if the ordering field is in the white list, otherwise use the incoming value. $value = $app->getUserStateFromRequest($this->context . '.ordercol', 'filter_order', $ordering); if (!in_array($value, $this->filter_fields)) { $value = $ordering; $app->setUserState($this->context . '.ordercol', $value); } $this->setState('list.ordering', $value); // Check if the ordering direction is valid, otherwise use the incoming value. $value = $app->getUserStateFromRequest($this->context . '.orderdirn', 'filter_order_Dir', $direction); if (!in_array(strtoupper($value), array('ASC', 'DESC', ''))) { $value = $direction; $app->setUserState($this->context . '.orderdirn', $value); } $this->setState('list.direction', $value); } else { $this->setState('list.start', 0); $this->state->set('list.limit', 0); } } /** * Gets the value of a user state variable and sets it in the session * * This is the same as the method in JApplication except that this also can optionally * force you back to the first page when a filter has changed * * @param string $key The key of the user state variable. * @param string $request The name of the variable passed in a request. * @param string $default The default value for the variable if not found. Optional. * @param string $type Filter for the variable, for valid values see {@link JFilterInput::clean()}. Optional. * @param boolean $resetPage If true, the limitstart in request is set to zero * * @return The request user state. * * @since 12.2 */ public function getUserStateFromRequest($key, $request, $default = null, $type = 'none', $resetPage = true) { $app = JFactory::getApplication(); $input = $app->input; $old_state = $app->getUserState($key); $cur_state = (!is_null($old_state)) ? $old_state : $default; $new_state = $input->get($request, null, $type); if (($cur_state != $new_state) && ($resetPage)) { $input->set('limitstart', 0); } // Save the new value only if it is set in this request. if ($new_state !== null) { $app->setUserState($key, $new_state); } else { $new_state = $cur_state; } return $new_state; } }