Spade

Mini Shell

Directory:~$ /home/lmsyaran/public_html/joomla4/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ /home/lmsyaran/public_html/joomla4/Helper.zip

PK䛈[�@IAuthenticationHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

/**
 * Authentication helper class
 *
 * @since  3.6.3
 */
abstract class AuthenticationHelper
{
	/**
	 * Get the Two Factor Authentication Methods available.
	 *
	 * @return  array  Two factor authentication methods.
	 *
	 * @since   3.6.3
	 */
	public static function getTwoFactorMethods()
	{
		// Get all the Two Factor Authentication plugins.
		\JPluginHelper::importPlugin('twofactorauth');

		// Trigger onUserTwofactorIdentify event and return the two factor
enabled plugins.
		$identities =
\JEventDispatcher::getInstance()->trigger('onUserTwofactorIdentify',
array());

		// Generate array with two factor auth methods.
		$options = array(
			\JHtml::_('select.option', 'none',
\JText::_('JGLOBAL_OTPMETHOD_NONE'), 'value',
'text'),
		);

		if (!empty($identities))
		{
			foreach ($identities as $identity)
			{
				if (!is_object($identity))
				{
					continue;
				}

				$options[] = \JHtml::_('select.option', $identity->method,
$identity->title, 'value', 'text');
			}
		}

		return $options;
	}
}
PK䛈[Q��
CMSHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Application\ApplicationHelper;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\LanguageHelper;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Table\TableInterface;
use Joomla\Registry\Registry;

/**
 * Base Helper class.
 *
 * @since  3.2
 */
class CMSHelper
{
	/**
	 * Gets the current language
	 *
	 * @param   boolean  $detectBrowser  Flag indicating whether to use the
browser language as a fallback.
	 *
	 * @return  string  The language string
	 *
	 * @since   3.2
	 */
	public function getCurrentLanguage($detectBrowser = true)
	{
		$app = Factory::getApplication();
		$langCode = null;

		// Get the languagefilter parameters
		if (Multilanguage::isEnabled())
		{
			$plugin       = PluginHelper::getPlugin('system',
'languagefilter');
			$pluginParams = new Registry($plugin->params);

			if ((int) $pluginParams->get('lang_cookie', 1) === 1)
			{
				$langCode =
$app->input->cookie->getString(ApplicationHelper::getHash('language'));
			}
			else
			{
				$langCode =
Factory::getSession()->get('plg_system_languagefilter.language');
			}
		}

		// No cookie - let's try to detect browser language or use site
default
		if (!$langCode)
		{
			if ($detectBrowser)
			{
				$langCode = LanguageHelper::detectLanguage();
			}
			else
			{
				$langCode =
ComponentHelper::getParams('com_languages')->get('site',
'en-GB');
			}
		}

		return $langCode;
	}

	/**
	 * Gets the associated language ID
	 *
	 * @param   string  $langCode  The language code to look up
	 *
	 * @return  integer  The language ID
	 *
	 * @since   3.2
	 */
	public function getLanguageId($langCode)
	{
		$db    = Factory::getDbo();
		$query = $db->getQuery(true)
			->select('lang_id')
			->from('#__languages')
			->where($db->quoteName('lang_code') . ' = ' .
$db->quote($langCode));
		$db->setQuery($query);

		return $db->loadResult();
	}

	/**
	 * Gets a row of data from a table
	 *
	 * @param   TableInterface  $table  Table instance for a row.
	 *
	 * @return  array  Associative array of all columns and values for a row
in a table.
	 *
	 * @since   3.2
	 */
	public function getRowData(TableInterface $table)
	{
		$fields = $table->getFields();
		$data = array();

		foreach ($fields as &$field)
		{
			$columnName = $field->Field;
			$value = $table->$columnName;
			$data[$columnName] = $value;
		}

		return $data;
	}

	/**
	 * Method to get an object containing all of the table columns and values.
	 *
	 * @param   TableInterface  $table  Table object.
	 *
	 * @return  \stdClass  Contains all of the columns and values.
	 *
	 * @since   3.2
	 */
	public function getDataObject(TableInterface $table)
	{
		$fields = $table->getFields();
		$dataObject = new \stdClass;

		foreach ($fields as $field)
		{
			$fieldName = $field->Field;
			$dataObject->$fieldName = $table->get($fieldName);
		}

		return $dataObject;
	}
}
PK䛈[��n!n!ContentHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Application\ApplicationHelper;
use Joomla\CMS\Access\Access;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\LanguageHelper;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Table\Table;
use Joomla\Registry\Registry;

/**
 * Helper for standard content style extensions.
 * This class mainly simplifies static helper methods often repeated in
individual components
 *
 * @since  3.1
 */
class ContentHelper
{
	/**
	 * Configure the Linkbar. Must be implemented by each extension.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   3.1
	 */
	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   3.9.1
	 */
	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.
	 *
	 * @param   integer  $categoryId  The category ID.
	 * @param   integer  $id          The item ID.
	 * @param   string   $assetName   The asset name
	 *
	 * @return  \JObject
	 *
	 * @since   3.1
	 * @deprecated  3.2  Use ContentHelper::getActions() instead
	 */
	public static function _getActions($categoryId = 0, $id = 0, $assetName =
'')
	{
		// Log usage of deprecated function
		Log::add(__METHOD__ . '() is deprecated, use
ContentHelper::getActions() with new arguments order instead.',
Log::WARNING, 'deprecated');

		// Reverted a change for version 2.5.6
		$user   = Factory::getUser();
		$result = new \JObject;

		$path = JPATH_ADMINISTRATOR . '/components/' . $assetName .
'/access.xml';

		if (empty($id) && empty($categoryId))
		{
			$section = 'component';
		}
		elseif (empty($id))
		{
			$section = 'category';
			$assetName .= '.category.' . (int) $categoryId;
		}
		else
		{
			// Used only in com_content
			$section = 'article';
			$assetName .= '.article.' . (int) $id;
		}

		$actions = Access::getActionsFromFile($path,
"/access/section[@name='" . $section .
"']/");

		foreach ($actions as $action)
		{
			$result->set($action->name, $user->authorise($action->name,
$assetName));
		}

		return $result;
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @param   string   $component  The component name.
	 * @param   string   $section    The access section name.
	 * @param   integer  $id         The item ID.
	 *
	 * @return  \JObject
	 *
	 * @since   3.2
	 */
	public static function getActions($component = '', $section =
'', $id = 0)
	{
		// Check for deprecated arguments order
		if (is_int($component) || $component === null)
		{
			$result = self::_getActions($component, $section, $id);

			return $result;
		}

		$assetName = $component;

		if ($section && $id)
		{
			$assetName .= '.' . $section . '.' . (int) $id;
		}

		$result = new \JObject;

		$user = Factory::getUser();

		$actions = Access::getActionsFromFile(
			JPATH_ADMINISTRATOR . '/components/' . $component .
'/access.xml',
'/access/section[@name="component"]/'
		);

		if ($actions === false)
		{
			Log::add(
				\JText::sprintf('JLIB_ERROR_COMPONENTS_ACL_CONFIGURATION_FILE_MISSING_OR_IMPROPERLY_STRUCTURED',
$component), Log::ERROR, 'jerror'
			);

			return $result;
		}

		foreach ($actions as $action)
		{
			$result->set($action->name, $user->authorise($action->name,
$assetName));
		}

		return $result;
	}

	/**
	 * Gets the current language
	 *
	 * @param   boolean  $detectBrowser  Flag indicating whether to use the
browser language as a fallback.
	 *
	 * @return  string  The language string
	 *
	 * @since   3.1
	 * @note    CmsHelper::getCurrentLanguage is the preferred method
	 */
	public static function getCurrentLanguage($detectBrowser = true)
	{
		$app = Factory::getApplication();
		$langCode = null;

		// Get the languagefilter parameters
		if (Multilanguage::isEnabled())
		{
			$plugin       = PluginHelper::getPlugin('system',
'languagefilter');
			$pluginParams = new Registry($plugin->params);

			if ((int) $pluginParams->get('lang_cookie', 1) === 1)
			{
				$langCode =
$app->input->cookie->getString(ApplicationHelper::getHash('language'));
			}
			else
			{
				$langCode =
Factory::getSession()->get('plg_system_languagefilter.language');
			}
		}

		// No cookie - let's try to detect browser language or use site
default
		if (!$langCode)
		{
			if ($detectBrowser)
			{
				$langCode = LanguageHelper::detectLanguage();
			}
			else
			{
				$langCode =
ComponentHelper::getParams('com_languages')->get('site',
'en-GB');
			}
		}

		return $langCode;
	}

	/**
	 * Gets the associated language ID
	 *
	 * @param   string  $langCode  The language code to look up
	 *
	 * @return  integer  The language ID
	 *
	 * @since   3.1
	 * @note    CmsHelper::getLanguage() is the preferred method.
	 */
	public static function getLanguageId($langCode)
	{
		$db    = Factory::getDbo();
		$query = $db->getQuery(true)
			->select('lang_id')
			->from('#__languages')
			->where($db->quoteName('lang_code') . ' = ' .
$db->quote($langCode));
		$db->setQuery($query);

		return $db->loadResult();
	}

	/**
	 * Gets a row of data from a table
	 *
	 * @param   Table  $table  Table instance for a row.
	 *
	 * @return  array  Associative array of all columns and values for a row
in a table.
	 *
	 * @since   3.1
	 */
	public function getRowData(Table $table)
	{
		$data = new CMSHelper;

		return $data->getRowData($table);
	}
}
PK䛈[h���EEContentHistoryHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Table\Table;

/**
 * Versions helper class, provides methods to perform various tasks
relevant
 * versioning of content.
 *
 * @since  3.2
 */
class ContentHistoryHelper extends CMSHelper
{
	/**
	 * Alias for storing type in versions table
	 *
	 * @var    string
	 * @since  3.2
	 */
	public $typeAlias = null;

	/**
	 * Constructor
	 *
	 * @param   string  $typeAlias  The type of content to be versioned (for
example, 'com_content.article').
	 *
	 * @since   3.2
	 */
	public function __construct($typeAlias = null)
	{
		$this->typeAlias = $typeAlias;
	}

	/**
	 * Method to delete the history for an item.
	 *
	 * @param   Table  $table  Table object being versioned
	 *
	 * @return  boolean  true on success, otherwise false.
	 *
	 * @since   3.2
	 */
	public function deleteHistory($table)
	{
		$key = $table->getKeyName();
		$id = $table->$key;
		$typeTable = Table::getInstance('Contenttype',
'JTable');
		$typeId = $typeTable->getTypeId($this->typeAlias);
		$db = \JFactory::getDbo();
		$query = $db->getQuery(true);
		$query->delete($db->quoteName('#__ucm_history'))
			->where($db->quoteName('ucm_item_id') . ' = '
. (int) $id)
			->where($db->quoteName('ucm_type_id') . ' = '
. (int) $typeId);
		$db->setQuery($query);

		return $db->execute();
	}

	/**
	 * Method to get a list of available versions of this item.
	 *
	 * @param   integer  $typeId  Type id for this component item.
	 * @param   mixed    $id      Primary key of row to get history for.
	 *
	 * @return  mixed   The return value or null if the query failed.
	 *
	 * @since   3.2
	 */
	public function getHistory($typeId, $id)
	{
		$db = \JFactory::getDbo();
		$query = $db->getQuery(true);
		$query->select($db->quoteName('h.version_note') .
',' . $db->quoteName('h.save_date') . ','
. $db->quoteName('u.name'))
			->from($db->quoteName('#__ucm_history') . ' AS h
')
			->leftJoin($db->quoteName('#__users') . ' AS u ON
' . $db->quoteName('u.id') . ' = ' .
$db->quoteName('h.editor_user_id'))
			->where($db->quoteName('ucm_item_id') . ' = '
. $db->quote($id))
			->where($db->quoteName('ucm_type_id') . ' = '
. (int) $typeId)
			->order($db->quoteName('save_date') . ' DESC
');
		$db->setQuery($query);

		return $db->loadObjectList();
	}

	/**
	 * Method to save a version snapshot to the content history table.
	 *
	 * @param   Table  $table  Table object being versioned
	 *
	 * @return  boolean  True on success, otherwise false.
	 *
	 * @since   3.2
	 */
	public function store($table)
	{
		$dataObject = $this->getDataObject($table);
		$historyTable = Table::getInstance('Contenthistory',
'JTable');
		$typeTable = Table::getInstance('Contenttype',
'JTable');
		$typeTable->load(array('type_alias' =>
$this->typeAlias));
		$historyTable->set('ucm_type_id', $typeTable->type_id);

		$key = $table->getKeyName();
		$historyTable->set('ucm_item_id', $table->$key);

		// Don't store unless we have a non-zero item id
		if (!$historyTable->ucm_item_id)
		{
			return true;
		}

		$historyTable->set('version_data',
json_encode($dataObject));
		$input = \JFactory::getApplication()->input;
		$data = $input->get('jform', array(), 'array');
		$versionName = false;

		if (isset($data['version_note']))
		{
			$versionName =
\JFilterInput::getInstance()->clean($data['version_note'],
'string');
			$historyTable->set('version_note', $versionName);
		}

		// Don't save if hash already exists and same version note
		$historyTable->set('sha1_hash',
$historyTable->getSha1($dataObject, $typeTable));

		if ($historyRow = $historyTable->getHashMatch())
		{
			if (!$versionName || ($historyRow->version_note === $versionName))
			{
				return true;
			}
			else
			{
				// Update existing row to set version note
				$historyTable->set('version_id',
$historyRow->version_id);
			}
		}

		$result = $historyTable->store();

		// Load history_limit config from extension.
		$aliasParts = explode('.', $this->typeAlias);

		$context = isset($aliasParts[1]) ? $aliasParts[1] : '';

		$maxVersionsContext =
ComponentHelper::getParams($aliasParts[0])->get('history_limit'
. '_' . $context, 0);

		if ($maxVersionsContext)
		{
			$historyTable->deleteOldVersions($maxVersionsContext);
		}
		elseif ($maxVersions =
ComponentHelper::getParams($aliasParts[0])->get('history_limit',
0))
		{
			$historyTable->deleteOldVersions($maxVersions);
		}

		return $result;
	}
}
PK䛈[5�0	yyLibraryHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

use Joomla\Registry\Registry;

/**
 * Library helper class
 *
 * @since  3.2
 */
class LibraryHelper
{
	/**
	 * The component list cache
	 *
	 * @var    array
	 * @since  3.2
	 */
	protected static $libraries = array();

	/**
	 * Get the library information.
	 *
	 * @param   string   $element  Element of the library in the extensions
table.
	 * @param   boolean  $strict   If set and the library does not exist, the
enabled attribute will be set to false.
	 *
	 * @return  \stdClass   An object with the library's information.
	 *
	 * @since   3.2
	 */
	public static function getLibrary($element, $strict = false)
	{
		// Is already cached?
		if (isset(static::$libraries[$element]) || static::loadLibrary($element))
		{
			$result = static::$libraries[$element];

			// Convert the params to an object.
			if (is_string($result->params))
			{
				$result->params = new Registry($result->params);
			}
		}
		else
		{
			$result = new \stdClass;
			$result->enabled = $strict ? false : true;
			$result->params = new Registry;
		}

		return $result;
	}

	/**
	 * Checks if a library is enabled
	 *
	 * @param   string  $element  Element of the library in the extensions
table.
	 *
	 * @return  boolean
	 *
	 * @since   3.2
	 */
	public static function isEnabled($element)
	{
		return static::getLibrary($element, true)->enabled;
	}

	/**
	 * Gets the parameter object for the library
	 *
	 * @param   string   $element  Element of the library in the extensions
table.
	 * @param   boolean  $strict   If set and the library does not exist,
false will be returned
	 *
	 * @return  Registry  A Registry object.
	 *
	 * @see     Registry
	 * @since   3.2
	 */
	public static function getParams($element, $strict = false)
	{
		return static::getLibrary($element, $strict)->params;
	}

	/**
	 * Save the parameters object for the library
	 *
	 * @param   string    $element  Element of the library in the extensions
table.
	 * @param   Registry  $params   Params to save
	 *
	 * @return  Registry  A Registry object.
	 *
	 * @see     Registry
	 * @since   3.2
	 */
	public static function saveParams($element, $params)
	{
		if (static::isEnabled($element))
		{
			// Save params in DB
			$db = \JFactory::getDbo();
			$query = $db->getQuery(true)
				->update($db->quoteName('#__extensions'))
				->set($db->quoteName('params') . ' = ' .
$db->quote($params->toString()))
				->where($db->quoteName('type') . ' = ' .
$db->quote('library'))
				->where($db->quoteName('element') . ' = ' .
$db->quote($element));
			$db->setQuery($query);

			$result = $db->execute();

			// Update params in libraries cache
			if ($result && isset(static::$libraries[$element]))
			{
				static::$libraries[$element]->params = $params;
			}

			return $result;
		}

		return false;
	}

	/**
	 * Load the installed library into the libraries property.
	 *
	 * @param   string  $element  The element value for the extension
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.2
	 * @deprecated  4.0  Use LibraryHelper::loadLibrary() instead
	 */
	protected static function _load($element)
	{
		return static::loadLibrary($element);
	}

	/**
	 * Load the installed library into the libraries property.
	 *
	 * @param   string  $element  The element value for the extension
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.7.0
	 */
	protected static function loadLibrary($element)
	{
		$loader = function($element)
		{
			$db = \JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName(array('extension_id',
'element', 'params', 'enabled'),
array('id', 'option', null, null)))
				->from($db->quoteName('#__extensions'))
				->where($db->quoteName('type') . ' = ' .
$db->quote('library'))
				->where($db->quoteName('element') . ' = ' .
$db->quote($element));
			$db->setQuery($query);

			return $db->loadObject();
		};

		/** @var \JCacheControllerCallback $cache */
		$cache = \JFactory::getCache('_system', 'callback');

		try
		{
			static::$libraries[$element] = $cache->get($loader, array($element),
__METHOD__ . $element);
		}
		catch (\JCacheException $e)
		{
			static::$libraries[$element] = $loader($element);
		}

		if (empty(static::$libraries[$element]))
		{
			// Fatal error.
			$error =
\JText::_('JLIB_APPLICATION_ERROR_LIBRARY_NOT_FOUND');
			\JLog::add(\JText::sprintf('JLIB_APPLICATION_ERROR_LIBRARY_NOT_LOADING',
$element, $error), \JLog::WARNING, 'jerror');

			return false;
		}

		return true;
	}
}
PK䛈[dpH+H+MediaHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Component\ComponentHelper;

/**
 * Media helper class
 *
 * @since  3.2
 */
class MediaHelper
{
	/**
	 * Checks if the file is an image
	 *
	 * @param   string  $fileName  The filename
	 *
	 * @return  boolean
	 *
	 * @since   3.2
	 */
	public function isImage($fileName)
	{
		static $imageTypes = 'xcf|odg|gif|jpg|png|bmp';

		return preg_match("/\.(?:$imageTypes)$/i", $fileName);
	}

	/**
	 * Gets the file extension for purposed of using an icon
	 *
	 * @param   string  $fileName  The filename
	 *
	 * @return  string  File extension to determine icon
	 *
	 * @since   3.2
	 */
	public static function getTypeIcon($fileName)
	{
		return strtolower(substr($fileName, strrpos($fileName, '.') +
1));
	}

	/**
	 * Get the Mime type
	 *
	 * @param   string   $file     The link to the file to be checked
	 * @param   boolean  $isImage  True if the passed file is an image else
false
	 *
	 * @return  mixed    the mime type detected false on error
	 *
	 * @since   3.7.2
	 */
	private function getMimeType($file, $isImage = false)
	{
		// If we can't detect anything mime is false
		$mime = false;

		try
		{
			if ($isImage && function_exists('exif_imagetype'))
			{
				$mime = image_type_to_mime_type(exif_imagetype($file));
			}
			elseif ($isImage && function_exists('getimagesize'))
			{
				$imagesize = getimagesize($file);
				$mime      = isset($imagesize['mime']) ?
$imagesize['mime'] : false;
			}
			elseif (function_exists('mime_content_type'))
			{
				// We have mime magic.
				$mime = mime_content_type($file);
			}
			elseif (function_exists('finfo_open'))
			{
				// We have fileinfo
				$finfo = finfo_open(FILEINFO_MIME_TYPE);
				$mime  = finfo_file($finfo, $file);
				finfo_close($finfo);
			}
		}
		catch (\Exception $e)
		{
			// If we have any kind of error here => false;
			return false;
		}

		// If we can't detect the mime try it again
		if ($mime === 'application/octet-stream' && $isImage
=== true)
		{
			$mime = $this->getMimeType($file, false);
		}

		// We have a mime here
		return $mime;
	}

	/**
	 * Checks the Mime type
	 *
	 * @param   string  $mime       The mime to be checked
	 * @param   string  $component  The optional name for the component
storing the parameters
	 *
	 * @return  boolean  true if mime type checking is disabled or it passes
the checks else false
	 *
	 * @since   3.7
	 */
	private function checkMimeType($mime, $component = 'com_media')
	{
		$params = ComponentHelper::getParams($component);

		if ($params->get('check_mime', 1))
		{
			// Get the mime type configuration
			$allowedMime = array_map('trim', explode(',',
$params->get('upload_mime')));

			// Mime should be available and in the whitelist
			return !empty($mime) && in_array($mime, $allowedMime);
		}

		// We don't check mime at all or it passes the checks
		return true;
	}

	/**
	 * Checks if the file can be uploaded
	 *
	 * @param   array   $file       File information
	 * @param   string  $component  The option name for the component storing
the parameters
	 *
	 * @return  boolean
	 *
	 * @since   3.2
	 */
	public function canUpload($file, $component = 'com_media')
	{
		$app    = \JFactory::getApplication();
		$params = ComponentHelper::getParams($component);

		if (empty($file['name']))
		{
			$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_UPLOAD_INPUT'),
'error');

			return false;
		}

		jimport('joomla.filesystem.file');

		if (str_replace(' ', '', $file['name']) !==
$file['name'] || $file['name'] !==
\JFile::makeSafe($file['name']))
		{
			$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILENAME'),
'error');

			return false;
		}

		$filetypes = explode('.', $file['name']);

		if (count($filetypes) < 2)
		{
			// There seems to be no extension
			$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILETYPE'),
'error');

			return false;
		}

		array_shift($filetypes);

		// Media file names should never have executable extensions buried in
them.
		$executable = array(
			'php', 'js', 'exe', 'phtml',
'java', 'perl', 'py', 'asp',
'dll', 'go', 'ade', 'adp',
'bat', 'chm', 'cmd', 'com',
'cpl', 'hta', 'ins', 'isp',
			'jse', 'lib', 'mde', 'msc',
'msp', 'mst', 'pif', 'scr',
'sct', 'shb', 'sys', 'vb',
'vbe', 'vbs', 'vxd', 'wsc',
'wsf', 'wsh',
		);

		$check = array_intersect($filetypes, $executable);

		if (!empty($check))
		{
			$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILETYPE'),
'error');

			return false;
		}

		$filetype  = array_pop($filetypes);
		$allowable = array_map('trim', explode(',',
$params->get('upload_extensions')));
		$ignored   = array_map('trim', explode(',',
$params->get('ignore_extensions')));

		if ($filetype == '' || $filetype == false ||
(!in_array($filetype, $allowable) && !in_array($filetype,
$ignored)))
		{
			$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILETYPE'),
'error');

			return false;
		}

		$maxSize = (int) ($params->get('upload_maxsize', 0) * 1024 *
1024);

		if ($maxSize > 0 && (int) $file['size'] >
$maxSize)
		{
			$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILETOOLARGE'),
'error');

			return false;
		}

		if ($params->get('restrict_uploads', 1))
		{
			$images = array_map('trim', explode(',',
$params->get('image_extensions')));

			if (in_array($filetype, $images))
			{
				// If tmp_name is empty, then the file was bigger than the PHP limit
				if (!empty($file['tmp_name']))
				{
					// Get the mime type this is an image file
					$mime = $this->getMimeType($file['tmp_name'], true);

					// Did we get anything useful?
					if ($mime != false)
					{
						$result = $this->checkMimeType($mime, $component);

						// If the mime type is not allowed we don't upload it and show
the mime code error to the user
						if ($result === false)
						{
							$app->enqueueMessage(\JText::sprintf('JLIB_MEDIA_ERROR_WARNINVALID_MIMETYPE',
$mime), 'error');

							return false;
						}
					}
					// We can't detect the mime type so it looks like an invalid
image
					else
					{
						$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNINVALID_IMG'),
'error');

						return false;
					}
				}
				else
				{
					$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILETOOLARGE'),
'error');

					return false;
				}
			}
			elseif (!in_array($filetype, $ignored))
			{
				// Get the mime type this is not an image file
				$mime = $this->getMimeType($file['tmp_name'], false);

				// Did we get anything useful?
				if ($mime != false)
				{
					$result = $this->checkMimeType($mime, $component);

					// If the mime type is not allowed we don't upload it and show
the mime code error to the user
					if ($result === false)
					{
						$app->enqueueMessage(\JText::sprintf('JLIB_MEDIA_ERROR_WARNINVALID_MIMETYPE',
$mime), 'error');

						return false;
					}
				}
				// We can't detect the mime type so it looks like an invalid file
				else
				{
					$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNINVALID_MIME'),
'error');

					return false;
				}

				if (!\JFactory::getUser()->authorise('core.manage',
$component))
				{
					$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNNOTADMIN'),
'error');

					return false;
				}
			}
		}

		$xss_check = file_get_contents($file['tmp_name'], false, null,
-1, 256);

		$html_tags = array(
			'abbr', 'acronym', 'address',
'applet', 'area', 'audioscope',
'base', 'basefont', 'bdo',
'bgsound', 'big', 'blackface',
'blink',
			'blockquote', 'body', 'bq',
'br', 'button', 'caption',
'center', 'cite', 'code', 'col',
'colgroup', 'comment', 'custom',
'dd', 'del',
			'dfn', 'dir', 'div', 'dl',
'dt', 'em', 'embed', 'fieldset',
'fn', 'font', 'form', 'frame',
'frameset', 'h1', 'h2', 'h3',
'h4', 'h5', 'h6',
			'head', 'hr', 'html', 'iframe',
'ilayer', 'img', 'input', 'ins',
'isindex', 'keygen', 'kbd',
'label', 'layer', 'legend', 'li',
'limittext',
			'link', 'listing', 'map',
'marquee', 'menu', 'meta',
'multicol', 'nobr', 'noembed',
'noframes', 'noscript', 'nosmartquotes',
'object',
			'ol', 'optgroup', 'option',
'param', 'plaintext', 'pre', 'rt',
'ruby', 's', 'samp', 'script',
'select', 'server', 'shadow',
'sidebar',
			'small', 'spacer', 'span',
'strike', 'strong', 'style', 'sub',
'sup', 'table', 'tbody', 'td',
'textarea', 'tfoot', 'th', 'thead',
'title',
			'tr', 'tt', 'ul', 'var',
'wbr', 'xml', 'xmp', '!DOCTYPE',
'!--',
		);

		foreach ($html_tags as $tag)
		{
			// A tag is '<tagname ', so we need to add < and a space
or '<tagname>'
			if (stripos($xss_check, '<' . $tag . ' ') !==
false || stripos($xss_check, '<' . $tag . '>')
!== false)
			{
				$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNIEXSS'),
'error');

				return false;
			}
		}

		return true;
	}

	/**
	 * Calculate the size of a resized image
	 *
	 * @param   integer  $width   Image width
	 * @param   integer  $height  Image height
	 * @param   integer  $target  Target size
	 *
	 * @return  array  The new width and height
	 *
	 * @since   3.2
	 */
	public static function imageResize($width, $height, $target)
	{
		/*
		 * Takes the larger size of the width and height and applies the
		 * formula accordingly. This is so this script will work
		 * dynamically with any size image
		 */
		if ($width > $height)
		{
			$percentage = ($target / $width);
		}
		else
		{
			$percentage = ($target / $height);
		}

		// Gets the new value and applies the percentage, then rounds the value
		$width  = round($width * $percentage);
		$height = round($height * $percentage);

		return array($width, $height);
	}

	/**
	 * Counts the files and directories in a directory that are not php or
html files.
	 *
	 * @param   string  $dir  Directory name
	 *
	 * @return  array  The number of media files and directories in the given
directory
	 *
	 * @since   3.2
	 */
	public function countFiles($dir)
	{
		$total_file = 0;
		$total_dir  = 0;

		if (is_dir($dir))
		{
			$d = dir($dir);

			while (($entry = $d->read()) !== false)
			{
				if ($entry[0] !== '.' && strpos($entry,
'.html') === false && strpos($entry, '.php')
=== false && is_file($dir . DIRECTORY_SEPARATOR . $entry))
				{
					$total_file++;
				}

				if ($entry[0] !== '.' && is_dir($dir .
DIRECTORY_SEPARATOR . $entry))
				{
					$total_dir++;
				}
			}

			$d->close();
		}

		return array($total_file, $total_dir);
	}

	/**
	 * Small helper function that properly converts any
	 * configuration options to their byte representation.
	 *
	 * @param   string|integer  $val  The value to be converted to bytes.
	 *
	 * @return integer The calculated bytes value from the input.
	 *
	 * @since 3.3
	 */
	public function toBytes($val)
	{
		switch ($val[strlen($val) - 1])
		{
			case 'M':
			case 'm':
				return (int) $val * 1048576;
			case 'K':
			case 'k':
				return (int) $val * 1024;
			case 'G':
			case 'g':
				return (int) $val * 1073741824;
			default:
				return $val;
		}
	}
}
PK䛈[��)�D�DModuleHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Language\LanguageHelper;
use Joomla\Registry\Registry;

