Файловый менеджер - Редактировать - /home/lmsyaran/public_html/pusher/Helper.zip
Назад
PK lE�[���S� � HelperFactoryAwareInterface.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Interface to be implemented by classes depending on a helper factory. * * @since 4.2.0 */ interface HelperFactoryAwareInterface { /** * Sets the helper factory to use. * * @param HelperFactory $helper The helper factory to use. * * @return void * * @since 4.2.0 */ public function setHelperFactory(HelperFactory $helper); } PK lE�[���( ( LibraryHelper.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use Joomla\CMS\Cache\CacheControllerFactoryInterface; use Joomla\CMS\Cache\Controller\CallbackController; use Joomla\CMS\Cache\Exception\CacheExceptionInterface; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; use Joomla\Database\DatabaseInterface; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Library helper class * * @since 3.2 */ class LibraryHelper { /** * The component list cache * * @var array * @since 3.2 */ protected static $libraries = []; /** * 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; $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|boolean A Registry object. * * @see Registry * @since 3.2 */ public static function saveParams($element, $params) { if (static::isEnabled($element)) { // Save params in DB $db = Factory::getContainer()->get(DatabaseInterface::class); $paramsString = $params->toString(); $query = $db->getQuery(true) ->update($db->quoteName('#__extensions')) ->set($db->quoteName('params') . ' = :params') ->where($db->quoteName('type') . ' = ' . $db->quote('library')) ->where($db->quoteName('element') . ' = :element') ->bind(':params', $paramsString) ->bind(':element', $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.7.0 */ protected static function loadLibrary($element) { $loader = function ($element) { $db = Factory::getContainer()->get(DatabaseInterface::class); $query = $db->getQuery(true) ->select($db->quoteName(['extension_id', 'element', 'params', 'enabled'], ['id', 'option', null, null])) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('library')) ->where($db->quoteName('element') . ' = :element') ->bind(':element', $element); $db->setQuery($query); return $db->loadObject(); }; /** @var CallbackController $cache */ $cache = Factory::getContainer()->get(CacheControllerFactoryInterface::class)->createCacheController('callback', ['defaultgroup' => '_system']); try { static::$libraries[$element] = $cache->get($loader, [$element], __METHOD__ . $element); } catch (CacheExceptionInterface $e) { static::$libraries[$element] = $loader($element); } if (empty(static::$libraries[$element])) { // Fatal error. $error = Text::_('JLIB_APPLICATION_ERROR_LIBRARY_NOT_FOUND'); Log::add(Text::sprintf('JLIB_APPLICATION_ERROR_LIBRARY_NOT_LOADING', $element, $error), Log::WARNING, 'jerror'); return false; } return true; } } PK lE�[�o�3� 3� TagsHelper.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Table\CoreContent; use Joomla\CMS\Table\Table; use Joomla\CMS\Table\TableInterface; use Joomla\CMS\UCM\UCMContent; use Joomla\CMS\UCM\UCMType; use Joomla\Database\DatabaseInterface; use Joomla\Database\ParameterType; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Tags helper class, provides methods to perform various tasks relevant * tagging of content. * * @since 3.1 */ class TagsHelper extends CMSHelper { /** * Helper object for storing and deleting tag information. * * @var boolean * @since 3.1 */ protected $tagsChanged = false; /** * Whether up replace all tags or just add tags * * @var boolean * @since 3.1 */ protected $replaceTags = false; /** * Alias for querying mapping and content type table. * * @var string * @since 3.1 */ public $typeAlias; /** * Array of item tags. * * @var array * @since 3.1 */ public $itemTags; /** * The tags as comma separated string or array. * * @var mixed * @since 4.3.0 */ public $tags; /** * The new tags as comma separated string or array. * * @var mixed * @since 4.3.0 */ public $newTags; /** * The old tags as comma separated string or array. * * @var mixed * @since 4.3.0 */ public $oldTags; /** * Method to add tag rows to mapping table. * * @param integer $ucmId ID of the #__ucm_content item being tagged * @param TableInterface $table Table object being tagged * @param array $tags Array of tags to be applied. * * @return boolean true on success, otherwise false. * * @since 3.1 */ public function addTagMapping($ucmId, TableInterface $table, $tags = []) { $db = $table->getDbo(); $key = $table->getKeyName(); $item = $table->$key; $ucm = new UCMType($this->typeAlias, $db); $typeId = $ucm->getTypeId(); // Insert the new tag maps if (strpos(implode(',', $tags), '#') !== false) { $tags = self::createTagsFromField($tags); } // Prevent saving duplicate tags $tags = array_values(array_unique($tags)); if (!$tags) { return true; } $query = $db->getQuery(true); $query->insert('#__contentitem_tag_map'); $query->columns( [ $db->quoteName('core_content_id'), $db->quoteName('content_item_id'), $db->quoteName('tag_id'), $db->quoteName('type_id'), $db->quoteName('type_alias'), $db->quoteName('tag_date'), ] ); foreach ($tags as $tag) { $query->values( implode( ',', array_merge( $query->bindArray([(int) $ucmId, (int) $item, (int) $tag, (int) $typeId]), $query->bindArray([$this->typeAlias], ParameterType::STRING), [$query->currentTimestamp()] ) ) ); } $db->setQuery($query); return (bool) $db->execute(); } /** * Function that converts tags paths into paths of names * * @param array $tags Array of tags * * @return array * * @since 3.1 */ public static function convertPathsToNames($tags) { // We will replace path aliases with tag names if ($tags) { // Create an array with all the aliases of the results $aliases = []; foreach ($tags as $tag) { if (!empty($tag->path)) { if ($pathParts = explode('/', $tag->path)) { $aliases = array_merge($aliases, $pathParts); } } } // Get the aliases titles in one single query and map the results if ($aliases) { // Remove duplicates $aliases = array_values(array_unique($aliases)); $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( [ $db->quoteName('alias'), $db->quoteName('title'), ] ) ->from($db->quoteName('#__tags')) ->whereIn($db->quoteName('alias'), $aliases, ParameterType::STRING); $db->setQuery($query); try { $aliasesMapper = $db->loadAssocList('alias'); } catch (\RuntimeException $e) { return false; } // Rebuild the items path if ($aliasesMapper) { foreach ($tags as $tag) { $namesPath = []; if (!empty($tag->path)) { if ($pathParts = explode('/', $tag->path)) { foreach ($pathParts as $alias) { if (isset($aliasesMapper[$alias])) { $namesPath[] = $aliasesMapper[$alias]['title']; } else { $namesPath[] = $alias; } } $tag->text = implode('/', $namesPath); } } } } } } return $tags; } /** * Create any new tags by looking for #new# in the strings * * @param array $tags Tags text array from the field * * @return mixed If successful, metadata with new tag titles replaced by tag ids. Otherwise false. * * @since 3.1 */ public function createTagsFromField($tags) { if (empty($tags) || $tags[0] == '') { return; } // We will use the tags table to store them $tagTable = Factory::getApplication()->bootComponent('com_tags')->getMVCFactory()->createTable('Tag', 'Administrator'); $newTags = []; $canCreate = Factory::getUser()->authorise('core.create', 'com_tags'); foreach ($tags as $key => $tag) { // User is not allowed to create tags, so don't create. if (!$canCreate && 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(['title' => $tagText])) { $newTags[] = (int) $tagTable->id; } else { // Prepare tag data $tagTable->id = 0; $tagTable->title = $tagText; $tagTable->published = 1; $tagTable->description = ''; // $tagTable->language = property_exists ($item, 'language') ? $item->language : '*'; $tagTable->language = '*'; $tagTable->access = 1; // Make this item a child of the root tag $tagTable->setLocation($tagTable->getRootId(), 'last-child'); // Try to store tag if ($tagTable->check()) { // Assign the alias as path (autogenerated tags have always level 1) $tagTable->path = $tagTable->alias; if ($tagTable->store()) { $newTags[] = (int) $tagTable->id; } } } } } // At this point $tags is an array of all tag ids $this->tags = $newTags; $result = $newTags; return $result; } /** * Method to delete the tag mappings and #__ucm_content record for an item * * @param TableInterface $table Table object of content table where delete occurred * @param integer|array $contentItemId ID of the content item. Or an array of key/value pairs with array key * being a primary key name and value being the content item ID. Note * multiple primary keys are not supported * * @return boolean true on success, false on failure * * @since 3.1 * @throws \InvalidArgumentException */ public function deleteTagData(TableInterface $table, $contentItemId) { $key = $table->getKeyName(); if (!\is_array($contentItemId)) { $contentItemId = [$key => $contentItemId]; } // If we have multiple items for the content item primary key we currently don't support this so // throw an InvalidArgumentException for now if (\count($contentItemId) != 1) { throw new \InvalidArgumentException('Multiple primary keys are not supported as a content item id'); } $result = $this->unTagItem($contentItemId[$key], $table); /** @var CoreContent $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 tag objects * * @since 3.1 */ public function getItemTags($contentType, $id, $getTagData = true) { // Cast as integer until method is typehinted. $id = (int) $id; // Initialize some variables. $db = Factory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('m.tag_id')) ->from($db->quoteName('#__contentitem_tag_map', 'm')) ->where( [ $db->quoteName('m.type_alias') . ' = :contentType', $db->quoteName('m.content_item_id') . ' = :id', $db->quoteName('t.published') . ' = 1', ] ) ->bind(':contentType', $contentType) ->bind(':id', $id, ParameterType::INTEGER); $user = Factory::getUser(); $groups = $user->getAuthorisedViewLevels(); $query->whereIn($db->quoteName('t.access'), $groups); // Optionally filter on language $language = ComponentHelper::getParams('com_tags')->get('tag_list_language_filter', 'all'); if ($language !== 'all') { if ($language === 'current_language') { $language = $this->getCurrentLanguage(); } $query->whereIn($db->quoteName('language'), [$language, '*'], ParameterType::STRING); } if ($getTagData) { $query->select($db->quoteName('t') . '.*'); } $query->join('INNER', $db->quoteName('#__tags', 't'), $db->quoteName('m.tag_id') . ' = ' . $db->quoteName('t.id')); $db->setQuery($query); $this->itemTags = $db->loadObjectList(); return $this->itemTags; } /** * Method to get a list of tags for multiple items, optionally with the tag data. * * @param string $contentType Content type alias. Dot separated. * @param array $ids Id of the item to retrieve tags for. * @param boolean $getTagData If true, data from the tags table will be included, defaults to true. * * @return array Array of tag objects grouped by Id. * * @since 4.2.0 */ public function getMultipleItemTags($contentType, array $ids, $getTagData = true) { $data = []; $ids = array_map('intval', $ids); /** @var DatabaseInterface $db */ $db = Factory::getContainer()->get(DatabaseInterface::class); $query = $db->getQuery(true) ->select($db->quoteName(['m.tag_id', 'm.content_item_id'])) ->from($db->quoteName('#__contentitem_tag_map', 'm')) ->where( [ $db->quoteName('m.type_alias') . ' = :contentType', $db->quoteName('t.published') . ' = 1', ] ) ->whereIn($db->quoteName('m.content_item_id'), $ids) ->bind(':contentType', $contentType); $query->join('INNER', $db->quoteName('#__tags', 't'), $db->quoteName('m.tag_id') . ' = ' . $db->quoteName('t.id')); $groups = Factory::getUser()->getAuthorisedViewLevels(); $query->whereIn($db->quoteName('t.access'), $groups); // Optionally filter on language $language = ComponentHelper::getParams('com_tags')->get('tag_list_language_filter', 'all'); if ($language !== 'all') { if ($language === 'current_language') { $language = $this->getCurrentLanguage(); } $query->whereIn($db->quoteName('language'), [$language, '*'], ParameterType::STRING); } if ($getTagData) { $query->select($db->quoteName('t') . '.*'); } $db->setQuery($query); $rows = $db->loadObjectList(); // Group data by item Id. foreach ($rows as $row) { $data[$row->content_item_id][] = $row; unset($row->content_item_id); } return $data; } /** * Method to get a list of tags for a given item. * Normally used for displaying a list of tags within a layout * * @param mixed $ids The id or array of ids (primary key) of the item to be tagged. * @param string $prefix Dot separated string with the option and view to be used for a url. * * @return string Comma separated list of tag Ids. * * @since 3.1 */ public function getTagIds($ids, $prefix) { if (empty($ids)) { return; } /** * Ids possible formats: * --------------------- * $id = 1; * $id = array(1,2); * $id = array('1,3,4,19'); * $id = '1,3'; */ $ids = (array) $ids; $ids = implode(',', $ids); $ids = explode(',', $ids); $ids = ArrayHelper::toInteger($ids); $db = Factory::getDbo(); // Load the tags. $query = $db->getQuery(true) ->select($db->quoteName('t.id')) ->from($db->quoteName('#__tags', 't')) ->join('INNER', $db->quoteName('#__contentitem_tag_map', 'm'), $db->quoteName('m.tag_id') . ' = ' . $db->quoteName('t.id')) ->where($db->quoteName('m.type_alias') . ' = :prefix') ->whereIn($db->quoteName('m.content_item_id'), $ids) ->bind(':prefix', $prefix); $db->setQuery($query); // Add the tags to the content data. $tagsList = $db->loadColumn(); $this->tags = implode(',', $tagsList); return $this->tags; } /** * Method to get a query to retrieve a detailed list of items for a tag. * * @param mixed $tagId Tag or array of tags to be matched * @param mixed $typesr Null, type or array of type aliases for content types to be included in the results * @param boolean $includeChildren True to include the results from child tags * @param string $orderByOption Column to order the results by * @param string $orderDir Direction to sort the results in * @param boolean $anyOrAll True to include items matching at least one tag, false to include * items all tags in the array. * @param string $languageFilter Optional filter on language. Options are 'all', 'current' or any string. * @param string $stateFilter Optional filtering on publication state, defaults to published or unpublished. * * @return \Joomla\Database\DatabaseQuery Query to retrieve a list of tags * * @since 3.1 */ public function getTagItemsQuery( $tagId, $typesr = null, $includeChildren = false, $orderByOption = 'c.core_title', $orderDir = 'ASC', $anyOrAll = true, $languageFilter = 'all', $stateFilter = '0,1' ) { // Create a new query object. $db = Factory::getDbo(); $query = $db->getQuery(true); $user = Factory::getUser(); $nullDate = $db->getNullDate(); $nowDate = Factory::getDate()->toSql(); // Force ids to array and sanitize $tagIds = (array) $tagId; $tagIds = implode(',', $tagIds); $tagIds = explode(',', $tagIds); $tagIds = ArrayHelper::toInteger($tagIds); $ntagsr = \count($tagIds); // If we want to include children we have to adjust the list of tags. // We do not search child tags when the match all option is selected. if ($includeChildren) { $tagTreeArray = []; foreach ($tagIds as $tag) { $this->getTagTreeArray($tag, $tagTreeArray); } $tagIds = array_values(array_unique(array_merge($tagIds, $tagTreeArray))); } // Sanitize filter states $stateFilters = explode(',', $stateFilter); $stateFilters = ArrayHelper::toInteger($stateFilters); // M is the mapping table. C is the core_content table. Ct is the content_types table. $query->select( [ $db->quoteName('m.type_alias'), $db->quoteName('m.content_item_id'), $db->quoteName('m.core_content_id'), 'COUNT(' . $db->quoteName('m.tag_id') . ') AS ' . $db->quoteName('match_count'), 'MAX(' . $db->quoteName('m.tag_date') . ') AS ' . $db->quoteName('tag_date'), 'MAX(' . $db->quoteName('c.core_title') . ') AS ' . $db->quoteName('core_title'), 'MAX(' . $db->quoteName('c.core_params') . ') AS ' . $db->quoteName('core_params'), 'MAX(' . $db->quoteName('c.core_alias') . ') AS ' . $db->quoteName('core_alias'), 'MAX(' . $db->quoteName('c.core_body') . ') AS ' . $db->quoteName('core_body'), 'MAX(' . $db->quoteName('c.core_state') . ') AS ' . $db->quoteName('core_state'), 'MAX(' . $db->quoteName('c.core_access') . ') AS ' . $db->quoteName('core_access'), 'MAX(' . $db->quoteName('c.core_metadata') . ') AS ' . $db->quoteName('core_metadata'), 'MAX(' . $db->quoteName('c.core_created_user_id') . ') AS ' . $db->quoteName('core_created_user_id'), 'MAX(' . $db->quoteName('c.core_created_by_alias') . ') AS' . $db->quoteName('core_created_by_alias'), 'MAX(' . $db->quoteName('c.core_created_time') . ') AS ' . $db->quoteName('core_created_time'), 'MAX(' . $db->quoteName('c.core_images') . ') AS ' . $db->quoteName('core_images'), 'CASE WHEN ' . $db->quoteName('c.core_modified_time') . ' = :nullDate THEN ' . $db->quoteName('c.core_created_time') . ' ELSE ' . $db->quoteName('c.core_modified_time') . ' END AS ' . $db->quoteName('core_modified_time'), 'MAX(' . $db->quoteName('c.core_language') . ') AS ' . $db->quoteName('core_language'), 'MAX(' . $db->quoteName('c.core_catid') . ') AS ' . $db->quoteName('core_catid'), 'MAX(' . $db->quoteName('c.core_publish_up') . ') AS ' . $db->quoteName('core_publish_up'), 'MAX(' . $db->quoteName('c.core_publish_down') . ') AS ' . $db->quoteName('core_publish_down'), 'MAX(' . $db->quoteName('ct.type_title') . ') AS ' . $db->quoteName('content_type_title'), 'MAX(' . $db->quoteName('ct.router') . ') AS ' . $db->quoteName('router'), 'CASE WHEN ' . $db->quoteName('c.core_created_by_alias') . ' > ' . $db->quote(' ') . ' THEN ' . $db->quoteName('c.core_created_by_alias') . ' ELSE ' . $db->quoteName('ua.name') . ' END AS ' . $db->quoteName('author'), $db->quoteName('ua.email', 'author_email'), ] ) ->bind(':nullDate', $nullDate) ->from($db->quoteName('#__contentitem_tag_map', 'm')) ->join( 'INNER', $db->quoteName('#__ucm_content', 'c'), $db->quoteName('m.type_alias') . ' = ' . $db->quoteName('c.core_type_alias') . ' AND ' . $db->quoteName('m.core_content_id') . ' = ' . $db->quoteName('c.core_content_id') ) ->join('INNER', $db->quoteName('#__content_types', 'ct'), $db->quoteName('ct.type_alias') . ' = ' . $db->quoteName('m.type_alias')); // Join over categories to get only tags from published categories $query->join('LEFT', $db->quoteName('#__categories', 'tc'), $db->quoteName('tc.id') . ' = ' . $db->quoteName('c.core_catid')); // Join over the users for the author and email $query->join('LEFT', $db->quoteName('#__users', 'ua'), $db->quoteName('ua.id') . ' = ' . $db->quoteName('c.core_created_user_id')) ->whereIn($db->quoteName('c.core_state'), $stateFilters) ->whereIn($db->quoteName('m.tag_id'), $tagIds) ->extendWhere( 'AND', [ $db->quoteName('c.core_catid') . ' = 0', $db->quoteName('tc.published') . ' = 1', ], 'OR' ); // Get the type data, limited to types in the request if there are any specified. $typesarray = self::getTypes('assocList', $typesr, false); $typeAliases = array_column($typesarray, 'type_alias'); $query->whereIn($db->quoteName('m.type_alias'), $typeAliases, ParameterType::STRING); $groups = array_values(array_unique($user->getAuthorisedViewLevels())); $groups[] = 0; $query->whereIn($db->quoteName('c.core_access'), $groups); if (!\in_array(0, $stateFilters, true)) { $query->extendWhere( 'AND', [ $db->quoteName('c.core_publish_up') . ' = :nullDate1', $db->quoteName('c.core_publish_up') . ' IS NULL', $db->quoteName('c.core_publish_up') . ' <= :nowDate1', ], 'OR' ) ->extendWhere( 'AND', [ $db->quoteName('c.core_publish_down') . ' = :nullDate2', $db->quoteName('c.core_publish_down') . ' IS NULL', $db->quoteName('c.core_publish_down') . ' >= :nowDate2', ], 'OR' ) ->bind([':nullDate1', ':nullDate2'], $nullDate) ->bind([':nowDate1', ':nowDate2'], $nowDate); } // Optionally filter on language if ($languageFilter !== 'all') { if ($languageFilter === 'current_language') { $languageFilter = $this->getCurrentLanguage(); } $query->whereIn($db->quoteName('c.core_language'), [$languageFilter, '*'], ParameterType::STRING); } $query->group( [ $db->quoteName('m.type_alias'), $db->quoteName('m.content_item_id'), $db->quoteName('m.core_content_id'), $db->quoteName('core_modified_time'), $db->quoteName('core_created_time'), $db->quoteName('core_created_by_alias'), $db->quoteName('author'), $db->quoteName('author_email'), ] ); // Use HAVING if matching all tags and we are matching more than one tag. if ($ntagsr > 1 && $anyOrAll != 1 && $includeChildren != 1) { // The number of results should equal the number of tags requested. $query->having('COUNT(' . $db->quoteName('m.tag_id') . ') = :ntagsr') ->bind(':ntagsr', $ntagsr, ParameterType::INTEGER); } // Set up the order by using the option chosen if ($orderByOption === 'match_count') { $orderBy = 'COUNT(' . $db->quoteName('m.tag_id') . ')'; } else { $orderBy = 'MAX(' . $db->quoteName($orderByOption) . ')'; } $query->order($orderBy . ' ' . $orderDir); return $query; } /** * Function that converts tag ids to their tag names * * @param array $tagIds Array of integer tag ids. * * @return array An array of tag names. * * @since 3.1 */ public function getTagNames($tagIds) { $tagNames = []; if (\is_array($tagIds) && \count($tagIds) > 0) { $tagIds = ArrayHelper::toInteger($tagIds); $db = Factory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('title')) ->from($db->quoteName('#__tags')) ->whereIn($db->quoteName('id'), $tagIds) ->order($db->quoteName('title')); $db->setQuery($query); $tagNames = $db->loadColumn(); } return $tagNames; } /** * Method to get an array of tag ids for the current tag and its children * * @param integer $id An optional ID * @param array &$tagTreeArray Array containing the tag tree * * @return mixed * * @since 3.1 */ public function getTagTreeArray($id, &$tagTreeArray = []) { // Get a level row instance. $table = Factory::getApplication()->bootComponent('com_tags')->getMVCFactory()->createTable('Tag', 'Administrator'); if ($table->isLeaf($id)) { $tagTreeArray[] = $id; return $tagTreeArray; } $tagTree = $table->getTree($id); // Attempt to load the tree if ($tagTree) { foreach ($tagTree as $tag) { $tagTreeArray[] = $tag->id; } return $tagTreeArray; } } /** * Method to get a list of types with associated data. * * @param string $arrayType Optionally specify that the returned list consist of objects, associative arrays, or arrays. * Options are: rowList, assocList, and objectList * @param array $selectTypes Optional array of type ids or aliases to limit the results to. Often from a request. * @param boolean $useAlias If true, the alias is used to match, if false the type_id is used. * * @return array Array of types * * @since 3.1 */ public static function getTypes($arrayType = 'objectList', $selectTypes = null, $useAlias = true) { // Initialize some variables. $db = Factory::getDbo(); $query = $db->getQuery(true) ->select('*'); if (!empty($selectTypes)) { $selectTypes = (array) $selectTypes; if ($useAlias) { $query->whereIn($db->quoteName('type_alias'), $selectTypes, ParameterType::STRING); } else { $selectTypes = ArrayHelper::toInteger($selectTypes); $query->whereIn($db->quoteName('type_id'), $selectTypes); } } $query->from($db->quoteName('#__content_types')); $db->setQuery($query); switch ($arrayType) { case 'assocList': $types = $db->loadAssocList(); break; case 'rowList': $types = $db->loadRowList(); break; case 'objectList': default: $types = $db->loadObjectList(); break; } return $types; } /** * Function that handles saving tags used in a table class after a store() * * @param TableInterface $table Table being processed * @param array $newTags Array of new tags * @param boolean $replace Flag indicating if all existing tags should be replaced * * @return boolean * * @since 3.1 */ public function postStoreProcess(TableInterface $table, $newTags = [], $replace = true) { if (!empty($table->newTags) && empty($newTags)) { $newTags = $table->newTags; } // If existing row, check to see if tags have changed. $newTable = clone $table; $newTable->reset(); $result = true; // Process ucm_content and ucm_base if either tags have changed or we have some tags. if ($this->tagsChanged || (!empty($newTags) && $newTags[0] != '')) { if (!$newTags && $replace == 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 UCMContent($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 = []) { if ($newTags != []) { $this->newTags = $newTags; } // If existing row, check to see if tags have changed. $oldTable = clone $table; $oldTable->reset(); $key = $oldTable->getKeyName(); $typeAlias = $this->typeAlias; if ($oldTable->$key && $oldTable->load()) { $this->oldTags = $this->getTagIds($oldTable->$key, $typeAlias); } // New items with no tags bypass this step. if ((!empty($newTags) && \is_string($newTags) || (isset($newTags[0]) && $newTags[0] != '')) || isset($this->oldTags)) { if (\is_array($newTags)) { $newTags = implode(',', $newTags); } // We need to process tags if the tags have changed or if we have a new row $this->tagsChanged = (empty($this->oldTags) && !empty($newTags)) || (!empty($this->oldTags) && $this->oldTags != $newTags) || !$table->$key; } } /** * Function to search tags * * @param array $filters Filter to apply to the search * * @return array * * @since 3.1 */ public static function searchTags($filters = []) { $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( [ $db->quoteName('a.id', 'value'), $db->quoteName('a.path', 'text'), $db->quoteName('a.path'), ] ) ->from($db->quoteName('#__tags', 'a')) ->join( 'LEFT', $db->quoteName('#__tags', 'b'), $db->quoteName('a.lft') . ' > ' . $db->quoteName('b.lft') . ' AND ' . $db->quoteName('a.rgt') . ' < ' . $db->quoteName('b.rgt') ); // Do not return root $query->where($db->quoteName('a.alias') . ' <> ' . $db->quote('root')); // Filter language if (!empty($filters['flanguage'])) { $query->whereIn($db->quoteName('a.language'), [$filters['flanguage'], '*'], ParameterType::STRING); } // Search in title or path if (!empty($filters['like'])) { $search = '%' . $filters['like'] . '%'; $query->extendWhere( 'AND', [ $db->quoteName('a.title') . ' LIKE :search1', $db->quoteName('a.path') . ' LIKE :search2', ], 'OR' ) ->bind([':search1', ':search2'], $search); } // Filter title if (!empty($filters['title'])) { $query->where($db->quoteName('a.title') . ' = :title') ->bind(':title', $filters['title']); } // Filter on the published state if (isset($filters['published']) && is_numeric($filters['published'])) { $published = (int) $filters['published']; $query->where($db->quoteName('a.published') . ' = :published') ->bind(':published', $published, ParameterType::INTEGER); } // Filter on the access level if (isset($filters['access']) && \is_array($filters['access']) && \count($filters['access'])) { $groups = ArrayHelper::toInteger($filters['access']); $query->whereIn($db->quoteName('a.access'), $groups); } // Filter by parent_id if (isset($filters['parent_id']) && is_numeric($filters['parent_id'])) { $tagTable = Factory::getApplication()->bootComponent('com_tags')->getMVCFactory()->createTable('Tag', 'Administrator'); if ($children = $tagTable->getTree($filters['parent_id'])) { $childrenIds = array_column($children, 'id'); $query->whereIn($db->quoteName('a.id'), $childrenIds); } } $query->group( [ $db->quoteName('a.id'), $db->quoteName('a.title'), $db->quoteName('a.level'), $db->quoteName('a.lft'), $db->quoteName('a.rgt'), $db->quoteName('a.parent_id'), $db->quoteName('a.published'), $db->quoteName('a.path'), ] ) ->order($db->quoteName('a.lft') . ' ASC'); // Get the options. $db->setQuery($query); try { $results = $db->loadObjectList(); } catch (\RuntimeException $e) { return []; } // We will replace path aliases with tag names return self::convertPathsToNames($results); } /** * Method to delete all instances of a tag from the mapping table. Generally used when a tag is deleted. * * @param integer $tagId The tag_id (primary key) for the deleted tag. * * @return void * * @since 3.1 */ public function tagDeleteInstances($tagId) { // Cast as integer until method is typehinted. $tag_id = (int) $tagId; // Delete the old tag maps. $db = Factory::getDbo(); $query = $db->getQuery(true) ->delete($db->quoteName('#__contentitem_tag_map')) ->where($db->quoteName('tag_id') . ' = :id') ->bind(':id', $tagId, ParameterType::INTEGER); $db->setQuery($query); $db->execute(); } /** * Method to add or update tags associated with an item. * * @param integer $ucmId Id of the #__ucm_content item being tagged * @param TableInterface $table Table object being tagged * @param array $tags Array of tags to be applied. * @param boolean $replace Flag indicating if all existing tags should be replaced * * @return boolean true on success, otherwise false. * * @since 3.1 */ public function tagItem($ucmId, TableInterface $table, $tags = [], $replace = true) { $key = $table->getKeyName(); $oldTags = $this->getTagIds((int) $table->$key, $this->typeAlias); $oldTags = explode(',', $oldTags); $result = $this->unTagItem($ucmId, $table); if ($replace) { $newTags = $tags; } else { if ($tags == []) { $newTags = $table->newTags; } else { $newTags = $tags; } if ($oldTags[0] != '') { $newTags = array_unique(array_merge($newTags, $oldTags)); } } if (\is_array($newTags) && \count($newTags) > 0 && $newTags[0] != '') { $result = $result && $this->addTagMapping($ucmId, $table, $newTags); } return $result; } /** * Method to untag an item * * @param integer $contentId ID of the content item being untagged * @param TableInterface $table Table object being untagged * @param array $tags Array of tags to be untagged. Use an empty array to untag all existing tags. * * @return boolean true on success, otherwise false. * * @since 3.1 */ public function unTagItem($contentId, TableInterface $table, $tags = []) { $key = $table->getKeyName(); $id = (int) $table->$key; $db = Factory::getDbo(); $query = $db->getQuery(true) ->delete($db->quoteName('#__contentitem_tag_map')) ->where( [ $db->quoteName('type_alias') . ' = :type', $db->quoteName('content_item_id') . ' = :id', ] ) ->bind(':type', $this->typeAlias) ->bind(':id', $id, ParameterType::INTEGER); if (\is_array($tags) && \count($tags) > 0) { $tags = ArrayHelper::toInteger($tags); $query->whereIn($db->quoteName('tag_id'), $tags); } $db->setQuery($query); return (bool) $db->execute(); } /** * Function that converts tag ids to their tag id and tag names * * @param array $tagIds Array of integer tag ids. * * @return array An array of tag id and name. * * @since 4.4.0 */ public function getTags($tagIds) { $tagNames = []; if (\is_array($tagIds) && \count($tagIds) > 0) { $tagIds = ArrayHelper::toInteger($tagIds); $db = Factory::getDbo(); $query = $db->getQuery(true) ->select([$db->quoteName('id'), $db->quoteName('title')]) ->from($db->quoteName('#__tags')) ->whereIn($db->quoteName('id'), $tagIds) ->order($db->quoteName('title')); $db->setQuery($query); $tagNames = $db->loadAssocList('id', 'title'); } return $tagNames; } } PK lE�[��9 9 PublicFolderGeneratorHelper.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Admin Component Public Folder Generator Helper * * @since 5.0.0 */ class PublicFolderGeneratorHelper { /** * Files and folders to be symlinked * * @var array */ private $filesSymLink = [ // Administrator 'administrator/components/com_joomlaupdate/extract.php', // Media static assets 'media', ]; /** * The template for the defines.php file * * @var string */ private $definesTemplate = <<<PHP <?php /** * Programmatically generated * * @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ define('JPATH_ROOT', {{ROOTFOLDER}}); define('JPATH_PUBLIC', {{PUBLICFOLDER}}); define('JPATH_BASE', JPATH_ROOT . \$applicationPath); PHP; /** * The template for the index.php file * * @var string */ private $indexTemplate = <<<PHP <?php /** * Programmatically generated * * @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ \$applicationPath = {{APPLICATIONPATH}}; require_once {{DEFINESPATH}} . '/defines.php'; unset(\$applicationPath); require_once JPATH_BASE . '/index.php'; PHP; /** * Creates a public folder * * @param string $destinationPath The full path for the public folder * * @return void * @throws \Exception * * @since 5.0.0 */ public function createPublicFolder(string $destinationPath): void { $destinationPath = rtrim($destinationPath, '/\\') . '/'; $fullDestinationPath = $destinationPath; $definePublic = '\'' . $destinationPath . '\''; $root = JPATH_ROOT . '/'; $defineRoot = '\'' . JPATH_ROOT . '\''; if (substr($destinationPath, 0, 1) !== '/') { $fullDestinationPath = JPATH_ROOT . '/' . $destinationPath; $root = ''; $dirsToRoot = substr_count($destinationPath, '/'); $defineRoot = str_repeat('dirname(', $dirsToRoot) . '__DIR__' . str_repeat(')', $dirsToRoot); $definePublic = 'JPATH_ROOT . \'/' . rtrim($destinationPath, '/') . '\''; } if (file_exists($fullDestinationPath . '/index.php')) { throw new \Exception('Unable to create the given folder, index.php already exists.'); } if ((!is_dir($fullDestinationPath) && !mkdir($fullDestinationPath, 0755, true))) { throw new \Exception('Unable to create the given folder, check the permissions.'); } // Create the required folders if ( !mkdir($fullDestinationPath . '/administrator/components/com_joomlaupdate', 0755, true) || !mkdir($fullDestinationPath . '/api', 0755, true) ) { throw new \Exception('Unable to create the given folder, check the permissions.'); } // Create essential symlinks foreach ($this->filesSymLink as $localDirectory) { $this->createSymlink($root . $localDirectory, $destinationPath . $localDirectory, JPATH_ROOT . '/'); } $filesHardCopies = []; // Copy the robots if (is_file(JPATH_ROOT . '/robots.txt')) { $filesHardCopies[] = '/robots.txt'; } elseif (is_file(JPATH_ROOT . '/robots.txt.dist')) { $filesHardCopies[] = '/robots.txt.dist'; } // Copy the apache config if (is_file(JPATH_ROOT . '/.htaccess')) { $filesHardCopies[] = '/.htaccess'; } elseif (is_file(JPATH_ROOT . '/htaccess.txt')) { $filesHardCopies[] = '/htaccess.txt'; } foreach ($filesHardCopies as $file) { $this->createFile($fullDestinationPath . $file, file_get_contents(JPATH_ROOT . $file)); } // Create the defines.php $this->createFile($fullDestinationPath . 'defines.php', str_replace(['{{ROOTFOLDER}}', '{{PUBLICFOLDER}}'], [$defineRoot, $definePublic], $this->definesTemplate)); // The root index.php $this->createFile($fullDestinationPath . 'index.php', str_replace(['{{APPLICATIONPATH}}', '{{DEFINESPATH}}'], ['\'\'', '__DIR__'], $this->indexTemplate)); // The Administrator root index.php $this->createFile($fullDestinationPath . 'administrator/index.php', str_replace(['{{APPLICATIONPATH}}', '{{DEFINESPATH}}'], ['\'' . DIRECTORY_SEPARATOR . 'administrator\'', 'dirname(__DIR__)'], $this->indexTemplate)); // The API root index.php $this->createFile($fullDestinationPath . 'api/index.php', str_replace(['{{APPLICATIONPATH}}', '{{DEFINESPATH}}'], ['\'' . DIRECTORY_SEPARATOR . 'api\'', 'dirname(__DIR__)'], $this->indexTemplate)); // Get all the local filesystem directories if (\defined('_JCLI_INSTALLATION')) { $localDirectories = [(object)['directory' => 'images']]; } elseif (PluginHelper::isEnabled('filesystem', 'local')) { $local = PluginHelper::getPlugin('filesystem', 'local'); $localDirectories = (new Registry($local->params))->get('directories', [(object)['directory' => 'images']]); } // Symlink all the local filesystem directories foreach ($localDirectories as $localDirectory) { if (!is_link($destinationPath . '/' . $localDirectory->directory)) { $this->createSymlink($root . $localDirectory->directory, $destinationPath . $localDirectory->directory, JPATH_ROOT . '/'); } } } /** * Creates a symlink * * @param string $source The source path * @param string $dest The destination path * @param string $base The base path if relative * * @return void * * @since 5.0.0 */ private function createSymlink(string $source, string $dest, string $base): void { if (substr($source, 0, 1) !== '/') { $source = str_repeat('../', substr_count($dest, '/')) . $source; $dest = $base . $dest; } if (!symlink($source, $dest)) { throw new \Exception('Unable to symlink the file: ' . str_replace(JPATH_ROOT, '', $source)); } } /** * Writes the content to a given file * * @param string $path The destination path * @param string $content The contents of the file * * @return void * * @since 5.0.0 */ private function createFile(string $path, string $content): void { if (!file_put_contents($path, $content)) { throw new \Exception('Unable to create the file: ' . $path); } } } PK lE�[� �f� � HelperFactoryInterface.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Factory to load helper classes. * * @since 4.0.0 */ interface HelperFactoryInterface { /** * Returns a helper instance for the given name. * * @param string $name The name * @param array $config The config * * @return \stdClass * * @since 4.0.0 */ public function getHelper(string $name, array $config = []); } PK lE�[žȀT T HelperFactory.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use Joomla\Database\DatabaseAwareInterface; use Joomla\Database\DatabaseAwareTrait; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Namespace based implementation of the HelperFactoryInterface * * @since 4.0.0 */ class HelperFactory implements HelperFactoryInterface { use DatabaseAwareTrait; /** * The extension namespace * * @var string * * @since 4.0.0 */ private $namespace; /** * HelperFactory constructor. * * @param string $namespace The namespace * * @since 4.0.0 */ public function __construct(string $namespace) { $this->namespace = $namespace; } /** * Returns a helper instance for the given name. * * @param string $name The name * @param array $config The config * * @return \stdClass * * @since 4.0.0 */ public function getHelper(string $name, array $config = []) { $className = '\\' . trim($this->namespace, '\\') . '\\' . $name; if (!class_exists($className)) { return null; } $helper = new $className($config); if ($helper instanceof DatabaseAwareInterface) { $helper->setDatabase($this->getDatabase()); } return $helper; } } PK lE�[����! �! RouteHelper.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use Joomla\CMS\Categories\Categories; use Joomla\CMS\Categories\CategoryNode; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Language\Multilanguage; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * 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 = Factory::getApplication()->getInput()->getString('view'); $this->extension = Factory::getApplication()->getInput()->getCmd('option'); } $name = ucfirst(substr_replace($this->extension, '', 0, 4)); $needles = []; if (isset($this->view)) { $needles[$this->view] = [(int) $id]; } if (empty($link)) { // Create the link $link = 'index.php?option=' . $this->extension . '&view=' . $this->view . '&id=' . $id; } if ($catid > 1) { $categories = Categories::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 = []) { $app = Factory::getApplication(); $menus = $app->getMenu('site'); $language = $needles['language'] ?? '*'; // $this->extension may not be set if coming from a static method, check it if ($this->extension === null) { $this->extension = $app->getInput()->getCmd('option'); } // Prepare the reverse lookup array. if (!isset(static::$lookup[$language])) { static::$lookup[$language] = []; $component = ComponentHelper::getComponent($this->extension); $attributes = ['component_id']; $values = [$component->id]; if ($language !== '*') { $attributes[] = 'language'; $values[] = [$needles['language'], '*']; } $items = $menus->getItems($attributes, $values); foreach ($items as $item) { if (isset($item->query['view'])) { $view = $item->query['view']; if (!isset(static::$lookup[$language][$view])) { static::$lookup[$language][$view] = []; } 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 CategoryNode 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 CategoryNode) { $id = $catid->id; $category = $catid; } else { $extensionName = ucfirst(substr($extension, 4)); $id = (int) $catid; $category = Categories::getInstance($extensionName)->get($id); } if ($id < 1) { $link = ''; } else { $link = 'index.php?option=' . $extension . '&view=category&id=' . $id; $needles = [ 'category' => [$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 = []) { $instance = new static(); return $instance->findItem($needles); } } PK lE�[�Ư��` �` ModuleHelper.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use Joomla\CMS\Cache\CacheControllerFactoryInterface; use Joomla\CMS\Cache\Controller\CallbackController; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Event\Module; use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Log\Log; use Joomla\CMS\Profiler\Profiler; use Joomla\Database\ParameterType; use Joomla\Filesystem\Path; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * 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 = static::createDummyModule(); $result->module = $name; } 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 = []; $input = Factory::getApplication()->getInput(); $modules = &static::load(); $total = \count($modules); for ($i = 0; $i < $total; $i++) { if ($modules[$i]->position === $position) { $result[] = &$modules[$i]; } } // Prepend a dummy module for template preview if no module is published in the position if (empty($result) && $input->getBool('tp') && ComponentHelper::getParams('com_templates')->get('template_positions_display')) { $dummy = static::createDummyModule(); $dummy->title = $position; $dummy->position = $position; $dummy->content = $position; $dummy->contentRendered = true; array_unshift($result, $dummy); } 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 = []) { $app = Factory::getApplication(); // Check that $module is a valid module object if (!\is_object($module) || !isset($module->module) || !isset($module->params)) { if (JDEBUG) { Log::addLogger(['text_file' => 'jmodulehelper.log.php'], Log::ALL, ['modulehelper']); $app->getLogger()->debug( __METHOD__ . '() - The $module parameter should be a module object.', ['category' => 'modulehelper'] ); } return ''; } // Get module parameters $params = new Registry($module->params); // Render the module content static::renderRawModule($module, $params, $attribs); // Return early if only the content is required if (!empty($attribs['contentOnly'])) { return $module->content; } if (JDEBUG) { Profiler::getInstance('Application')->mark('beforeRenderModule ' . $module->module . ' (' . $module->title . ')'); } // Record the scope. $scope = $app->scope; // Set scope to component name $app->scope = $module->module; $dispatcher = $app->getDispatcher(); // Get the template $template = $app->getTemplate(); // Check if the current module has a style param to override template module style $paramsChromeStyle = $params->get('style'); $basePath = ''; if ($paramsChromeStyle) { $paramsChromeStyle = explode('-', $paramsChromeStyle, 2); $ChromeStyleTemplate = strtolower($paramsChromeStyle[0]); $attribs['style'] = $paramsChromeStyle[1]; // Only set $basePath if the specified template isn't the current or system one. if ($ChromeStyleTemplate !== $template && $ChromeStyleTemplate !== 'system') { $basePath = JPATH_THEMES . '/' . $ChromeStyleTemplate . '/html/layouts'; } } // Make sure a style is set if (!isset($attribs['style'])) { $attribs['style'] = 'none'; } // Dynamically add outline style if ($app->getInput()->getBool('tp') && ComponentHelper::getParams('com_templates')->get('template_positions_display')) { $attribs['style'] .= ' outline'; } $module->style = $attribs['style']; // If the $module is nulled it will return an empty content, otherwise it will render the module normally. $brEvent = $dispatcher->dispatch('onRenderModule', new Module\BeforeRenderModuleEvent('onRenderModule', [ 'subject' => $module, 'attributes' => &$attribs, // @todo: Remove reference in Joomla 6, see BeforeRenderModuleEvent::__constructor() ])); // Get final attributes $attribs = $brEvent->getArgument('attributes', $attribs); if (!isset($module->content)) { return ''; } // Prevent double modification of the module content by chrome style $module = clone $module; $displayData = [ 'module' => $module, 'params' => $params, 'attribs' => $attribs, ]; foreach (explode(' ', $attribs['style']) as $style) { $moduleContent = LayoutHelper::render('chromes.' . $style, $displayData, $basePath); if ($moduleContent) { $module->content = $moduleContent; } } // Revert the scope $app->scope = $scope; $dispatcher->dispatch('onAfterRenderModule', new Module\AfterRenderModuleEvent('onAfterRenderModule', [ 'subject' => $module, 'attributes' => $attribs, ])); if (JDEBUG) { Profiler::getInstance('Application')->mark('afterRenderModule ' . $module->module . ' (' . $module->title . ')'); } return $module->content; } /** * Render the module content. * * @param object $module A module object * @param Registry $params A module parameters * @param array $attribs An array of attributes for the module (probably from the XML). * * @return string * * @since 4.0.0 */ public static function renderRawModule($module, Registry $params, $attribs = []) { if (!empty($module->contentRendered)) { return $module->content; } if (JDEBUG) { Profiler::getInstance('Application')->mark('beforeRenderRawModule ' . $module->module . ' (' . $module->title . ')'); } $app = Factory::getApplication(); // Record the scope. $scope = $app->scope; // Set scope to component name $app->scope = $module->module; // Get module path $module->module = preg_replace('/[^A-Z0-9_\.-]/i', '', $module->module); $dispatcher = $app->bootModule($module->module, $app->getName())->getDispatcher($module, $app); // Check if we have a dispatcher if ($dispatcher) { ob_start(); $dispatcher->dispatch(); $module->content = ob_get_clean(); } // Add the flag that the module content has been rendered $module->contentRendered = true; // Revert the scope $app->scope = $scope; if (JDEBUG) { Profiler::getInstance('Application')->mark('afterRenderRawModule ' . $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') { $templateObj = Factory::getApplication()->getTemplate(true); $defaultLayout = $layout; $template = $templateObj->template; 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'; } $dPath = JPATH_BASE . '/modules/' . $module . '/tmpl/default.php'; try { // Build the template and base path for the layout $tPath = Path::check(JPATH_THEMES . '/' . $template . '/html/' . $module . '/' . $layout . '.php'); $iPath = Path::check(JPATH_THEMES . '/' . $templateObj->parent . '/html/' . $module . '/' . $layout . '.php'); $bPath = Path::check(JPATH_BASE . '/modules/' . $module . '/tmpl/' . $defaultLayout . '.php'); } catch (\Exception $e) { // On error fallback to the default path return $dPath; } // If the template has a layout override use it if (is_file($tPath)) { return $tPath; } if (!empty($templateObj->parent) && is_file($iPath)) { return $iPath; } if (is_file($bPath)) { return $bPath; } return $dPath; } /** * Load published modules. * * @return array * * @since 3.2 */ protected static function &load() { static $modules; if (isset($modules)) { return $modules; } $dispatcher = Factory::getApplication()->getDispatcher(); $modules = []; $modules = $dispatcher->dispatch('onPrepareModuleList', new Module\PrepareModuleListEvent('onPrepareModuleList', [ 'modules' => &$modules, // @todo: Remove reference in Joomla 6, see PrepareModuleListEvent::__constructor() ]))->getArgument('modules', $modules); // If the onPrepareModuleList event returns an array of modules, then ignore the default module list creation if (!$modules) { $modules = static::getModuleList(); } $modules = $dispatcher->dispatch('onAfterModuleList', new Module\AfterModuleListEvent('onAfterModuleList', [ 'modules' => &$modules, // @todo: Remove reference in Joomla 6, see AfterModuleListEvent::__constructor() ]))->getArgument('modules', $modules); $modules = static::cleanModuleList($modules); $modules = $dispatcher->dispatch('onAfterCleanModuleList', new Module\AfterCleanModuleListEvent('onAfterCleanModuleList', [ 'modules' => &$modules, // @todo: Remove reference in Joomla 6, see AfterCleanModuleListEvent::__constructor() ]))->getArgument('modules', $modules); return $modules; } /** * Module list * * @return array */ public static function getModuleList() { $app = Factory::getApplication(); $itemId = $app->getInput()->getInt('Itemid', 0); $groups = $app->getIdentity()->getAuthorisedViewLevels(); $clientId = (int) $app->getClientId(); // Build a cache ID for the resulting data object $cacheId = implode(',', $groups) . '.' . $clientId . '.' . $itemId; $db = Factory::getDbo(); $query = $db->getQuery(true); $nowDate = Factory::getDate()->toSql(); $query->select($db->quoteName(['m.id', 'm.title', 'm.module', 'm.position', 'm.content', 'm.showtitle', 'm.params', 'mm.menuid'])) ->from($db->quoteName('#__modules', 'm')) ->join( 'LEFT', $db->quoteName('#__modules_menu', 'mm'), $db->quoteName('mm.moduleid') . ' = ' . $db->quoteName('m.id') ) ->join( 'LEFT', $db->quoteName('#__extensions', 'e'), $db->quoteName('e.element') . ' = ' . $db->quoteName('m.module') . ' AND ' . $db->quoteName('e.client_id') . ' = ' . $db->quoteName('m.client_id') ) ->where( [ $db->quoteName('m.published') . ' = 1', $db->quoteName('e.enabled') . ' = 1', $db->quoteName('m.client_id') . ' = :clientId', ] ) ->bind(':clientId', $clientId, ParameterType::INTEGER) ->whereIn($db->quoteName('m.access'), $groups) ->extendWhere( 'AND', [ $db->quoteName('m.publish_up') . ' IS NULL', $db->quoteName('m.publish_up') . ' <= :publishUp', ], 'OR' ) ->bind(':publishUp', $nowDate) ->extendWhere( 'AND', [ $db->quoteName('m.publish_down') . ' IS NULL', $db->quoteName('m.publish_down') . ' >= :publishDown', ], 'OR' ) ->bind(':publishDown', $nowDate) ->extendWhere( 'AND', [ $db->quoteName('mm.menuid') . ' = :itemId', $db->quoteName('mm.menuid') . ' <= 0', ], 'OR' ) ->bind(':itemId', $itemId, ParameterType::INTEGER); // Filter by language if ($app->isClient('site') && $app->getLanguageFilter() || $app->isClient('administrator') && static::isAdminMultilang()) { $language = $app->getLanguage()->getTag(); $query->whereIn($db->quoteName('m.language'), [$language, '*'], ParameterType::STRING); $cacheId .= $language . '*'; } $query->order($db->quoteName(['m.position', 'm.ordering'])); // Set the query $db->setQuery($query); try { /** @var CallbackController $cache */ $cache = Factory::getContainer()->get(CacheControllerFactoryInterface::class) ->createCacheController('callback', ['defaultgroup' => 'com_modules']); $modules = $cache->get([$db, 'loadObjectList'], [], md5($cacheId), false); } catch (\RuntimeException $e) { $app->getLogger()->warning( Text::sprintf('JLIB_APPLICATION_ERROR_MODULE_LOAD', $e->getMessage()), ['category' => 'jerror'] ); return []; } 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 = Factory::getApplication()->getInput()->getInt('Itemid'); $negId = $Itemid ? -(int) $Itemid : false; $clean = []; $dupes = []; 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 * '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 InputFilter::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; } if (!isset($cacheparams->cachesuffix)) { $cacheparams->cachesuffix = ''; } $user = Factory::getUser(); $app = Factory::getApplication(); /** @var CallbackController $cache */ $cache = Factory::getContainer()->get(CacheControllerFactoryInterface::class) ->createCacheController('callback', ['defaultgroup' => $cacheparams->cachegroup]); // 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 || $app->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', $app->get('cachetime') * 60) / 60); $wrkaroundoptions = ['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( [$cacheparams->class, $cacheparams->method], $cacheparams->methodparams, $cacheparams->modeparams . $cacheparams->cachesuffix, $wrkarounds, $wrkaroundoptions ); break; case 'safeuri': $safeuri = new \stdClass(); if (\is_array($cacheparams->modeparams)) { $input = $app->getInput(); $uri = $input->getArray(); $noHtmlFilter = InputFilter::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([$safeuri, $cacheparams->method, $moduleparams])); $ret = $cache->get( [$cacheparams->class, $cacheparams->method], $cacheparams->methodparams, $module->id . $view_levels . $secureid . $cacheparams->cachesuffix, $wrkarounds, $wrkaroundoptions ); break; case 'static': $ret = $cache->get( [$cacheparams->class, $cacheparams->method], $cacheparams->methodparams, $module->module . md5(serialize($cacheparams->methodparams)) . $cacheparams->cachesuffix, $wrkarounds, $wrkaroundoptions ); break; case 'itemid': default: $ret = $cache->get( [$cacheparams->class, $cacheparams->method], $cacheparams->methodparams, $module->id . $view_levels . $app->getInput()->getInt('Itemid', null) . $cacheparams->cachesuffix, $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 = static::createDummyModule(); return $result; } /** * Method to create a dummy module. * * @return \stdClass The Module object * * @since 4.0.0 */ protected static function createDummyModule(): \stdClass { $module = new \stdClass(); $module->id = 0; $module->title = ''; $module->module = ''; $module->position = ''; $module->content = ''; $module->showtitle = 0; $module->control = ''; $module->params = ''; return $module; } } PK lE�[&���! �! ContentHelper.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use Joomla\CMS\Access\Access; 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\Language\Text; use Joomla\CMS\Log\Log; use Joomla\CMS\MVC\View\CanDo; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Table\Table; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * 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 = $config->counter_names ?? [ '-2' => 'count_trashed', '0' => 'count_unpublished', '1' => 'count_published', '2' => 'count_archived', ]; // Index category objects by their ID $records = []; 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 = '#__' . $config->related_tbl; $state_col = 'c.' . $config->state_col; // Supported cases switch ($config->relation_type) { case 'tag_assigments': $recid_col = 'ct.' . $config->group_col; $query = $db->getQuery(true) ->from($db->quoteName('#__contentitem_tag_map', 'ct')) ->join( 'INNER', $db->quoteName($related_tbl, 'c'), $db->quoteName('ct.content_item_id') . ' = ' . $db->quoteName('c.id') . ' AND ' . $db->quoteName('ct.type_alias') . ' = :extension' ) ->bind(':extension', $config->extension); break; case 'category_or_group': $recid_col = 'c.' . $config->group_col; $query = $db->getQuery(true) ->from($db->quoteName($related_tbl, 'c')); 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( [ $db->quoteName($recid_col, 'catid'), $db->quoteName($state_col, 'state'), 'COUNT(*) AS ' . $db->quoteName('count'), ] ) ->whereIn($db->quoteName($recid_col), array_keys($records)) ->whereIn($db->quoteName($state_col), array_keys($counter_names)) ->group($db->quoteName([$recid_col, $state_col])); $relationsAll = $db->setQuery($query)->loadObjectList(); // Loop through the DB data overwriting 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 string $component The component name. * @param string $section The access section name. * @param integer $id The item ID. * * @return Registry * * @since 3.2 */ public static function getActions($component = '', $section = '', $id = 0) { $assetName = $component; if ($section && $id) { $assetName .= '.' . $section . '.' . (int) $id; } // Return a CanDo object to prevent any BC break, will be changed in 7.0 to Registry $result = new CanDo(); $user = Factory::getUser(); $actions = Access::getActionsFromFile( JPATH_ADMINISTRATOR . '/components/' . $component . '/access.xml', '/access/section[@name="component"]/' ); if ($actions === false) { Log::add( Text::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->getInput()->cookie->getString(ApplicationHelper::getHash('language')); } else { $langCode = $app->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($db->quoteName('lang_id')) ->from($db->quoteName('#__languages')) ->where($db->quoteName('lang_code') . ' = :language') ->bind(':language', $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 lE�[k��� � AuthenticationHelper.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use Joomla\CMS\Event\User\LoginButtonsEvent; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Authentication helper class * * @since 3.6.3 */ abstract class AuthenticationHelper { /** * No longer used * * @return array Always empty * * @since 3.6.3 * * @deprecated 4.2 will be removed in 6.0 * Will be removed without replacement */ public static function getTwoFactorMethods() { return []; } /** * Get additional login buttons to add in a login module. These buttons can be used for * authentication methods external to Joomla such as WebAuthn, login with social media * providers, login with third party providers or even login with third party Single Sign On * (SSO) services. * * Button definitions are returned by the onUserLoginButtons event handlers in plugins. By * default, only system and user plugins are taken into account. The former because they are * always loaded. The latter are explicitly loaded in this method. * * The onUserLoginButtons event handlers must conform to the following method definition: * * public function onUserLoginButtons(string $formId): array * * The onUserLoginButtons event handlers must return a simple array containing 0 or more button * definitions. * * Each button definition is a hash array with the following keys: * * * `label` The translation string used as the label and title of the button. Required * * `id` The HTML ID of the button. Required. * * `tooltip` (optional) The translation string used as the alt tag of the button's image * * `onclick` (optional) The onclick attribute, used to fire a JavaScript event. Not * recommended. * * `data-*` (optional) Data attributes to pass verbatim. Use these and JavaScript to handle * the button. * * `icon` (optional) A CSS class for an optional icon displayed before the label; has * precedence over 'image' * * `image` (optional) An image path for an optional icon displayed before the label * * `class` (optional) CSS class(es) to be added to the button * * You can find a real world implementation of the onUserLoginButtons plugin event in the * system/webauthn plugin. * * You can find a real world implementation of consuming the output of this method in the * modules/mod_login module. * * Third party developers implementing a login module or a login form in their component are * strongly advised to call this method and consume its results to display additional login * buttons. Not doing that means that you are not fully compatible with Joomla 4. * * @param string $formId The HTML ID of the login form container. Use it to filter when and * where to show your additional login button(s) * * @return array Button definitions. * * @since 4.0.0 */ public static function getLoginButtons(string $formId): array { try { // Get all the User plugins. $dispatcher = Factory::getApplication()->getDispatcher(); PluginHelper::importPlugin('user', null, true, $dispatcher); } catch (\Exception $e) { return []; } // Trigger the onUserLoginButtons event and return the button definitions. $btnEvent = new LoginButtonsEvent('onUserLoginButtons', ['subject' => $formId]); $dispatcher->dispatch('onUserLoginButtons', $btnEvent); $results = $btnEvent['result'] ?? []; $buttons = []; foreach ($results as $result) { // Did we get garbage back from the plugin? if (!\is_array($result) || empty($result)) { continue; } // Did the developer accidentally return a single button definition instead of an array? if (\array_key_exists('label', $result)) { $result = [$result]; } // Process each button, making sure it conforms to the required definition foreach ($result as $item) { // Force mandatory fields $defaultButtonDefinition = [ 'label' => '', 'tooltip' => '', 'icon' => '', 'image' => '', 'class' => '', 'id' => '', 'onclick' => '', ]; $button = array_merge($defaultButtonDefinition, $item); // Unset anything that doesn't conform to a button definition foreach (array_keys($button) as $key) { if (substr($key, 0, 5) == 'data-') { continue; } if (!\in_array($key, ['label', 'tooltip', 'icon', 'image', 'svg', 'class', 'id', 'onclick'])) { unset($button[$key]); } } // We need a label and an ID as the bare minimum if (empty($button['label']) || empty($button['id'])) { continue; } $buttons[] = $button; } } return $buttons; } } PK lE�[AG: : HelperFactoryAwareTrait.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Defines the trait for a HelperFactory Aware Class. * * @since 4.2.0 */ trait HelperFactoryAwareTrait { /** * HelperFactory * * @var HelperFactory * * @since 4.2.0 */ private $helper; /** * Get the HelperFactory. * * @return HelperFactory * * @since 4.2.0 * * @throws \UnexpectedValueException May be thrown if the HelperFactory has not been set. */ public function getHelperFactory(): HelperFactory { if ($this->helper) { return $this->helper; } throw new \UnexpectedValueException('HelperFactory not set in ' . __CLASS__); } /** * Sets the helper factory to use. * * @param HelperFactory $helperFactory The helper factory to use. * * @return void * * @since 4.2.0 */ public function setHelperFactory(HelperFactory $helperFactory) { $this->helper = $helperFactory; } } PK lE�[��Р� � UserGroupsHelper.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use Joomla\CMS\Factory; use Joomla\Database\ParameterType; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * 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 */ public const MODE_SINGLETON = 1; /** * Indicates the current helper instance is a standalone class instance. * * @var integer * @since 3.6.3 */ public const MODE_INSTANCE = 2; /** * Singleton instance. * * @var UserGroupsHelper * @since 3.6.3 */ private static $instance; /** * Available user groups * * @var array * @since 3.6.3 */ private $groups = []; /** * 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 = [], $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 = []; 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 = Factory::getDbo(); $query = $db->getQuery(true) ->select('COUNT(' . $db->quoteName('id') . ')') ->from($db->quoteName('#__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) { // Cast as integer until method is typehinted. $id = (int) $id; $db = Factory::getDbo(); $query = $db->getQuery(true) ->select('*') ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('id') . ' = :id') ->bind(':id', $id, ParameterType::INTEGER); $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 = []; $db = Factory::getDbo(); $query = $db->getQuery(true) ->select('*') ->from($db->quoteName('#__usergroups')) ->order($db->quoteName('lft') . ' ASC'); $db->setQuery($query); $groups = $db->loadObjectList('id'); $this->groups = $groups ?: []; $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 = [$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, [$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 lE�[��D�� � CMSHelper.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use Joomla\CMS\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; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * 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->getInput()->cookie->getString(ApplicationHelper::getHash('language')); } else { $langCode = $app->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($db->quoteName('lang_id')) ->from($db->quoteName('#__languages')) ->where($db->quoteName('lang_code') . ' = :language') ->bind(':language', $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 = []; 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->$fieldName ?? null; } return $dataObject; } } PK lE�[(�\�EF EF MediaHelper.phpnu �[��� <?php /** * Joomla! Content Management System * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Helper; use enshrined\svgSanitize\Sanitizer; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Filesystem\File; use Joomla\CMS\Filter\InputFilter; use Joomla\CMS\Language\Text; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Media helper class * * @since 3.2 */ class MediaHelper { /** * A special list of blocked executable extensions, skipping executables that are * typically executable in the webserver context as those are fetched from * Joomla\CMS\Filter\InputFilter * * @var string[] * @since 4.0.0 */ public const EXECUTABLES = [ 'js', 'exe', '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', 'html', 'htm', 'msi', ]; /** * Checks if the file is an image * * @param string $fileName The filename * * @return boolean * * @since 3.2 */ public static function isImage($fileName) { static $imageTypes = 'xcf|odg|gif|jpg|jpeg|png|bmp|webp|avif'; 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 */ public static 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 = $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 = static::getMimeType($file, false); } if ( ($mime === 'application/octet-stream' || $mime === 'image/svg' || $mime === 'image/svg+xml') && !$isImage && strtolower(pathinfo($file, PATHINFO_EXTENSION)) === 'svg' && self::isValidSvg($file, false) ) { return 'image/svg+xml'; } // 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'): bool { $params = ComponentHelper::getParams($component); if ($params->get('check_mime', 1)) { $allowedMime = $params->get( 'upload_mime', 'image/jpeg,image/gif,image/png,image/bmp,image/webp,image/avif,application/msword,' . 'application/excel,application/pdf,application/powerpoint,text/plain,application/x-zip' ); // Get the mime type configuration $allowedMime = array_map('trim', explode(',', str_replace('\\', '', $allowedMime))); // Mime should be available and in the allowed list return !empty($mime) && \in_array($mime, $allowedMime); } // We don't check mime at all or it passes the checks return true; } /** * Checks the file extension * * @param string $extension The extension to be checked * @param string $component The optional name for the component storing the parameters * * @return boolean true if it passes the checks else false * * @since 4.0.0 */ public static function checkFileExtension($extension, $component = 'com_media', $allowedExecutables = []): bool { $params = ComponentHelper::getParams($component); // Media file names should never have executable extensions buried in them. $executables = array_merge(self::EXECUTABLES, InputFilter::FORBIDDEN_FILE_EXTENSIONS); // Remove allowed executables from array if (\count($allowedExecutables)) { $executables = array_diff($executables, $allowedExecutables); } if (\in_array($extension, $executables, true)) { return false; } $allowable = array_map('trim', explode(',', $params->get('restrict_uploads_extensions', 'bmp,gif,jpg,jpeg,png,webp,avif,ico,mp3,m4a,mp4a,ogg,mp4,mp4v,mpeg,mov,odg,odp,ods,odt,pdf,ppt,txt,xcf,xls,csv'))); $ignored = array_map('trim', explode(',', $params->get('ignore_extensions', ''))); if ($extension == '' || $extension == false || (!\in_array($extension, $allowable, true) && !\in_array($extension, $ignored, true))) { return false; } // 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 * @param string[] $allowedExecutables Array of executable file types that shall be whitelisted * * @return boolean * * @since 3.2 */ public function canUpload($file, $component = 'com_media', $allowedExecutables = []) { $app = Factory::getApplication(); $params = ComponentHelper::getParams($component); if (empty($file['name'])) { $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_UPLOAD_INPUT'), 'error'); return false; } if ($file['name'] !== File::makeSafe($file['name'])) { $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNFILENAME'), 'error'); return false; } $filetypes = explode('.', $file['name']); if (\count($filetypes) < 2) { // There seems to be no extension $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNFILETYPE'), 'error'); return false; } array_shift($filetypes); // Media file names should never have executable extensions buried in them. $executables = array_merge(self::EXECUTABLES, InputFilter::FORBIDDEN_FILE_EXTENSIONS); // Remove allowed executables from array if (\count($allowedExecutables)) { $executables = array_diff($executables, $allowedExecutables); } // Ensure lowercase extension $filetypes = array_map('strtolower', $filetypes); $check = array_intersect($filetypes, $executables); if (!empty($check)) { $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNFILETYPE'), 'error'); return false; } $filetype = array_pop($filetypes); $allowable = array_map('trim', explode(',', $params->get('restrict_uploads_extensions', 'bmp,gif,jpg,jpeg,png,webp,avif,ico,mp3,m4a,mp4a,ogg,mp4,mp4v,mpeg,mov,odg,odp,ods,odt,pdf,png,ppt,txt,xcf,xls,csv'))); $ignored = array_map('trim', explode(',', $params->get('ignore_extensions', ''))); if ($filetype == '' || $filetype == false || (!\in_array($filetype, $allowable) && !\in_array($filetype, $ignored))) { $app->enqueueMessage(Text::_('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(Text::_('JLIB_MEDIA_ERROR_WARNFILETOOLARGE'), 'error'); return false; } if ($params->get('restrict_uploads', 1)) { $allowedExtensions = array_map('trim', explode(',', $params->get('restrict_uploads_extensions', 'bmp,gif,jpg,jpeg,png,webp,avif,ico,mp3,m4a,mp4a,ogg,mp4,mp4v,mpeg,mov,odg,odp,ods,odt,pdf,png,ppt,txt,xcf,xls,csv'))); if (\in_array($filetype, $allowedExtensions)) { // 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 = static::getMimeType($file['tmp_name'], static::isImage($file['tmp_name'])); // 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(Text::sprintf('JLIB_MEDIA_ERROR_WARNINVALID_MIMETYPE', $mime), 'error'); return false; } } else { // We can't detect the mime type so it looks like an invalid image $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNINVALID_IMG'), 'error'); return false; } } else { $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNFILETOOLARGE'), 'error'); return false; } } elseif (!\in_array($filetype, $ignored)) { // Get the mime type this is not an image file $mime = static::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(Text::sprintf('JLIB_MEDIA_ERROR_WARNINVALID_MIMETYPE', $mime), 'error'); return false; } } else { // We can't detect the mime type so it looks like an invalid file $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNINVALID_MIME'), 'error'); return false; } if (!Factory::getUser()->authorise('core.manage', $component)) { $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNNOTADMIN'), 'error'); return false; } } } if ($filetype === 'svg') { return self::isValidSvg($file['tmp_name'], true); } 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 [$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 [$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; } } /** * Method to check if the given directory is a directory configured in FileSystem - Local plugin * * @param string $directory * * @return boolean * * @since 4.0.0 */ public static function isValidLocalDirectory($directory) { $plugin = PluginHelper::getPlugin('filesystem', 'local'); if ($plugin) { $params = new Registry($plugin->params); $directories = $params->get('directories', '[{"directory": "images"}]'); // Do a check if default settings are not saved by user // If not initialize them manually if (\is_string($directories)) { $directories = json_decode($directories); } foreach ($directories as $directoryEntity) { if ($directoryEntity->directory === $directory) { return true; } } } return false; } /** * Helper method get clean data for value stores in a Media form field by removing adapter information * from the value if available (in this case, the value will have this format: * images/headers/blue-flower.jpg#joomlaImage://local-images/headers/blue-flower.jpg?width=700&height=180) * * @param string $value * * @return string * * @since 4.0.0 */ public static function getCleanMediaFieldValue($value) { if ($pos = strpos($value, '#')) { return substr($value, 0, $pos); } return $value; } /** * Check if a file is a valid SVG * * @param string $file * @param bool $shouldLogErrors * * @return boolean * * @since 4.3.0 */ private static function isValidSvg($file, $shouldLogErrors = true): bool { $sanitizer = new Sanitizer(); $isValid = $sanitizer->sanitize(file_get_contents($file)); $svgErrors = $sanitizer->getXmlIssues(); /** * We allow comments and temp fix for bugs in svg-santitizer * https://github.com/darylldoyle/svg-sanitizer/issues/64 * https://github.com/darylldoyle/svg-sanitizer/issues/63 * https://github.com/darylldoyle/svg-sanitizer/pull/65 * https://github.com/darylldoyle/svg-sanitizer/issues/82 */ foreach ($svgErrors as $i => $error) { if ( ($error['message'] === 'Suspicious node \'#comment\'') || ($error['message'] === 'Suspicious attribute \'space\'') || ($error['message'] === 'Suspicious attribute \'enable-background\'') || ($error['message'] === 'Suspicious node \'svg\'') ) { unset($svgErrors[$i]); } } if ($isValid === false || \count($svgErrors)) { if ($shouldLogErrors) { Factory::getApplication()->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNIEXSS'), 'error'); } return false; } return true; } } PK lE�[���S� � HelperFactoryAwareInterface.phpnu �[��� PK lE�[���( ( / LibraryHelper.phpnu �[��� PK lE�[�o�3� 3� � TagsHelper.phpnu �[��� PK lE�[��9 9 � PublicFolderGeneratorHelper.phpnu �[��� PK lE�[� �f� � �� HelperFactoryInterface.phpnu �[��� PK lE�[žȀT T �� HelperFactory.phpnu �[��� PK lE�[����! �! O� RouteHelper.phpnu �[��� PK lE�[�Ư��` �` � ModuleHelper.phpnu �[��� PK lE�[&���! �! �b ContentHelper.phpnu �[��� PK lE�[k��� � �� AuthenticationHelper.phpnu �[��� PK lE�[AG: : �� HelperFactoryAwareTrait.phpnu �[��� PK lE�[��Р� � � UserGroupsHelper.phpnu �[��� PK lE�[��D�� � ;� CMSHelper.phpnu �[��� PK lE�[(�\�EF EF ^� MediaHelper.phpnu �[��� PK � �
| ver. 1.4 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0.01 |
proxy
|
phpinfo
|
Настройка