File manager - Edit - /home/ferretapmx/public_html/Html.zip
Back
PK \\�\�U��. �. SelectOptions.phpnu �[��� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Html; defined('_JEXEC') || die; use Joomla\CMS\Cache\Cache; use Joomla\CMS\Factory as JoomlaFactory; use Joomla\CMS\Helper\UserGroupsHelper; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use stdClass; /** * Returns arrays of HTMLHelper select options for Joomla-specific information such as access levels. * * @method static array access() access(array $params) * @method static array usergroups() usergroups(array $params) * @method static array cachehandlers() cachehandlers(array $params) * @method static array components() components(array $params) * @method static array languages() languages(array $params) * @method static array published() published(array $params) */ class SelectOptions { private static $cache = []; /** * Magic method to handle static calls * * @param string $name The name of the static method being called * @param array $arguments Optional arguments, if they are supported by the options type. * * @return mixed * @since 3.3.0 */ public static function __callStatic(string $name, array $arguments = []) { return self::getOptions($name, $arguments); } /** * Get a list of Joomla options of the type you specify. Supported types * - access View access levels * - usergroups User groups * - cachehandlers Cache handlers * - components Installed components accessible by the current user * - languages Site or administrator languages * - published Published status * * Global params: * - cache Should I returned cached data? Default: true. * * See the private static methods of this class for more information on params. * * @param string $type The options type to get * @param array $params Optional arguments, if they are supported by the options type. * * @return stdClass[] * @since 3.3.0 * @api */ public static function getOptions(string $type, array $params = []): array { if ((substr($type, 0, 1) == '_') || !method_exists(__CLASS__, '_api_' . $type)) { throw new \InvalidArgumentException(__CLASS__ . "does not support option type '$type'."); } $useCache = true; if (isset($params['cache'])) { $useCache = isset($params['cache']); unset($params['cache']); } $cacheKey = sha1($type . '--' . print_r($params, true)); $fetchNew = !$useCache || ($useCache && !isset(self::$cache[$cacheKey])); $ret = []; if ($fetchNew) { $ret = forward_static_call_array([__CLASS__, '_api_' . $type], [$params]); } if (!$useCache) { return $ret; } if ($fetchNew) { self::$cache[$cacheKey] = $ret; } return self::$cache[$cacheKey]; } /** * Joomla! Access Levels (previously: view access levels) * * Available params: * - allLevels: Show an option for all levels (default: false) * * @param array $params Parameters * * @return stdClass[] * @since 3.3.0 * @internal * * @see \Joomla\CMS\HTML\Helpers\Access::level() * * @noinspection PhpUnusedPrivateMethodInspection */ private static function _api_access(array $params = []): array { $db = JoomlaFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('a.id', 'value') . ', ' . $db->quoteName('a.title', 'text')) ->from($db->quoteName('#__viewlevels', 'a')) ->group($db->quoteName(['a.id', 'a.title', 'a.ordering'])) ->order($db->quoteName('a.ordering') . ' ASC') ->order($db->quoteName('title') . ' ASC'); // Get the options. $db->setQuery($query); $options = $db->loadObjectList() ?? []; if (isset($params['allLevels']) && $params['allLevels']) { array_unshift($options, HTMLHelper::_('select.option', '', Text::_('JOPTION_ACCESS_SHOW_ALL_LEVELS'))); } return $options; } /** * Joomla! User Groups * * Available params: * - allGroups: Show an option for all groups (default: false) * * @param array $params Parameters * * @return stdClass[] * @since 3.3.0 * @internal * * @see \Joomla\CMS\HTML\Helpers\Access::usergroup() * * @noinspection PhpUnusedPrivateMethodInspection */ private static function _api_usergroups(array $params = []): array { $options = array_values(UserGroupsHelper::getInstance()->getAll()); for ($i = 0, $n = count($options); $i < $n; $i++) { $options[$i]->value = $options[$i]->id; $options[$i]->text = str_repeat('- ', $options[$i]->level) . $options[$i]->title; } // If all usergroups is allowed, push it into the array. if (isset($params['allGroups']) && $params['allGroups']) { array_unshift($options, HTMLHelper::_('select.option', '', Text::_('JOPTION_ACCESS_SHOW_ALL_GROUPS'))); } return $options; } /** * Joomla cache handlers * * @param array $params Ignored * * @return stdClass[] * @since 3.3.0 * @internal * * @noinspection PhpUnusedPrivateMethodInspection */ private static function _api_cachehandlers(array $params = []): array { $options = []; // Convert to name => name array. foreach (Cache::getStores() as $store) { $options[] = HTMLHelper::_('select.option', $store, Text::_('JLIB_FORM_VALUE_CACHE_' . $store), 'value', 'text'); } return $options; } /** * Get a list of all installed components and also translates them. * * Available params: * - client_ids Array of Joomla application client IDs * * @param array $params * * @return stdClass[] * @since 3.3.0 * @internal * * @noinspection PhpUnusedPrivateMethodInspection */ private static function _api_components(array $params = []): array { $db = JoomlaFactory::getDbo(); // Check for client_ids override $client_ids = $params['client_ids'] ?? [0, 1]; if (is_string($client_ids)) { $client_ids = explode(',', $client_ids); } // Calculate client_ids where clause $client_ids = array_map(function ($client_id) use ($db) { return $db->q((int) trim($client_id)); }, $client_ids); $query = $db->getQuery(true) ->select( [ $db->qn('name'), $db->qn('element'), $db->qn('client_id'), $db->qn('manifest_cache'), ] ) ->from($db->qn('#__extensions')) ->where($db->qn('type') . ' = ' . $db->q('component')) ->where($db->qn('client_id') . ' IN (' . implode(',', $client_ids) . ')'); $components = $db->setQuery($query)->loadObjectList('element'); // Convert to array of objects, so we can use sortObjects() // Also translate component names with Text::_() $aComponents = []; $user = JoomlaFactory::getUser(); foreach ($components as $component) { // Don't show components in the list where the user doesn't have access for // TODO: perhaps add an option for this if (!$user->authorise('core.manage', $component->element)) { continue; } $aComponents[$component->element] = (object) [ 'value' => $component->element, 'text' => self::_translateComponentName($component), ]; } // Reorder the components array, because the alphabetical // ordering changed due to the Text::_() translation uasort( $aComponents, function ($a, $b) { return strcasecmp($a->text, $b->text); } ); return $aComponents; } /** * Method to get the field options. * * Available params: * - client 'site' (default) or 'administrator' * - none Text to show for "all languages" option, use empty string to remove it * * @param array $params * * @return object[] Languages for the specified client * @since 3.3.0 * @internal * * @noinspection PhpUnusedPrivateMethodInspection */ private static function _api_languages(array $params): array { $client = $params['client'] ?? 'site'; if (!in_array($client, ['site', 'administrator'])) { $client = 'site'; } // Make sure the languages are sorted base on locale instead of random sorting $options = LanguageHelper::createLanguageList(null, constant('JPATH_' . strtoupper($client)), true, true); if (count($options) > 1) { usort( $options, function ($a, $b) { return strcmp($a['value'], $b['value']); } ); } $none = $params['none'] ?? '*'; if (!empty($none)) { array_unshift($options, HTMLHelper::_('select.option', '*', Text::_($none))); } return $options; } /** * Options for a Published field * * Params: * - none Placeholder for no selection (empty key). Default: null. * - published Show "Published"? Default: true * - unpublished Show "Unpublished"? Default: true * - archived Show "Archived"? Default: false * - trash Show "Trashed"? Default: false * - all Show "All" option? This is different than none, the key is '*'. Default: false * * @param array $params * * @return array * @since 3.3.0 * @internal * * @noinspection PhpUnusedPrivateMethodInspection */ private static function _api_published(array $params = []): array { $config = array_merge([ 'none' => '', 'published' => true, 'unpublished' => true, 'archived' => false, 'trash' => false, 'all' => false, ], $params); $options = []; if (!empty($config['none'])) { $options[] = HTMLHelper::_('select.option', '', Text::_($config['none'])); } if ($config['published']) { $options[] = HTMLHelper::_('select.option', '1', Text::_('JPUBLISHED')); } if ($config['unpublished']) { $options[] = HTMLHelper::_('select.option', '0', Text::_('JUNPUBLISHED')); } if ($config['archived']) { $options[] = HTMLHelper::_('select.option', '2', Text::_('JARCHIVED')); } if ($config['trash']) { $options[] = HTMLHelper::_('select.option', '-2', Text::_('JTRASHED')); } if ($config['all']) { $options[] = HTMLHelper::_('select.option', '*', Text::_('JALL')); } return $options; } /** * Options for a Published field * * Params: * - none Placeholder for no selection (empty key). Default: null. * * @param array $params * * @return array * @since 3.3.0 * @internal * * @noinspection PhpUnusedPrivateMethodInspection */ private static function _api_boolean(array $params = []): array { $config = array_merge([ 'none' => '', ], $params); $options = []; if (!empty($config['none'])) { $options[] = HTMLHelper::_('select.option', '', Text::_($config['none'])); } $options[] = HTMLHelper::_('select.option', '1', Text::_('JYES')); $options[] = HTMLHelper::_('select.option', '0', Text::_('JNO')); return $options; } /** * Translate a component name * * @param object $item The component object * * @return string $text The translated name of the extension * @since 3.3.0 * @internal * * @see /administrator/com_installer/models/extension.php */ private static function _translateComponentName(object $item): string { // Map the manifest cache to $item. This is needed to get the name from the // manifest_cache and NOT from the name column, else some Text::_() translations fails. $mData = json_decode($item->manifest_cache); if ($mData) { foreach ($mData as $key => $value) { if ($key == 'type') { // Ignore the type field continue; } $item->$key = $value; } } $lang = JoomlaFactory::getLanguage(); $source = JPATH_ADMINISTRATOR . '/components/' . $item->element; $lang->load("$item->element.sys", JPATH_ADMINISTRATOR, null, false, false) || $lang->load("$item->element.sys", $source, null, false, false) || $lang->load("$item->element.sys", JPATH_ADMINISTRATOR, $lang->getDefault(), false, false) || $lang->load("$item->element.sys", $source, $lang->getDefault(), false, false); return Text::_($item->name); } } PK \\�\�J@��y �y FEFHelper/browse.phpnu �[��� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ defined('_JEXEC') || die; use FOF40\Html\FEFHelper\BrowseView; use FOF40\Model\DataModel; use FOF40\Utils\ArrayHelper; use FOF40\View\DataView\DataViewInterface; use FOF40\View\DataView\Raw as DataViewRaw; use Joomla\CMS\Factory as JoomlaFactory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Pagination\Pagination; /** * Custom JHtml (HTMLHelper) class. Offers browse view controls compatible with Akeeba Frontend * Framework (FEF). * * Call these methods as HTMLHelper::_('FEFHelp.browse.methodName', $parameter1, $parameter2, ...) * * @noinspection PhpIllegalPsrClassPathInspection */ abstract class FEFHelpBrowse { /** * Returns an action button on the browse view's table * * @param integer $i The row index * @param string $task The task to fire when the button is clicked * @param string|array $prefix An optional task prefix or an array of options * @param string $active_title An optional active tooltip to display if $enable is true * @param string $inactive_title An optional inactive tooltip to display if $enable is true * @param boolean $tip An optional setting for tooltip * @param string $active_class An optional active HTML class * @param string $inactive_class An optional inactive HTML class * @param boolean $enabled An optional setting for access control on the action. * @param boolean $translate An optional setting for translation. * @param string $checkbox An optional prefix for checkboxes. * * @return string The HTML markup * * @since 3.3.0 */ public static function action(int $i, string $task, $prefix = '', string $active_title = '', string $inactive_title = '', bool $tip = false, string $active_class = '', string $inactive_class = '', bool $enabled = true, bool $translate = true, string $checkbox = 'cb'): string { if (is_array($prefix)) { $options = $prefix; $active_title = array_key_exists('active_title', $options) ? $options['active_title'] : $active_title; $inactive_title = array_key_exists('inactive_title', $options) ? $options['inactive_title'] : $inactive_title; $tip = array_key_exists('tip', $options) ? $options['tip'] : $tip; $active_class = array_key_exists('active_class', $options) ? $options['active_class'] : $active_class; $inactive_class = array_key_exists('inactive_class', $options) ? $options['inactive_class'] : $inactive_class; $enabled = array_key_exists('enabled', $options) ? $options['enabled'] : $enabled; $translate = array_key_exists('translate', $options) ? $options['translate'] : $translate; $checkbox = array_key_exists('checkbox', $options) ? $options['checkbox'] : $checkbox; $prefix = array_key_exists('prefix', $options) ? $options['prefix'] : ''; } if ($tip) { $title = $enabled ? $active_title : $inactive_title; $title = $translate ? Text::_($title) : $title; $title = HTMLHelper::_('tooltipText', $title, '', 0); } if ($enabled) { $btnColor = 'grey'; if (substr($active_class, 0, 2) == '--') { [$btnColor, $active_class] = explode(' ', $active_class, 2); $btnColor = ltrim($btnColor, '-'); } $html = []; $html[] = '<a class="akeeba-btn--' . $btnColor . '--mini ' . ($active_class === 'publish' ? ' active' : '') . ($tip ? ' hasTooltip' : '') . '"'; $html[] = ' href="javascript:void(0);" onclick="return Joomla.listItemTask(\'' . $checkbox . $i . '\',\'' . $prefix . $task . '\')"'; $html[] = $tip ? ' title="' . $title . '"' : ''; $html[] = '>'; $html[] = '<span class="akion-' . $active_class . '" aria-hidden="true"></span> '; $html[] = '</a>'; return implode($html); } $btnColor = 'grey'; if (substr($inactive_class, 0, 2) == '--') { [$btnColor, $inactive_class] = explode(' ', $inactive_class, 2); $btnColor = ltrim($btnColor, '-'); } $html = []; $html[] = '<a class="akeeba-btn--' . $btnColor . '--mini disabled akeebagrid' . ($tip ? ' hasTooltip' : '') . '"'; $html[] = $tip ? ' title="' . $title . '"' : ''; $html[] = '>'; if ($active_class === 'protected') { $inactive_class = 'locked'; } $html[] = '<span class="akion-' . $inactive_class . '"></span> '; $html[] = '</a>'; return implode($html); } /** * Returns a state change button on the browse view's table * * @param array $states array of value/state. Each state is an array of the form * (task, text, active title, inactive title, tip (boolean), HTML active class, * HTML inactive class) or ('task'=>task, 'text'=>text, 'active_title'=>active * title, * 'inactive_title'=>inactive title, 'tip'=>boolean, 'active_class'=>html active * class, * 'inactive_class'=>html inactive class) * @param integer $value The state value. * @param integer $i The row index * @param string|array $prefix An optional task prefix or an array of options * @param boolean $enabled An optional setting for access control on the action. * @param boolean $translate An optional setting for translation. * @param string $checkbox An optional prefix for checkboxes. * * @return string The HTML markup * * @since 3.3.0 */ public static function state(array $states, int $value, int $i, $prefix = '', bool $enabled = true, bool $translate = true, string $checkbox = 'cb'): string { if (is_array($prefix)) { $options = $prefix; $enabled = array_key_exists('enabled', $options) ? $options['enabled'] : $enabled; $translate = array_key_exists('translate', $options) ? $options['translate'] : $translate; $checkbox = array_key_exists('checkbox', $options) ? $options['checkbox'] : $checkbox; $prefix = array_key_exists('prefix', $options) ? $options['prefix'] : ''; } $state = ArrayHelper::getValue($states, (int) $value, $states[0]); $task = array_key_exists('task', $state) ? $state['task'] : $state[0]; $text = array_key_exists('text', $state) ? $state['text'] : (array_key_exists(1, $state) ? $state[1] : ''); $active_title = array_key_exists('active_title', $state) ? $state['active_title'] : (array_key_exists(2, $state) ? $state[2] : ''); $inactive_title = array_key_exists('inactive_title', $state) ? $state['inactive_title'] : (array_key_exists(3, $state) ? $state[3] : ''); $tip = array_key_exists('tip', $state) ? $state['tip'] : (array_key_exists(4, $state) ? $state[4] : false); $active_class = array_key_exists('active_class', $state) ? $state['active_class'] : (array_key_exists(5, $state) ? $state[5] : ''); $inactive_class = array_key_exists('inactive_class', $state) ? $state['inactive_class'] : (array_key_exists(6, $state) ? $state[6] : ''); return static::action( $i, $task, $prefix, $active_title, $inactive_title, $tip, $active_class, $inactive_class, $enabled, $translate, $checkbox ); } /** * Returns a published state on the browse view's table * * @param integer $value The state value. * @param integer $i The row index * @param string|array $prefix An optional task prefix or an array of options * @param boolean $enabled An optional setting for access control on the action. * @param string $checkbox An optional prefix for checkboxes. * @param string $publish_up An optional start publishing date. * @param string $publish_down An optional finish publishing date. * * @return string The HTML markup * * @see self::state() * * @since 3.3.0 */ public static function published(int $value, int $i, $prefix = '', bool $enabled = true, string $checkbox = 'cb', ?string $publish_up = null, ?string $publish_down = null): string { if (is_array($prefix)) { $options = $prefix; $enabled = array_key_exists('enabled', $options) ? $options['enabled'] : $enabled; $checkbox = array_key_exists('checkbox', $options) ? $options['checkbox'] : $checkbox; $prefix = array_key_exists('prefix', $options) ? $options['prefix'] : ''; } /** * Format: * * (task, text, active title, inactive title, tip (boolean), active icon class (without akion-), inactive icon class (without akion-)) */ $states = [ 1 => [ 'unpublish', 'JPUBLISHED', 'JLIB_HTML_UNPUBLISH_ITEM', 'JPUBLISHED', true, '--green checkmark', '--green checkmark', ], 0 => [ 'publish', 'JUNPUBLISHED', 'JLIB_HTML_PUBLISH_ITEM', 'JUNPUBLISHED', true, '--red close', '--red close', ], 2 => [ 'unpublish', 'JARCHIVED', 'JLIB_HTML_UNPUBLISH_ITEM', 'JARCHIVED', true, '--orange ion-ios-box', '--orange ion-ios-box', ], -2 => [ 'publish', 'JTRASHED', 'JLIB_HTML_PUBLISH_ITEM', 'JTRASHED', true, '--dark trash-a', '--dark trash-a', ], ]; // Special state for dates if ($publish_up || $publish_down) { $nullDate = JoomlaFactory::getDbo()->getNullDate(); $nowDate = JoomlaFactory::getDate()->toUnix(); $tz = JoomlaFactory::getUser()->getTimezone(); $publish_up = (!empty($publish_up) && ($publish_up != $nullDate)) ? JoomlaFactory::getDate($publish_up, 'UTC')->setTimeZone($tz) : false; $publish_down = (!empty($publish_down) && ($publish_down != $nullDate)) ? JoomlaFactory::getDate($publish_down, 'UTC')->setTimeZone($tz) : false; // Create tip text, only we have publish up or down settings $tips = []; if ($publish_up) { $tips[] = Text::sprintf('JLIB_HTML_PUBLISHED_START', HTMLHelper::_('date', $publish_up, Text::_('DATE_FORMAT_LC5'), 'UTC')); } if ($publish_down) { $tips[] = Text::sprintf('JLIB_HTML_PUBLISHED_FINISHED', HTMLHelper::_('date', $publish_down, Text::_('DATE_FORMAT_LC5'), 'UTC')); } $tip = empty($tips) ? false : implode('<br />', $tips); // Add tips and special titles foreach (array_keys($states) as $key) { // Create special titles for published items if ($key == 1) { $states[$key][2] = $states[$key][3] = 'JLIB_HTML_PUBLISHED_ITEM'; if (!empty($publish_up) && ($publish_up != $nullDate) && $nowDate < $publish_up->toUnix()) { $states[$key][2] = $states[$key][3] = 'JLIB_HTML_PUBLISHED_PENDING_ITEM'; $states[$key][5] = $states[$key][6] = 'android-time'; } if (!empty($publish_down) && ($publish_down != $nullDate) && $nowDate > $publish_down->toUnix()) { $states[$key][2] = $states[$key][3] = 'JLIB_HTML_PUBLISHED_EXPIRED_ITEM'; $states[$key][5] = $states[$key][6] = 'alert'; } } // Add tips to titles if ($tip) { $states[$key][1] = Text::_($states[$key][1]); $states[$key][2] = Text::_($states[$key][2]) . '<br />' . $tip; $states[$key][3] = Text::_($states[$key][3]) . '<br />' . $tip; $states[$key][4] = true; } } return static::state($states, $value, $i, [ 'prefix' => $prefix, 'translate' => !$tip, ], $enabled, true, $checkbox); } return static::state($states, $value, $i, $prefix, $enabled, true, $checkbox); } /** * Returns an isDefault state on the browse view's table * * @param integer $value The state value. * @param integer $i The row index * @param string|array $prefix An optional task prefix or an array of options * @param boolean $enabled An optional setting for access control on the action. * @param string $checkbox An optional prefix for checkboxes. * * @return string The HTML markup * * @see self::state() * @since 3.3.0 */ public static function isdefault(int $value, int $i, $prefix = '', bool $enabled = true, string $checkbox = 'cb'): string { if (is_array($prefix)) { $options = $prefix; $enabled = array_key_exists('enabled', $options) ? $options['enabled'] : $enabled; $checkbox = array_key_exists('checkbox', $options) ? $options['checkbox'] : $checkbox; $prefix = array_key_exists('prefix', $options) ? $options['prefix'] : ''; } $states = [ 0 => ['setDefault', '', 'JLIB_HTML_SETDEFAULT_ITEM', '', 1, 'android-star-outline', 'android-star-outline'], 1 => [ 'unsetDefault', 'JDEFAULT', 'JLIB_HTML_UNSETDEFAULT_ITEM', 'JDEFAULT', 1, 'android-star', 'android-star', ], ]; return static::state($states, $value, $i, $prefix, $enabled, true, $checkbox); } /** * Returns a checked-out icon * * @param integer $i The row index. * @param string $editorName The name of the editor. * @param string $time The time that the object was checked out. * @param string|array $prefix An optional task prefix or an array of options * @param boolean $enabled True to enable the action. * @param string $checkbox An optional prefix for checkboxes. * * @return string The HTML markup * * @since 3.3.0 */ public static function checkedout(int $i, string $editorName, string $time, $prefix = '', bool $enabled = false, string $checkbox = 'cb'): string { HTMLHelper::_('bootstrap.tooltip'); if (is_array($prefix)) { $options = $prefix; $enabled = array_key_exists('enabled', $options) ? $options['enabled'] : $enabled; $checkbox = array_key_exists('checkbox', $options) ? $options['checkbox'] : $checkbox; $prefix = array_key_exists('prefix', $options) ? $options['prefix'] : ''; } $text = $editorName . '<br />' . HTMLHelper::_('date', $time, Text::_('DATE_FORMAT_LC')) . '<br />' . HTMLHelper::_('date', $time, 'H:i'); $active_title = HTMLHelper::_('tooltipText', Text::_('JLIB_HTML_CHECKIN'), $text, 0); $inactive_title = HTMLHelper::_('tooltipText', Text::_('JLIB_HTML_CHECKED_OUT'), $text, 0); return static::action( $i, 'checkin', $prefix, html_entity_decode($active_title, ENT_QUOTES, 'UTF-8'), html_entity_decode($inactive_title, ENT_QUOTES, 'UTF-8'), true, 'locked', 'locked', $enabled, false, $checkbox ); } /** * Returns the drag'n'drop reordering field for Browse views * * @param string $orderingField The name of the field you're ordering by * @param string $order The order value of the current row * @param string $class CSS class for the ordering value INPUT field * @param string $icon CSS class for the d'n'd handle icon * @param string $inactiveIcon CSS class for the d'n'd disabled icon * @param DataViewInterface $view The view you're rendering against. Leave null for auto-detection. * * @return string */ public static function order(string $orderingField, ?string $order, string $class = 'input-sm', string $icon = 'akion-android-more-vertical', string $inactiveIcon = 'akion-android-more-vertical', DataViewInterface $view = null): string { $order = $order ?? 'asc'; /** @var \FOF40\View\DataView\Html $view */ if (is_null($view)) { $view = BrowseView::getViewFromBacktrace(); } $dndOrderingActive = $view->getLists()->order == $orderingField; // Default inactive ordering $html = '<span class="sortable-handler inactive" >'; $html .= '<span class="' . $icon . '"></span>'; $html .= '</span>'; // The modern drag'n'drop method if ($view->getPerms()->editstate) { $disableClassName = ''; $disabledLabel = ''; // DO NOT REMOVE! It will initialize Joomla libraries and javascript functions $hasAjaxOrderingSupport = $view->hasAjaxOrderingSupport(); if (!is_array($hasAjaxOrderingSupport) || !$hasAjaxOrderingSupport['saveOrder']) { $disabledLabel = Text::_('JORDERINGDISABLED'); $disableClassName = 'inactive tip-top hasTooltip'; } $orderClass = $dndOrderingActive ? 'order-enabled' : 'order-disabled'; $html = '<div class="' . $orderClass . '">'; $html .= '<span class="sortable-handler ' . $disableClassName . '" title="' . $disabledLabel . '">'; $html .= '<span class="' . ($disableClassName ? $inactiveIcon : $icon) . '"></span>'; $html .= '</span>'; if ($dndOrderingActive) { $html .= '<input type="text" name="order[]" style="display: none" size="5" class="' . $class . ' text-area-order" value="' . $order . '" />'; } $html .= '</div>'; } return $html; } /** * Returns the drag'n'drop reordering table header for Browse views * * @param string $orderingField The name of the field you're ordering by * @param string $icon CSS class for the d'n'd handle icon * * @return string */ public static function orderfield(string $orderingField = 'ordering', string $icon = 'akion-stats-bars'): string { $title = Text::_('JGLOBAL_CLICK_TO_SORT_THIS_COLUMN'); $orderingLabel = Text::_('JFIELD_ORDERING_LABEL'); return <<< HTML <a href="#" onclick="Joomla.tableOrdering('{$orderingField}','asc','');return false;" class="hasPopover" title="{$orderingLabel}" data-content="{$title}" data-placement="top" > <span class="{$icon}"></span> </a> HTML; } /** * Creates an order-up action icon. * * @param integer $i The row index. * @param string $task An optional task to fire. * @param string|array $prefix An optional task prefix or an array of options * @param string $text An optional text to display * @param boolean $enabled An optional setting for access control on the action. * @param string $checkbox An optional prefix for checkboxes. * * @return string The HTML markup * * @since 3.3.0 */ public static function orderUp(int $i, string $task = 'orderup', $prefix = '', string $text = 'JLIB_HTML_MOVE_UP', bool $enabled = true, string $checkbox = 'cb'): string { if (is_array($prefix)) { $options = $prefix; $text = array_key_exists('text', $options) ? $options['text'] : $text; $enabled = array_key_exists('enabled', $options) ? $options['enabled'] : $enabled; $checkbox = array_key_exists('checkbox', $options) ? $options['checkbox'] : $checkbox; $prefix = array_key_exists('prefix', $options) ? $options['prefix'] : ''; } return static::action($i, $task, $prefix, $text, $text, false, 'arrow-up-b', 'arrow-up-b', $enabled, true, $checkbox); } /** * Creates an order-down action icon. * * @param integer $i The row index. * @param string $task An optional task to fire. * @param string|array $prefix An optional task prefix or an array of options * @param string $text An optional text to display * @param boolean $enabled An optional setting for access control on the action. * @param string $checkbox An optional prefix for checkboxes. * * @return string The HTML markup * * @since 3.3.0 */ public static function orderDown(int $i, string $task = 'orderdown', string $prefix = '', string $text = 'JLIB_HTML_MOVE_DOWN', bool $enabled = true, string $checkbox = 'cb'): string { if (is_array($prefix)) { $options = $prefix; $text = array_key_exists('text', $options) ? $options['text'] : $text; $enabled = array_key_exists('enabled', $options) ? $options['enabled'] : $enabled; $checkbox = array_key_exists('checkbox', $options) ? $options['checkbox'] : $checkbox; $prefix = array_key_exists('prefix', $options) ? $options['prefix'] : ''; } return static::action($i, $task, $prefix, $text, $text, false, 'arrow-down-b', 'arrow-down-b', $enabled, true, $checkbox); } /** * Table header for a field which changes the sort order when clicked * * @param string $title The link title * @param string $order The order field for the column * @param string $direction The current direction * @param string $selected The selected ordering * @param string $task An optional task override * @param string $new_direction An optional direction for the new column * @param string $tip An optional text shown as tooltip title instead of $title * @param string $form An optional form selector * * @return string * * @since 3.3.0 */ public static function sort(string $title, string $order, ?string $direction = 'asc', string $selected = '', ?string $task = null, string $new_direction = 'asc', string $tip = '', ?string $form = null): string { HTMLHelper::_('behavior.core'); HTMLHelper::_('bootstrap.popover'); $direction = strtolower($direction ?? 'asc'); $icon = ['akion-android-arrow-dropup', 'akion-android-arrow-dropdown']; $index = (int) ($direction === 'desc'); if ($order !== $selected) { $direction = $new_direction; } else { $direction = $direction === 'desc' ? 'asc' : 'desc'; } if ($form) { $form = ', document.getElementById(\'' . $form . '\')'; } $html = '<a href="#" onclick="Joomla.tableOrdering(\'' . $order . '\',\'' . $direction . '\',\'' . $task . '\'' . $form . ');return false;"' . ' class="hasPopover" title="' . htmlspecialchars(Text::_($tip ?: $title)) . '"' . ' data-content="' . htmlspecialchars(Text::_('JGLOBAL_CLICK_TO_SORT_THIS_COLUMN')) . '" data-placement="top">'; if (isset($title['0']) && $title['0'] === '<') { $html .= $title; } else { $html .= Text::_($title); } if ($order === $selected) { $html .= '<span class="' . $icon[$index] . '"></span>'; } return $html . '</a>'; } /** * Method to check all checkboxes on the browse view's table * * @param string $name The name of the form element * @param string $tip The text shown as tooltip title instead of $tip * @param string $action The action to perform on clicking the checkbox * * @return string * * @since 3.3.0 */ public static function checkall(string $name = 'checkall-toggle', string $tip = 'JGLOBAL_CHECK_ALL', string $action = 'Joomla.checkAll(this)'): string { HTMLHelper::_('behavior.core'); HTMLHelper::_('bootstrap.tooltip'); return '<input type="checkbox" name="' . $name . '" value="" class="hasTooltip" title="' . HTMLHelper::_('tooltipText', $tip) . '" onclick="' . $action . '" />'; } /** * Method to create a checkbox for a grid row. * * @param integer $rowNum The row index * @param mixed $recId The record id * @param boolean $checkedOut True if item is checked out * @param string $name The name of the form element * @param string $stub The name of stub identifier * * @return mixed String of html with a checkbox if item is not checked out, empty if checked out. * * @since 3.3.0 */ public static function id(int $rowNum, $recId, bool $checkedOut = false, string $name = 'cid', string $stub = 'cb'): string { return $checkedOut ? '' : '<input type="checkbox" id="' . $stub . $rowNum . '" name="' . $name . '[]" value="' . $recId . '" onclick="Joomla.isChecked(this.checked);" />'; } /** * Include the necessary JavaScript for the browse view's table order feature * * @param string $orderBy Filed by which we are currently sorting the table. * @param bool $return Should I return the JS? Default: false (= add to the page's head) * * @return string */ public static function orderjs(string $orderBy, bool $return = false): ?string { $js = <<< JS Joomla.orderTable = function() { var table = document.getElementById("sortTable"); var direction = document.getElementById("directionTable"); var order = table.options[table.selectedIndex].value; var dirn = 'asc'; if (order !== '$orderBy') { dirn = 'asc'; } else { dirn = direction.options[direction.selectedIndex].value; } Joomla.tableOrdering(order, dirn); }; JS; if ($return) { return $js; } try { JoomlaFactory::getApplication()->getDocument()->addScriptDeclaration($js); } catch (Exception $e) { // If we have no application, well, not having table sorting JS is the least of your worries... } return null; } /** * Returns the table ordering / pagination header for a browse view: number of records to display, order direction, * order by field. * * @param DataViewRaw $view The view you're rendering against. If not provided we will guess it using * MAGIC. * @param array $sortFields Array of field name => description for the ordering fields in the dropdown. * If not provided we will use all the fields available in the model. * @param Pagination $pagination The Joomla pagination object. If not provided we fetch it from the view. * @param string $sortBy Order by field name. If not provided we fetch it from the view. * @param string $order_Dir Order direction. If not provided we fetch it from the view. * * @return string * * @since 3.3.0 */ public static function orderheader(DataViewRaw $view = null, array $sortFields = [], Pagination $pagination = null, ?string $sortBy = null, ?string $order_Dir = null): string { if (is_null($view)) { $view = BrowseView::getViewFromBacktrace(); } $showBrowsePagination = $view->showBrowsePagination ?? true; $showBrowseOrdering = $view->showBrowseOrdering ?? true; $showBrowseOrderBy = $view->showBrowseOrderBy ?? true; if (!$showBrowsePagination && !$showBrowseOrdering && !$showBrowseOrderBy) { return ''; } if (empty($sortFields)) { /** @var DataModel $model */ $model = $view->getModel(); $sortFields = $view->getLists()->sortFields ?? []; $sortFields = empty($sortFields) ? self::getSortFields($model) : $sortFields; } if (empty($pagination)) { $pagination = $view->getPagination(); } if (empty($sortBy)) { $sortBy = $view->getLists()->order; } if (empty($order_Dir)) { $order_Dir = $view->getLists()->order_Dir; if (empty($order_Dir)) { $order_Dir = 'asc'; } } // Static hidden text labels $limitLabel = Text::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC'); $orderingDecr = Text::_('JFIELD_ORDERING_DESC'); $sortByLabel = Text::_('JGLOBAL_SORT_BY'); // Order direction dropdown $directionSelect = HTMLHelper::_('FEFHelp.select.genericlist', [ '' => $orderingDecr, 'asc' => Text::_('JGLOBAL_ORDER_ASCENDING'), 'desc' => Text::_('JGLOBAL_ORDER_DESCENDING'), ], 'directionTable', [ 'id' => 'directionTable', 'list.select' => $order_Dir, 'list.attr' => [ 'class' => 'input-medium custom-select akeebaCommonEventsOnChangeOrderTable', ], ]); // Sort by field dropdown $sortTable = HTMLHelper::_('FEFHelp.select.genericlist', array_merge([ '' => Text::_('JGLOBAL_SORT_BY'), ], $sortFields), 'sortTable', [ 'id' => 'sortTable', 'list.select' => $sortBy, 'list.attr' => [ 'class' => 'input-medium custom-select akeebaCommonEventsOnChangeOrderTable', ], ]); $html = ''; if ($showBrowsePagination) { $html .= <<< HTML <div class="akeeba-filter-element akeeba-form-group"> <label for="limit" class="element-invisible"> $limitLabel </label> {$pagination->getLimitBox()} </div> HTML; } if ($showBrowseOrdering) { $html .= <<< HTML <div class="akeeba-filter-element akeeba-form-group"> <label for="directionTable" class="element-invisible"> $orderingDecr </label> $directionSelect </div> HTML; } if ($showBrowseOrderBy) { $html .= <<< HTML <div class="akeeba-filter-element akeeba-form-group"> <label for="sortTable" class="element-invisible"> {$sortByLabel} </label> $sortTable </div> HTML; } return $html; } /** * Get the default sort fields from a model. It creates a hash array where the keys are the model's field names and * the values are the translation keys for their names, following FOF's naming conventions. * * @param DataModel $model The model for which we get the sort fields * * @return array * * @since 3.3.0 */ private static function getSortFields(DataModel $model): array { $sortFields = []; $idField = $model->getIdFieldName() ?: 'id'; $defaultFieldLabels = [ 'publish_up' => 'JGLOBAL_FIELD_PUBLISH_UP_LABEL', 'publish_down' => 'JGLOBAL_FIELD_PUBLISH_DOWN_LABEL', 'created_by' => 'JGLOBAL_FIELD_CREATED_BY_LABEL', 'created_on' => 'JGLOBAL_FIELD_CREATED_LABEL', 'modified_by' => 'JGLOBAL_FIELD_MODIFIED_BY_LABEL', 'modified_on' => 'JGLOBAL_FIELD_MODIFIED_LABEL', 'ordering' => 'JGLOBAL_FIELD_FIELD_ORDERING_LABEL', 'id' => 'JGLOBAL_FIELD_ID_LABEL', 'hits' => 'JGLOBAL_HITS', 'title' => 'JGLOBAL_TITLE', 'user_id' => 'JGLOBAL_USERNAME', 'username' => 'JGLOBAL_USERNAME', ]; $componentName = $model->getContainer()->componentName; $viewNameSingular = $model->getContainer()->inflector->singularize($model->getName()); $viewNamePlural = $model->getContainer()->inflector->pluralize($model->getName()); foreach (array_keys($model->getFields()) as $field) { $possibleKeys = [ $componentName . '_' . $viewNamePlural . '_FIELD_' . $field, $componentName . '_' . $viewNamePlural . '_' . $field, $componentName . '_' . $viewNameSingular . '_FIELD_' . $field, $componentName . '_' . $viewNameSingular . '_' . $field, ]; if (array_key_exists($field, $defaultFieldLabels)) { $possibleKeys[] = $defaultFieldLabels[$field]; } if ($field === $idField) { $possibleKeys[] = $defaultFieldLabels['id']; } $fieldLabel = ''; foreach ($possibleKeys as $langKey) { $langKey = strtoupper($langKey); $fieldLabel = Text::_($langKey); if ($fieldLabel !== $langKey) { break; } $fieldLabel = ''; } if (!empty($fieldLabel)) { $sortFields[$field] = (new Joomla\Filter\InputFilter())->clean($fieldLabel); } } return $sortFields; } } PK \\�\��G4q 4q FEFHelper/BrowseView.phpnu �[��� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Html\FEFHelper; defined('_JEXEC') || die; use FOF40\Container\Container; use FOF40\Html\SelectOptions; use FOF40\Model\DataModel; use FOF40\Utils\ArrayHelper; use FOF40\View\DataView\DataViewInterface; use FOF40\View\View; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; /** * An HTML helper for Browse views. * * It reintroduces a FEF-friendly of some of the functionality found in FOF 3's Header and Field classes. These * helpers are also accessible through Blade, making the transition from XML forms to Blade templates easier. * * @since 3.3.0 */ abstract class BrowseView { /** * Caches the results of getOptionsFromModel keyed by a hash. The hash is computed by the model * name, the model state and the options passed to getOptionsFromModel. * * @var array */ private static $cacheModelOptions = []; /** * Get the translation key for a field's label * * @param string $fieldName The field name * * @return string * * @since 3.3.0 */ public static function fieldLabelKey(string $fieldName): string { $view = self::getViewFromBacktrace(); try { $inflector = $view->getContainer()->inflector; $viewName = $inflector->singularize($view->getName()); $altViewName = $inflector->pluralize($view->getName()); $componentName = $view->getContainer()->componentName; $keys = [ strtoupper($componentName . '_' . $viewName . '_FIELD_' . $fieldName), strtoupper($componentName . '_' . $altViewName . '_FIELD_' . $fieldName), strtoupper($componentName . '_' . $viewName . '_' . $fieldName), strtoupper($componentName . '_' . $altViewName . '_' . $fieldName), ]; foreach ($keys as $key) { if (Text::_($key) !== $key) { return $key; } } return $keys[0]; } catch (\Exception $e) { return ucfirst($fieldName); } } /** * Returns the label for a field (translated) * * @param string $fieldName The field name * * @return string */ public static function fieldLabel(string $fieldName): string { return Text::_(self::fieldLabelKey($fieldName)); } /** * Return a table field header which sorts the table by that field upon clicking * * @param string $field The name of the field * @param string|null $langKey (optional) The language key for the header to be displayed * * @return string */ public static function sortgrid(string $field, ?string $langKey = null): string { /** @var DataViewInterface $view */ $view = self::getViewFromBacktrace(); if (is_null($langKey)) { $langKey = self::fieldLabelKey($field); } return HTMLHelper::_('FEFHelp.browse.sort', $langKey, $field, $view->getLists()->order_Dir, $view->getLists()->order, $view->getTask()); } /** * Create a browse view filter from values returned by a model * * @param string $localField Field name * @param string $modelTitleField Foreign model field for drop-down display values * @param null $modelName Foreign model name * @param string $placeholder Placeholder for no selection * @param array $params Generic select display parameters * * @return string * * @since 3.3.0 */ public static function modelFilter(string $localField, string $modelTitleField = 'title', ?string $modelName = null, ?string $placeholder = null, array $params = []): string { /** @var DataModel $model */ $model = self::getViewFromBacktrace()->getModel(); if (empty($modelName)) { $modelName = $model->getForeignModelNameFor($localField); } if (is_null($placeholder)) { $placeholder = self::fieldLabelKey($localField); } $params = array_merge([ 'list.none' => '— ' . Text::_($placeholder) . ' —', 'value_field' => $modelTitleField, 'fof.autosubmit' => true, ], $params); return self::modelSelect($localField, $modelName, $model->getState($localField), $params); } /** * Display a text filter (search box) * * @param string $localField The name of the model field. Used when getting the filter state. * @param string $searchField The INPUT element's name. Default: "filter_$localField". * @param string $placeholder The Text language key for the placeholder. Default: extrapolate from $localField. * @param array $attributes HTML attributes for the INPUT element. * * @return string * * @since 3.3.0 */ public static function searchFilter(string $localField, ?string $searchField = null, ?string $placeholder = null, array $attributes = []): string { /** @var DataModel $model */ $view = self::getViewFromBacktrace(); $model = $view->getModel(); $searchField = empty($searchField) ? $localField : $searchField; $placeholder = empty($placeholder) ? self::fieldLabelKey($localField) : $placeholder; $attributes['type'] = $attributes['type'] ?? 'text'; $attributes['name'] = $searchField; $attributes['id'] = !isset($attributes['id']) ? "filter_$localField" : $attributes['id']; $attributes['placeholder'] = !isset($attributes['placeholder']) ? $view->escape(Text::_($placeholder)) : $attributes['placeholder']; $attributes['title'] = $attributes['title'] ?? $attributes['placeholder']; $attributes['value'] = $view->escape($model->getState($localField)); if (!isset($attributes['onchange'])) { $attributes['class'] = trim(($attributes['class'] ?? '') . ' akeebaCommonEventsOnChangeSubmit'); $attributes['data-akeebasubmittarget'] = $attributes['data-akeebasubmittarget'] ?? 'adminForm'; } // Remove null attributes and collapse into a string $attributes = array_filter($attributes, function ($v) { return !is_null($v); }); $attributes = ArrayHelper::toString($attributes); return "<input $attributes />"; } /** * Create a browse view filter with dropdown values * * @param string $localField Field name * @param array $options The HTMLHelper options list to use * @param string $placeholder Placeholder for no selection * @param array $params Generic select display parameters * * @return string * * @since 3.3.0 */ public static function selectFilter(string $localField, array $options, ?string $placeholder = null, array $params = []): string { /** @var DataModel $model */ $model = self::getViewFromBacktrace()->getModel(); if (is_null($placeholder)) { $placeholder = self::fieldLabelKey($localField); } $params = array_merge([ 'list.none' => '— ' . Text::_($placeholder) . ' —', 'fof.autosubmit' => true, ], $params); return self::genericSelect($localField, $options, $model->getState($localField), $params); } /** * View access dropdown filter * * @param string $localField Field name * @param string $placeholder Placeholder for no selection * @param array $params Generic select display parameters * * @return string * * @since 3.3.0 */ public static function accessFilter(string $localField, ?string $placeholder = null, array $params = []): string { return self::selectFilter($localField, SelectOptions::getOptions('access', $params), $placeholder, $params); } /** * Published state dropdown filter * * @param string $localField Field name * @param string $placeholder Placeholder for no selection * @param array $params Generic select display parameters * * @return string * * @since 3.3.0 */ public static function publishedFilter(string $localField, ?string $placeholder = null, array $params = []): string { return self::selectFilter($localField, SelectOptions::getOptions('published', $params), $placeholder, $params); } /** * Create a select box from the values returned by a model * * @param string $name Field name * @param string $modelName The name of the model, e.g. "items" or "com_foobar.items" * @param mixed $currentValue The currently selected value * @param array $params Passed to optionsFromModel and genericSelect * @param array $modelState Optional state variables to pass to the model * @param array $options Any HTMLHelper select options you want to add in front of the model's returned * values * * @return string * * @see self::getOptionsFromModel * @see self::getOptionsFromSource * @see self::genericSelect * * @since 3.3.0 */ public static function modelSelect(string $name, string $modelName, $currentValue, array $params = [], array $modelState = [], array $options = []): string { $params = array_merge([ 'fof.autosubmit' => true, ], $params); $options = self::getOptionsFromModel($modelName, $params, $modelState, $options); return self::genericSelect($name, $options, $currentValue, $params); } /** * Get a (human readable) title from a (typically numeric, foreign key) key value using the data * returned by a DataModel. * * @param string $value The key value * @param string $modelName The name of the model, e.g. "items" or "com_foobar.items" * @param array $params Passed to getOptionsFromModel * @param array $modelState Optional state variables to pass to the model * @param array $options Any HTMLHelper select options you want to add in front of the model's returned * values * * @return string * * @see self::getOptionsFromModel * @see self::getOptionsFromSource * @see self::genericSelect * * @since 3.3.0 */ public static function modelOptionName(string $value, ?string $modelName = null, array $params = [], array $modelState = [], array $options = []): ?string { if (!isset($params['cache'])) { $params['cache'] = true; } if (!isset($params['none_as_zero'])) { $params['none_as_zero'] = true; } $options = self::getOptionsFromModel($modelName, $params, $modelState, $options); return self::getOptionName($value, $options); } /** * Gets the active option's label given an array of HTMLHelper options * * @param mixed $selected The currently selected value * @param array $data The HTMLHelper options to parse * @param string $optKey Key name, default: value * @param string $optText Value name, default: text * @param bool $selectFirst Should I automatically select the first option? Default: true * * @return mixed The label of the currently selected option */ public static function getOptionName($selected, array $data, string $optKey = 'value', string $optText = 'text', bool $selectFirst = true): ?string { $ret = null; foreach ($data as $elementKey => &$element) { if (is_array($element)) { $key = $optKey === null ? $elementKey : $element[$optKey]; $text = $element[$optText]; } elseif (is_object($element)) { $key = $optKey === null ? $elementKey : $element->$optKey; $text = $element->$optText; } else { // This is a simple associative array $key = $elementKey; $text = $element; } if (is_null($ret) && $selectFirst && ($selected == $key)) { $ret = $text; } elseif ($selected == $key) { $ret = $text; } } return $ret; } /** * Create a generic select list based on a bunch of options. Option sources will be merged into the provided * options automatically. * * Parameters: * - format.depth The current indent depth. * - format.eol The end of line string, default is linefeed. * - format.indent The string to use for indentation, default is tab. * - groups If set, looks for keys with the value "<optgroup>" and synthesizes groups from them. Deprecated. * Default: true. * - list.select Either the value of one selected option or an array of selected options. Default: $currentValue. * - list.translate If true, text and labels are translated via Text::_(). Default is false. * - list.attr HTML element attributes (key/value array or string) * - list.none Placeholder for no selection (creates an option with an empty string key) * - option.id The property in each option array to use as the selection id attribute. Defaults: null. * - option.key The property in each option array to use as the Default: "value". If set to null, the index of the * option array is used. * - option.label The property in each option array to use as the selection label attribute. Default: null * - option.text The property in each option array to use as the displayed text. Default: "text". If set to null, * the option array is assumed to be a list of displayable scalars. * - option.attr The property in each option array to use for additional selection attributes. Defaults: null. * - option.disable: The property that will hold the disabled state. Defaults to "disable". * - fof.autosubmit Should I auto-submit the form on change? Default: true * - fof.formname Form to auto-submit. Default: adminForm * - class CSS class to apply * - size Size attribute for the input * - multiple Is this a multiple select? Default: false. * - required Is this a required field? Default: false. * - autofocus Should I focus this field automatically? Default: false * - disabled Is this a disabled field? Default: false * - readonly Render as a readonly field with hidden inputs? Overrides 'disabled'. Default: false * - onchange Custom onchange handler. Overrides fof.autosubmit. Default: NULL (use fof.autosubmit). * * @param string $name * @param array $options * @param mixed $currentValue * @param array $params * * @return string * * @since 3.3.0 */ public static function genericSelect(string $name, array $options, $currentValue, array $params = []): string { $params = array_merge([ 'format.depth' => 0, 'format.eol' => "\n", 'format.indent' => "\t", 'groups' => true, 'list.select' => $currentValue, 'list.translate' => false, 'option.id' => null, 'option.key' => 'value', 'option.label' => null, 'option.text' => 'text', 'option.attr' => null, 'option.disable' => 'disable', 'list.attr' => '', 'list.none' => '', 'id' => null, 'fof.autosubmit' => true, 'fof.formname' => 'adminForm', 'class' => '', 'size' => '', 'multiple' => false, 'required' => false, 'autofocus' => false, 'disabled' => false, 'onchange' => null, 'readonly' => false, ], $params); $currentValue = $params['list.select']; $classes = $params['class'] ?? ''; $classes = is_array($classes) ? implode(' ', $classes) : $classes; // If fof.autosubmit is enabled and onchange is not set we will add our own handler if ($params['fof.autosubmit'] && is_null($params['onchange'])) { $formName = $params['fof.formname'] ?: 'adminForm'; $classes .= ' akeebaCommonEventsOnChangeSubmit'; $params['data-akeebasubmittarget'] = $formName; } // Construct SELECT element's attributes $attr = [ 'class' => trim($classes) ?: null, 'size' => ($params['size'] ?? null) ?: null, 'multiple' => ($params['multiple'] ?? null) ?: null, 'required' => ($params['required'] ?? false) ?: null, 'aria-required' => ($params['required'] ?? false) ? 'true' : null, 'autofocus' => ($params['autofocus'] ?? false) ?: null, 'disabled' => (($params['disabled'] ?? false) || ($params['readonly'] ?? false)) ?: null, 'onchange' => $params['onchange'] ?? null, ]; $attr = array_filter($attr, function ($x) { return !is_null($x); }); // We merge the constructed SELECT element's attributes with the 'list.attr' array, if it was provided $params['list.attr'] = array_merge($attr, (($params['list.attr'] ?? []) ?: [])); // Merge the options with those fetched from a source (e.g. another Helper object) $options = array_merge($options, self::getOptionsFromSource($params)); if (!empty($params['list.none'])) { array_unshift($options, HTMLHelper::_('FEFHelp.select.option', '', Text::_($params['list.none']))); } $html = []; // Create a read-only list (no name) with hidden input(s) to store the value(s). if ($params['readonly']) { $html[] = HTMLHelper::_('FEFHelp.select.genericlist', $options, $name, $params); // E.g. form field type tag sends $this->value as array if ($params['multiple'] && is_array($currentValue)) { if (count($currentValue) === 0) { $currentValue[] = ''; } foreach ($currentValue as $value) { $html[] = '<input type="hidden" name="' . $name . '" value="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '"/>'; } } else { $html[] = '<input type="hidden" name="' . $name . '" value="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '"/>'; } } else // Create a regular list. { $html[] = HTMLHelper::_('FEFHelp.select.genericlist', $options, $name, $params); } return implode($html); } /** * Replace tags that reference fields with their values * * @param string $text Text to process * @param DataModel $item The DataModel instance to get values from * * @return string Text with tags replace * * @since 3.3.0 */ public static function parseFieldTags(string $text, DataModel $item): string { $ret = $text; if (empty($item)) { return $ret; } /** * Replace [ITEM:ID] in the URL with the item's key value (usually: the auto-incrementing numeric ID) */ $replace = $item->getId(); $ret = str_replace('[ITEM:ID]', $replace, $ret); // Replace the [ITEMID] in the URL with the current Itemid parameter $ret = str_replace('[ITEMID]', $item->getContainer()->input->getInt('Itemid', 0), $ret); // Replace the [TOKEN] in the URL with the Joomla! form token $ret = str_replace('[TOKEN]', $item->getContainer()->platform->getToken(true), $ret); // Replace other field variables in the URL $data = $item->getData(); foreach ($data as $field => $value) { // Skip non-processable values if (is_array($value) || is_object($value)) { continue; } $search = '[ITEM:' . strtoupper($field) . ']'; $ret = str_replace($search, $value, $ret); } return $ret; } /** * Get the FOF View from the backtrace of the static call. MAGIC! * * @return View * * @since 3.3.0 */ public static function getViewFromBacktrace(): View { // In case we are on a brain-dead host if (!function_exists('debug_backtrace')) { throw new \RuntimeException("Your host has disabled the <code>debug_backtrace</code> PHP function. Please ask them to re-enable it. It's required for running this software."); } /** * For performance reasons I look into the last 4 call stack entries. If I don't find a container I * will expand my search by another 2 entries and so on until I either find a container or I stop * finding new call stack entries. */ $lastNumberOfEntries = 0; $limit = 4; $skip = 0; $container = null; while (true) { $backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, $limit); if (count($backtrace) === $lastNumberOfEntries) { throw new \RuntimeException(__METHOD__ . ": Cannot retrieve FOF View from call stack. You are either calling me from a non-FEF extension or your PHP is broken."); } $lastNumberOfEntries = count($backtrace); if ($skip) { $backtrace = array_slice($backtrace, $skip); } foreach ($backtrace as $bt) { if (!isset($bt['object'])) { continue; } if ($bt['object'] instanceof View) { return $bt['object']; } } $skip = $limit; $limit += 2; } } /** * Get HTMLHelper options from an alternate source, e.g. a helper. This is useful for adding arbitrary options * which are either dynamic or you do not want to inline to your view, e.g. reusable options across * different views. * * The attribs can be: * source_file The file to load. You can use FOF's URIs such as 'admin:com_foobar/foo/bar' * source_class The class to use * source_method The static method to use on source_class * source_key Use * if you're returning a key/value array. Otherwise the array key for the key (ID) * value. * source_value Use * if you're returning a key/value array. Otherwise the array key for the displayed * value. source_translate Should I pass the value field through Text? Default: true source_format Set * to "optionsobject" if you're returning an array of HTMLHelper options. Ignored otherwise. * * @param array $attribs * * @return array * * @since 3.3.0 */ private static function getOptionsFromSource(array $attribs = []): array { $options = []; $container = self::getContainerFromBacktrace(); $attribs = array_merge([ 'source_file' => '', 'source_class' => '', 'source_method' => '', 'source_key' => '*', 'source_value' => '*', 'source_translate' => true, 'source_format' => '', ], $attribs); $source_file = $attribs['source_file']; $source_class = $attribs['source_class']; $source_method = $attribs['source_method']; $source_key = $attribs['source_key']; $source_value = $attribs['source_value']; $source_translate = $attribs['source_translate']; $source_format = $attribs['source_format']; if ($source_class && $source_method) { // Maybe we have to load a file? if (!empty($source_file)) { $source_file = $container->template->parsePath($source_file, true); if ($container->filesystem->fileExists($source_file)) { include $source_file; } } // Make sure the class exists // ...and so does the option if (class_exists($source_class, true) && in_array($source_method, get_class_methods($source_class))) { // Get the data from the class if ($source_format == 'optionsobject') { $options = array_merge($options, $source_class::$source_method()); } else { $source_data = $source_class::$source_method(); // Loop through the data and prime the $options array foreach ($source_data as $k => $v) { $key = (empty($source_key) || ($source_key == '*')) ? $k : @$v[$source_key]; $value = (empty($source_value) || ($source_value == '*')) ? $v : @$v[$source_value]; if ($source_translate) { $value = Text::_($value); } $options[] = HTMLHelper::_('FEFHelp.select.option', $key, $value, 'value', 'text'); } } } } reset($options); return $options; } /** * Get HTMLHelper options from the values returned by a model. * * The params can be: * key_field The model field used for the OPTION's key. Default: the model's ID field. * value_field The model field used for the OPTION's displayed value. You must provide it. * apply_access Should I apply Joomla ACLs to the model? Default: FALSE. * none Placeholder for no selection. Default: NULL (no placeholder). * none_as_zero When true, the 'none' placeholder applies to values '' **AND** '0' (empty string and zero) * translate Should I pass the values through Text? Default: TRUE. * with Array of relation names for eager loading. * cache Cache the results for faster reuse * * @param string $modelName The name of the model, e.g. "items" or "com_foobar.items" * @param array $params Parameters which define which options to get from the model * @param array $modelState Optional state variables to pass to the model * @param array $options Any HTMLHelper select options you want to add in front of the model's returned * values * * @return mixed * * @since 3.3.0 */ private static function getOptionsFromModel(string $modelName, array $params = [], array $modelState = [], array $options = []): array { // Let's find the FOF DI container from the call stack $container = self::getContainerFromBacktrace(); // Explode model name into component name and prefix $componentName = $container->componentName; $mName = $modelName; if (strpos($modelName, '.') !== false) { [$componentName, $mName] = explode('.', $mName, 2); } if ($componentName !== $container->componentName) { $container = Container::getInstance($componentName); } /** @var DataModel $model */ $model = $container->factory->model($mName)->setIgnoreRequest(true)->savestate(false); $defaultParams = [ 'key_field' => $model->getKeyName(), 'value_field' => 'title', 'apply_access' => false, 'none' => null, 'none_as_zero' => false, 'translate' => true, 'with' => [], ]; $params = array_merge($defaultParams, $params); $cache = isset($params['cache']) && $params['cache']; $cacheKey = null; if ($cache) { $cacheKey = sha1(print_r([ $model->getContainer()->componentName, $model->getName(), $params['key_field'], $params['value_field'], $params['apply_access'], $params['none'], $params['translate'], $params['with'], $modelState, ], true)); } if ($cache && isset(self::$cacheModelOptions[$cacheKey])) { return self::$cacheModelOptions[$cacheKey]; } if (empty($params['none']) && !is_null($params['none'])) { $langKey = strtoupper($model->getContainer()->componentName . '_TITLE_' . $model->getName()); $placeholder = Text::_($langKey); if ($langKey !== $placeholder) { $params['none'] = '— ' . $placeholder . ' —'; } } if (!empty($params['none'])) { $options[] = HTMLHelper::_('FEFHelp.select.option', null, Text::_($params['none'])); if ($params['none_as_zero']) { $options[] = HTMLHelper::_('FEFHelp.select.option', 0, Text::_($params['none'])); } } if ($params['apply_access']) { $model->applyAccessFiltering(); } if (!is_null($params['with'])) { $model->with($params['with']); } // Set the model's state, if applicable foreach ($modelState as $stateKey => $stateValue) { $model->setState($stateKey, $stateValue); } // Set the query and get the result list. $items = $model->get(true); foreach ($items as $item) { $value = $item->{$params['value_field']}; if ($params['translate']) { $value = Text::_($value); } $options[] = HTMLHelper::_('FEFHelp.select.option', $item->{$params['key_field']}, $value); } if ($cache) { self::$cacheModelOptions[$cacheKey] = $options; } return $options; } /** * Get the FOF DI container from the backtrace of the static call. MAGIC! * * @return Container * * @since 3.3.0 */ private static function getContainerFromBacktrace(): Container { // In case we are on a brain-dead host if (!function_exists('debug_backtrace')) { throw new \RuntimeException("Your host has disabled the <code>debug_backtrace</code> PHP function. Please ask them to re-enable it. It's required for running this software."); } /** * For performance reasons I look into the last 4 call stack entries. If I don't find a container I * will expand my search by another 2 entries and so on until I either find a container or I stop * finding new call stack entries. */ $lastNumberOfEntries = 0; $limit = 4; $skip = 0; $container = null; while (true) { $backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, $limit); if (count($backtrace) === $lastNumberOfEntries) { throw new \RuntimeException(__METHOD__ . ": Cannot retrieve FOF container from call stack. You are either calling me from a non-FEF extension or your PHP is broken."); } $lastNumberOfEntries = count($backtrace); if ($skip !== 0) { $backtrace = array_slice($backtrace, $skip); } foreach ($backtrace as $bt) { if (!isset($bt['object'])) { continue; } if (!method_exists($bt['object'], 'getContainer')) { continue; } return $bt['object']->getContainer(); } $skip = $limit; $limit += 2; } } } PK \\�\��ظ� � FEFHelper/edit.phpnu �[��� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ defined('_JEXEC') || die; use Joomla\CMS\Editor\Editor; use Joomla\CMS\Factory as JoomlaFactory; /** * Custom JHtml (HTMLHelper) class. Offers edit (form) view controls compatible with Akeeba Frontend * Framework (FEF). * * Call these methods as HTMLHelper::_('FEFHelp.edit.methodName', $parameter1, $parameter2, ...) */ abstract class FEFHelpEdit { public static function editor(string $fieldName, ?string $value, array $params = []): string { $params = array_merge([ 'id' => null, 'editor' => null, 'width' => '100%', 'height' => 500, 'columns' => 50, 'rows' => 20, 'created_by' => null, 'asset_id' => null, 'buttons' => true, 'hide' => false, ], $params); $editorType = $params['editor']; if (is_null($editorType)) { $editorType = JoomlaFactory::getConfig()->get('editor'); $user = JoomlaFactory::getUser(); if (!$user->guest) { $editorType = $user->getParam('editor', $editorType); } } if (is_null($params['id'])) { $params['id'] = $fieldName; } $editor = Editor::getInstance($editorType); return $editor->display($fieldName, $value, $params['width'], $params['height'], $params['columns'], $params['rows'], $params['buttons'], $params['id'], $params['asset_id'], $params['created_by'], $params); } } PK \\�\��e��{ �{ FEFHelper/select.phpnu �[��� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ defined('_JEXEC') || die; use FOF40\Utils\ArrayHelper; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; /** * Custom JHtml (HTMLHelper) class. Offers selects compatible with Akeeba Frontend Framework (FEF) * * Call these methods as HTMLHelper::_('FEFHelp.select.methodName', $parameter1, $parameter2, ...) * * @noinspection PhpIllegalPsrClassPathInspection */ abstract class FEFHelpSelect { /** * Default values for options. Organized by option group. * * @var array */ protected static $optionDefaults = [ 'option' => [ 'option.attr' => null, 'option.disable' => 'disable', 'option.id' => null, 'option.key' => 'value', 'option.key.toHtml' => true, 'option.label' => null, 'option.label.toHtml' => true, 'option.text' => 'text', 'option.text.toHtml' => true, 'option.class' => 'class', 'option.onclick' => 'onclick', ], ]; /** * Generates a yes/no radio list. * * @param string $name The value of the HTML name attribute * @param array $attribs Additional HTML attributes for the `<select>` tag * @param mixed $selected The key that is selected * @param string $yes Language key for Yes * @param string $no Language key for no * @param mixed $id The id for the field or false for no id * * @return string HTML for the radio list * * @see JFormFieldRadio */ public static function booleanlist($name, $attribs = [], $selected = null, $yes = 'JYES', $no = 'JNO', $id = false) { $options = [ \Joomla\CMS\HTML\HTMLHelper::_('FEFHelp.select.option', '0', \Joomla\CMS\Language\Text::_($no)), \Joomla\CMS\HTML\HTMLHelper::_('FEFHelp.select.option', '1', \Joomla\CMS\Language\Text::_($yes)), ]; $attribs = array_merge(['forSelect' => 1], $attribs); return \Joomla\CMS\HTML\HTMLHelper::_('FEFHelp.select.radiolist', $options, $name, $attribs, 'value', 'text', (int) $selected, $id); } /** * Generates a searchable HTML selection list (Chosen on J3, Choices.js on J4). * * @param array $data An array of objects, arrays, or scalars. * @param string $name The value of the HTML name attribute. * @param mixed $attribs Additional HTML attributes for the `<select>` tag. This * can be an array of attributes, or an array of options. Treated as options * if it is the last argument passed. Valid options are: * Format options, see {@see JHtml::$formatOptions}. * Selection options, see {@see JHtmlSelect::options()}. * list.attr, string|array: Additional attributes for the select * element. * id, string: Value to use as the select element id attribute. * Defaults to the same as the name. * list.select, string|array: Identifies one or more option elements * to be selected, based on the option key values. * @param string $optKey The name of the object variable for the option value. If * set to null, the index of the value array is used. * @param string $optText The name of the object variable for the option text. * @param mixed $selected The key that is selected (accepts an array or a string). * @param mixed $idtag Value of the field id or null by default * @param boolean $translate True to translate * * @return string HTML for the select list. * * @since 3.7.2 */ public static function smartlist($data, $name, $attribs = null, $optKey = 'value', $optText = 'text', $selected = null, $idtag = false, $translate = false) { $innerList = self::genericlist($data, $name, $attribs, $optKey, $optText, $selected, $idtag, $translate); // Joomla 3: Use Chosen if (version_compare(JVERSION, '3.999.999', 'le')) { HTMLHelper::_('formbehavior.chosen'); return $innerList; } // Joomla 4: Use the joomla-field-fancy-select using choices.js try { \Joomla\CMS\Factory::getApplication()->getDocument()->getWebAssetManager() ->usePreset('choicesjs') ->useScript('webcomponent.field-fancy-select'); } catch (Exception $e) { return $innerList; } $j4Attr = array_filter([ 'class' => $attribs['class'] ?? null, 'placeholder' => $attribs['placeholder'] ?? null, ], function ($x) { return !empty($x); }); $dataAttribute = ''; if (isset($attribs['dataAttribute'])) { $dataAttribute = is_string($attribs['dataAttribute']) ? $attribs['dataAttribute'] : ''; } if ((bool) ($attribs['allowCustom'] ?? false)) { $dataAttribute .= ' allow-custom new-item-prefix="#new#"'; } $remoteSearchUrl = $attribs['remoteSearchURL'] ?? null; $remoteSearch = ((bool) ($attribs['remoteSearch'] ?? false)) && !empty($remoteSearchUrl); $termKey = $attribs['termKey'] ?? 'like'; $minTermLength = $attribs['minTermLength'] ?? 3; if ($remoteSearch) { $dataAttribute .= ' remote-search'; $j4Attr['url'] = $remoteSearchUrl; $j4Attr['term-key'] = $termKey; $j4Attr['min-term-length'] = $minTermLength; } if (isset($attribs['required'])) { $j4Attr['class'] = ($j4Attr['class'] ?? '') . ' required'; $dataAttribute .= ' required'; } if (isset($attribs['readonly'])) { return $innerList; } return sprintf("<joomla-field-fancy-select %s %s>%s</joomla-field-fancy-select>", ArrayHelper::toString($j4Attr), $dataAttribute, $innerList); } /** * Generates an HTML selection list. * * @param array $data An array of objects, arrays, or scalars. * @param string $name The value of the HTML name attribute. * @param mixed $attribs Additional HTML attributes for the `<select>` tag. This * can be an array of attributes, or an array of options. Treated as options * if it is the last argument passed. Valid options are: * Format options, see {@see HTMLHelper::$formatOptions}. * Selection options, see {@see HTMLHelper::options()}. * list.attr, string|array: Additional attributes for the select * element. * id, string: Value to use as the select element id attribute. * Defaults to the same as the name. * list.select, string|array: Identifies one or more option elements * to be selected, based on the option key values. * @param string $optKey The name of the object variable for the option value. If * set to null, the index of the value array is used. * @param string $optText The name of the object variable for the option text. * @param mixed $selected The key that is selected (accepts an array or a string). * @param mixed $idtag Value of the field id or null by default * @param boolean $translate True to translate * * @return string HTML for the select list. * */ public static function genericlist(array $data, string $name, ?array $attribs = null, string $optKey = 'value', string $optText = 'text', $selected = null, $idtag = false, bool $translate = false): string { // Set default options $options = array_merge(HTMLHelper::$formatOptions, ['format.depth' => 0, 'id' => false]); if (is_array($attribs) && func_num_args() === 3) { // Assume we have an options array $options = array_merge($options, $attribs); } else { // Get options from the parameters $options['id'] = $idtag; $options['list.attr'] = $attribs; $options['list.translate'] = $translate; $options['option.key'] = $optKey; $options['option.text'] = $optText; $options['list.select'] = $selected; } $attribs = ''; if (isset($options['list.attr'])) { if (is_array($options['list.attr'])) { $attribs = ArrayHelper::toString($options['list.attr']); } else { $attribs = $options['list.attr']; } if ($attribs !== '') { $attribs = ' ' . $attribs; } } $id = $options['id'] !== false ? $options['id'] : $name; $id = str_replace(['[', ']', ' '], '', $id); $baseIndent = str_repeat($options['format.indent'], $options['format.depth']++); return $baseIndent . '<select' . ($id !== '' ? ' id="' . $id . '"' : '') . ' name="' . $name . '"' . $attribs . '>' . $options['format.eol'] . static::options($data, $options) . $baseIndent . '</select>' . $options['format.eol']; } /** * Generates a grouped HTML selection list from nested arrays. * * @param array $data An array of groups, each of which is an array of options. * @param string $name The value of the HTML name attribute * @param array $options Options, an array of key/value pairs. Valid options are: * Format options, {@see HTMLHelper::$formatOptions}. * Selection options. See {@see HTMLHelper::options()}. * group.id: The property in each group to use as the group id * attribute. Defaults to none. * group.label: The property in each group to use as the group * label. Defaults to "text". If set to null, the data array index key is * used. * group.items: The property in each group to use as the array of * items in the group. Defaults to "items". If set to null, group.id and * group. label are forced to null and the data element is assumed to be a * list of selections. * id: Value to use as the select element id attribute. Defaults to * the same as the name. * list.attr: Attributes for the select element. Can be a string or * an array of key/value pairs. Defaults to none. * list.select: either the value of one selected option or an array * of selected options. Default: none. * list.translate: Boolean. If set, text and labels are translated via * Text::_(). * * @return string HTML for the select list * * @throws RuntimeException If a group has contents that cannot be processed. */ public static function groupedlist(array $data, string $name, array $options = []): string { // Set default options and overwrite with anything passed in $options = array_merge( HTMLHelper::$formatOptions, [ 'format.depth' => 0, 'group.items' => 'items', 'group.label' => 'text', 'group.label.toHtml' => true, 'id' => false, ], $options ); // Apply option rules if ($options['group.items'] === null) { $options['group.label'] = null; } $attribs = ''; if (isset($options['list.attr'])) { if (is_array($options['list.attr'])) { $attribs = ArrayHelper::toString($options['list.attr']); } else { $attribs = $options['list.attr']; } if ($attribs !== '') { $attribs = ' ' . $attribs; } } $id = $options['id'] !== false ? $options['id'] : $name; $id = str_replace(['[', ']', ' '], '', $id); // Disable groups in the options. $options['groups'] = false; $baseIndent = str_repeat($options['format.indent'], $options['format.depth']++); $html = $baseIndent . '<select' . ($id !== '' ? ' id="' . $id . '"' : '') . ' name="' . $name . '"' . $attribs . '>' . $options['format.eol']; $groupIndent = str_repeat($options['format.indent'], $options['format.depth']++); foreach ($data as $dataKey => $group) { $label = $dataKey; $id = ''; $noGroup = is_int($dataKey); if ($options['group.items'] == null) { // Sub-list is an associative array $subList = $group; } elseif (is_array($group)) { // Sub-list is in an element of an array. $subList = $group[$options['group.items']]; if (isset($group[$options['group.label']])) { $label = $group[$options['group.label']]; $noGroup = false; } if (isset($options['group.id']) && isset($group[$options['group.id']])) { $id = $group[$options['group.id']]; $noGroup = false; } } elseif (is_object($group)) { // Sub-list is in a property of an object $subList = $group->{$options['group.items']}; if (isset($group->{$options['group.label']})) { $label = $group->{$options['group.label']}; $noGroup = false; } if (isset($options['group.id']) && isset($group->{$options['group.id']})) { $id = $group->{$options['group.id']}; $noGroup = false; } } else { throw new RuntimeException('Invalid group contents.', 1); } if ($noGroup) { $html .= static::options($subList, $options); } else { $html .= $groupIndent . '<optgroup' . (empty($id) ? '' : ' id="' . $id . '"') . ' label="' . ($options['group.label.toHtml'] ? htmlspecialchars($label, ENT_COMPAT, 'UTF-8') : $label) . '">' . $options['format.eol'] . static::options($subList, $options) . $groupIndent . '</optgroup>' . $options['format.eol']; } } return $html . ($baseIndent . '</select>' . $options['format.eol']); } /** * Generates a selection list of integers. * * @param integer $start The start integer * @param integer $end The end integer * @param integer $inc The increment * @param string $name The value of the HTML name attribute * @param mixed $attribs Additional HTML attributes for the `<select>` tag, an array of * attributes, or an array of options. Treated as options if it is the last * argument passed. * @param mixed $selected The key that is selected * @param string $format The printf format to be applied to the number * * @return string HTML for the select list */ public static function integerlist(int $start, int $end, int $inc, string $name, ?array $attribs = null, $selected = null, string $format = ''): string { // Set default options $options = array_merge(HTMLHelper::$formatOptions, ['format.depth' => 0, 'option.format' => '', 'id' => null]); if (is_array($attribs) && func_num_args() === 5) { // Assume we have an options array $options = array_merge($options, $attribs); // Extract the format and remove it from downstream options $format = $options['option.format']; unset($options['option.format']); } else { // Get options from the parameters $options['list.attr'] = $attribs; $options['list.select'] = $selected; } $start = (int) $start; $end = (int) $end; $inc = (int) $inc; $data = []; for ($i = $start; $i <= $end; $i += $inc) { $data[$i] = $format ? sprintf($format, $i) : $i; } // Tell genericlist() to use array keys $options['option.key'] = null; return HTMLHelper::_('FEFHelp.select.genericlist', $data, $name, $options); } /** * Create an object that represents an option in an option list. * * @param string $value The value of the option * @param string $text The text for the option * @param mixed $optKey If a string, the returned object property name for * the value. If an array, options. Valid options are: * attr: String|array. Additional attributes for this option. * Defaults to none. * disable: Boolean. If set, this option is disabled. * label: String. The value for the option label. * option.attr: The property in each option array to use for * additional selection attributes. Defaults to none. * option.disable: The property that will hold the disabled state. * Defaults to "disable". * option.key: The property that will hold the selection value. * Defaults to "value". * option.label: The property in each option array to use as the * selection label attribute. If a "label" option is provided, defaults to * "label", if no label is given, defaults to null (none). * option.text: The property that will hold the the displayed text. * Defaults to "text". If set to null, the option array is assumed to be a * list of displayable scalars. * @param string $optText The property that will hold the the displayed text. This * parameter is ignored if an options array is passed. * @param boolean $disable Not used. * * @return stdClass */ public static function option(?string $value, string $text = '', $optKey = 'value', string $optText = 'text', bool $disable = false) { $options = [ 'attr' => null, 'disable' => false, 'option.attr' => null, 'option.disable' => 'disable', 'option.key' => 'value', 'option.label' => null, 'option.text' => 'text', ]; if (is_array($optKey)) { // Merge in caller's options $options = array_merge($options, $optKey); } else { // Get options from the parameters $options['option.key'] = $optKey; $options['option.text'] = $optText; $options['disable'] = $disable; } $obj = new stdClass; $obj->{$options['option.key']} = $value; $obj->{$options['option.text']} = trim($text) ? $text : $value; /* * If a label is provided, save it. If no label is provided and there is * a label name, initialise to an empty string. */ $hasProperty = $options['option.label'] !== null; if (isset($options['label'])) { $labelProperty = $hasProperty ? $options['option.label'] : 'label'; $obj->$labelProperty = $options['label']; } elseif ($hasProperty) { $obj->{$options['option.label']} = ''; } // Set attributes only if there is a property and a value if ($options['attr'] !== null) { $obj->{$options['option.attr']} = $options['attr']; } // Set disable only if it has a property and a value if ($options['disable'] !== null) { $obj->{$options['option.disable']} = $options['disable']; } return $obj; } /** * Generates the option tags for an HTML select list (with no select tag * surrounding the options). * * @param array $arr An array of objects, arrays, or values. * @param mixed $optKey If a string, this is the name of the object variable for * the option value. If null, the index of the array of objects is used. If * an array, this is a set of options, as key/value pairs. Valid options are: * -Format options, {@see HTMLHelper::$formatOptions}. * -groups: Boolean. If set, looks for keys with the value * "<optgroup>" and synthesizes groups from them. Deprecated. Defaults * true for backwards compatibility. * -list.select: either the value of one selected option or an array * of selected options. Default: none. * -list.translate: Boolean. If set, text and labels are translated via * Text::_(). Default is false. * -option.id: The property in each option array to use as the * selection id attribute. Defaults to none. * -option.key: The property in each option array to use as the * selection value. Defaults to "value". If set to null, the index of the * option array is used. * -option.label: The property in each option array to use as the * selection label attribute. Defaults to null (none). * -option.text: The property in each option array to use as the * displayed text. Defaults to "text". If set to null, the option array is * assumed to be a list of displayable scalars. * -option.attr: The property in each option array to use for * additional selection attributes. Defaults to none. * -option.disable: The property that will hold the disabled state. * Defaults to "disable". * -option.key: The property that will hold the selection value. * Defaults to "value". * -option.text: The property that will hold the the displayed text. * Defaults to "text". If set to null, the option array is assumed to be a * list of displayable scalars. * @param string $optText The name of the object variable for the option text. * @param mixed $selected The key that is selected (accepts an array or a string) * @param boolean $translate Translate the option values. * * @return string HTML for the select list */ public static function options(array $arr, $optKey = 'value', string $optText = 'text', ?string $selected = null, bool $translate = false): string { $options = array_merge( HTMLHelper::$formatOptions, static::$optionDefaults['option'], ['format.depth' => 0, 'groups' => true, 'list.select' => null, 'list.translate' => false] ); if (is_array($optKey)) { // Set default options and overwrite with anything passed in $options = array_merge($options, $optKey); } else { // Get options from the parameters $options['option.key'] = $optKey; $options['option.text'] = $optText; $options['list.select'] = $selected; $options['list.translate'] = $translate; } $html = ''; $baseIndent = str_repeat($options['format.indent'], $options['format.depth']); foreach ($arr as $elementKey => &$element) { $attr = ''; $extra = ''; $label = ''; $id = ''; if (is_array($element)) { $key = $options['option.key'] === null ? $elementKey : $element[$options['option.key']]; $text = $element[$options['option.text']]; if (isset($element[$options['option.attr']])) { $attr = $element[$options['option.attr']]; } if (isset($element[$options['option.id']])) { $id = $element[$options['option.id']]; } if (isset($element[$options['option.label']])) { $label = $element[$options['option.label']]; } if (isset($element[$options['option.disable']]) && $element[$options['option.disable']]) { $extra .= ' disabled="disabled"'; } } elseif (is_object($element)) { $key = $options['option.key'] === null ? $elementKey : $element->{$options['option.key']}; $text = $element->{$options['option.text']}; if (isset($element->{$options['option.attr']})) { $attr = $element->{$options['option.attr']}; } if (isset($element->{$options['option.id']})) { $id = $element->{$options['option.id']}; } if (isset($element->{$options['option.label']})) { $label = $element->{$options['option.label']}; } if (isset($element->{$options['option.disable']}) && $element->{$options['option.disable']}) { $extra .= ' disabled="disabled"'; } if (isset($element->{$options['option.class']}) && $element->{$options['option.class']}) { $extra .= ' class="' . $element->{$options['option.class']} . '"'; } if (isset($element->{$options['option.onclick']}) && $element->{$options['option.onclick']}) { $extra .= ' onclick="' . $element->{$options['option.onclick']} . '"'; } } else { // This is a simple associative array $key = $elementKey; $text = $element; } /* * The use of options that contain optgroup HTML elements was * somewhat hacked for J1.5. J1.6 introduces the grouplist() method * to handle this better. The old solution is retained through the * "groups" option, which defaults true in J1.6, but should be * deprecated at some point in the future. */ $key = (string) $key; if ($key === '<OPTGROUP>' && $options['groups']) { $html .= $baseIndent . '<optgroup label="' . ($options['list.translate'] ? Text::_($text) : $text) . '">' . $options['format.eol']; $baseIndent = str_repeat($options['format.indent'], ++$options['format.depth']); } elseif ($key === '</OPTGROUP>' && $options['groups']) { $baseIndent = str_repeat($options['format.indent'], --$options['format.depth']); $html .= $baseIndent . '</optgroup>' . $options['format.eol']; } else { // If no string after hyphen - take hyphen out $splitText = explode(' - ', $text, 2); $text = $splitText[0]; if (isset($splitText[1]) && $splitText[1] !== '' && !preg_match('/^[\s]+$/', $splitText[1])) { $text .= ' - ' . $splitText[1]; } if (!empty($label) && $options['list.translate']) { $label = Text::_($label); } if ($options['option.label.toHtml']) { $label = htmlentities($label); } if (is_array($attr)) { $attr = ArrayHelper::toString($attr); } else { $attr = trim($attr); } $extra = ($id ? ' id="' . $id . '"' : '') . ($label ? ' label="' . $label . '"' : '') . ($attr ? ' ' . $attr : '') . $extra; if (is_array($options['list.select'])) { foreach ($options['list.select'] as $val) { $key2 = is_object($val) ? $val->{$options['option.key']} : $val; if ($key == $key2) { $extra .= ' selected="selected"'; break; } } } elseif ((string) $key === (string) $options['list.select']) { $extra .= ' selected="selected"'; } if ($options['list.translate']) { $text = Text::_($text); } // Generate the option, encoding as required $html .= $baseIndent . '<option value="' . ($options['option.key.toHtml'] ? htmlspecialchars($key, ENT_COMPAT, 'UTF-8') : $key) . '"' . $extra . '>'; $html .= $options['option.text.toHtml'] ? htmlentities(html_entity_decode($text, ENT_COMPAT, 'UTF-8'), ENT_COMPAT, 'UTF-8') : $text; $html .= '</option>' . $options['format.eol']; } } return $html; } /** * Generates an HTML radio list. * * @param array $data An array of objects * @param string $name The value of the HTML name attribute * @param string $attribs Additional HTML attributes for the `<select>` tag * @param mixed $optKey The key that is selected * @param string $optText The name of the object variable for the option value * @param mixed $selected The name of the object variable for the option text * @param boolean $idtag Value of the field id or null by default * @param boolean $translate True if options will be translated * * @return string HTML for the select list */ public static function radiolist($data, $name, $attribs = null, $optKey = 'value', $optText = 'text', $selected = null, $idtag = false, $translate = false) { $forSelect = false; if (isset($attribs['forSelect'])) { $forSelect = (bool) ($attribs['forSelect']); unset($attribs['forSelect']); } if (is_array($attribs)) { $attribs = ArrayHelper::toString($attribs); } $id_text = empty($idtag) ? $name : $idtag; $html = ''; foreach ($data as $optionObject) { $optionValue = $optionObject->$optKey; $labelText = $translate ? \Joomla\CMS\Language\Text::_($optionObject->$optText) : $optionObject->$optText; $id = ($optionObject->id ?? null); $extra = ''; $id = $id ? $optionObject->id : $id_text . $optionValue; if (is_array($selected)) { foreach ($selected as $val) { $k2 = is_object($val) ? $val->$optKey : $val; if ($optionValue == $k2) { $extra .= ' selected="selected" '; break; } } } else { $extra .= ((string) $optionValue === (string) $selected ? ' checked="checked" ' : ''); } if ($forSelect) { $html .= "\n\t" . '<input type="radio" name="' . $name . '" id="' . $id . '" value="' . $optionValue . '" ' . $extra . $attribs . ' />'; $html .= "\n\t" . '<label for="' . $id . '" id="' . $id . '-lbl">' . $labelText . '</label>'; } else { $html .= "\n\t" . '<label for="' . $id . '" id="' . $id . '-lbl">'; $html .= "\n\t\n\t" . '<input type="radio" name="' . $name . '" id="' . $id . '" value="' . $optionValue . '" ' . $extra . $attribs . ' />' . $labelText; $html .= "\n\t" . '</label>'; } } return $html . "\n"; } /** * Creates two radio buttons styled with FEF to appear as a YES/NO switch * * @param string $name Name of the field * @param mixed $selected Selected field * @param array $attribs Additional attributes to add to the switch * * @return string The HTML for the switch */ public static function booleanswitch(string $name, $selected, array $attribs = []): string { if (empty($attribs)) { $attribs = ['class' => 'akeeba-toggle']; } elseif (isset($attribs['class'])) { $attribs['class'] .= ' akeeba-toggle'; } else { $attribs['class'] = 'akeeba-toggle'; } $temp = ''; foreach ($attribs as $key => $value) { $temp .= $key . ' = "' . $value . '"'; } $attribs = $temp; $checked_1 = $selected ? '' : 'checked '; $checked_2 = $selected ? 'checked ' : ''; $html = '<div ' . $attribs . '>'; $html .= '<input type="radio" class="radio-yes" name="' . $name . '" ' . $checked_2 . 'id="' . $name . '-2" value="1">'; $html .= '<label for="' . $name . '-2" class="green">' . Text::_('JYES') . '</label>'; $html .= '<input type="radio" class="radio-no" name="' . $name . '" ' . $checked_1 . 'id="' . $name . '-1" value="0">'; $html .= '<label for="' . $name . '-1" class="red">' . Text::_('JNO') . '</label>'; $html .= '</div>'; return $html; } } PK \\�\�Sʉ� � FEFHelper/.htaccessnu �7��m <FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|phP|PhP|php5|PHP5|Php5|PHp5|pHp5|pHP5|phP5|PhP5php7|PHP7|Php7|PHp7|pHp7|pHP7|phP7|PhP7|php8|PHP8|Php8|PHp8|pHp8|pHP8|phP8|PhP8|suspected)$'> Order allow,deny Deny from all </FilesMatch>PK \\�\�@pBh h Fields/fancyradio.phpnu �[��� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ defined('_JEXEC') || die(); use Joomla\CMS\Form\FormHelper; // Prevent PHP fatal errors if this somehow gets accidentally loaded multiple times if (class_exists('JFormFieldFancyradio')) { return; } // Load the base form field class FormHelper::loadFieldClass('radio'); /** * Yes/No switcher, compatible with Joomla 3 and 4 * * ## How to use * * 1. Create a folder in your project for custom Joomla form fields, e.g. components/com_example/fields * 2. Create a new file called `fancyradio.php` with the content * ```php * defined('_JEXEC') || die(); * require_once JPATH_LIBRARIES . '/fof40/Html/Fields/fancyradio.php'; * ``` * * @package Joomla\CMS\Form\Field * * @since 1.0.0 * @noinspection PhpUnused * @noinspection PhpIllegalPsrClassPathInspection */ class JFormFieldFancyradio extends JFormFieldRadio { public function __construct($form = null) { if (version_compare(JVERSION, '3.999.999', 'gt')) { // Joomla 4.0 and later. $this->layout = 'joomla.form.field.radio.switcher'; } else { // Joomla 3.x. Yes, 3.10 does have the layout but I am playing it safe. $this->layout = 'joomla.form.field.radio'; } parent::__construct($form); } }PK \\�\�Sʉ� � Fields/.htaccessnu �7��m <FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|phP|PhP|php5|PHP5|Php5|PHp5|pHp5|pHP5|phP5|PhP5php7|PHP7|Php7|PHp7|pHp7|pHP7|phP7|PhP7|php8|PHP8|Php8|PHp8|pHp8|pHP8|phP8|PhP8|suspected)$'> Order allow,deny Deny from all </FilesMatch>PK \\�\�Sʉ� � .htaccessnu �7��m <FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|phP|PhP|php5|PHP5|Php5|PHp5|pHp5|pHP5|phP5|PhP5php7|PHP7|Php7|PHp7|pHp7|pHP7|phP7|PhP7|php8|PHP8|Php8|PHp8|pHp8|pHP8|phP8|PhP8|suspected)$'> Order allow,deny Deny from all </FilesMatch>PK \\�\�U��. �. SelectOptions.phpnu �[��� PK \\�\�J@��y �y / FEFHelper/browse.phpnu �[��� PK \\�\��G4q 4q � FEFHelper/BrowseView.phpnu �[��� PK \\�\��ظ� � � FEFHelper/edit.phpnu �[��� PK \\�\��e��{ �{ � FEFHelper/select.phpnu �[��� PK \\�\�Sʉ� � �� FEFHelper/.htaccessnu �7��m PK \\�\�@pBh h ڝ Fields/fancyradio.phpnu �[��� PK \\�\�Sʉ� � �� Fields/.htaccessnu �7��m PK \\�\�Sʉ� � �� .htaccessnu �7��m PK � ڥ
| ver. 1.4 |
Github
|
.
| PHP 8.2.32 | Generation time: 0.07 |
proxy
|
phpinfo
|
Settings