/**
 * Module helper class
 *
 * @since  1.5
 */
abstract class ModuleHelper
{
	/**
	 * Get module by name (real, eg 'Breadcrumbs' or folder, eg
'mod_breadcrumbs')
	 *
	 * @param   string  $name   The name of the module
	 * @param   string  $title  The title of the module, optional
	 *
	 * @return  \stdClass  The Module object
	 *
	 * @since   1.5
	 */
	public static function &getModule($name, $title = null)
	{
		$result = null;
		$modules =& static::load();
		$total = count($modules);

		for ($i = 0; $i < $total; $i++)
		{
			// Match the name of the module
			if ($modules[$i]->name === $name || $modules[$i]->module ===
$name)
			{
				// Match the title if we're looking for a specific instance of the
module
				if (!$title || $modules[$i]->title === $title)
				{
					// Found it
					$result = &$modules[$i];
					break;
				}
			}
		}

		// If we didn't find it, and the name is mod_something, create a
dummy object
		if ($result === null && strpos($name, 'mod_') === 0)
		{
			$result            = new \stdClass;
			$result->id        = 0;
			$result->title     = '';
			$result->module    = $name;
			$result->position  = '';
			$result->content   = '';
			$result->showtitle = 0;
			$result->control   = '';
			$result->params    = '';
		}

		return $result;
	}

