Source for file articles.php
Documentation is available at articles.php
* @subpackage com_content
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* This models supports retrieving lists of articles.
* @subpackage com_content
* @param array $config An optional associative array of configuration settings.
if (empty($config['filter_fields']))
$config['filter_fields'] =
array(
'checked_out', 'a.checked_out',
'checked_out_time', 'a.checked_out_time',
'catid', 'a.catid', 'category_title',
'access', 'a.access', 'access_level',
'created_by', 'a.created_by',
'ordering', 'a.ordering',
'featured', 'a.featured',
'language', 'a.language',
'publish_up', 'a.publish_up',
'publish_down', 'a.publish_down',
* 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).
protected function populateState($ordering =
'ordering', $direction =
'ASC')
// List state information
$value =
$app->input->get('limit', $app->getCfg('list_limit', 0), 'uint');
$value =
$app->input->get('limitstart', 0, 'uint');
$orderCol =
$app->input->get('filter_order', 'a.ordering');
$orderCol =
'a.ordering';
$this->setState('list.ordering', $orderCol);
$listOrder =
$app->input->get('filter_order_Dir', 'ASC');
$this->setState('list.direction', $listOrder);
$params =
$app->getParams();
if ((!$user->authorise('core.edit.state', 'com_content')) &&
(!$user->authorise('core.edit', 'com_content')))
// Filter on published for those who do not have edit or edit.state rights.
// Process show_noauth parameter
if (!$params->get('show_noauth'))
$this->setState('filter.access', false);
$this->setState('layout', $app->input->get('layout'));
* Method to get a store id based on 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
* @param string $id A prefix for the store id.
* @return string A store id.
$id .=
':' .
$this->getState('filter.access');
$id .=
':' .
$this->getState('filter.featured');
$id .=
':' .
$this->getState('filter.article_id');
$id .=
':' .
$this->getState('filter.article_id.include');
$id .=
':' .
$this->getState('filter.category_id.include');
$id .=
':' .
$this->getState('filter.author_id.include');
$id .=
':' .
$this->getState('filter.author_alias.include');
$id .=
':' .
$this->getState('filter.date_filtering');
$id .=
':' .
$this->getState('filter.date_field');
$id .=
':' .
$this->getState('filter.start_date_range');
$id .=
':' .
$this->getState('filter.end_date_range');
$id .=
':' .
$this->getState('filter.relative_date');
* Get the master query for retrieving a list of articles subject to the model state.
// Create a new query object.
$query =
$db->getQuery(true);
// Select the required fields from the table.
'a.id, a.title, a.alias, a.introtext, a.fulltext, ' .
'a.checked_out, a.checked_out_time, ' .
'a.catid, a.created, a.created_by, a.created_by_alias, ' .
// Use created if modified is 0
'CASE WHEN a.modified = ' .
$db->quote($db->getNullDate()) .
' THEN a.created ELSE a.modified END as modified, ' .
'a.modified_by, uam.name as modified_by_name,' .
// Use created if publish_up is 0
'CASE WHEN a.publish_up = ' .
$db->quote($db->getNullDate()) .
' THEN a.created ELSE a.publish_up END as publish_up,' .
'a.publish_down, a.images, a.urls, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, ' .
'a.hits, a.xreference, a.featured,' .
' ' .
$query->length('a.fulltext') .
' AS readmore'
// Process an Archived Article layout
if ($this->getState('filter.published') ==
2)
// If badcats is not null, this means that the article is inside an archived category
// In this case, the state is set to 2 to indicate Archived (even if the article state is Published)
$query->select($this->getState('list.select', 'CASE WHEN badcats.id is null THEN a.state ELSE 2 END AS state'));
Process non-archived layout
If badcats is not null, this means that the article is inside an unpublished category
In this case, the state is set to 0 to indicate Unpublished (even if the article state is Published)
$query->select($this->getState('list.select', 'CASE WHEN badcats.id is not null THEN 0 ELSE a.state END AS state'));
$query->from('#__content AS a');
// Join over the frontpage articles.
if ($this->context !=
'com_content.featured')
$query->join('LEFT', '#__content_frontpage AS fp ON fp.content_id = a.id');
// Join over the categories.
$query->select('c.title AS category_title, c.path AS category_route, c.access AS category_access, c.alias AS category_alias')
->join('LEFT', '#__categories AS c ON c.id = a.catid');
// Join over the users for the author and modified_by names.
$query->select("CASE WHEN a.created_by_alias > ' ' THEN a.created_by_alias ELSE ua.name END AS author")
->select("ua.email AS author_email")
->join('LEFT', '#__users AS ua ON ua.id = a.created_by')
->join('LEFT', '#__users AS uam ON uam.id = a.modified_by');
$subQuery =
$db->getQuery(true)
->select('MAX(contact.id) AS id')
->from('#__contact_details AS contact')
->where('contact.published = 1')
->where('contact.user_id = a.created_by');
$subQuery->where('(contact.language in (' .
$db->quote(JFactory::getLanguage()->getTag()) .
',' .
$db->quote('*') .
') OR contact.language IS NULL)');
$query->select('(' .
$subQuery .
') as contactid');
// Join over the categories to get parent category titles
$query->select('parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias')
->join('LEFT', '#__categories as parent ON parent.id = c.parent_id');
$query->select('ROUND(v.rating_sum / v.rating_count, 0) AS rating, v.rating_count as rating_count')
->join('LEFT', '#__content_rating AS v ON a.id = v.content_id');
// Join to check for category published state in parent categories up the tree
$query->select('c.published, CASE WHEN badcats.id is null THEN c.published ELSE 0 END AS parents_published');
$subquery =
'SELECT cat.id as id FROM #__categories AS cat JOIN #__categories AS parent ';
$subquery .=
'ON cat.lft BETWEEN parent.lft AND parent.rgt ';
$subquery .=
'WHERE parent.extension = ' .
$db->quote('com_content');
if ($this->getState('filter.published') ==
2)
// Find any up-path categories that are archived
// If any up-path categories are archived, include all children in archived layout
$subquery .=
' AND parent.published = 2 GROUP BY cat.id ';
// Set effective state to archived if up-path category is archived
$publishedWhere =
'CASE WHEN badcats.id is null THEN a.state ELSE 2 END';
// Find any up-path categories that are not published
// If all categories are published, badcats.id will be null, and we just use the article state
$subquery .=
' AND parent.published != 1 GROUP BY cat.id ';
// Select state to unpublished if up-path category is unpublished
$publishedWhere =
'CASE WHEN badcats.id is null THEN a.state ELSE 0 END';
$query->join('LEFT OUTER', '(' .
$subquery .
') AS badcats ON badcats.id = c.id');
// Filter by access level.
if ($access =
$this->getState('filter.access'))
$groups =
implode(',', $user->getAuthorisedViewLevels());
$query->where('a.access IN (' .
$groups .
')')
->where('c.access IN (' .
$groups .
')');
// Filter by published state
$published =
$this->getState('filter.published');
// Use article state if badcats.id is null, otherwise, force 0 for unpublished
$query->where($publishedWhere .
' = ' . (int)
$published);
$published =
implode(',', $published);
// Use article state if badcats.id is null, otherwise, force 0 for unpublished
$query->where($publishedWhere .
' IN (' .
$published .
')');
// Filter by featured state
$featured =
$this->getState('filter.featured');
$query->where('a.featured = 0');
$query->where('a.featured = 1');
// Normally we do not discriminate
// between featured/unfeatured items.
// Filter by a single or group of articles.
$articleId =
$this->getState('filter.article_id');
$type =
$this->getState('filter.article_id.include', true) ?
'= ' :
'<> ';
$query->where('a.id ' .
$type . (int)
$articleId);
$articleId =
implode(',', $articleId);
$type =
$this->getState('filter.article_id.include', true) ?
'IN' :
'NOT IN';
$query->where('a.id ' .
$type .
' (' .
$articleId .
')');
// Filter by a single or group of categories
$categoryId =
$this->getState('filter.category_id');
$type =
$this->getState('filter.category_id.include', true) ?
'= ' :
'<> ';
$includeSubcategories =
$this->getState('filter.subcategories', false);
$categoryEquals =
'a.catid ' .
$type . (int)
$categoryId;
if ($includeSubcategories)
$levels = (int)
$this->getState('filter.max_category_levels', '1');
// Create a subquery for the subcategory list
$subQuery =
$db->getQuery(true)
->from('#__categories as sub')
->join('INNER', '#__categories as this ON sub.lft > this.lft AND sub.rgt < this.rgt')
->where('this.id = ' . (int)
$categoryId);
$subQuery->where('sub.level <= this.level + ' .
$levels);
// Add the subquery to the main query
$query->where('(' .
$categoryEquals .
' OR a.catid IN (' .
$subQuery->__toString() .
'))');
$query->where($categoryEquals);
$categoryId =
implode(',', $categoryId);
$type =
$this->getState('filter.category_id.include', true) ?
'IN' :
'NOT IN';
$query->where('a.catid ' .
$type .
' (' .
$categoryId .
')');
$authorId =
$this->getState('filter.author_id');
$type =
$this->getState('filter.author_id.include', true) ?
'= ' :
'<> ';
$authorWhere =
'a.created_by ' .
$type . (int)
$authorId;
$authorId =
implode(',', $authorId);
$type =
$this->getState('filter.author_id.include', true) ?
'IN' :
'NOT IN';
$authorWhere =
'a.created_by ' .
$type .
' (' .
$authorId .
')';
// Filter by author alias
$authorAlias =
$this->getState('filter.author_alias');
$type =
$this->getState('filter.author_alias.include', true) ?
'= ' :
'<> ';
$authorAliasWhere =
'a.created_by_alias ' .
$type .
$db->quote($authorAlias);
foreach ($authorAlias as $key =>
$alias)
$authorAlias[$key] =
$db->quote($alias);
$authorAlias =
implode(',', $authorAlias);
$type =
$this->getState('filter.author_alias.include', true) ?
'IN' :
'NOT IN';
$authorAliasWhere =
'a.created_by_alias ' .
$type .
' (' .
$authorAlias .
if (!empty($authorWhere) &&
!empty($authorAliasWhere))
$query->where('(' .
$authorWhere .
' OR ' .
$authorAliasWhere .
')');
elseif (empty($authorWhere) &&
empty($authorAliasWhere))
// If both are empty we don't want to add to the query
// One of these is empty, the other is not so we just add both
$query->where($authorWhere .
$authorAliasWhere);
// Filter by start and end dates.
$nullDate =
$db->quote($db->getNullDate());
$query->where('(a.publish_up = ' .
$nullDate .
' OR a.publish_up <= ' .
$nowDate .
')')
->where('(a.publish_down = ' .
$nullDate .
' OR a.publish_down >= ' .
$nowDate .
')');
// Filter by Date Range or Relative Date
$dateFiltering =
$this->getState('filter.date_filtering', 'off');
$dateField =
$this->getState('filter.date_field', 'a.created');
$startDateRange =
$db->quote($this->getState('filter.start_date_range', $nullDate));
$endDateRange =
$db->quote($this->getState('filter.end_date_range', $nullDate));
'(' .
$dateField .
' >= ' .
$startDateRange .
' AND ' .
$dateField .
' <= ' .
$endDateRange .
')'
$relativeDate = (int)
$this->getState('filter.relative_date', 0);
$dateField .
' >= DATE_SUB(' .
$nowDate .
', INTERVAL ' .
// Process the filter for list views with user-entered filters
if ((is_object($params)) &&
($params->get('filter_field') !=
'hide') &&
($filter =
$this->getState('list.filter')))
$hitsFilter = (int)
$filter;
$filter =
$db->quote('%' .
$db->escape($filter, true) .
'%', false);
switch ($params->get('filter_field'))
'LOWER( CASE WHEN a.created_by_alias > ' .
$db->quote(' ') .
' THEN a.created_by_alias ELSE ua.name END ) LIKE ' .
$filter .
' '
$query->where('a.hits >= ' .
$hitsFilter .
' ');
// Default to 'title' if parameter is not valid
$query->where('LOWER( a.title ) LIKE ' .
$filter);
$query->where('a.language in (' .
$db->quote(JFactory::getLanguage()->getTag()) .
',' .
$db->quote('*') .
')');
// Add the list ordering clause.
$query->order($this->getState('list.ordering', 'a.ordering') .
' ' .
$this->getState('list.direction', 'ASC'));
* Method to get a list of articles.
* Overriden to inject convert the attribs field into a JParameter object.
* @return mixed An array of objects on success, false on failure.
$userId =
$user->get('id');
$guest =
$user->get('guest');
$groups =
$user->getAuthorisedViewLevels();
// Convert the parameter fields into objects.
foreach ($items as &$item)
$articleParams->loadString($item->attribs);
// Unpack readmore and layout params
$item->alternative_readmore =
$articleParams->get('alternative_readmore');
$item->layout =
$articleParams->get('layout');
$item->params =
clone $this->getState('params');
/*For blogs, article params override menu item params only if menu param = 'use_article'
Otherwise, menu item params control the layout
If menu item is 'use_article' and there is no article param, use global*/
if (($input->getString('layout') ==
'blog') ||
($input->getString('view') ==
'featured')
||
($this->getState('params')->get('layout_type') ==
'blog'))
// Create an array of just the params set to 'use_article'
$menuParamsArray =
$this->getState('params')->toArray();
foreach ($menuParamsArray as $key =>
$value)
if ($value ===
'use_article')
// If the article has a value, use it
if ($articleParams->get($key) !=
'')
// Get the value from the article
$articleArray[$key] =
$articleParams->get($key);
// Otherwise, use the global value
$articleArray[$key] =
$globalParams->get($key);
// Merge the selected article params
if (count($articleArray) >
0)
$articleParams->loadArray($articleArray);
$item->params->merge($articleParams);
// For non-blog layouts, merge all of the article params
$item->params->merge($articleParams);
switch ($item->params->get('list_show_date'))
$item->displayDate =
$item->modified;
$item->displayDate =
($item->publish_up ==
0) ?
$item->created :
$item->publish_up;
$item->displayDate =
$item->created;
// Compute the asset access permissions.
// Technically guest could edit an article, but lets not check that to improve performance a little.
$asset =
'com_content.article.' .
$item->id;
// Check general edit permission first.
if ($user->authorise('core.edit', $asset))
$item->params->set('access-edit', true);
// Now check if edit.own is available.
elseif (!empty($userId) &&
$user->authorise('core.edit.own', $asset))
// Check for a valid user and that they are the owner.
if ($userId ==
$item->created_by)
$item->params->set('access-edit', true);
$access =
$this->getState('filter.access');
// If the access filter has been set, we already have only the articles this user can view.
$item->params->set('access-view', true);
// If no access filter is set, the layout takes some responsibility for display of limited information.
if ($item->catid ==
0 ||
$item->category_access ===
null)
$item->params->set('access-view', in_array($item->access, $groups));
$item->params->set('access-view', in_array($item->access, $groups) &&
in_array($item->category_access, $groups));
$item->tags->getItemTags('com_content.article', $item->id);
* Method to get the starting number of items for the data set.
* @return integer The starting number of items available in the data set.
Documentation generated on Tue, 19 Nov 2013 14:54:03 +0100 by phpDocumentor 1.4.3