diff --git a/administrator/components/com_banners/helpers/banners.php b/administrator/components/com_banners/helpers/banners.php index 77f95e798c69e..fa958309a87af 100644 --- a/administrator/components/com_banners/helpers/banners.php +++ b/administrator/components/com_banners/helpers/banners.php @@ -188,7 +188,7 @@ public static function getClientOptions() /** * Adds Count Items for Category Manager. * - * @param stdClass[] $items The banner category objects + * @param stdClass[] &$items The category objects * * @return stdClass[] * @@ -196,46 +196,13 @@ public static function getClientOptions() */ public static function countItems(&$items) { - $db = JFactory::getDbo(); - - foreach ($items as $item) - { - $item->count_trashed = 0; - $item->count_archived = 0; - $item->count_unpublished = 0; - $item->count_published = 0; - $query = $db->getQuery(true); - $query->select('state, count(*) AS count') - ->from($db->qn('#__banners')) - ->where('catid = ' . (int) $item->id) - ->group('state'); - $db->setQuery($query); - $banners = $db->loadObjectList(); - - foreach ($banners as $banner) - { - if ($banner->state == 1) - { - $item->count_published = $banner->count; - } - - if ($banner->state == 0) - { - $item->count_unpublished = $banner->count; - } - - if ($banner->state == 2) - { - $item->count_archived = $banner->count; - } - - if ($banner->state == -2) - { - $item->count_trashed = $banner->count; - } - } - } + $config = (object) array( + 'related_tbl' => 'banners', + 'state_col' => 'state', + 'group_col' => 'catid', + 'relation_type' => 'category_or_group', + ); - return $items; + return parent::countRelations($items, $config); } } diff --git a/administrator/components/com_contact/helpers/contact.php b/administrator/components/com_contact/helpers/contact.php index fa33ca7b492e4..0be6346a0e3dd 100644 --- a/administrator/components/com_contact/helpers/contact.php +++ b/administrator/components/com_contact/helpers/contact.php @@ -57,7 +57,7 @@ public static function addSubmenu($vName) /** * Adds Count Items for Category Manager. * - * @param stdClass[] $items The contact category objects + * @param stdClass[] &$items The category objects * * @return stdClass[] * @@ -65,53 +65,20 @@ public static function addSubmenu($vName) */ public static function countItems(&$items) { - $db = JFactory::getDbo(); - - foreach ($items as $item) - { - $item->count_trashed = 0; - $item->count_archived = 0; - $item->count_unpublished = 0; - $item->count_published = 0; - $query = $db->getQuery(true); - $query->select('published AS state, count(*) AS count') - ->from($db->qn('#__contact_details')) - ->where('catid = ' . (int) $item->id) - ->group('published'); - $db->setQuery($query); - $contacts = $db->loadObjectList(); - - foreach ($contacts as $contact) - { - if ($contact->state == 1) - { - $item->count_published = $contact->count; - } - - if ($contact->state == 0) - { - $item->count_unpublished = $contact->count; - } - - if ($contact->state == 2) - { - $item->count_archived = $contact->count; - } - - if ($contact->state == -2) - { - $item->count_trashed = $contact->count; - } - } - } + $config = (object) array( + 'related_tbl' => 'contact_details', + 'state_col' => 'published', + 'group_col' => 'catid', + 'relation_type' => 'category_or_group', + ); - return $items; + return parent::countRelations($items, $config); } /** * Adds Count Items for Tag Manager. * - * @param stdClass[] $items The banner tag objects + * @param stdClass[] &$items The tag objects * @param string $extension The name of the active view. * * @return stdClass[] @@ -120,64 +87,18 @@ public static function countItems(&$items) */ public static function countTagItems(&$items, $extension) { - $db = JFactory::getDbo(); - $parts = explode('.', $extension); - $section = null; - - if (count($parts) > 1) - { - $section = $parts[1]; - } - - $join = $db->qn('#__contact_details') . ' AS c ON ct.content_item_id=c.id'; - - if ($section === 'category') - { - $join = $db->qn('#__categories') . ' AS c ON ct.content_item_id=c.id'; - } - - foreach ($items as $item) - { - $item->count_trashed = 0; - $item->count_archived = 0; - $item->count_unpublished = 0; - $item->count_published = 0; - $query = $db->getQuery(true); - $query->select('published as state, count(*) AS count') - ->from($db->qn('#__contentitem_tag_map') . 'AS ct ') - ->where('ct.tag_id = ' . (int) $item->id) - ->where('ct.type_alias =' . $db->q($extension)) - ->join('LEFT', $join) - ->group('published'); - - $db->setQuery($query); - $contacts = $db->loadObjectList(); - - foreach ($contacts as $contact) - { - if ($contact->state == 1) - { - $item->count_published = $contact->count; - } - - if ($contact->state == 0) - { - $item->count_unpublished = $contact->count; - } - - if ($contact->state == 2) - { - $item->count_archived = $contact->count; - } - - if ($contact->state == -2) - { - $item->count_trashed = $contact->count; - } - } - } + $parts = explode('.', $extension); + $section = count($parts) > 1 ? $parts[1] : null; + + $config = (object) array( + 'related_tbl' => ($section === 'category' ? 'categories' : 'contact_details'), + 'state_col' => 'published', + 'group_col' => 'tag_id', + 'extension' => $extension, + 'relation_type' => 'tag_assigments', + ); - return $items; + return parent::countRelations($items, $config); } /** diff --git a/administrator/components/com_content/helpers/content.php b/administrator/components/com_content/helpers/content.php index a8a0b62e72c7c..e83f1e9a36a38 100644 --- a/administrator/components/com_content/helpers/content.php +++ b/administrator/components/com_content/helpers/content.php @@ -91,7 +91,7 @@ public static function filterText($text) /** * Adds Count Items for Category Manager. * - * @param stdClass[] $items The banner category objects + * @param stdClass[] &$items The category objects * * @return stdClass[] * @@ -99,53 +99,20 @@ public static function filterText($text) */ public static function countItems(&$items) { - $db = JFactory::getDbo(); - - foreach ($items as $item) - { - $item->count_trashed = 0; - $item->count_archived = 0; - $item->count_unpublished = 0; - $item->count_published = 0; - $query = $db->getQuery(true); - $query->select('state, count(*) AS count') - ->from($db->qn('#__content')) - ->where('catid = ' . (int) $item->id) - ->group('state'); - $db->setQuery($query); - $articles = $db->loadObjectList(); - - foreach ($articles as $article) - { - if ($article->state == 1) - { - $item->count_published = $article->count; - } - - if ($article->state == 0) - { - $item->count_unpublished = $article->count; - } - - if ($article->state == 2) - { - $item->count_archived = $article->count; - } - - if ($article->state == -2) - { - $item->count_trashed = $article->count; - } - } - } + $config = (object) array( + 'related_tbl' => 'content', + 'state_col' => 'state', + 'group_col' => 'catid', + 'relation_type' => 'category_or_group', + ); - return $items; + return parent::countRelations($items, $config); } /** * Adds Count Items for Tag Manager. * - * @param stdClass[] $items The content objects + * @param stdClass[] &$items The tag objects * @param string $extension The name of the active view. * * @return stdClass[] @@ -154,65 +121,18 @@ public static function countItems(&$items) */ public static function countTagItems(&$items, $extension) { - $db = JFactory::getDbo(); - $parts = explode('.', $extension); - $section = null; - - if (count($parts) > 1) - { - $section = $parts[1]; - } - - $join = $db->qn('#__content') . ' AS c ON ct.content_item_id=c.id'; - $state = 'state'; - - if ($section === 'category') - { - $join = $db->qn('#__categories') . ' AS c ON ct.content_item_id=c.id'; - $state = 'published as state'; - } - - foreach ($items as $item) - { - $item->count_trashed = 0; - $item->count_archived = 0; - $item->count_unpublished = 0; - $item->count_published = 0; - $query = $db->getQuery(true); - $query->select($state . ', count(*) AS count') - ->from($db->qn('#__contentitem_tag_map') . 'AS ct ') - ->where('ct.tag_id = ' . (int) $item->id) - ->where('ct.type_alias =' . $db->q($extension)) - ->join('LEFT', $join) - ->group('state'); - $db->setQuery($query); - $contents = $db->loadObjectList(); - - foreach ($contents as $content) - { - if ($content->state == 1) - { - $item->count_published = $content->count; - } - - if ($content->state == 0) - { - $item->count_unpublished = $content->count; - } - - if ($content->state == 2) - { - $item->count_archived = $content->count; - } - - if ($content->state == -2) - { - $item->count_trashed = $content->count; - } - } - } + $parts = explode('.', $extension); + $section = count($parts) > 1 ? $parts[1] : null; + + $config = (object) array( + 'related_tbl' => ($section === 'category' ? 'categories' : 'content'), + 'state_col' => ($section === 'category' ? 'published' : 'state'), + 'group_col' => 'tag_id', + 'extension' => $extension, + 'relation_type' => 'tag_assigments', + ); - return $items; + return parent::countRelations($items, $config); } /** diff --git a/administrator/components/com_fields/helpers/fields.php b/administrator/components/com_fields/helpers/fields.php index c53bc9e6cd4f2..954b64644cfa2 100644 --- a/administrator/components/com_fields/helpers/fields.php +++ b/administrator/components/com_fields/helpers/fields.php @@ -590,7 +590,7 @@ public static function displayFieldOnForm($field) /** * Adds Count Items for Category Manager. * - * @param stdClass[] $items The field category objects + * @param stdClass[] &$items The fieldgroup objects * * @return stdClass[] * @@ -598,39 +598,14 @@ public static function displayFieldOnForm($field) */ public static function countItems(&$items) { - $db = JFactory::getDbo(); - - foreach ($items as $item) - { - $item->count_trashed = 0; - $item->count_archived = 0; - $item->count_unpublished = 0; - $item->count_published = 0; - - $query = $db->getQuery(true); - $query->select('state, count(1) AS count') - ->from($db->quoteName('#__fields')) - ->where('group_id = ' . (int) $item->id) - ->group('state'); - $db->setQuery($query); - - $fields = $db->loadObjectList(); - - $states = array( - '-2' => 'count_trashed', - '0' => 'count_unpublished', - '1' => 'count_published', - '2' => 'count_archived', - ); - - foreach ($fields as $field) - { - $property = $states[$field->state]; - $item->$property = $field->count; - } - } - - return $items; + $config = (object) array( + 'related_tbl' => 'fields', + 'state_col' => 'state', + 'group_col' => 'group_id', + 'relation_type' => 'category_or_group', + ); + + return parent::countRelations($items, $config); } /** diff --git a/administrator/components/com_newsfeeds/helpers/newsfeeds.php b/administrator/components/com_newsfeeds/helpers/newsfeeds.php index d2c65e4517c03..c453740f65ef7 100644 --- a/administrator/components/com_newsfeeds/helpers/newsfeeds.php +++ b/administrator/components/com_newsfeeds/helpers/newsfeeds.php @@ -43,7 +43,7 @@ public static function addSubmenu($vName) /** * Adds Count Items for Category Manager. * - * @param stdClass[] &$items The banner category objects + * @param stdClass[] &$items The category objects * * @return stdClass[] * @@ -51,53 +51,20 @@ public static function addSubmenu($vName) */ public static function countItems(&$items) { - $db = JFactory::getDbo(); - - foreach ($items as $item) - { - $item->count_trashed = 0; - $item->count_archived = 0; - $item->count_unpublished = 0; - $item->count_published = 0; - $query = $db->getQuery(true); - $query->select('published AS state, count(*) AS count') - ->from($db->qn('#__newsfeeds')) - ->where('catid = ' . (int) $item->id) - ->group('state'); - $db->setQuery($query); - $newfeeds = $db->loadObjectList(); - - foreach ($newfeeds as $newsfeed) - { - if ($newsfeed->state == 1) - { - $item->count_published = $newsfeed->count; - } - - if ($newsfeed->state == 0) - { - $item->count_unpublished = $newsfeed->count; - } - - if ($newsfeed->state == 2) - { - $item->count_archived = $newsfeed->count; - } - - if ($newsfeed->state == -2) - { - $item->count_trashed = $newsfeed->count; - } - } - } + $config = (object) array( + 'related_tbl' => 'newsfeeds', + 'state_col' => 'published', + 'group_col' => 'catid', + 'relation_type' => 'category_or_group', + ); - return $items; + return parent::countRelations($items, $config); } /** * Adds Count Items for Tag Manager. * - * @param stdClass[] &$items The newsfeed tag objects + * @param stdClass[] &$items The tag objects * @param string $extension The name of the active view. * * @return stdClass[] @@ -106,63 +73,17 @@ public static function countItems(&$items) */ public static function countTagItems(&$items, $extension) { - $db = JFactory::getDbo(); - $parts = explode('.', $extension); - $section = null; - - if (count($parts) > 1) - { - $section = $parts[1]; - } - - $join = $db->qn('#__newsfeeds') . ' AS c ON ct.content_item_id=c.id'; - - if ($section === 'category') - { - $join = $db->qn('#__categories') . ' AS c ON ct.content_item_id=c.id'; - } - - foreach ($items as $item) - { - $item->count_trashed = 0; - $item->count_archived = 0; - $item->count_unpublished = 0; - $item->count_published = 0; - $query = $db->getQuery(true); - $query->select('published AS state, count(*) AS count') - ->from($db->qn('#__contentitem_tag_map') . 'AS ct ') - ->where('ct.tag_id = ' . (int) $item->id) - ->where('ct.type_alias =' . $db->q($extension)) - ->join('LEFT', $join) - ->group('state'); - - $db->setQuery($query); - $newsfeeds = $db->loadObjectList(); - - foreach ($newsfeeds as $newsfeed) - { - if ($newsfeed->state == 1) - { - $item->count_published = $newsfeed->count; - } - - if ($newsfeed->state == 0) - { - $item->count_unpublished = $newsfeed->count; - } - - if ($newsfeed->state == 2) - { - $item->count_archived = $newsfeed->count; - } - - if ($newsfeed->state == -2) - { - $item->count_trashed = $newsfeed->count; - } - } - } + $parts = explode('.', $extension); + $section = count($parts) > 1 ? $parts[1] : null; + + $config = (object) array( + 'related_tbl' => ($section === 'category' ? 'categories' : 'newsfeeds'), + 'state_col' => 'published', + 'group_col' => 'tag_id', + 'extension' => $extension, + 'relation_type' => 'tag_assigments', + ); - return $items; + return parent::countRelations($items, $config); } } diff --git a/libraries/src/Helper/ContentHelper.php b/libraries/src/Helper/ContentHelper.php index cc951414544aa..d13eb43e221a6 100644 --- a/libraries/src/Helper/ContentHelper.php +++ b/libraries/src/Helper/ContentHelper.php @@ -42,6 +42,101 @@ public static function addSubmenu($vName) { } + /** + * Adds Count relations for Category and Tag Managers + * + * @param stdClass[] &$items The category or tag objects + * @param stdClass $config Configuration object allowing to use a custom relations table + * + * @return stdClass[] + * + * @since __DEPLOY_VERSION__ + */ + public static function countRelations(&$items, $config) + { + $db = Factory::getDbo(); + + // Allow custom state / condition values and custom column names to support custom components + $counter_names = isset($config->counter_names) ? $config->counter_names : array( + '-2' => 'count_trashed', + '0' => 'count_unpublished', + '1' => 'count_published', + '2' => 'count_archived', + ); + + // Index category objects by their ID + $records = array(); + + foreach ($items as $item) + { + $records[(int) $item->id] = $item; + } + + // The relation query does not return a value for cases without relations of a particular state / condition, set zero as default + foreach ($items as $item) + { + foreach ($counter_names as $n) + { + $item->{$n} = 0; + } + } + + // Table alias for related data table below will be 'c', and state / condition column is inside related data table + $related_tbl = $db->quoteName('#__' . $config->related_tbl, 'c'); + $state_col = $db->quoteName('c.' . $config->state_col); + + // Supported cases + switch ($config->relation_type) + { + case 'tag_assigments': + $recid_col = $db->quoteName('ct.' . $config->group_col); + + $query = $db->getQuery(true) + ->from($db->quoteName('#__contentitem_tag_map', 'ct')) + ->join('INNER', $related_tbl . ' ON ' . $db->quoteName('ct.content_item_id') . ' = ' . $db->quoteName('c.id') . ' AND ' . + $db->quoteName('ct.type_alias') . ' = ' . $db->quote($config->extension) + ); + break; + + case 'category_or_group': + $recid_col = $db->quoteName('c.' . $config->group_col); + + $query = $db->getQuery(true) + ->from($related_tbl); + break; + + default: + return $items; + } + + /** + * Get relation counts for all category objects with single query + * NOTE: 'state IN', allows counting specific states / conditions only, also prevents warnings with custom states / conditions, do not remove + */ + $query + ->select($recid_col . ' AS catid, ' . $state_col . ' AS state, COUNT(*) AS count') + ->where($recid_col . ' IN (' . implode(',', array_keys($records)) . ')') + ->where($state_col . ' IN (' . implode(',', array_keys($counter_names)) . ')') + ->group($recid_col . ', ' . $state_col); + + $relationsAll = $db->setQuery($query)->loadObjectList(); + + // Loop through the DB data overwritting the above zeros with the found count + foreach ($relationsAll as $relation) + { + // Sanity check in case someone removes the state IN above ... and some views may start throwing warnings + if (isset($counter_names[$relation->state])) + { + $id = (int) $relation->catid; + $cn = $counter_names[$relation->state]; + + $records[$id]->{$cn} = $relation->count; + } + } + + return $items; + } + /** * Gets a list of the actions that can be performed. *