	/**
	 * Get modules by position
	 *
	 * @param   string  $position  The position of the module
	 *
	 * @return  array  An array of module objects
	 *
	 * @since   1.5
	 */
	public static function &getModules($position)
	{
		$position = strtolower($position);
		$result = array();
		$input  = \JFactory::getApplication()->input;

		$modules =& static::load();

		$total = count($modules);

		for ($i = 0; $i < $total; $i++)
		{
			if ($modules[$i]->position === $position)
			{
				$result[] = &$modules[$i];
			}
		}

		if (count($result) === 0)
		{
			if ($input->getBool('tp') &&
ComponentHelper::getParams('com_templates')->get('template_positions_display'))
			{
				$result[0] = static::getModule('mod_' . $position);
				$result[0]->title = $position;
				$result[0]->position = $position;
			}
		}

		return $result;
	}

	/**
	 * Checks if a module is enabled. A given module will only be returned
	 * if it meets the following criteria: it is enabled, it is assigned to
	 * the current menu item or all items, and the user meets the access level
	 * requirements.
	 *
	 * @param   string  $module  The module name
	 *
	 * @return  boolean See description for conditions.
	 *
	 * @since   1.5
	 */
	public static function isEnabled($module)
	{
		$result = static::getModule($module);

		return $result !== null && $result->id !== 0;
	}

