diff --git a/administrator/components/com_categories/models/categories.php b/administrator/components/com_categories/models/categories.php
index 5750db24708b4..e16fd4d4cdc2b 100644
--- a/administrator/components/com_categories/models/categories.php
+++ b/administrator/components/com_categories/models/categories.php
@@ -130,7 +130,7 @@ protected function getStoreId($id = '')
$id .= ':' . $this->getState('filter.access');
$id .= ':' . $this->getState('filter.language');
$id .= ':' . $this->getState('filter.level');
- $id .= ':' . $this->getState('filter.tag');
+ $id .= ':' . serialize($this->getState('filter.tag'));
return parent::getStoreId($id);
}
@@ -153,7 +153,7 @@ protected function getListQuery()
$query->select(
$this->getState(
'list.select',
- 'a.id, a.title, a.alias, a.note, a.published, a.access' .
+ 'DISTINCT a.id, a.title, a.alias, a.note, a.published, a.access' .
', a.checked_out, a.checked_out_time, a.created_user_id' .
', a.path, a.parent_id, a.level, a.lft, a.rgt' .
', a.language'
@@ -247,17 +247,34 @@ protected function getListQuery()
$query->where('a.language = ' . $db->quote($language));
}
- // Filter by a single tag.
+ // Filter by a single or group of tags.
+ $hasTag = false;
$tagId = $this->getState('filter.tag');
if (is_numeric($tagId))
{
- $query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId)
- ->join(
- 'LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
- . ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
- . ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote($extension . '.category')
- );
+ $hasTag = true;
+
+ $query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId);
+ }
+ elseif (is_array($tagId))
+ {
+ JArrayHelper::toInteger($tagId);
+ $tagId = implode(',', $tagId);
+ if (!empty($tagId))
+ {
+ $hasTag = true;
+
+ $query->where($db->quoteName('tagmap.tag_id') . ' IN (' . $tagId . ')');
+ }
+ }
+
+ if ($hasTag)
+ {
+ $query->join('LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
+ . ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
+ . ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote($extension . '.category')
+ );
}
// Add the list ordering clause
@@ -360,7 +377,7 @@ public function getItems()
/**
* Method to load the countItems method from the extensions
- *
+ *
* @param stdClass[] &$items The category items
* @param string $extension The category extension
*
diff --git a/administrator/components/com_categories/models/forms/filter_categories.xml b/administrator/components/com_categories/models/forms/filter_categories.xml
index 3dd53359d3527..c46ae1297adc6 100644
--- a/administrator/components/com_categories/models/forms/filter_categories.xml
+++ b/administrator/components/com_categories/models/forms/filter_categories.xml
@@ -45,12 +45,13 @@
-
+ >
JText::_('JOPTION_SELECT_TAG')));
JHtml::_('formbehavior.chosen', 'select');
$app = JFactory::getApplication();
diff --git a/administrator/components/com_content/models/articles.php b/administrator/components/com_content/models/articles.php
index 5e525fed1236d..1a5011fa551dd 100644
--- a/administrator/components/com_content/models/articles.php
+++ b/administrator/components/com_content/models/articles.php
@@ -144,11 +144,12 @@ protected function getStoreId($id = '')
{
// Compile the store id.
$id .= ':' . $this->getState('filter.search');
- $id .= ':' . $this->getState('filter.access');
+ $id .= ':' . serialize($this->getState('filter.access'));
$id .= ':' . $this->getState('filter.published');
- $id .= ':' . $this->getState('filter.category_id');
- $id .= ':' . $this->getState('filter.author_id');
+ $id .= ':' . serialize($this->getState('filter.category_id'));
+ $id .= ':' . serialize($this->getState('filter.author_id'));
$id .= ':' . $this->getState('filter.language');
+ $id .= ':' . serialize($this->getState('filter.tag'));
return parent::getStoreId($id);
}
@@ -172,7 +173,7 @@ protected function getListQuery()
$query->select(
$this->getState(
'list.select',
- 'a.id, a.title, a.alias, a.checked_out, a.checked_out_time, a.catid' .
+ 'DISTINCT a.id, a.title, a.alias, a.checked_out, a.checked_out_time, a.catid' .
', a.state, a.access, a.created, a.created_by, a.created_by_alias, a.ordering, a.featured, a.language, a.hits' .
', a.publish_up, a.publish_down'
)
@@ -209,10 +210,18 @@ protected function getListQuery()
}
// Filter by access level.
- if ($access = $this->getState('filter.access'))
+ $access = $this->getState('filter.access');
+
+ if (is_numeric($access))
{
$query->where('a.access = ' . (int) $access);
}
+ elseif(is_array($access))
+ {
+ JArrayHelper::toInteger($access);
+ $access = implode(',', $access);
+ $query->where('a.access IN (' . $access . ')');
+ }
// Implement View Level Access
if (!$user->authorise('core.admin'))
@@ -269,6 +278,13 @@ protected function getListQuery()
$query->where('a.created_by ' . $type . (int) $authorId);
}
+ elseif (is_array($authorId))
+ {
+ JArrayHelper::toInteger($categoryId);
+ $authorId = implode(',', $authorId);
+ $query->where('a.created_by IN (' . $authorId . ')');
+ }
+
// Filter by search in title.
$search = $this->getState('filter.search');
@@ -296,17 +312,34 @@ protected function getListQuery()
$query->where('a.language = ' . $db->quote($language));
}
- // Filter by a single tag.
+ // Filter by a single or group of tags.
+ $hasTag = false;
$tagId = $this->getState('filter.tag');
if (is_numeric($tagId))
{
- $query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId)
- ->join(
- 'LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
- . ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
- . ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_content.article')
- );
+ $hasTag = true;
+
+ $query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId);
+ }
+ elseif (is_array($tagId))
+ {
+ JArrayHelper::toInteger($tagId);
+ $tagId = implode(',', $tagId);
+ if (!empty($tagId))
+ {
+ $hasTag = true;
+
+ $query->where($db->quoteName('tagmap.tag_id') . ' IN (' . $tagId . ')');
+ }
+ }
+
+ if ($hasTag)
+ {
+ $query->join('LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
+ . ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
+ . ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_content.article')
+ );
}
// Add the list ordering clause.
diff --git a/administrator/components/com_content/models/featured.php b/administrator/components/com_content/models/featured.php
index f5d2ef8faeb59..ae8aa12f4c785 100644
--- a/administrator/components/com_content/models/featured.php
+++ b/administrator/components/com_content/models/featured.php
@@ -79,7 +79,7 @@ protected function getListQuery($resolveFKs = true)
$query->select(
$this->getState(
'list.select',
- 'a.id, a.title, a.alias, a.checked_out, a.checked_out_time, a.catid, a.state, a.access, a.created, a.hits,' .
+ 'DISTINCT a.id, a.title, a.alias, a.checked_out, a.checked_out_time, a.catid, a.state, a.access, a.created, a.hits,' .
'a.featured, a.language, a.created_by_alias, a.publish_up, a.publish_down'
)
);
@@ -110,10 +110,18 @@ protected function getListQuery($resolveFKs = true)
->join('LEFT', '#__users AS ua ON ua.id = a.created_by');
// Filter by access level.
- if ($access = $this->getState('filter.access'))
+ $access = $this->getState('filter.access');
+
+ if (is_numeric($access))
{
$query->where('a.access = ' . (int) $access);
}
+ elseif(is_array($access))
+ {
+ JArrayHelper::toInteger($access);
+ $access = implode(',', $access);
+ $query->where('a.access IN (' . $access . ')');
+ }
// Filter by published state
$published = $this->getState('filter.published');
@@ -162,6 +170,13 @@ protected function getListQuery($resolveFKs = true)
$query->where('a.created_by ' . $type . (int) $authorId);
}
+ elseif (is_array($authorId))
+ {
+ JArrayHelper::toInteger($categoryId);
+ $authorId = implode(',', $authorId);
+ $query->where('a.created_by IN (' . $authorId . ')');
+ }
+
// Filter by search in title.
$search = $this->getState('filter.search');
@@ -189,17 +204,34 @@ protected function getListQuery($resolveFKs = true)
$query->where('a.language = ' . $db->quote($language));
}
- // Filter by a single tag.
+ // Filter by a single or group of tags.
+ $hasTag = false;
$tagId = $this->getState('filter.tag');
if (is_numeric($tagId))
{
- $query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId)
- ->join(
- 'LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
- . ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
- . ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_content.article')
- );
+ $hasTag = true;
+
+ $query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId);
+ }
+ elseif (is_array($tagId))
+ {
+ JArrayHelper::toInteger($tagId);
+ $tagId = implode(',', $tagId);
+ if (!empty($tagId))
+ {
+ $hasTag = true;
+
+ $query->where($db->quoteName('tagmap.tag_id') . ' IN (' . $tagId . ')');
+ }
+ }
+
+ if ($hasTag)
+ {
+ $query->join('LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
+ . ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
+ . ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_content.article')
+ );
}
// Add the list ordering clause.
diff --git a/administrator/components/com_content/models/forms/filter_articles.xml b/administrator/components/com_content/models/forms/filter_articles.xml
index 51e0dca100994..ed5b7f03c0026 100644
--- a/administrator/components/com_content/models/forms/filter_articles.xml
+++ b/administrator/components/com_content/models/forms/filter_articles.xml
@@ -20,32 +20,35 @@
-
-
-
-
+ name="author_id"
+ type="author"
+ multiple="true"
+ class="multipleAuthors"
+ label="COM_CONTENT_FILTER_AUTHOR"
+ description="COM_CONTENT_FILTER_AUTHOR_DESC"
+ onchange="this.form.submit();"
+ >
+
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
JText::_('JOPTION_SELECT_ACCESS')));
+JHtml::_('formbehavior.chosen', '.multipleAuthors', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_AUTHOR')));
+JHtml::_('formbehavior.chosen', '.multipleCategories', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_CATEGORY')));
+JHtml::_('formbehavior.chosen', '.multipleTags', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_TAG')));
JHtml::_('formbehavior.chosen', 'select');
$app = JFactory::getApplication();
diff --git a/administrator/components/com_content/views/featured/tmpl/default.php b/administrator/components/com_content/views/featured/tmpl/default.php
index 161469ce2be31..a1a02696324a9 100644
--- a/administrator/components/com_content/views/featured/tmpl/default.php
+++ b/administrator/components/com_content/views/featured/tmpl/default.php
@@ -13,6 +13,10 @@
JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
+JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_ACCESS')));
+JHtml::_('formbehavior.chosen', '.multipleAuthors', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_AUTHOR')));
+JHtml::_('formbehavior.chosen', '.multipleCategories', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_CATEGORY')));
+JHtml::_('formbehavior.chosen', '.multipleTags', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_TAG')));
JHtml::_('formbehavior.chosen', 'select');
$user = JFactory::getUser();
diff --git a/administrator/components/com_modules/views/module/tmpl/edit.php b/administrator/components/com_modules/views/module/tmpl/edit.php
index a51f41fdd9016..649502b7b58bc 100644
--- a/administrator/components/com_modules/views/module/tmpl/edit.php
+++ b/administrator/components/com_modules/views/module/tmpl/edit.php
@@ -14,6 +14,8 @@
JHtml::_('behavior.formvalidator');
JHtml::_('behavior.combobox');
JHtml::_('formbehavior.chosen', 'select', null, array('disable_search_threshold' => 0));
+JHtml::_('formbehavior.chosen', '.multipleCategories', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_CATEGORY')));
+JHtml::_('formbehavior.chosen', '.multipleTags', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_TAG')));
$hasContent = empty($this->item->module) || isset($this->item->xml->customContent);
$hasContentFieldName = "content";
diff --git a/administrator/components/com_newsfeeds/models/newsfeeds.php b/administrator/components/com_newsfeeds/models/newsfeeds.php
index fb5ca49e8e8a6..8c4ef22ac8c8f 100644
--- a/administrator/components/com_newsfeeds/models/newsfeeds.php
+++ b/administrator/components/com_newsfeeds/models/newsfeeds.php
@@ -46,6 +46,7 @@ public function __construct($config = array())
'numarticles',
'tag',
'level', 'c.level',
+ 'tag',
);
$assoc = JLanguageAssociations::isEnabled();
@@ -130,8 +131,8 @@ protected function getStoreId($id = '')
$id .= ':' . $this->getState('filter.category_id');
$id .= ':' . $this->getState('filter.access');
$id .= ':' . $this->getState('filter.language');
- $id .= ':' . $this->getState('filter.tag');
$id .= ':' . $this->getState('filter.level');
+ $id .= ':' . serialize($this->getState('filter.tag'));
return parent::getStoreId($id);
}
@@ -153,7 +154,7 @@ protected function getListQuery()
$query->select(
$this->getState(
'list.select',
- 'a.id, a.name, a.alias, a.checked_out, a.checked_out_time, a.catid,' .
+ 'DISTINCT a.id, a.name, a.alias, a.checked_out, a.checked_out_time, a.catid,' .
' a.numarticles, a.cache_time,' .
' a.published, a.access, a.ordering, a.language, a.publish_up, a.publish_down'
)
@@ -248,17 +249,34 @@ protected function getListQuery()
$query->where($db->quoteName('a.language') . ' = ' . $db->quote($language));
}
- // Filter by a single tag.
+ // Filter by a single or group of tags.
+ $hasTag = false;
$tagId = $this->getState('filter.tag');
if (is_numeric($tagId))
{
- $query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId)
- ->join(
- 'LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
- . ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
- . ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_newsfeeds.newsfeed')
- );
+ $hasTag = true;
+
+ $query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId);
+ }
+ elseif (is_array($tagId))
+ {
+ JArrayHelper::toInteger($tagId);
+ $tagId = implode(',', $tagId);
+ if (!empty($tagId))
+ {
+ $hasTag = true;
+
+ $query->where($db->quoteName('tagmap.tag_id') . ' IN (' . $tagId . ')');
+ }
+ }
+
+ if ($hasTag)
+ {
+ $query->join('LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
+ . ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
+ . ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_newsfeeds.newsfeed')
+ );
}
// Add the list ordering clause.
diff --git a/administrator/language/en-GB/en-GB.ini b/administrator/language/en-GB/en-GB.ini
index 2ff06b3d36883..97fc33c74b3d9 100644
--- a/administrator/language/en-GB/en-GB.ini
+++ b/administrator/language/en-GB/en-GB.ini
@@ -799,6 +799,7 @@ JOPTION_ACCESS_SHOW_ALL_ACCESS="Show All Access"
JOPTION_ACCESS_SHOW_ALL_GROUPS="Show All Groups"
JOPTION_ACCESS_SHOW_ALL_LEVELS="Show All Access Levels"
JOPTION_ALL_CATEGORIES="- All Categories -"
+JOPTION_ALL_TAGS="- All Tags -"
JOPTION_ANY_CATEGORY="Any Category"
JOPTION_ANY="Any"
JOPTION_DO_NOT_USE="- None Selected -"
diff --git a/components/com_content/models/articles.php b/components/com_content/models/articles.php
index 15d0fa8f61967..ffee9300d685c 100644
--- a/components/com_content/models/articles.php
+++ b/components/com_content/models/articles.php
@@ -50,7 +50,8 @@ public function __construct($config = array())
'publish_down', 'a.publish_down',
'images', 'a.images',
'urls', 'a.urls',
- 'filter_tag'
+ 'filter_tag',
+ 'tag'
);
}
@@ -162,6 +163,7 @@ protected function getStoreId($id = '')
$id .= ':' . $this->getState('filter.start_date_range');
$id .= ':' . $this->getState('filter.end_date_range');
$id .= ':' . $this->getState('filter.relative_date');
+ $id .= ':' . serialize($this->getState('filter.tag'));
return parent::getStoreId($id);
}
@@ -186,7 +188,7 @@ protected function getListQuery()
$query->select(
$this->getState(
'list.select',
- 'a.id, a.title, a.alias, a.introtext, a.fulltext, ' .
+ 'DISTINCT 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
@@ -532,17 +534,34 @@ protected function getListQuery()
$query->where('a.language in (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
}
- // Filter by a single tag.
+ // Filter by a single or group of tags.
+ $hasTag = false;
$tagId = $this->getState('filter.tag');
- if (!empty($tagId) && is_numeric($tagId))
+ if (is_numeric($tagId))
{
- $query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId)
- ->join(
- 'LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
- . ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
- . ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_content.article')
- );
+ $hasTag = true;
+
+ $query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId);
+ }
+ elseif (is_array($tagId))
+ {
+ JArrayHelper::toInteger($tagId);
+ $tagId = implode(',', $tagId);
+ if (!empty($tagId))
+ {
+ $hasTag = true;
+
+ $query->where($db->quoteName('tagmap.tag_id') . ' IN (' . $tagId . ')');
+ }
+ }
+
+ if ($hasTag)
+ {
+ $query->join('LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
+ . ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
+ . ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_content.article')
+ );
}
// Add the list ordering clause.
diff --git a/modules/mod_articles_news/helper.php b/modules/mod_articles_news/helper.php
index d41ceebf2620a..414fbb5e8a0bd 100644
--- a/modules/mod_articles_news/helper.php
+++ b/modules/mod_articles_news/helper.php
@@ -58,6 +58,9 @@ public static function getList(&$params)
// Filter by language
$model->setState('filter.language', $app->getLanguageFilter());
+ // Filter by tag
+ $model->setState('filter.tag', $params->get('tag'), array());
+
// Set ordering
$ordering = $params->get('ordering', 'a.publish_up');
$model->setState('list.ordering', $ordering);
diff --git a/modules/mod_articles_news/mod_articles_news.xml b/modules/mod_articles_news/mod_articles_news.xml
index 9eba4e0ce235b..1d1a675a8437c 100644
--- a/modules/mod_articles_news/mod_articles_news.xml
+++ b/modules/mod_articles_news/mod_articles_news.xml
@@ -25,14 +25,25 @@
-
+ label="JCATEGORY"
+ description="MOD_ARTICLES_NEWS_FIELD_CATEGORY_DESC"
+ >
+
+
+