	/**
	 * Render the module.
	 *
	 * @param   object  $module   A module object.
	 * @param   array   $attribs  An array of attributes for the module
(probably from the XML).
	 *
	 * @return  string  The HTML content of the module output.
	 *
	 * @since   1.5
	 */
	public static function renderModule($module, $attribs = array())
	{
		static $chrome;

		// Check that $module is a valid module object
		if (!is_object($module) || !isset($module->module) ||
!isset($module->params))
		{
			if (JDEBUG)
			{
				\JLog::addLogger(array('text_file' =>
'jmodulehelper.log.php'), \JLog::ALL,
array('modulehelper'));
				\JLog::add('ModuleHelper::renderModule($module) expects a module
object', \JLog::DEBUG, 'modulehelper');
			}

			return;
		}

		if (JDEBUG)
		{
			\JProfiler::getInstance('Application')->mark('beforeRenderModule
' . $module->module . ' (' . $module->title .
')');
		}

		$app = \JFactory::getApplication();

		// Record the scope.
		$scope = $app->scope;

		// Set scope to component name
		$app->scope = $module->module;

		// Get module parameters
		$params = new Registry($module->params);

		// Get the template
		$template = $app->getTemplate();

		// Get module path
		$module->module = preg_replace('/[^A-Z0-9_\.-]/i',
'', $module->module);
		$path = JPATH_BASE . '/modules/' . $module->module .
'/' . $module->module . '.php';

		// Load the module
		if (file_exists($path))
		{
			$lang = \JFactory::getLanguage();

			$coreLanguageDirectory      = JPATH_BASE;
			$extensionLanguageDirectory = dirname($path);

			$langPaths = $lang->getPaths();

			// Only load the module's language file if it hasn't been
already
			if (!$langPaths || (!isset($langPaths[$coreLanguageDirectory])
&& !isset($langPaths[$extensionLanguageDirectory])))
			{
				// 1.5 or Core then 1.6 3PD
				$lang->load($module->module, $coreLanguageDirectory, null, false,
true) ||
					$lang->load($module->module, $extensionLanguageDirectory, null,
false, true);
			}

			$content = '';
			ob_start();
			include $path;
			$module->content = ob_get_contents() . $content;
			ob_end_clean();
		}

		// Load the module chrome functions
		if (!$chrome)
		{
			$chrome = array();
		}

		include_once JPATH_THEMES . '/system/html/modules.php';
		$chromePath = JPATH_THEMES . '/' . $template .
'/html/modules.php';

		if (!isset($chrome[$chromePath]))
		{
			if (file_exists($chromePath))
			{
				include_once $chromePath;
			}

			$chrome[$chromePath] = true;
		}

		// Check if the current module has a style param to override template
module style
		$paramsChromeStyle = $params->get('style');

		if ($paramsChromeStyle)
		{
			$attribs['style'] = preg_replace('/^(system|' .
$template . ')\-/i', '', $paramsChromeStyle);
		}

		// Make sure a style is set
		if (!isset($attribs['style']))
		{
			$attribs['style'] = 'none';
		}

		// Dynamically add outline style
		if ($app->input->getBool('tp') &&
ComponentHelper::getParams('com_templates')->get('template_positions_display'))
		{
			$attribs['style'] .= ' outline';
		}

		// If the $module is nulled it will return an empty content, otherwise it
will render the module normally.
		$app->triggerEvent('onRenderModule', array(&$module,
&$attribs));

		if ($module === null || !isset($module->content))
		{
			return '';
		}

		foreach (explode(' ', $attribs['style']) as $style)
		{
			$chromeMethod = 'modChrome_' . $style;

			// Apply chrome and render module
			if (function_exists($chromeMethod))
			{
				$module->style = $attribs['style'];

				ob_start();
				$chromeMethod($module, $params, $attribs);
				$module->content = ob_get_contents();
				ob_end_clean();
			}
		}

		// Revert the scope
		$app->scope = $scope;

		$app->triggerEvent('onAfterRenderModule',
array(&$module, &$attribs));

		if (JDEBUG)
		{
			\JProfiler::getInstance('Application')->mark('afterRenderModule
' . $module->module . ' (' . $module->title .
')');
		}

		return $module->content;
	}

	/**
	 * Get the path to a layout for a module
	 *
	 * @param   string  $module  The name of the module
	 * @param   string  $layout  The name of the module layout. If alternative
layout, in the form template:filename.
	 *
	 * @return  string  The path to the module layout
	 *
	 * @since   1.5
	 */
	public static function getLayoutPath($module, $layout =
'default')
	{
		$template = \JFactory::getApplication()->getTemplate();
		$defaultLayout = $layout;

		if (strpos($layout, ':') !== false)
		{
			// Get the template and file name from the string
			$temp = explode(':', $layout);
			$template = $temp[0] === '_' ? $template : $temp[0];
			$layout = $temp[1];
			$defaultLayout = $temp[1] ?: 'default';
		}

		// Build the template and base path for the layout
		$tPath = JPATH_THEMES . '/' . $template . '/html/' .
$module . '/' . $layout . '.php';
		$bPath = JPATH_BASE . '/modules/' . $module .
'/tmpl/' . $defaultLayout . '.php';
		$dPath = JPATH_BASE . '/modules/' . $module .
'/tmpl/default.php';

		// If the template has a layout override use it
		if (file_exists($tPath))
		{
			return $tPath;
		}

		if (file_exists($bPath))
		{
			return $bPath;
		}

		return $dPath;
	}

	/**
	 * Load published modules.
	 *
	 * @return  array
	 *
	 * @since   1.5
	 * @deprecated  4.0  Use ModuleHelper::load() instead
	 */
	protected static function &_load()
	{
		return static::load();
	}

	/**
	 * Load published modules.
	 *
	 * @return  array
	 *
	 * @since   3.2
	 */
	protected static function &load()
	{
		static $modules;

		if (isset($modules))
		{
			return $modules;
		}

		$app = \JFactory::getApplication();

		$modules = null;

		$app->triggerEvent('onPrepareModuleList',
array(&$modules));

		// If the onPrepareModuleList event returns an array of modules, then
ignore the default module list creation
		if (!is_array($modules))
		{
			$modules = static::getModuleList();
		}

		$app->triggerEvent('onAfterModuleList',
array(&$modules));

		$modules = static::cleanModuleList($modules);

		$app->triggerEvent('onAfterCleanModuleList',
array(&$modules));

		return $modules;
	}

	/**
	 * Module list
	 *
	 * @return  array
	 */
	public static function getModuleList()
	{
		$app = \JFactory::getApplication();
		$Itemid = $app->input->getInt('Itemid', 0);
		$groups = implode(',',
\JFactory::getUser()->getAuthorisedViewLevels());
		$lang = \JFactory::getLanguage()->getTag();
		$clientId = (int) $app->getClientId();

		// Build a cache ID for the resulting data object
		$cacheId = $groups . '.' . $clientId . '.' . $Itemid;

		$db = \JFactory::getDbo();

		$query = $db->getQuery(true)
			->select('m.id, m.title, m.module, m.position, m.content,
m.showtitle, m.params, mm.menuid')
			->from('#__modules AS m')
			->join('LEFT', '#__modules_menu AS mm ON mm.moduleid =
m.id')
			->where('m.published = 1')
			->join('LEFT', '#__extensions AS e ON e.element =
m.module AND e.client_id = m.client_id')
			->where('e.enabled = 1');

		$date = \JFactory::getDate();
		$now = $date->toSql();
		$nullDate = $db->getNullDate();
		$query->where('(m.publish_up = ' . $db->quote($nullDate)
. ' OR m.publish_up <= ' . $db->quote($now) .
')')
			->where('(m.publish_down = ' . $db->quote($nullDate) .
' OR m.publish_down >= ' . $db->quote($now) .
')')
			->where('m.access IN (' . $groups . ')')
			->where('m.client_id = ' . $clientId)
			->where('(mm.menuid = ' . $Itemid . ' OR mm.menuid
<= 0)');

		// Filter by language
		if ($app->isClient('site') &&
$app->getLanguageFilter())
		{
			$query->where('m.language IN (' . $db->quote($lang) .
',' . $db->quote('*') . ')');
			$cacheId .= $lang . '*';
		}

		if ($app->isClient('administrator') &&
static::isAdminMultilang())
		{
			$query->where('m.language IN (' . $db->quote($lang) .
',' . $db->quote('*') . ')');
			$cacheId .= $lang . '*';
		}

		$query->order('m.position, m.ordering');

		// Set the query
		$db->setQuery($query);

		try
		{
			/** @var \JCacheControllerCallback $cache */
			$cache = \JFactory::getCache('com_modules',
'callback');

			$modules = $cache->get(array($db, 'loadObjectList'),
array(), md5($cacheId), false);
		}
		catch (\RuntimeException $e)
		{
			\JLog::add(\JText::sprintf('JLIB_APPLICATION_ERROR_MODULE_LOAD',
$e->getMessage()), \JLog::WARNING, 'jerror');

			return array();
		}

		return $modules;
	}

	/**
	 * Clean the module list
	 *
	 * @param   array  $modules  Array with module objects
	 *
	 * @return  array
	 */
	public static function cleanModuleList($modules)
	{
		// Apply negative selections and eliminate duplicates
		$Itemid =
\JFactory::getApplication()->input->getInt('Itemid');
		$negId = $Itemid ? -(int) $Itemid : false;
		$clean = array();
		$dupes = array();

		foreach ($modules as $i => $module)
		{
			// The module is excluded if there is an explicit prohibition
			$negHit = ($negId === (int) $module->menuid);

			if (isset($dupes[$module->id]))
			{
				// If this item has been excluded, keep the duplicate flag set,
				// but remove any item from the modules array.
				if ($negHit)
				{
					unset($clean[$module->id]);
				}

				continue;
			}

			$dupes[$module->id] = true;

			// Only accept modules without explicit exclusions.
			if ($negHit)
			{
				continue;
			}

			$module->name = substr($module->module, 4);
			$module->style = null;
			$module->position = strtolower($module->position);

			$clean[$module->id] = $module;
		}

		unset($dupes);

		// Return to simple indexing that matches the query order.
		return array_values($clean);
	}

	/**
	 * Module cache helper
	 *
	 * Caching modes:
	 * To be set in XML:
	 * 'static'      One cache file for all pages with the same
module parameters
	 * 'oldstatic'   1.5 definition of module caching, one cache
file for all pages
	 *               with the same module id and user aid,
	 * 'itemid'      Changes on itemid change, to be called from
inside the module:
	 * 'safeuri'     Id created from $cacheparams->modeparams
array,
	 * 'id'          Module sets own cache id's
	 *
	 * @param   object  $module        Module object
	 * @param   object  $moduleparams  Module parameters
	 * @param   object  $cacheparams   Module cache parameters - id or URL
parameters, depending on the module cache mode
	 *
	 * @return  string
	 *
	 * @see     \JFilterInput::clean()
	 * @since   1.6
	 */
	public static function moduleCache($module, $moduleparams, $cacheparams)
	{
		if (!isset($cacheparams->modeparams))
		{
			$cacheparams->modeparams = null;
		}

		if (!isset($cacheparams->cachegroup))
		{
			$cacheparams->cachegroup = $module->module;
		}

		$user = \JFactory::getUser();
		$conf = \JFactory::getConfig();

		/** @var \JCacheControllerCallback $cache */
		$cache = \JFactory::getCache($cacheparams->cachegroup,
'callback');

		// Turn cache off for internal callers if parameters are set to off and
for all logged in users
		$ownCacheDisabled = $moduleparams->get('owncache') === 0 ||
$moduleparams->get('owncache') === '0';
		$cacheDisabled = $moduleparams->get('cache') === 0 ||
$moduleparams->get('cache') === '0';

		if ($ownCacheDisabled || $cacheDisabled ||
$conf->get('caching') == 0 || $user->get('id'))
		{
			$cache->setCaching(false);
		}

		// Module cache is set in seconds, global cache in minutes, setLifeTime
works in minutes
		$cache->setLifeTime($moduleparams->get('cache_time',
$conf->get('cachetime') * 60) / 60);

		$wrkaroundoptions = array('nopathway' => 1,
'nohead' => 0, 'nomodules' => 1,
'modulemode' => 1, 'mergehead' => 1);

		$wrkarounds = true;
		$view_levels = md5(serialize($user->getAuthorisedViewLevels()));

		switch ($cacheparams->cachemode)
		{
			case 'id':
				$ret = $cache->get(
					array($cacheparams->class, $cacheparams->method),
					$cacheparams->methodparams,
					$cacheparams->modeparams,
					$wrkarounds,
					$wrkaroundoptions
				);
				break;

			case 'safeuri':
				$secureid = null;

				if (is_array($cacheparams->modeparams))
				{
					$input   = \JFactory::getApplication()->input;
					$uri     = $input->getArray();
					$safeuri = new \stdClass;
					$noHtmlFilter = \JFilterInput::getInstance();

					foreach ($cacheparams->modeparams as $key => $value)
					{
						// Use int filter for id/catid to clean out spamy slugs
						if (isset($uri[$key]))
						{
							$safeuri->$key = $noHtmlFilter->clean($uri[$key], $value);
						}
					}
				}

				$secureid = md5(serialize(array($safeuri, $cacheparams->method,
$moduleparams)));
				$ret = $cache->get(
					array($cacheparams->class, $cacheparams->method),
					$cacheparams->methodparams,
					$module->id . $view_levels . $secureid,
					$wrkarounds,
					$wrkaroundoptions
				);
				break;

			case 'static':
				$ret = $cache->get(
					array($cacheparams->class, $cacheparams->method),
					$cacheparams->methodparams,
					$module->module . md5(serialize($cacheparams->methodparams)),
					$wrkarounds,
					$wrkaroundoptions
				);
				break;

			// Provided for backward compatibility, not really useful.
			case 'oldstatic':
				$ret = $cache->get(
					array($cacheparams->class, $cacheparams->method),
					$cacheparams->methodparams,
					$module->id . $view_levels,
					$wrkarounds,
					$wrkaroundoptions
				);
				break;

			case 'itemid':
			default:
				$ret = $cache->get(
					array($cacheparams->class, $cacheparams->method),
					$cacheparams->methodparams,
					$module->id . $view_levels .
\JFactory::getApplication()->input->getInt('Itemid', null),
					$wrkarounds,
					$wrkaroundoptions
				);
				break;
		}

		return $ret;
	}

	/**
	 * Method to determine if filtering by language is enabled in back-end for
modules.
	 *
	 * @return  boolean  True if enabled; false otherwise.
	 *
	 * @since   3.8.0
	 */
	public static function isAdminMultilang()
	{
		static $enabled = false;

		if (count(LanguageHelper::getInstalledLanguages(1)) > 1)
		{
			$enabled = (bool)
ComponentHelper::getParams('com_modules')->get('adminlangfilter',
0);
		}

		return $enabled;
	}

	/**
	 * Get module by id
	 *
	 * @param   string  $id  The id of the module
	 *
	 * @return  \stdClass  The Module object
	 *
	 * @since   3.9.0
	 */
	public static function &getModuleById($id)
	{
		$modules =& static::load();

		$total = count($modules);

		for ($i = 0; $i < $total; $i++)
		{
			// Match the id of the module
			if ((string) $modules[$i]->id === $id)
			{
				// Found it
				return $modules[$i];
			}
		}

		// If we didn't find it, create a dummy object
		$result            = new \stdClass;
		$result->id        = 0;
		$result->title     = '';
		$result->module    = '';
		$result->position  = '';
		$result->content   = '';
		$result->showtitle = 0;
		$result->control   = '';
		$result->params    = '';

		return $result;
	}
}
PK䛈[F�q$$RouteHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Language\Multilanguage;

/**
 * Route Helper
 *
 * A class providing basic routing for urls that are for content types
found in
 * the #__content_types table and rows found in the #__ucm_content table.
 *
 * @since  3.1
 */
class RouteHelper
{
	/**
	 * @var    array  Holds the reverse lookup
	 * @since  3.1
	 */
	protected static $lookup;

	/**
	 * @var    string  Option for the extension (such as com_content)
	 * @since  3.1
	 */
	protected $extension;

	/**
	 * @var    string  Value of the primary key in the content type table
	 * @since  3.1
	 */
	protected $id;

	/**
	 * @var    string  Name of the view for the url
	 * @since  3.1
	 */
	protected $view;

	/**
	 * A method to get the route for a specific item
	 *
	 * @param   integer  $id         Value of the primary key for the item in
its content table
	 * @param   string   $typealias  The type_alias for the item being routed.
Of the form extension.view.
	 * @param   string   $link       The link to be routed
	 * @param   string   $language   The language of the content for
multilingual sites
	 * @param   integer  $catid      Optional category id
	 *
	 * @return  string  The route of the item
	 *
	 * @since   3.1
	 */
	public function getRoute($id, $typealias, $link = '', $language
= null, $catid = null)
	{
		$typeExploded = explode('.', $typealias);

		if (isset($typeExploded[1]))
		{
			$this->view = $typeExploded[1];
			$this->extension = $typeExploded[0];
		}
		else
		{
			$this->view =
\JFactory::getApplication()->input->getCmd('view');
			$this->extension =
\JFactory::getApplication()->input->getCmd('option');
		}

		$name = ucfirst(substr_replace($this->extension, '', 0, 4));

		$needles = array();

		if (isset($this->view))
		{
			$needles[$this->view] = array((int) $id);
		}

		if (empty($link))
		{
			// Create the link
			$link = 'index.php?option=' . $this->extension .
'&view=' . $this->view . '&id=' . $id;
		}

		if ($catid > 1)
		{
			$categories = \JCategories::getInstance($name);

			if ($categories)
			{
				$category = $categories->get((int) $catid);

				if ($category)
				{
					$needles['category'] =
array_reverse($category->getPath());
					$needles['categories'] = $needles['category'];
					$link .= '&catid=' . $catid;
				}
			}
		}

		// Deal with languages only if needed
		if (!empty($language) && $language !== '*' &&
Multilanguage::isEnabled())
		{
			$link .= '&lang=' . $language;
			$needles['language'] = $language;
		}

		if ($item = $this->findItem($needles))
		{
			$link .= '&Itemid=' . $item;
		}

		return $link;
	}

	/**
	 * Method to find the item in the menu structure
	 *
	 * @param   array  $needles  Array of lookup values
	 *
	 * @return  mixed
	 *
	 * @since   3.1
	 */
	protected function findItem($needles = array())
	{
		$app      = \JFactory::getApplication();
		$menus    = $app->getMenu('site');
		$language = isset($needles['language']) ?
$needles['language'] : '*';

		// $this->extension may not be set if coming from a static method,
check it
		if ($this->extension === null)
		{
			$this->extension = $app->input->getCmd('option');
		}

		// Prepare the reverse lookup array.
		if (!isset(static::$lookup[$language]))
		{
			static::$lookup[$language] = array();

			$component = ComponentHelper::getComponent($this->extension);

			$attributes = array('component_id');
			$values     = array($component->id);

			if ($language !== '*')
			{
				$attributes[] = 'language';
				$values[]     = array($needles['language'], '*');
			}

			$items = $menus->getItems($attributes, $values);

			foreach ($items as $item)
			{
				if (isset($item->query) &&
isset($item->query['view']))
				{
					$view = $item->query['view'];

					if (!isset(static::$lookup[$language][$view]))
					{
						static::$lookup[$language][$view] = array();
					}

					if (isset($item->query['id']))
					{
						if (is_array($item->query['id']))
						{
							$item->query['id'] =
$item->query['id'][0];
						}

						/*
						 * Here it will become a bit tricky
						 * $language != * can override existing entries
						 * $language == * cannot override existing entries
						 */
						if ($item->language !== '*' ||
!isset(static::$lookup[$language][$view][$item->query['id']]))
						{
							static::$lookup[$language][$view][$item->query['id']] =
$item->id;
						}
					}
				}
			}
		}

		if ($needles)
		{
			foreach ($needles as $view => $ids)
			{
				if (isset(static::$lookup[$language][$view]))
				{
					foreach ($ids as $id)
					{
						if (isset(static::$lookup[$language][$view][(int) $id]))
						{
							return static::$lookup[$language][$view][(int) $id];
						}
					}
				}
			}
		}

		$active = $menus->getActive();

		if ($active && $active->component === $this->extension
&& ($active->language === '*' ||
!Multilanguage::isEnabled()))
		{
			return $active->id;
		}

		// If not found, return language specific home link
		$default = $menus->getDefault($language);

		return !empty($default->id) ? $default->id : null;
	}

	/**
	 * Fetches the category route
	 *
	 * @param   mixed   $catid      Category ID or \JCategoryNode instance
	 * @param   mixed   $language   Language code
	 * @param   string  $extension  Extension to lookup
	 *
	 * @return  string
	 *
	 * @since   3.2
	 *
	 * @throws  \InvalidArgumentException
	 */
	public static function getCategoryRoute($catid, $language = 0, $extension
= '')
	{
		// Note: $extension is required but has to be an optional argument in the
function call due to argument order
		if (empty($extension))
		{
			throw new \InvalidArgumentException(sprintf('$extension is a
required argument in %s()', __METHOD__));
		}

		if ($catid instanceof \JCategoryNode)
		{
			$id       = $catid->id;
			$category = $catid;
		}
		else
		{
			$extensionName = ucfirst(substr($extension, 4));
			$id            = (int) $catid;
			$category      = \JCategories::getInstance($extensionName)->get($id);
		}

		if ($id < 1)
		{
			$link = '';
		}
		else
		{
			$link = 'index.php?option=' . $extension .
'&view=category&id=' . $id;

			$needles = array(
				'category' => array($id),
			);

			if ($language && $language !== '*' &&
Multilanguage::isEnabled())
			{
				$link .= '&lang=' . $language;
				$needles['language'] = $language;
			}

			// Create the link
			if ($category)
			{
				$catids                = array_reverse($category->getPath());
				$needles['category']   = $catids;
				$needles['categories'] = $catids;
			}

			if ($item = static::lookupItem($needles))
			{
				$link .= '&Itemid=' . $item;
			}
		}

		return $link;
	}

	/**
	 * Static alias to findItem() used to find the item in the menu structure
	 *
	 * @param   array  $needles  Array of lookup values
	 *
	 * @return  mixed
	 *
	 * @since   3.2
	 */
	protected static function lookupItem($needles = array())
	{
		$instance = new static;

		return $instance->findItem($needles);
	}
}
PK䛈[W�
�ooSearchHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Component\ComponentHelper;

/**
 * Helper class for Joomla! Search components
 *
 * @since  3.0
 */
class SearchHelper
{
	/**
	 * Method to log search terms to the database
	 *
	 * @param   string  $term       The term being searched
	 * @param   string  $component  The component being used for the search
	 *
	 * @return  void
	 *
	 * @since   3.0
	 */
	public static function logSearch($term, $component)
	{
		// Initialise our variables
		$db = \JFactory::getDbo();
		$query = $db->getQuery(true);
		$enable_log_searches =
ComponentHelper::getParams($component)->get('enabled');

		// Sanitise the term for the database
		$search_term = $db->escape(trim(strtolower($term)));

		if ($enable_log_searches)
		{
			// Query the table to determine if the term has been searched previously
			$query->select($db->quoteName('hits'))
				->from($db->quoteName('#__core_log_searches'))
				->where($db->quoteName('search_term') . ' = '
. $db->quote($search_term));
			$db->setQuery($query);
			$hits = (int) $db->loadResult();

			// Reset the $query object
			$query->clear();

			// Update the table based on the results
			if ($hits)
			{
				$query->update($db->quoteName('#__core_log_searches'))
					->set('hits = (hits + 1)')
					->where($db->quoteName('search_term') . ' =
' . $db->quote($search_term));
			}
			else
			{
				$query->insert($db->quoteName('#__core_log_searches'))
					->columns(array($db->quoteName('search_term'),
$db->quoteName('hits')))
					->values($db->quote($search_term) . ', 1');
			}

			// Execute the update query
			$db->setQuery($query);
			$db->execute();
		}
	}
}
PK䛈[R+�\v\vTagsHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Table\TableInterface;
use Joomla\Utilities\ArrayHelper;

/**
 * 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 = null;

	/**
	 * 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 =
array())
	{
		$db = $table->getDbo();
		$key = $table->getKeyName();
		$item = $table->$key;
		$typeId = $this->getTypeId($this->typeAlias);

		// Insert the new tag maps
		if (strpos('#', implode(',', $tags)) === false)
		{
			$tags = self::createTagsFromField($tags);
		}

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

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

		foreach ($tags as $tag)
		{
			$query->values(
				$db->quote($this->typeAlias)
				. ', ' . (int) $ucmId
				. ', ' . (int) $item
				. ', ' . $db->quote($tag)
				. ', ' . $query->currentTimestamp()
				. ', ' . (int) $typeId
			);
		}

		$db->setQuery($query);

		return (boolean) $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 = array();

			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_unique($aliases);

				$db = \JFactory::getDbo();

				$query = $db->getQuery(true)
					->select('alias, title')
					->from('#__tags')
					->where('alias IN (' . implode(',',
array_map(array($db, 'quote'), $aliases)) . ')');
				$db->setQuery($query);

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

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

						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;
		}
		else
		{
			// We will use the tags table to store them
			Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_tags/tables');
			$tagTable  = Table::getInstance('Tag', 'TagsTable');
			$newTags   = array();
			$canCreate = \JFactory::getUser()->authorise('core.create',
'com_tags');

			foreach ($tags as $key => $tag)
			{
				// User is not allowed to create tags, so don't create.
				if (!$canCreate && strpos($tag, '#new#') !== false)
				{
					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(array('title' => $tagText)))
					{
						$newTags[] = (int) $tagTable->id;
					}
					else
					{
						// Prepare tag data
						$tagTable->id = 0;
						$tagTable->title = $tagText;
						$tagTable->published = 1;

						// $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;
	}

	/**
	 * Create any new tags by looking for #new# in the metadata
	 *
	 * @param   string  $metadata  Metadata JSON string
	 *
	 * @return  mixed   If successful, metadata with new tag titles replaced
by tag ids. Otherwise false.
	 *
	 * @since   3.1
	 * @deprecated  4.0  This method is no longer used in the CMS and will not
be replaced.
	 */
	public function createTagsFromMetadata($metadata)
	{
		$metaObject = json_decode($metadata);

		if (empty($metaObject->tags))
		{
			return $metadata;
		}

		$tags = $metaObject->tags;

		if (empty($tags) || !is_array($tags))
		{
			$result = $metadata;
		}
		else
		{
			// We will use the tags table to store them
			Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_tags/tables');
			$tagTable = Table::getInstance('Tag', 'TagsTable');
			$newTags = array();

			foreach ($tags as $tag)
			{
				// 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(array('title' => $tagText)))
					{
						$newTags[] = (int) $tagTable->id;
					}
					else
					{
						// Prepare tag data
						$tagTable->id = 0;
						$tagTable->title = $tagText;
						$tagTable->published = 1;

						// $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
			$metaObject->tags = $newTags;
			$result = json_encode($metaObject);
		}

		return $result;
	}

	/**
	 * Method to delete the tag mappings and #__ucm_content record for 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 = array($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  \JTableCorecontent $ucmContentTable */
		$ucmContentTable = Table::getInstance('Corecontent');

		return $result &&
$ucmContentTable->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 of tag objects
	 *
	 * @since   3.1
	 */
	public function getItemTags($contentType, $id, $getTagData = true)
	{
		// Initialize some variables.
		$db = \JFactory::getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('m.tag_id'))
			->from($db->quoteName('#__contentitem_tag_map') . '
AS m ')
			->where(
				array(
					$db->quoteName('m.type_alias') . ' = ' .
$db->quote($contentType),
					$db->quoteName('m.content_item_id') . ' = ' .
(int) $id,
					$db->quoteName('t.published') . ' = 1',
				)
			);

		$user = \JFactory::getUser();
		$groups = implode(',', $user->getAuthorisedViewLevels());

		$query->where('t.access IN (' . $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->where($db->quoteName('language') . ' IN
(' . $db->quote($language) . ', ' .
$db->quote('*') . ')');
		}

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

		$query->join('INNER', $db->quoteName('#__tags')
. ' AS t ' . ' ON ' .
$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 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 = \JFactory::getDbo();

		// Load the tags.
		$query = $db->getQuery(true)
			->select($db->quoteName('t.id'))
			->from($db->quoteName('#__tags') . ' AS t ')
			->join(
				'INNER',
$db->quoteName('#__contentitem_tag_map') . ' AS m'
				. ' ON ' . $db->quoteName('m.tag_id') . ' =
' . $db->quoteName('t.id')
				. ' AND ' . $db->quoteName('m.type_alias') .
' = ' . $db->quote($prefix)
				. ' AND ' . $db->quoteName('m.content_item_id')
. ' IN ( ' . implode(',', $ids) . ')'
			);

		$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  \JDatabaseQuery  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 = \JFactory::getDbo();
		$query = $db->getQuery(true);
		$user = \JFactory::getUser();
		$nullDate = $db->quote($db->getNullDate());
		$nowDate = $db->quote(\JFactory::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 = array();

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

			$tagIds = 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(
				'm.type_alias'
				. ', ' . 'm.content_item_id'
				. ', ' . 'm.core_content_id'
				. ', ' . 'count(m.tag_id) AS match_count'
				. ', ' . 'MAX(m.tag_date) as tag_date'
				. ', ' . 'MAX(c.core_title) AS core_title'
				. ', ' . 'MAX(c.core_params) AS core_params'
			)
			->select('MAX(c.core_alias) AS core_alias, MAX(c.core_body) AS
core_body, MAX(c.core_state) AS core_state, MAX(c.core_access) AS
core_access')
			->select(
				'MAX(c.core_metadata) AS core_metadata'
				. ', ' . 'MAX(c.core_created_user_id) AS
core_created_user_id'
				. ', ' . 'MAX(c.core_created_by_alias) AS
core_created_by_alias'
			)
			->select('MAX(c.core_created_time) as core_created_time,
MAX(c.core_images) as core_images')
			->select('CASE WHEN c.core_modified_time = ' . $nullDate .
' THEN c.core_created_time ELSE c.core_modified_time END as
core_modified_time')
			->select('MAX(c.core_language) AS core_language,
MAX(c.core_catid) AS core_catid')
			->select('MAX(c.core_publish_up) AS core_publish_up,
MAX(c.core_publish_down) as core_publish_down')
			->select('MAX(ct.type_title) AS content_type_title,
MAX(ct.router) AS router')

			->from('#__contentitem_tag_map AS m')
			->join(
				'INNER',
				'#__ucm_content AS c ON m.type_alias = c.core_type_alias AND
m.core_content_id = c.core_content_id AND c.core_state IN ('
					. implode(',', $stateFilters) . ')'
					. (in_array('0', $stateFilters) ? '' : ' AND
(c.core_publish_up = ' . $nullDate
					. ' OR c.core_publish_up <= ' . $nowDate . ') '
					. ' AND (c.core_publish_down = ' . $nullDate . ' OR 
c.core_publish_down >= ' . $nowDate . ')')
			)
			->join('INNER', '#__content_types AS ct ON
ct.type_alias = m.type_alias')

			// Join over categories for get only tags from published categories
			->join('LEFT', '#__categories AS tc ON tc.id =
c.core_catid')

			// Join over the users for the author and email
			->select("CASE WHEN c.core_created_by_alias > ' '
THEN c.core_created_by_alias ELSE ua.name END AS author")
			->select('ua.email AS author_email')

			->join('LEFT', '#__users AS ua ON ua.id =
c.core_created_user_id')

			->where('m.tag_id IN (' . implode(',', $tagIds) .
')')
			->where('(c.core_catid = 0 OR tc.published = 1)');

		// Optionally filter on language
		if (empty($language))
		{
			$language = $languageFilter;
		}

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

			$query->where($db->quoteName('c.core_language') . '
IN (' . $db->quote($language) . ', ' .
$db->quote('*') . ')');
		}

		// Get the type data, limited to types in the request if there are any
specified.
		$typesarray = self::getTypes('assocList', $typesr, false);

		$typeAliases = array();

		foreach ($typesarray as $type)
		{
			$typeAliases[] = $db->quote($type['type_alias']);
		}

		$query->where('m.type_alias IN (' . implode(',',
$typeAliases) . ')');

		$groups = '0,' . implode(',',
array_unique($user->getAuthorisedViewLevels()));
		$query->where('c.core_access IN (' . $groups .
')')
			->group('m.type_alias, m.content_item_id, m.core_content_id,
core_modified_time, core_created_time, core_created_by_alias, author,
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('m.tag_id') = " . (int)
$ntagsr);
		}

		// Set up the order by using the option chosen
		if ($orderByOption === 'match_count')
		{
			$orderBy = 'COUNT(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 = array();

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

			$db = \JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('title'))
				->from($db->quoteName('#__tags'))
				->where($db->quoteName('id') . ' IN (' .
implode(',', $tagIds) . ')');
			$query->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 = array())
	{
		// Get a level row instance.
		Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_tags/tables');
		$table = Table::getInstance('Tag', 'TagsTable');

		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 the type id for a type alias.
	 *
	 * @param   string  $typeAlias  A type alias.
	 *
	 * @return  string  Name of the table for a type
	 *
	 * @since   3.1
	 * @deprecated  4.0  Use \JUcmType::getTypeId() instead
	 */
	public function getTypeId($typeAlias)
	{
		$contentType = new \JUcmType;

		return $contentType->getTypeId($typeAlias);
	}

	/**
	 * 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 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 of types
	 *
	 * @since   3.1
	 */
	public static function getTypes($arrayType = 'objectList',
$selectTypes = null, $useAlias = true)
	{
		// Initialize some variables.
		$db = \JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('*');

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

			if ($useAlias)
			{
				$selectTypes = array_map(array($db, 'quote'), $selectTypes);

				$query->where($db->quoteName('type_alias') . ' IN
(' . implode(',', $selectTypes) . ')');
			}
			else
			{
				$selectTypes = ArrayHelper::toInteger($selectTypes);

				$query->where($db->quoteName('type_id') . ' IN
(' . implode(',', $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
	 */
	public function postStoreProcess(TableInterface $table, $newTags =
array(), $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 == true)
			{
				// Delete all tags data
				$key = $table->getKeyName();
				$result = $this->deleteTagData($table, $table->$key);
			}
			else
			{
				// Process the tags
				$data = $this->getRowData($table);
				$ucmContentTable = Table::getInstance('Corecontent');

				$ucm = new \JUcmContent($table, $this->typeAlias);
				$ucmData = $data ? $ucm->mapData($data) : $ucm->ucmData;

				$primaryId =
$ucm->getPrimaryKey($ucmData['common']['core_type_id'],
$ucmData['common']['core_content_item_id']);
				$result = $ucmContentTable->load($primaryId);
				$result = $result &&
$ucmContentTable->bind($ucmData['common']);
				$result = $result && $ucmContentTable->check();
				$result = $result && $ucmContentTable->store();
				$ucmId = $ucmContentTable->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 = array())
	{
		if ($newTags != array())
		{
			$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 = array())
	{
		$db = \JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('a.id AS value')
			->select('a.path AS text')
			->select('a.path')
			->from('#__tags AS a')
			->join('LEFT', $db->quoteName('#__tags',
'b') . ' ON a.lft > b.lft AND a.rgt < b.rgt');

		// Filter language
		if (!empty($filters['flanguage']))
		{
			$query->where('a.language IN (' .
$db->quote($filters['flanguage']) . ',' .
$db->quote('*') . ') ');
		}

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

		// Search in title or path
		if (!empty($filters['like']))
		{
			$query->where(
				'(' . $db->quoteName('a.title') . ' LIKE
' . $db->quote('%' . $filters['like'] .
'%')
					. ' OR ' . $db->quoteName('a.path') . '
LIKE ' . $db->quote('%' . $filters['like'] .
'%') . ')'
			);
		}

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

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

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

		// Filter by parent_id
		if (isset($filters['parent_id']) &&
is_numeric($filters['parent_id']))
		{
			Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_tags/tables');
			$tagTable = Table::getInstance('Tag', 'TagsTable');

			if ($children = $tagTable->getTree($filters['parent_id']))
			{
				foreach ($children as $child)
				{
					$childrenIds[] = $child->id;
				}

				$query->where('a.id IN (' . implode(',',
$childrenIds) . ')');
			}
		}

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

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

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

		// 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)
	{
		// Delete the old tag maps.
		$db = \JFactory::getDbo();
		$query = $db->getQuery(true)
			->delete($db->quoteName('#__contentitem_tag_map'))
			->where($db->quoteName('tag_id') . ' = ' .
(int) $tagId);
		$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 = array(),
$replace = true)
	{
		$key = $table->get('_tbl_key');
		$oldTags = $this->getTagIds((int) $table->$key,
$this->typeAlias);
		$oldTags = explode(',', $oldTags);
		$result = $this->unTagItem($ucmId, $table);

		if ($replace)
		{
			$newTags = $tags;
		}
		else
		{
			if ($tags == array())
			{
				$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 =
array())
	{
		$key = $table->getKeyName();
		$id = $table->$key;
		$db = \JFactory::getDbo();
		$query = $db->getQuery(true)
			->delete('#__contentitem_tag_map')
			->where($db->quoteName('type_alias') . ' = ' .
$db->quote($this->typeAlias))
			->where($db->quoteName('content_item_id') . ' =
' . (int) $id);

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

			$query->where($db->quoteName('tag_id') . ' IN
(' . implode(',', $tags) . ')');
		}

		$db->setQuery($query);

		return (boolean) $db->execute();
	}
}
PK䛈[�xJ�//UserGroupsHelper.phpnu�[���<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Helper;

defined('JPATH_PLATFORM') or die;

/**
 * Helper to deal with user groups.
 *
 * @since  3.6.3
 */
final class UserGroupsHelper
{
	/**
	 * Indicates the current helper instance is the singleton instance.
	 *
	 * @var    integer
	 * @since  3.6.3
	 */
	const MODE_SINGLETON = 1;

	/**
	 * Indicates the current helper instance is a standalone class instance.
	 *
	 * @var    integer
	 * @since  3.6.3
	 */
	const MODE_INSTANCE = 2;

	/**
	 * Singleton instance.
	 *
	 * @var    array
	 * @since  3.6.3
	 */
	private static $instance;

	/**
	 * Available user groups
	 *
	 * @var    array
	 * @since  3.6.3
	 */
	private $groups = array();

	/**
	 * Mode this class is working: singleton or std instance
	 *
	 * @var    integer
	 * @since  3.6.3
	 */
	private $mode;

	/**
	 * Total available groups
	 *
	 * @var    integer
	 * @since  3.6.3
	 */
	private $total;

	/**
	 * Constructor
	 *
	 * @param   array    $groups  Array of groups
	 * @param   integer  $mode    Working mode for this class
	 *
	 * @since   3.6.3
	 */
	public function __construct(array $groups = array(), $mode =
self::MODE_INSTANCE)
	{
		$this->mode = (int) $mode;

		if ($groups)
		{
			$this->setGroups($groups);
		}
	}

	/**
	 * Count loaded user groups.
	 *
	 * @return  integer
	 *
	 * @since   3.6.3
	 */
	public function count()
	{
		return count($this->groups);
	}

	/**
	 * Get the helper instance.
	 *
	 * @return  self
	 *
	 * @since   3.6.3
	 */
	public static function getInstance()
	{
		if (static::$instance === null)
		{
			// Only here to avoid code style issues...
			$groups = array();

			static::$instance = new static($groups, static::MODE_SINGLETON);
		}

		return static::$instance;
	}

	/**
	 * Get a user group by its id.
	 *
	 * @param   integer  $id  Group identifier
	 *
	 * @return  mixed  stdClass on success. False otherwise
	 *
	 * @since   3.6.3
	 */
	public function get($id)
	{
		if ($this->has($id))
		{
			return $this->groups[$id];
		}

		// Singleton will load groups as they are requested
		if ($this->isSingleton())
		{
			$this->groups[$id] = $this->load($id);

			return $this->groups[$id];
		}

		return false;
	}

	/**
	 * Get the list of existing user groups.
	 *
	 * @return  array
	 *
	 * @since   3.6.3
	 */
	public function getAll()
	{
		if ($this->isSingleton() && $this->total() !==
$this->count())
		{
			$this->loadAll();
		}

		return $this->groups;
	}

	/**
	 * Check if a group is in the list.
	 *
	 * @param   integer  $id  Group identifier
	 *
	 * @return  boolean
	 *
	 * @since   3.6.3
	 */
	public function has($id)
	{
		return (array_key_exists($id, $this->groups) &&
$this->groups[$id] !== false);
	}

	/**
	 * Check if this instance is a singleton.
	 *
	 * @return  boolean
	 *
	 * @since   3.6.3
	 */
	private function isSingleton()
	{
		return $this->mode === static::MODE_SINGLETON;
	}

	/**
	 * Get total available user groups in database.
	 *
	 * @return  integer
	 *
	 * @since   3.6.3
	 */
	public function total()
	{
		if ($this->total === null)
		{
			$db = \JFactory::getDbo();

			$query = $db->getQuery(true)
				->select('count(id)')
				->from('#__usergroups');

			$db->setQuery($query);

			$this->total = (int) $db->loadResult();
		}

		return $this->total;
	}

	/**
	 * Load a group from database.
	 *
	 * @param   integer  $id  Group identifier
	 *
	 * @return  mixed
	 *
	 * @since   3.6.3
	 */
	public function load($id)
	{
		$db = \JFactory::getDbo();

		$query = $db->getQuery(true)
			->select('*')
			->from('#__usergroups')
			->where('id = ' . (int) $id);

		$db->setQuery($query);

		$group = $db->loadObject();

		if (!$group)
		{
			return false;
		}

		return $this->populateGroupData($group);
	}

	/**
	 * Load all user groups from the database.
	 *
	 * @return  self
	 *
	 * @since   3.6.3
	 */
	public function loadAll()
	{
		$this->groups = array();

		$db = \JFactory::getDbo();

		$query = $db->getQuery(true)
			->select('*')
			->from('#__usergroups')
			->order('lft ASC');

		$db->setQuery($query);

		$groups = $db->loadObjectList('id');

		$this->groups = $groups ?: array();
		$this->populateGroupsData();

		return $this;
	}

	/**
	 * Populates extra information for groups.
	 *
	 * @return  array
	 *
	 * @since   3.6.3
	 */
	private function populateGroupsData()
	{
		foreach ($this->groups as $group)
		{
			$this->populateGroupData($group);
		}

		return $this->groups;
	}

	/**
	 * Populate data for a specific user group.
	 *
	 * @param   \stdClass  $group  Group
	 *
	 * @return  \stdClass
	 *
	 * @since   3.6.3
	 */
	public function populateGroupData($group)
	{
		if (!$group || property_exists($group, 'path'))
		{
			return $group;
		}

		$parentId = (int) $group->parent_id;

		if ($parentId === 0)
		{
			$group->path = array($group->id);
			$group->level = 0;

			return $group;
		}

		$parentGroup = $this->has($parentId) ? $this->get($parentId) :
$this->load($parentId);

		if (!property_exists($parentGroup, 'path'))
		{
			$parentGroup = $this->populateGroupData($parentGroup);
		}

		$group->path = array_merge($parentGroup->path,
array($group->id));
		$group->level = count($group->path) - 1;

		return $group;
	}

	/**
	 * Set the groups to be used as source.
	 *
	 * @param   array  $groups  Array of user groups.
	 *
	 * @return  self
	 *
	 * @since   3.6.3
	 */
	public function setGroups(array $groups)
	{
		$this->groups = $groups;
		$this->populateGroupsData();
		$this->total  = count($groups);

		return $this;
	}
}
PK䛈[�@IAuthenticationHelper.phpnu�[���PK䛈[Q��
\CMSHelper.phpnu�[���PK䛈[��n!n!ContentHelper.phpnu�[���PK䛈[h���EE�3ContentHistoryHelper.phpnu�[���PK䛈[5�0	yyVFLibraryHelper.phpnu�[���PK䛈[dpH+H+YMediaHelper.phpnu�[���PK䛈[��)�D�D��ModuleHelper.phpnu�[���PK䛈[F�q$$��RouteHelper.phpnu�[���PK䛈[W�
�oo�SearchHelper.phpnu�[���PK䛈[R+�\v\v��TagsHelper.phpnu�[���PK䛈[�xJ�//ZdUserGroupsHelper.phpnu�[���PK�z