File manager - Edit - /home/opticamezl/www/newok/HTML.tar
Back
Helpers/Form.php 0000644 00000004036 15172602426 0007572 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Document\HtmlDocument; use Joomla\CMS\Factory; use Joomla\CMS\Session\Session; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for form elements * * @since 1.5 */ abstract class Form { /** * Array containing information for loaded files. * * @var array * * @since 3.8.0 */ protected static $loaded = []; /** * Displays a hidden token field to reduce the risk of CSRF exploits * * Use in conjunction with Session::checkToken() * * @param array $attribs Input element attributes. * * @return string A hidden input field with a token * * @see Session::checkToken() * @since 1.5 */ public static function token(array $attribs = []) { $attributes = ''; if ($attribs !== []) { $attributes .= ' ' . ArrayHelper::toString($attribs); } return '<input type="hidden" name="' . Session::getFormToken() . '" value="1"' . $attributes . '>'; } /** * Add CSRF form token to Joomla script options that developers can get it by Javascript. * * @param string $name The script option key name. * * @return void * * @since 3.8.0 */ public static function csrf($name = 'csrf.token') { if (isset(static::$loaded[__METHOD__][$name])) { return; } /** @var HtmlDocument $doc */ $doc = Factory::getDocument(); if (!$doc instanceof HtmlDocument || $doc->getType() !== 'html') { return; } $doc->addScriptOptions($name, Session::getFormToken()); static::$loaded[__METHOD__][$name] = true; } } Helpers/Bootstrap.php 0000644 00000101727 15172602426 0010651 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Layout\FileLayout; use Joomla\CMS\Layout\LayoutHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for Bootstrap elements. * * @since 3.0 */ abstract class Bootstrap { /** * @var array Array containing information for loaded files * @since 3.0 */ protected static $loaded = []; /** * Add javascript support for Bootstrap alerts * * @param string $selector Common class for the alerts * * @return void * * @throws \Exception * * @since 3.0 */ public static function alert($selector = ''): void { // Only load once if (!empty(static::$loaded[__METHOD__][$selector])) { return; } $doc = Factory::getDocument(); if ($selector !== '') { $scriptOptions = $doc->getScriptOptions('bootstrap.alert'); $options = [$selector]; if (is_array($scriptOptions)) { $options = array_merge($scriptOptions, $options); } $doc->addScriptOptions('bootstrap.alert', $options, false); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.alert'); static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap buttons * * @param string $selector Common class for the buttons * * @return void * * @throws \Exception * * @since 3.1 */ public static function button($selector = ''): void { // Only load once if (!empty(static::$loaded[__METHOD__][$selector])) { return; } $doc = Factory::getDocument(); if ($selector !== '') { $scriptOptions = $doc->getScriptOptions('bootstrap.button'); $options = [$selector]; if (is_array($scriptOptions)) { $options = array_merge($scriptOptions, $options); } $doc->addScriptOptions('bootstrap.button', $options, false); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.button'); static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap carousels * * @param string $selector Common class for the carousels. * @param array $params An array of options for the carousel. * * @return void * * @throws \Exception * * @since 3.0 * * Options for the carousel can be: * - interval number 5000 The amount of time to delay between automatically cycling an item. * If false, carousel will not automatically cycle. * - keyboard boolean true Whether the carousel should react to keyboard events. * - pause string| hover Pauses the cycling of the carousel on mouseenter and resumes the cycling * boolean of the carousel on mouseleave. * - slide string| false Autoplays the carousel after the user manually cycles the first item. * boolean If "carousel", autoplays the carousel on load. */ public static function carousel($selector = '', $params = []): void { // Only load once if (!empty(static::$loaded[__METHOD__][$selector])) { return; } if ($selector !== '') { // Setup options object $opt = [ 'interval' => (isset($params['interval']) ? (int) $params['interval'] : 5000), 'keyboard' => (isset($params['keyboard']) ? (bool) $params['keyboard'] : true), 'pause' => (isset($params['pause']) ? $params['pause'] : 'hover'), 'slide' => (isset($params['slide']) ? (bool) $params['slide'] : false), 'wrap' => (isset($params['wrap']) ? (bool) $params['wrap'] : true), 'touch' => (isset($params['touch']) ? (bool) $params['touch'] : true), ]; Factory::getDocument()->addScriptOptions('bootstrap.carousel', [$selector => (object) array_filter((array) $opt)]); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.carousel'); static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap collapse * * @param string $selector Common class for the collapse * @param string[] $params Additional parameters - see below * * @return void * * @throws \Exception * * @since 4.0.0 * * Options for the collapse can be: * - parent string false If parent is provided, then all collapsible elements under the specified parent will * be closed when this collapsible item is shown. * - toggle boolean true Toggles the collapsible element on invocation */ public static function collapse($selector = '', $params = []): void { // Only load once if (!empty(static::$loaded[__METHOD__][$selector])) { return; } if ($selector !== '') { // Setup options object $opt = []; $opt['parent'] = isset($params['parent']) ? $params['parent'] : false; $opt['toggle'] = isset($params['toggle']) ? (bool) $params['toggle'] : true; Factory::getDocument()->addScriptOptions('bootstrap.collapse', [$selector => (object) array_filter((array) $opt)]); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.collapse'); static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap dropdowns * * @param string $selector Common class for the dropdowns * @param array $params The options for the dropdowns * * @return void * * @since 4.0.0 * * Options for the collapse can be: * - flip boolean true Allow Dropdown to flip in case of an overlapping on the reference element * - boundary string scrollParent Overflow constraint boundary of the dropdown menu * - reference string toggle Reference element of the dropdown menu. Accepts 'toggle' or 'parent' * - display string dynamic By default, we use Popper for dynamic positioning. Disable this with static */ public static function dropdown($selector = '', $params = []): void { // Only load once if (!empty(static::$loaded[__METHOD__][$selector])) { return; } if ($selector !== '') { // Setup options object $opt = []; $opt['flip'] = isset($params['flip']) ? $params['flip'] : true; $opt['boundary'] = isset($params['boundary']) ? $params['boundary'] : 'scrollParent'; $opt['reference'] = isset($params['reference']) ? $params['reference'] : 'toggle'; $opt['display'] = isset($params['display']) ? $params['display'] : 'dynamic'; $opt['popperConfig'] = isset($params['popperConfig']) ? (bool) $params['popperConfig'] : true; Factory::getDocument()->addScriptOptions('bootstrap.dropdown', [$selector => (object) array_filter((array) $opt)]); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.dropdown'); static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap modal * * @param string $selector The ID selector for the modal. * @param array $options An array of options for the modal. * * @return void * * @since 4.0.0 * * Options for the modal can be: * - backdrop string| true Includes a modal-backdrop element. Alternatively, specify static * boolean for a backdrop which doesn't close the modal on click. * - keyboard boolean true Closes the modal when escape key is pressed * - focus boolean true Closes the modal when escape key is pressed */ public static function modal($selector = '', $options = []): void { // Only load once if (!empty(static::$loaded[__METHOD__][$selector])) { return; } if ($selector !== '') { // Setup options object $opt = [ 'backdrop' => (isset($options['backdrop']) ? $options['backdrop'] : false), 'keyboard' => (isset($options['keyboard']) ? (bool) $options['keyboard'] : true), 'focus' => (isset($options['focus']) ? (bool) $options['focus'] : true), ]; Factory::getDocument()->addScriptOptions('bootstrap.modal', [$selector => (object) array_filter((array) $opt)]); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.modal'); static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap offcanvas * * @param string $selector The ID selector for the offcanvas. * @param array $options An array of options for the offcanvas. * * @return void * * @since 4.0.0 * * Options for the offcanvas can be: * - backdrop boolean true Apply a backdrop on body while offcanvas is open * - keyboard boolean true Closes the offcanvas when escape key is pressed * - scroll boolean false Allow body scrolling while offcanvas is open */ public static function offcanvas($selector = '', $options = []): void { // Only load once if (!empty(static::$loaded[__METHOD__][$selector])) { return; } if ($selector !== '') { // Setup options object $opt = [ 'backdrop' => (isset($options['backdrop']) ? (bool) $options['backdrop'] : true), 'keyboard' => (isset($options['keyboard']) ? (bool) $options['keyboard'] : true), 'scroll' => (isset($options['scroll']) ? (bool) $options['scroll'] : false), ]; Factory::getDocument()->addScriptOptions('bootstrap.offcanvas', [$selector => (object) array_filter((array) $opt)]); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.offcanvas'); static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap popovers * * Use element's Title as popover content * * @param string $selector Selector for the popover * @param array $options The options for the popover * * @return void * * @since 3.0 * * - Options for the popover can be: * - animation boolean true Apply a CSS fade transition to the popover * - container string| false Appends the popover to a specific element. Eg.: 'body' * boolean * - content string null Default content value if data-bs-content attribute isn't present * - delay number 0 Delay showing and hiding the popover (ms) * does not apply to manual trigger type * - html boolean true Insert HTML into the popover. If false, innerText property will be used * to insert content into the DOM. * - placement string right How to position the popover - auto | top | bottom | left | right. * When auto is specified, it will dynamically reorient the popover * - selector string false If a selector is provided, popover objects will be delegated to the * specified targets. * - template string null Base HTML to use when creating the popover. * - title string null Default title value if `title` tag isn't present * - trigger string click How popover is triggered - click | hover | focus | manual * - offset integer 0 Offset of the popover relative to its target. */ public static function popover($selector = '', $options = []): void { // Only load once if (isset(static::$loaded[__METHOD__][$selector])) { return; } if ($selector !== '') { // Setup options object $opt = [ 'animation' => isset($options['animation']) ? (bool) $options['animation'] : true, 'container' => isset($options['container']) ? $options['container'] : 'body', 'content' => isset($options['content']) ? $options['content'] : null, 'delay' => isset($options['delay']) ? (int) $options['delay'] : ['show' => 50, 'hide' => 200], 'html' => isset($options['html']) ? (bool) $options['html'] : true, 'placement' => isset($options['placement']) ? $options['placement'] : null, 'selector' => isset($options['selector']) ? $options['selector'] : false, 'template' => isset($options['template']) ? $options['template'] : null, 'title' => isset($options['title']) ? $options['title'] : null, 'trigger' => isset($options['trigger']) ? $options['trigger'] : 'click', 'offset' => isset($options['offset']) ? $options['offset'] : [0, 10], 'fallbackPlacement' => isset($options['fallbackPlacement']) ? $options['fallbackPlacement'] : null, 'boundary' => isset($options['boundary']) ? $options['boundary'] : 'scrollParent', 'customClass' => isset($options['customClass']) ? $options['customClass'] : null, 'sanitize' => isset($options['sanitize']) ? (bool) $options['sanitize'] : null, 'allowList' => isset($options['allowList']) ? $options['allowList'] : null, ]; Factory::getDocument()->addScriptOptions('bootstrap.popover', [$selector => (object) array_filter((array) $opt)]); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.popover'); static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap Scrollspy * * @param string $selector The ID selector for the ScrollSpy element. * @param array $options An array of options for the ScrollSpy. * * @return void * * @since 3.0 * * Options for the Scrollspy can be: * - offset number Pixels to offset from top when calculating position of scroll. * - method string Finds which section the spied element is in. * - target string Specifies element to apply Scrollspy plugin. */ public static function scrollspy($selector = '', $options = []): void { // Only load once if (isset(static::$loaded[__METHOD__][$selector])) { return; } if ($selector !== '') { // Setup options object $opt = [ 'offset' => isset($options['offset']) ? (int) $options['offset'] : 10, 'method' => isset($options['method']) ? $options['method'] : 'auto', 'target' => isset($options['target']) ? $options['target'] : null, ]; Factory::getDocument()->addScriptOptions('bootstrap.scrollspy', [$selector => (object) array_filter((array) $opt)]); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.scrollspy'); static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap tab * * @param string $selector Common class for the tabs * @param array $options Options for the tabs * * @return void * * @throws \Exception * * @since 4.0.0 */ public static function tab($selector = '', $options = []): void { // Only load once if (!empty(static::$loaded[__METHOD__][$selector])) { return; } if ($selector !== '') { Factory::getDocument()->addScriptOptions('bootstrap.tabs', [$selector => (object) $options]); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.tab'); static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap tooltips * * Add a title attribute to any element in the form * title="title::text" * * @param string $selector The ID selector for the tooltip. * @param array $options An array of options for the tooltip. * * @return void * * @since 3.0 * * Options for the tooltip can be: * - animation boolean apply a css fade transition to the popover * - container string|boolean Appends the popover to a specific element: { container: 'body' } * - delay number|object delay showing and hiding the popover (ms) - does not apply to manual trigger type * If a number is supplied, delay is applied to both hide/show * Object structure is: delay: { show: 500, hide: 100 } * - html boolean Insert HTML into the popover. If false, jQuery's text method will be used to * insert content into the dom. * - placement string|function how to position the popover - top | bottom | left | right * - selector string If a selector is provided, popover objects will be * delegated to the specified targets. * - template string Base HTML to use when creating the popover. * - title string|function default title value if `title` tag isn't present * - trigger string how popover is triggered - hover | focus | manual * - constraints array An array of constraints - passed through to Popper. * - offset string Offset of the popover relative to its target. */ public static function tooltip($selector = '', $options = []): void { // Only load once if (isset(static::$loaded[__METHOD__][$selector])) { return; } if ($selector !== '') { // Setup options object $opt = [ 'animation' => isset($options['animation']) ? (bool) $options['animation'] : true, 'container' => isset($options['container']) ? $options['container'] : 'body', 'delay' => isset($options['delay']) ? (int) $options['delay'] : 0, 'html' => isset($options['html']) ? (bool) $options['html'] : true, 'placement' => isset($options['placement']) ? $options['placement'] : null, 'selector' => isset($options['selector']) ? $options['selector'] : false, 'template' => isset($options['template']) ? $options['template'] : null, 'title' => isset($options['title']) ? $options['title'] : null, 'trigger' => isset($options['trigger']) ? $options['trigger'] : 'hover focus', 'fallbackPlacement' => isset($options['fallbackPlacement']) ? $options['fallbackPlacement'] : null, 'boundary' => isset($options['boundary']) ? $options['boundary'] : 'clippingParents', 'customClass' => isset($options['customClass']) ? $options['customClass'] : null, 'sanitize' => isset($options['sanitize']) ? (bool) $options['sanitize'] : true, 'allowList' => isset($options['allowList']) ? $options['allowList'] : null, ]; Factory::getDocument()->addScriptOptions('bootstrap.tooltip', [$selector => (object) array_filter((array) $opt)]); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.popover'); // Set static array static::$loaded[__METHOD__][$selector] = true; } /** * Add javascript support for Bootstrap toasts * * @param string $selector Common class for the toasts * @param array $options Options for the toasts * * @return void * * @throws \Exception * * @since 4.0.0 */ public static function toast($selector = '', $options = []): void { // Only load once if (!empty(static::$loaded[__METHOD__][$selector])) { return; } if ($selector !== '') { // Setup options object $opt = [ 'animation' => isset($options['animation']) ? (string) $options['animation'] : null, 'autohide' => isset($options['autohide']) ? (bool) $options['autohide'] : true, 'delay' => isset($options['delay']) ? (int) $options['delay'] : 5000, ]; Factory::getDocument()->addScriptOptions('bootstrap.toast', [$selector => (object) array_filter((array) $opt)]); } // Include the Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.toast'); static::$loaded[__METHOD__][$selector] = true; } /** * Method to load the ALL the Bootstrap Components * * If debugging mode is on an uncompressed version of Bootstrap is included for easier debugging. * * @param mixed $debug Is debugging mode on? [optional] * * @return void * * @since 3.0 * * @deprecated 4.0 will be removed in 6.0 * Will be removed without replacement * Load the different scripts with their individual method calls */ public static function framework($debug = null): void { $wa = Factory::getApplication() ->getDocument() ->getWebAssetManager(); array_map( function ($script) use ($wa) { $wa->useScript('bootstrap.' . $script); }, ['alert', 'button', 'carousel', 'collapse', 'dropdown', 'modal', 'offcanvas', 'popover', 'scrollspy', 'tab', 'toast'] ); } /** * Loads CSS files needed by Bootstrap * * @param boolean $includeMainCss If true, main bootstrap.css files are loaded * @param string $direction rtl or ltr direction. If empty, ltr is assumed * @param array $attribs Optional array of attributes to be passed to HTMLHelper::_('stylesheet') * * @return void * * @since 3.0 */ public static function loadCss($includeMainCss = true, $direction = 'ltr', $attribs = []): void { // Load Bootstrap main CSS if ($includeMainCss) { Factory::getDocument()->getWebAssetManager()->useStyle('bootstrap.css'); } } /** * Add javascript support for Bootstrap accordions and insert the accordion * * @param string $selector The ID selector for the tooltip. Expects a valid ID without the #! * @param array $options An array of options for the tooltip. * * @return string HTML for the accordion * * @since 3.0 * * Options for the tooltip can be: * - parent selector If selector then all collapsible elements under the specified parent will be closed when this * collapsible item is shown. (similar to traditional accordion behavior) * - toggle boolean Toggles the collapsible element on invocation * - active string Sets the active slide during load */ public static function startAccordion($selector = 'myAccordian', $options = []): string { // Only load once if (isset(static::$loaded[__METHOD__][$selector])) { return ''; } // Include Bootstrap component Factory::getApplication() ->getDocument() ->getWebAssetManager() ->useScript('bootstrap.collapse'); // Setup options object $opt = []; $opt['parent'] = isset($options['parent']) ? ($options['parent'] == true ? '#' . preg_replace('/^[\.#]/', '', $selector) : $options['parent']) : ''; $opt['toggle'] = isset($options['toggle']) ? (bool) $options['toggle'] : !($opt['parent'] === false || isset($options['active'])); $opt['active'] = isset($options['active']) ? (string) $options['active'] : ''; // Initialise with the Joomla specifics $opt['isJoomla'] = true; Factory::getDocument()->addScriptOptions('bootstrap.accordion', ['#' . preg_replace('/^[\.#]/', '', $selector) => (object) array_filter((array) $opt)]); static::$loaded[__METHOD__][$selector] = $opt; return '<div id="' . $selector . '" class="accordion" role="tablist">'; } /** * Close the current accordion * * @return string HTML to close the accordion * * @since 3.0 */ public static function endAccordion(): string { return '</div>'; } /** * Begins the display of a new accordion slide. * * @param string $selector Identifier of the accordion group. * @param string $text Text to display. * @param string $id Identifier of the slide. * @param string $class Class of the accordion group. * * @return string HTML to add the slide * * @since 3.0 */ public static function addSlide($selector, $text, $id, $class = ''): string { $in = static::$loaded[__CLASS__ . '::startAccordion'][$selector]['active'] === $id ? ' show' : ''; $collapsed = static::$loaded[__CLASS__ . '::startAccordion'][$selector]['active'] === $id ? '' : ' collapsed'; $parent = static::$loaded[__CLASS__ . '::startAccordion'][$selector]['parent'] ? 'data-bs-parent="' . static::$loaded[__CLASS__ . '::startAccordion'][$selector]['parent'] . '"' : ''; $class = (!empty($class)) ? ' ' . $class : ''; $ariaExpanded = $in === 'show' ? true : false; return <<<HTMLSTR <div class="accordion-item $class"> <h2 class="accordion-header" id="$id-heading"> <button class="accordion-button $collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#$id" aria-expanded="$ariaExpanded" aria-controls="$id" role="tab"> $text </button> </h2> <div id="$id" class="accordion-collapse collapse $in" aria-labelledby="$id-heading" $parent role="tabpanel"> <div class="accordion-body"> HTMLSTR; } /** * Close the current slide * * @return string HTML to close the slide * * @since 3.0 */ public static function endSlide(): string { return <<<HTMLSTR </div> </div> </div> HTMLSTR; } /** * Method to render a Bootstrap modal * * @param string $selector The ID selector for the modal. Expects a valid ID without the #! * @param array $options An array of options for the modal. * @param string $body Markup for the modal body. Appended after the `<iframe>` if the URL option is set * * @return string HTML markup for a modal * * @since 3.0 * * Options for the modal can be: * - backdrop string| true Includes a modal-backdrop element. Alternatively, specify static * boolean for a backdrop which doesn't close the modal on click. * - keyboard boolean true Closes the modal when escape key is pressed * - focus boolean true Closes the modal when escape key is pressed * - title string null The modal title * - closeButton boolean true Display modal close button (default = true) * - footer string null Optional markup for the modal footer * - url string null URL of a resource to be inserted as an `<iframe>` inside the modal body * - height string null Height of the `<iframe>` containing the remote resource * - width string null Width of the `<iframe>` containing the remote resource */ public static function renderModal($selector = 'modal', $options = [], $body = ''): string { // Only load once if (!empty(static::$loaded[__METHOD__][$selector])) { return ''; } // Initialise with the Joomla specifics $options['isJoomla'] = true; // Include Basic Bootstrap component HTMLHelper::_('bootstrap.modal', '#' . preg_replace('/^[\.#]/', '', $selector), $options); $layoutData = [ 'selector' => $selector, 'params' => $options, 'body' => $body, ]; static::$loaded[__METHOD__][$selector] = true; return LayoutHelper::render('libraries.html.bootstrap.modal.main', $layoutData); } /** * Creates a tab pane * * @param string $selector The pane identifier. Expects a valid ID without the #! * @param array $params The parameters for the pane * * @return string * * @since 3.1 */ public static function startTabSet($selector = 'myTab', $params = []): string { $sig = md5(serialize([$selector, $params])); if (!isset(static::$loaded[__METHOD__][$sig])) { // Setup options object $opt = []; $opt['active'] = (isset($params['active']) && ($params['active'])) ? (string) $params['active'] : ''; // Initialise with the Joomla specifics $opt['isJoomla'] = true; // Include the Bootstrap Tab Component HTMLHelper::_('bootstrap.tab', '#' . preg_replace('/^[\.#]/', '', $selector), $opt); // Set static array static::$loaded[__METHOD__][$sig] = true; static::$loaded[__METHOD__][$selector]['active'] = $opt['active']; return LayoutHelper::render('libraries.html.bootstrap.tab.starttabset', ['selector' => $selector]); } } /** * Close the current tab pane * * @return string HTML to close the pane * * @since 3.1 */ public static function endTabSet(): string { return LayoutHelper::render('libraries.html.bootstrap.tab.endtabset'); } /** * Begins the display of a new tab content panel. * * @param string $selector Identifier of the panel. Expects a valid ID without the #! * @param string $id The ID of the div element. Expects a valid ID without the #! * @param string $title The title text for the new UL tab * * @return string HTML to start a new panel * * @since 3.1 */ public static function addTab($selector, $id, $title): string { static $tabLayout = null; $tabLayout = $tabLayout === null ? new FileLayout('libraries.html.bootstrap.tab.addtab') : $tabLayout; $active = (static::$loaded[__CLASS__ . '::startTabSet'][$selector]['active'] == $id) ? ' active' : ''; return $tabLayout->render(['id' => preg_replace('/^[\.#]/', '', $id), 'active' => $active, 'title' => $title]); } /** * Close the current tab content panel * * @return string HTML to close the pane * * @since 3.1 */ public static function endTab(): string { return LayoutHelper::render('libraries.html.bootstrap.tab.endtab'); } } Helpers/Tag.php 0000644 00000016616 15172602426 0007411 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Uri\Uri; use Joomla\Database\ParameterType; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for tags * * @since 3.1 */ abstract class Tag { /** * Cached array of the tag items. * * @var array * @since 3.1 */ protected static $items = []; /** * Returns an array of tags. * * @param array $config An array of configuration options. By default, only * published and unpublished categories are returned. * * @return array * * @since 3.1 */ public static function options($config = ['filter.published' => [0, 1]]) { $hash = md5(serialize($config)); if (!isset(static::$items[$hash])) { $config = (array) $config; $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( [ $db->quoteName('a.id'), $db->quoteName('a.title'), $db->quoteName('a.level'), ] ) ->from($db->quoteName('#__tags', 'a')) ->where($db->quoteName('a.parent_id') . ' > 0'); // Filter on the published state if (isset($config['filter.published'])) { if (is_numeric($config['filter.published'])) { $query->where('a.published = :published') ->bind(':published', $config['filter.published'], ParameterType::INTEGER); } elseif (is_array($config['filter.published'])) { $config['filter.published'] = ArrayHelper::toInteger($config['filter.published']); $query->whereIn($db->quoteName('a.published'), $config['filter.published']); } } // Filter on the language if (isset($config['filter.language'])) { if (is_string($config['filter.language'])) { $query->where($db->quoteName('a.language') . ' = :language') ->bind(':language', $config['filter.language']); } elseif (is_array($config['filter.language'])) { $query->whereIn($db->quoteName('a.language'), $config['filter.language'], ParameterType::STRING); } } $query->order($db->quoteName('a.lft')); $db->setQuery($query); $items = $db->loadObjectList(); // Assemble the list options. static::$items[$hash] = []; foreach ($items as &$item) { $repeat = ($item->level - 1 >= 0) ? $item->level - 1 : 0; $item->title = str_repeat('- ', $repeat) . $item->title; static::$items[$hash][] = HTMLHelper::_('select.option', $item->id, $item->title); } } return static::$items[$hash]; } /** * Returns an array of tags. * * @param array $config An array of configuration options. By default, only published and unpublished tags are returned. * * @return array Tag data * * @since 3.1 */ public static function tags($config = ['filter.published' => [0, 1]]) { $hash = md5(serialize($config)); $config = (array) $config; $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( [ $db->quoteName('a.id'), $db->quoteName('a.title'), $db->quoteName('a.level'), $db->quoteName('a.parent_id'), ] ) ->from($db->quoteName('#__tags', 'a')) ->where($db->quoteName('a.parent_id') . ' > 0'); // Filter on the published state if (isset($config['filter.published'])) { if (is_numeric($config['filter.published'])) { $query->where($db->quoteName('a.published') . ' = :published') ->bind(':published', $config['filter.published'], ParameterType::INTEGER); } elseif (is_array($config['filter.published'])) { $config['filter.published'] = ArrayHelper::toInteger($config['filter.published']); $query->whereIn($db->quoteName('a.published'), $config['filter.published']); } } $query->order($db->quoteName('a.lft')); $db->setQuery($query); $items = $db->loadObjectList(); // Assemble the list options. static::$items[$hash] = []; foreach ($items as &$item) { $repeat = ($item->level - 1 >= 0) ? $item->level - 1 : 0; $item->title = str_repeat('- ', $repeat) . $item->title; static::$items[$hash][] = HTMLHelper::_('select.option', $item->id, $item->title); } return static::$items[$hash]; } /** * This is just a proxy for the formbehavior.ajaxchosen method * * @param string $selector DOM id of the tag field * @param boolean $allowCustom Flag to allow custom values * * @return void * * @since 3.1 * * @deprecated 4.0 will be removed in 6.0 * Will be removed without replacement */ public static function ajaxfield($selector = '#jform_tags', $allowCustom = true) { // Get the component parameters $params = ComponentHelper::getParams('com_tags'); $minTermLength = (int) $params->get('min_term_length', 3); Text::script('JGLOBAL_KEEP_TYPING'); Text::script('JGLOBAL_LOOKING_FOR'); // Include scripts HTMLHelper::_('behavior.core'); HTMLHelper::_('jquery.framework'); HTMLHelper::_('formbehavior.chosen'); HTMLHelper::_('script', 'legacy/ajax-chosen.min.js', ['version' => 'auto', 'relative' => true]); Factory::getDocument()->addScriptOptions( 'ajax-chosen', [ 'url' => Uri::root() . 'index.php?option=com_tags&task=tags.searchAjax', 'debug' => JDEBUG, 'selector' => $selector, 'type' => 'GET', 'dataType' => 'json', 'jsonTermKey' => 'like', 'afterTypeDelay' => 500, 'minTermLength' => $minTermLength, ] ); // Allow custom values ? if ($allowCustom) { HTMLHelper::_('script', 'system/fields/tag.min.js', ['version' => 'auto', 'relative' => true]); Factory::getDocument()->addScriptOptions( 'field-tag-custom', [ 'minTermLength' => $minTermLength, 'selector' => $selector, 'allowCustom' => Factory::getUser()->authorise('core.create', 'com_tags') ? $allowCustom : false, ] ); } } } Helpers/UiTab.php 0000644 00000006256 15172602426 0007701 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for the Joomla core UI Tab element. * * @since 4.0.0 */ abstract class UiTab { /** * @var array Array containing information for loaded files * @since 4.0.0 */ protected static $loaded = []; /** * Creates a core UI tab pane * * @param string $selector The pane identifier. * @param array $params The parameters for the pane * * @return string * * @since 4.0.0 */ public static function startTabSet($selector = 'myTab', $params = []) { $sig = md5(serialize([$selector, $params])); if (!isset(static::$loaded[__METHOD__][$sig])) { // Include the custom element Factory::getDocument()->getWebAssetManager() ->useStyle('webcomponent.joomla-tab') ->useScript('webcomponent.joomla-tab'); // Setup options object $opt = ['active' => (isset($params['active']) && ($params['active'])) ? (string) $params['active'] : '']; // Set static array static::$loaded[__METHOD__][$sig] = true; static::$loaded[__METHOD__][$selector]['active'] = $opt['active']; } $orientation = isset($params['orientation']) ? $params['orientation'] : 'horizontal'; $recall = isset($params['recall']) ? 'recall' : ''; $breakpoint = isset($params['breakpoint']) ? 'breakpoint="' . $params['breakpoint'] . '"' : ''; if (!isset($params['breakpoint']) && $breakpoint === '') { $breakpoint = 'breakpoint="768"'; } return '<joomla-tab id="' . $selector . '" orientation="' . $orientation . '" ' . $recall . ' ' . $breakpoint . '>'; } /** * Close the current tab pane * * @return string HTML to close the pane * * @since 4.0.0 */ public static function endTabSet() { return '</joomla-tab>'; } /** * Begins the display of a new tab content panel. * * @param string $selector Identifier of the panel. * @param string $id The ID of the div element * @param string $title The title text for the button * * @return string HTML to start a new panel * * @since 4.0.0 */ public static function addTab($selector, $id, $title) { $active = (static::$loaded[__CLASS__ . '::startTabSet'][$selector]['active'] == $id) ? ' active' : ''; return '<joomla-tab-element id="' . $id . '"' . $active . ' name="' . htmlspecialchars($title, ENT_COMPAT, 'UTF-8') . '">'; } /** * Close the current tab content panel * * @return string HTML to close the pane * * @since 4.0.0 */ public static function endTab() { return '</joomla-tab-element>'; } } Helpers/WorkflowStage.php 0000644 00000004636 15172602426 0011473 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class working with workflow states select lists * * @since 4.0.0 */ abstract class WorkflowStage { /** * Get a list of the available workflow stages. * * @param array $options An array of options for the control * * @return array * * @since 4.0.0 */ public static function existing($options) { // Get the database object and a new query object. $db = Factory::getDbo(); $query = $db->getQuery(true); // Build the query. $query->select( [ $db->quoteName('ws.id', 'workflow_stage_id'), $db->quoteName('ws.title', 'workflow_stage_title'), $db->quoteName('w.id', 'workflow_id'), $db->quoteName('w.title', 'workflow_title'), ] ) ->from($db->quoteName('#__workflow_stages', 'ws')) ->join('LEFT', $db->quoteName('#__workflows', 'w'), $db->quoteName('w.id') . ' = ' . $db->quoteName('ws.workflow_id')) ->where($db->quoteName('w.published') . ' = 1') ->order($db->quoteName('ws.ordering')); // Set the query and load the options. $stages = $db->setQuery($query)->loadObjectList(); $workflowStages = []; // Grouping the stages by workflow foreach ($stages as $stage) { // Using workflow ID to differentiate workflows having same title $workflowStageKey = Text::_($stage->workflow_title) . ' (' . $stage->workflow_id . ')'; if (!array_key_exists($workflowStageKey, $workflowStages)) { $workflowStages[$workflowStageKey] = []; } $workflowStages[$workflowStageKey][] = HTMLHelper::_('select.option', $stage->workflow_stage_id, Text::_($stage->workflow_stage_title)); } $prefix = [[ HTMLHelper::_('select.option', '', $options['title']), ]]; return array_merge($prefix, $workflowStages); } } Helpers/Icons.php 0000644 00000004032 15172602426 0007736 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Layout\FileLayout; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for icons. * * @since 2.5 */ abstract class Icons { /** * Method to generate html code for a list of buttons * * @param array $buttons Array of buttons * * @return string * * @since 2.5 */ public static function buttons($buttons) { if (empty($buttons)) { return ''; } $html = []; foreach ($buttons as $button) { $html[] = HTMLHelper::_('icons.button', $button); } return implode($html); } /** * Method to generate html code for a list of buttons * * @param array $button Button properties * * @return string * * @since 2.5 */ public static function button($button) { if (isset($button['access'])) { if (is_bool($button['access'])) { if ($button['access'] == false) { return ''; } } else { // Get the user object to verify permissions $user = Factory::getUser(); // Take each pair of permission, context values. for ($i = 0, $n = count($button['access']); $i < $n; $i += 2) { if (!$user->authorise($button['access'][$i], $button['access'][$i + 1])) { return ''; } } } } // Instantiate a new FileLayout instance and render the layout $layout = new FileLayout('joomla.quickicons.icon'); return $layout->render($button); } } Helpers/StringHelper.php 0000644 00000026014 15172602426 0011275 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\HTML\HTMLHelper; use Joomla\String\StringHelper as FrameworkStringHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * HTML helper class for rendering manipulated strings. * * @since 1.6 */ abstract class StringHelper { /** * Truncates text blocks over the specified character limit and closes * all open HTML tags. The method will optionally not truncate an individual * word, it will find the first space that is within the limit and * truncate at that point. This method is UTF-8 safe. * * @param string $text The text to truncate. * @param integer $length The maximum length of the text. * @param boolean $noSplit Don't split a word if that is where the cutoff occurs (default: true). * @param boolean $allowHtml Allow HTML tags in the output, and close any open tags (default: true). * * @return string The truncated text. * * @since 1.6 */ public static function truncate($text, $length = 0, $noSplit = true, $allowHtml = true) { // Assume a lone open tag is invalid HTML. if ($length === 1 && $text[0] === '<') { return '...'; } // Check if HTML tags are allowed. if (!$allowHtml) { // Decode entities $text = html_entity_decode($text, ENT_QUOTES, 'UTF-8'); // Deal with spacing issues in the input. $text = str_replace('>', '> ', $text); $text = str_replace([' ', ' '], ' ', $text); $text = FrameworkStringHelper::trim(preg_replace('#\s+#mui', ' ', $text)); // Strip tags from the input. $text = strip_tags($text); // Remove remaining extra spaces. $text = str_replace(' ', ' ', $text); $text = FrameworkStringHelper::trim(preg_replace('#\s+#mui', ' ', $text)); } // Whether or not allowing HTML, truncate the item text if it is too long. if ($length > 0 && FrameworkStringHelper::strlen($text) > $length) { $tmp = trim(FrameworkStringHelper::substr($text, 0, $length)); if ($tmp[0] === '<' && strpos($tmp, '>') === false) { return '...'; } // $noSplit true means that we do not allow splitting of words. if ($noSplit) { // Find the position of the last space within the allowed length. $offset = FrameworkStringHelper::strrpos($tmp, ' '); $tmp = FrameworkStringHelper::substr($tmp, 0, $offset + 1); // If there are no spaces and the string is longer than the maximum // we need to just use the ellipsis. In that case we are done. if ($offset === false && strlen($text) > $length) { return '...'; } if (FrameworkStringHelper::strlen($tmp) > $length - 3) { $tmp = trim(FrameworkStringHelper::substr($tmp, 0, FrameworkStringHelper::strrpos($tmp, ' '))); } } if ($allowHtml) { // Put all opened tags into an array preg_match_all("#<([a-z][a-z0-9]*)\b.*?(?!/)>#i", $tmp, $result); $openedTags = $result[1]; // Some tags self close so they do not need a separate close tag. $openedTags = array_diff($openedTags, ['img', 'hr', 'br']); $openedTags = array_values($openedTags); // Put all closed tags into an array preg_match_all("#</([a-z][a-z0-9]*)\b(?:[^>]*?)>#iU", $tmp, $result); $closedTags = $result[1]; $numOpened = count($openedTags); // Not all tags are closed so trim the text and finish. if (count($closedTags) !== $numOpened) { // Closing tags need to be in the reverse order of opening tags. $openedTags = array_reverse($openedTags); // Close tags for ($i = 0; $i < $numOpened; $i++) { if (!in_array($openedTags[$i], $closedTags)) { $tmp .= '</' . $openedTags[$i] . '>'; } else { unset($closedTags[array_search($openedTags[$i], $closedTags)]); } } } // Check if we are within a tag if (FrameworkStringHelper::strrpos($tmp, '<') > FrameworkStringHelper::strrpos($tmp, '>')) { $offset = FrameworkStringHelper::strrpos($tmp, '<'); $tmp = FrameworkStringHelper::trim(FrameworkStringHelper::substr($tmp, 0, $offset)); } } if ($tmp === false || strlen($text) > strlen($tmp)) { $text = trim($tmp) . '...'; } } // Clean up any internal spaces created by the processing. $text = str_replace(' </', '</', $text); $text = str_replace(' ...', '...', $text); return $text; } /** * Method to extend the truncate method to more complex situations * * The goal is to get the proper length plain text string with as much of * the html intact as possible with all tags properly closed. * * @param string $html The content of the introtext to be truncated * @param integer $maxLength The maximum number of characters to render * @param boolean $noSplit Don't split a word if that is where the cutoff occurs (default: true). * * @return string The truncated string. If the string is truncated an ellipsis * (...) will be appended. * * @note If a maximum length of 3 or less is selected and the text has more than * that number of characters an ellipsis will be displayed. * This method will not create valid HTML from malformed HTML. * * @since 3.1 */ public static function truncateComplex($html, $maxLength = 0, $noSplit = true) { // Start with some basic rules. $baseLength = strlen($html); // If the original HTML string is shorter than the $maxLength do nothing and return that. if ($baseLength <= $maxLength || $maxLength === 0) { return $html; } // Take care of short simple cases. if ($maxLength <= 3 && $html[0] !== '<' && strpos(substr($html, 0, $maxLength - 1), '<') === false && $baseLength > $maxLength) { return '...'; } // Deal with maximum length of 1 where the string starts with a tag. if ($maxLength === 1 && $html[0] === '<') { $endTagPos = strlen(strstr($html, '>', true)); $tag = substr($html, 1, $endTagPos); $l = $endTagPos + 1; if ($noSplit) { return substr($html, 0, $l) . '</' . $tag . '...'; } // @todo: $character doesn't seem to be used... $character = substr(strip_tags($html), 0, 1); return substr($html, 0, $l) . '</' . $tag . '...'; } // First get the truncated plain text string. This is the rendered text we want to end up with. $ptString = HTMLHelper::_('string.truncate', $html, $maxLength, $noSplit, $allowHtml = false); // It's all HTML, just return it. if ($ptString === '') { return $html; } // If the plain text is shorter than the max length the variable will not end in ... // In that case we use the whole string. if (substr($ptString, -3) !== '...') { return $html; } // Regular truncate gives us the ellipsis but we want to go back for text and tags. if ($ptString === '...') { $stripped = substr(strip_tags($html), 0, $maxLength); $ptString = HTMLHelper::_('string.truncate', $stripped, $maxLength, $noSplit, $allowHtml = false); } // We need to trim the ellipsis that truncate adds. $ptString = rtrim($ptString, '.'); // Now deal with more complex truncation. while ($maxLength <= $baseLength) { // Get the truncated string assuming HTML is allowed. $htmlString = HTMLHelper::_('string.truncate', $html, $maxLength, $noSplit, $allowHtml = true); if ($htmlString === '...' && strlen($ptString) + 3 > $maxLength) { return $htmlString; } $htmlString = rtrim($htmlString, '.'); // Now get the plain text from the HTML string and trim it. $htmlStringToPtString = HTMLHelper::_('string.truncate', $htmlString, $maxLength, $noSplit, $allowHtml = false); $htmlStringToPtString = rtrim($htmlStringToPtString, '.'); // If the new plain text string matches the original plain text string we are done. if ($ptString === $htmlStringToPtString) { return $htmlString . '...'; } // Get the number of HTML tag characters in the first $maxLength characters $diffLength = strlen($ptString) - strlen($htmlStringToPtString); if ($diffLength <= 0) { return $htmlString . '...'; } // Set new $maxlength that adjusts for the HTML tags $maxLength += $diffLength; } } /** * Abridges text strings over the specified character limit. The * behavior will insert an ellipsis into the text replacing a section * of variable size to ensure the string does not exceed the defined * maximum length. This method is UTF-8 safe. * * For example, it transforms "Really long title" to "Really...title". * * Note that this method does not scan for HTML tags so will potentially break them. * * @param string $text The text to abridge. * @param integer $length The maximum length of the text (default is 50). * @param integer $intro The maximum length of the intro text (default is 30). * * @return string The abridged text. * * @since 1.6 */ public static function abridge($text, $length = 50, $intro = 30) { // Abridge the item text if it is too long. if (FrameworkStringHelper::strlen($text) > $length) { // Determine the remaining text length. $remainder = $length - ($intro + 3); // Extract the beginning and ending text sections. $beg = FrameworkStringHelper::substr($text, 0, $intro); $end = FrameworkStringHelper::substr($text, FrameworkStringHelper::strlen($text) - $remainder); // Build the resulting string. $text = $beg . '...' . $end; } return $text; } } Helpers/AdminLanguage.php 0000644 00000003334 15172602426 0011363 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Object\CMSObject; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class working with administrator language select lists * * @since 3.8.0 */ abstract class AdminLanguage { /** * Cached array of the administrator language items. * * @var array * @since 3.8.0 */ protected static $items = null; /** * Get a list of the available administrator language items. * * @param boolean $all True to include All (*) * @param boolean $translate True to translate All * * @return array * * @since 3.8.0 */ public static function existing($all = false, $translate = false) { if (empty(static::$items)) { $languages = []; $admin_languages = LanguageHelper::getKnownLanguages(JPATH_ADMINISTRATOR); foreach ($admin_languages as $tag => $language) { $languages[$tag] = $language['nativeName']; } ksort($languages); static::$items = $languages; } if ($all) { $all_option = [new CMSObject(['value' => '*', 'text' => $translate ? Text::alt('JALL', 'language') : 'JALL_LANGUAGE'])]; return array_merge($all_option, static::$items); } else { return static::$items; } } } Helpers/DraggableList.php 0000644 00000004573 15172602426 0011401 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\Session\Session; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * HTML utility class for creating a sortable table list * * @since 4.0.0 */ abstract class DraggableList { /** * Array containing information for loaded files * * @var array * @since 4.0.0 */ protected static $loaded = []; /** * Method to load the Dragula script and make table sortable * * @param string $tableId DOM id of the table * @param string $formId DOM id of the form * @param string $sortDir Sort direction * @param string $saveOrderingUrl Save ordering url, ajax-load after an item dropped * @param string $redundant Not used * @param boolean $nestedList Set whether the list is a nested list * * @return void * * @since 4.0.0 */ public static function draggable( string $tableId = '', string $formId = '', string $sortDir = 'asc', string $saveOrderingUrl = '', $redundant = null, bool $nestedList = false ) { // Only load once if (isset(static::$loaded[__METHOD__])) { return; } $doc = Factory::getDocument(); // Please consider using data attributes instead of passing arguments here! if (!empty($tableId) && !empty($saveOrderingUrl) && !empty($formId) && !empty($sortDir)) { $doc->addScriptOptions( 'draggable-list', [ 'id' => '#' . $tableId . ' tbody', 'formId' => $formId, 'direction' => $sortDir, 'url' => $saveOrderingUrl . '&' . Session::getFormToken() . '=1', 'nested' => $nestedList, ] ); } $doc->getWebAssetManager() ->usePreset('dragula') ->useScript('joomla.draggable'); // Set static array static::$loaded[__METHOD__] = true; } } Helpers/SearchTools.php 0000644 00000010003 15172602426 0011104 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\Layout\LayoutHelper; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Searchtools elements. * * @since 3.2 */ abstract class SearchTools { /** * @var array Array containing information for loaded files * @since 3.2 */ protected static $loaded = []; /** * Load searchtools for a specific form * * @param mixed $selector Is debugging mode on? [optional] * @param array $options Optional array of parameters for search tools * * @return void * * @since 3.2 */ public static function form($selector = '.js-stools-form', $options = []) { $sig = md5(serialize([$selector, $options])); // Only load once if (!isset(static::$loaded[__METHOD__][$sig])) { // Add the form selector to the search tools options $options['formSelector'] = $selector; // Generate options with default values $options = static::optionsToRegistry($options); // Load the script && css files Factory::getApplication()->getDocument()->getWebAssetManager() ->useStyle('searchtools') ->useScript('searchtools'); Factory::getDocument()->addScriptOptions('searchtools', $options); static::$loaded[__METHOD__][$sig] = true; } } /** * Function to receive & pre-process javascript options * * @param mixed $options Associative array/Registry object with options * * @return Registry Options converted to Registry object */ private static function optionsToRegistry($options) { // Support options array if (is_array($options)) { $options = new Registry($options); } if (!($options instanceof Registry)) { $options = new Registry(); } return $options; } /** * Method to sort a column in a grid * * @param string $title The link title * @param string $order The order field for the column * @param string $direction The current direction * @param mixed $selected The selected ordering * @param string $task An optional task override * @param string $newDirection An optional direction for the new column * @param string $tip An optional text shown as tooltip title instead of $title * @param string $icon Icon to show * @param string $formName Name of the form to submit * * @return string */ public static function sort( $title, $order, $direction = 'asc', $selected = 0, $task = null, $newDirection = 'asc', $tip = '', $icon = null, $formName = 'adminForm' ) { $direction = strtolower($direction); $orderIcons = ['icon-caret-up', 'icon-caret-down']; $index = (int) ($direction === 'desc'); if ($order !== $selected) { $direction = $newDirection; } else { $direction = $direction === 'desc' ? 'asc' : 'desc'; } // Create an object to pass it to the layouts $data = new \stdClass(); $data->order = $order; $data->direction = $direction; $data->selected = $selected; $data->task = $task; $data->tip = $tip; $data->title = $title; $data->orderIcon = $orderIcons[$index]; $data->icon = $icon; $data->formName = $formName; return LayoutHelper::render('joomla.searchtools.grid.sort', $data); } } Helpers/ContentLanguage.php 0000644 00000004212 15172602426 0011741 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Object\CMSObject; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class working with content language select lists * * @since 1.6 */ abstract class ContentLanguage { /** * Cached array of the content language items. * * @var array * @since 1.6 */ protected static $items = null; /** * Get a list of the available content language items. * * @param boolean $all True to include All (*) * @param boolean $translate True to translate All * * @return array * * @see \Joomla\CMS\Form\Field\ContentlanguageField * @since 1.6 */ public static function existing($all = false, $translate = false) { if (empty(static::$items)) { // Get the database object and a new query object. $db = Factory::getDbo(); $query = $db->getQuery(true); // Build the query. $query->select( [ $db->quoteName('a.lang_code', 'value'), $db->quoteName('a.title', 'text'), $db->quoteName('a.title_native'), ] ) ->from($db->quoteName('#__languages', 'a')) ->where($db->quoteName('a.published') . ' >= 0') ->order($db->quoteName('a.title')); // Set the query and load the options. $db->setQuery($query); static::$items = $db->loadObjectList(); } if ($all) { $all_option = [new CMSObject(['value' => '*', 'text' => $translate ? Text::alt('JALL', 'language') : 'JALL_LANGUAGE'])]; return array_merge($all_option, static::$items); } else { return static::$items; } } } Helpers/Menu.php 0000644 00000033502 15172602426 0007573 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\Database\ParameterType; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class working with menu select lists * * @since 1.5 */ abstract class Menu { /** * Cached array of the menus. * * @var array * @since 1.6 */ protected static $menus = []; /** * Cached array of the menus items. * * @var array * @since 1.6 */ protected static $items = []; /** * Get a list of the available menus. * * @param int $clientId The client id * * @return array * * @since 1.6 */ public static function menus($clientId = 0) { $key = serialize($clientId); if (!isset(static::$menus[$key])) { $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( [ $db->quoteName('id'), $db->quoteName('menutype', 'value'), $db->quoteName('title', 'text'), $db->quoteName('client_id'), ] ) ->from($db->quoteName('#__menu_types')) ->order( [ $db->quoteName('client_id'), $db->quoteName('title'), ] ); if (isset($clientId)) { $clientId = (int) $clientId; $query->where($db->quoteName('client_id') . ' = :client') ->bind(':client', $clientId, ParameterType::INTEGER); } static::$menus[$key] = $db->setQuery($query)->loadObjectList(); } return static::$menus[$key]; } /** * Returns an array of menu items grouped by menu. * * @param array $config An array of configuration options [published, checkacl, clientid]. * * @return array * * @since 1.6 */ public static function menuItems($config = []) { $key = serialize($config); if (empty(static::$items[$key])) { // B/C - not passed = 0, null can be passed for both clients $clientId = array_key_exists('clientid', $config) ? $config['clientid'] : 0; $menus = static::menus($clientId); $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( [ $db->quoteName('a.id', 'value'), $db->quoteName('a.title', 'text'), $db->quoteName('a.level'), $db->quoteName('a.menutype'), $db->quoteName('a.client_id'), ] ) ->from($db->quoteName('#__menu', 'a')) ->where($db->quoteName('a.parent_id') . ' > 0'); // Filter on the client id if (isset($clientId)) { $query->where($db->quoteName('a.client_id') . ' = :client') ->bind(':client', $clientId, ParameterType::INTEGER); } // Filter on the published state if (isset($config['published'])) { if (is_numeric($config['published'])) { $query->where($db->quoteName('a.published') . ' = :published') ->bind(':published', $config['published'], ParameterType::INTEGER); } elseif ($config['published'] === '') { $query->where($db->quoteName('a.published') . ' IN (0,1)'); } } $query->order($db->quoteName('a.lft')); $db->setQuery($query); $items = $db->loadObjectList(); // Collate menu items based on menutype $lookup = []; foreach ($items as &$item) { if (!isset($lookup[$item->menutype])) { $lookup[$item->menutype] = []; } $lookup[$item->menutype][] = &$item; // Translate the menu item title when client is administrator if ($clientId === 1) { $item->text = Text::_($item->text); } $item->text = str_repeat('- ', $item->level) . $item->text; } static::$items[$key] = []; $user = Factory::getUser(); $aclcheck = !empty($config['checkacl']) ? (int) $config['checkacl'] : 0; foreach ($menus as &$menu) { if ($aclcheck) { $action = $aclcheck == $menu->id ? 'edit' : 'create'; if (!$user->authorise('core.' . $action, 'com_menus.menu.' . $menu->id)) { continue; } } // Start group: $optGroup = new \stdClass(); $optGroup->value = '<OPTGROUP>'; $optGroup->text = $menu->text; static::$items[$key][] = $optGroup; // Special "Add to this Menu" option: static::$items[$key][] = HTMLHelper::_('select.option', $menu->value . '.1', Text::_('JLIB_HTML_ADD_TO_THIS_MENU')); // Menu items: if (isset($lookup[$menu->value])) { foreach ($lookup[$menu->value] as &$item) { static::$items[$key][] = HTMLHelper::_('select.option', $menu->value . '.' . $item->value, $item->text); } } // Finish group: $closeOptGroup = new \stdClass(); $closeOptGroup->value = '</OPTGROUP>'; $closeOptGroup->text = $menu->text; static::$items[$key][] = $closeOptGroup; } } return static::$items[$key]; } /** * Displays an HTML select list of menu items. * * @param string $name The name of the control. * @param string $selected The value of the selected option. * @param string $attribs Attributes for the control. * @param array $config An array of options for the control [id, published, checkacl, clientid]. * * @return string * * @since 1.6 */ public static function menuItemList($name, $selected = null, $attribs = null, $config = []) { static $count; $options = static::menuItems($config); return HTMLHelper::_( 'select.genericlist', $options, $name, [ 'id' => $config['id'] ?? 'assetgroups_' . (++$count), 'list.attr' => $attribs ?? 'class="inputbox" size="1"', 'list.select' => (int) $selected, 'list.translate' => false, ] ); } /** * Build the select list for Menu Ordering * * @param object $row The row object * @param integer $id The id for the row. Must exist to enable menu ordering * * @return string * * @since 1.5 */ public static function ordering(&$row, $id) { if ($id) { $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( [ $db->quoteName('ordering', 'value'), $db->quoteName('title', 'text'), ] ) ->from($db->quoteName('#__menu')) ->where( [ $db->quoteName('menutype') . ' = :menutype', $db->quoteName('parent_id') . ' = :parent', $db->quoteName('published') . ' != -2', ] ) ->order($db->quoteName('ordering')) ->bind(':menutype', $row->menutype) ->bind(':parent', $row->parent_id, ParameterType::INTEGER); $order = HTMLHelper::_('list.genericordering', $query); $ordering = HTMLHelper::_( 'select.genericlist', $order, 'ordering', ['list.attr' => 'class="inputbox" size="1"', 'list.select' => (int) $row->ordering] ); } else { $ordering = '<input type="hidden" name="ordering" value="' . $row->ordering . '">' . Text::_('JGLOBAL_NEWITEMSLAST_DESC'); } return $ordering; } /** * Build the multiple select list for Menu Links/Pages * * @param boolean $all True if all can be selected * @param boolean $unassigned True if unassigned can be selected * @param int $clientId The client id * * @return string * * @since 1.5 */ public static function linkOptions($all = false, $unassigned = false, $clientId = 0) { $db = Factory::getDbo(); // Get a list of the menu items $query = $db->getQuery(true) ->select( [ $db->quoteName('m.id'), $db->quoteName('m.parent_id'), $db->quoteName('m.title'), $db->quoteName('m.menutype'), $db->quoteName('m.client_id'), ] ) ->from($db->quoteName('#__menu', 'm')) ->where($db->quoteName('m.published') . ' = 1') ->order( [ $db->quoteName('m.client_id'), $db->quoteName('m.menutype'), $db->quoteName('m.parent_id'), ] ); if (isset($clientId)) { $clientId = (int) $clientId; $query->where($db->quoteName('m.client_id') . ' = :client') ->bind(':client', $clientId, ParameterType::INTEGER); } $db->setQuery($query); $mitems = $db->loadObjectList(); if (!$mitems) { $mitems = []; } // Establish the hierarchy of the menu $children = []; // First pass - collect children foreach ($mitems as $v) { $pt = $v->parent_id; $list = @$children[$pt] ? $children[$pt] : []; $list[] = $v; $children[$pt] = $list; } // Second pass - get an indent list of the items $list = static::treerecurse((int) $mitems[0]->parent_id, '', [], $children, 9999, 0, 0); // Code that adds menu name to Display of Page(s) $mitems = []; if ($all | $unassigned) { $mitems[] = HTMLHelper::_('select.option', '<OPTGROUP>', Text::_('JOPTION_MENUS')); if ($all) { $mitems[] = HTMLHelper::_('select.option', 0, Text::_('JALL')); } if ($unassigned) { $mitems[] = HTMLHelper::_('select.option', -1, Text::_('JOPTION_UNASSIGNED')); } $mitems[] = HTMLHelper::_('select.option', '</OPTGROUP>'); } $lastMenuType = null; $tmpMenuType = null; foreach ($list as $list_a) { if ($list_a->menutype != $lastMenuType) { if ($tmpMenuType) { $mitems[] = HTMLHelper::_('select.option', '</OPTGROUP>'); } $mitems[] = HTMLHelper::_('select.option', '<OPTGROUP>', $list_a->menutype); $lastMenuType = $list_a->menutype; $tmpMenuType = $list_a->menutype; } $mitems[] = HTMLHelper::_('select.option', $list_a->id, $list_a->title); } if ($lastMenuType !== null) { $mitems[] = HTMLHelper::_('select.option', '</OPTGROUP>'); } return $mitems; } /** * Build the list representing the menu tree * * @param integer $id Id of the menu item * @param string $indent The indentation string * @param array $list The list to process * @param array $children The children of the current item * @param integer $maxlevel The maximum number of levels in the tree * @param integer $level The starting level * @param int $type Set the type of spacer to use. Use 1 for |_ or 0 for - * * @return array * * @since 1.5 */ public static function treerecurse($id, $indent, $list, &$children, $maxlevel = 9999, $level = 0, $type = 1) { if ($level <= $maxlevel && isset($children[$id]) && is_array($children[$id])) { if ($type) { $pre = '<sup>|_</sup> '; $spacer = '.      '; } else { $pre = '- '; $spacer = '  '; } foreach ($children[$id] as $v) { $id = $v->id; if ($v->parent_id == 0) { $txt = $v->title; } else { $txt = $pre . $v->title; } $list[$id] = $v; $list[$id]->treename = $indent . $txt; if (isset($children[$id]) && is_array($children[$id])) { $list[$id]->children = count($children[$id]); $list = static::treerecurse($id, $indent . $spacer, $list, $children, $maxlevel, $level + 1, $type); } else { $list[$id]->children = 0; } } } return $list; } } Helpers/FormBehavior.php 0000644 00000013217 15172602426 0011253 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for form related behaviors * * @since 3.0 * * @deprecated 4.0 will be removed in 6.0 * Will be removed without replacement * Use choice.js instead * Example: * Factory::getDocument()->getWebAssetManager()->enableAsset('choicesjs'); * HTMLHelper::_('webcomponent', 'system/webcomponents/joomla-field-fancy-select.min.js', ['version' => 'auto', 'relative' => true]); */ abstract class FormBehavior { /** * @var array Array containing information for loaded files * @since 3.0 */ protected static $loaded = []; /** * Method to load the Chosen JavaScript framework and supporting CSS into the document head * * If debugging mode is on an uncompressed version of Chosen is included for easier debugging. * * @param string $selector Class for Chosen elements. * @param mixed $debug Is debugging mode on? [optional] * @param array $options the possible Chosen options as name => value [optional] * * @return void * * @since 3.0 */ public static function chosen($selector = '.advancedSelect', $debug = null, $options = []) { if (isset(static::$loaded[__METHOD__][$selector])) { return; } // If no debugging value is set, use the configuration setting if ($debug === null) { $debug = JDEBUG; } // Default settings if (!isset($options['disable_search_threshold'])) { $options['disable_search_threshold'] = 10; } // Allow searching contains space in query if (!isset($options['search_contains'])) { $options['search_contains'] = true; } if (!isset($options['allow_single_deselect'])) { $options['allow_single_deselect'] = true; } if (!isset($options['placeholder_text_multiple'])) { $options['placeholder_text_multiple'] = Text::_('JGLOBAL_TYPE_OR_SELECT_SOME_OPTIONS'); } if (!isset($options['placeholder_text_single'])) { $options['placeholder_text_single'] = Text::_('JGLOBAL_SELECT_AN_OPTION'); } if (!isset($options['no_results_text'])) { $options['no_results_text'] = Text::_('JGLOBAL_SELECT_NO_RESULTS_MATCH'); } // Options array to json options string $options_str = \json_encode($options, ($debug && \defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : false)); // Add chosen.js assets /** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); $wa->usePreset('chosen') ->registerAndUseScript('joomla-chosen', 'legacy/joomla-chosen.min.js', [], [], ['chosen']) ->addInlineScript( " jQuery(document).ready(function (){ jQuery('" . $selector . "').jchosen(" . $options_str . "); }); " ); static::$loaded[__METHOD__][$selector] = true; } /** * Method to load the AJAX Chosen library * * If debugging mode is on an uncompressed version of AJAX Chosen is included for easier debugging. * * @param Registry $options Options in a Registry object * @param mixed $debug Is debugging mode on? [optional] * * @return void * * @since 3.0 */ public static function ajaxchosen(Registry $options, $debug = null) { // Retrieve options/defaults $selector = $options->get('selector', '.tagfield'); $type = $options->get('type', 'GET'); $url = $options->get('url', null); $dataType = $options->get('dataType', 'json'); $jsonTermKey = $options->get('jsonTermKey', 'term'); $afterTypeDelay = $options->get('afterTypeDelay', '500'); $minTermLength = $options->get('minTermLength', '3'); // Ajax URL is mandatory if (!empty($url)) { if (isset(static::$loaded[__METHOD__][$selector])) { return; } // Requires chosen to work static::chosen($selector, $debug); Text::script('JGLOBAL_KEEP_TYPING'); Text::script('JGLOBAL_LOOKING_FOR'); // Include scripts HTMLHelper::_('behavior.core'); HTMLHelper::_('jquery.framework'); HTMLHelper::_('script', 'legacy/ajax-chosen.min.js', ['version' => 'auto', 'relative' => true, 'detectDebug' => $debug]); Factory::getDocument()->addScriptOptions( 'ajax-chosen', [ 'url' => $url, 'debug' => $debug, 'options' => $options, 'selector' => $selector, 'type' => $type, 'dataType' => $dataType, 'jsonTermKey' => $jsonTermKey, 'afterTypeDelay' => $afterTypeDelay, 'minTermLength' => $minTermLength, ] ); static::$loaded[__METHOD__][$selector] = true; } } } Helpers/SortableList.php 0000644 00000003416 15172602426 0011277 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\HTML\HTMLHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * HTML utility class for creating a sortable table list * * @since 3.0 * * @deprecated 4.0 will be removed in 6.0 * Sortable List will be deprecated in favour of a new dragula script in 4.0 */ abstract class SortableList { /** * Method to load the Sortable script and make table sortable * * @param string $tableId DOM id of the table * @param string $formId DOM id of the form * @param string $sortDir Sort direction * @param string $saveOrderingUrl Save ordering url, ajax-load after an item dropped * @param boolean $proceedSaveOrderButton Set whether a save order button is displayed * @param boolean $nestedList Set whether the list is a nested list * * @return void * * @since 3.0 * * @deprecated 4.0 will be removed in 6.0 * Use the new dragula script * Example: JHtml::_('draggablelist.draggable') and add a class of js-draggable to the tbody element of the table */ public static function sortable($tableId, $formId, $sortDir = 'asc', $saveOrderingUrl = null, $proceedSaveOrderButton = true, $nestedList = false) { HTMLHelper::_('draggablelist.draggable', $tableId, $formId, $sortDir, $saveOrderingUrl, $proceedSaveOrderButton, $nestedList); } } Helpers/Links.php 0000644 00000006341 15172602426 0007750 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Layout\FileLayout; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for icons. * * @since 3.2 */ abstract class Links { /** * Method to generate html code for groups of lists of links * * @param array $groupsOfLinks Array of links * * @return string * * @since 3.2 */ public static function linksgroups($groupsOfLinks) { $html = []; if (count($groupsOfLinks) > 0) { $layout = new FileLayout('joomla.links.groupsopen'); $html[] = $layout->render(''); foreach ($groupsOfLinks as $title => $links) { if (isset($links[0]['separategroup'])) { $layout = new FileLayout('joomla.links.groupseparator'); $html[] = $layout->render($title); } $layout = new FileLayout('joomla.links.groupopen'); $htmlHeader = $layout->render($title); $htmlLinks = HTMLHelper::_('links.links', $links); if ($htmlLinks !== '') { $html[] = $htmlHeader; $html[] = $htmlLinks; $layout = new FileLayout('joomla.links.groupclose'); $html[] = $layout->render(''); } } $layout = new FileLayout('joomla.links.groupsclose'); $html[] = $layout->render(''); } return implode($html); } /** * Method to generate html code for a list of links * * @param array $links Array of links * * @return string * * @since 3.2 */ public static function links($links) { $html = []; foreach ($links as $link) { $html[] = HTMLHelper::_('links.link', $link); } return implode($html); } /** * Method to generate html code for a single link * * @param array $link link properties * * @return string * * @since 3.2 */ public static function link($link) { if (isset($link['access'])) { if (is_bool($link['access'])) { if ($link['access'] == false) { return ''; } } else { // Get the user object to verify permissions $user = Factory::getUser(); // Take each pair of permission, context values. for ($i = 0, $n = count($link['access']); $i < $n; $i += 2) { if (!$user->authorise($link['access'][$i], $link['access'][$i + 1])) { return ''; } } } } // Instantiate a new FileLayout instance and render the layout $layout = new FileLayout('joomla.links.link'); return $layout->render($link); } } Helpers/JGrid.php 0000644 00000047416 15172602426 0007677 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for creating HTML Grids * * @since 1.6 */ abstract class JGrid { /** * Returns an action on a grid * * @param integer $i The row index * @param string $task The task to fire * @param string|array $prefix An optional task prefix or an array of options * @param string $activeTitle An optional active tooltip to display if $enable is true * @param string $inactiveTitle An optional inactive tooltip to display if $enable is true * @param boolean $tip An optional setting for tooltip * @param string $activeClass An optional active HTML class * @param string $inactiveClass 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. * @param string $formId An optional form selector. * * @return string The HTML markup * * @since 1.6 */ public static function action( $i, $task, $prefix = '', $activeTitle = '', $inactiveTitle = '', $tip = false, $activeClass = '', $inactiveClass = '', $enabled = true, $translate = true, $checkbox = 'cb', $formId = null ) { $html = []; if (is_array($prefix)) { $options = $prefix; $activeTitle = array_key_exists('active_title', $options) ? $options['active_title'] : $activeTitle; $inactiveTitle = array_key_exists('inactive_title', $options) ? $options['inactive_title'] : $inactiveTitle; $tip = array_key_exists('tip', $options) ? $options['tip'] : $tip; $activeClass = array_key_exists('active_class', $options) ? $options['active_class'] : $activeClass; $inactiveClass = array_key_exists('inactive_class', $options) ? $options['inactive_class'] : $inactiveClass; $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 ? $activeTitle : $inactiveTitle; $title = $translate ? Text::_($title) : $title; $ariaid = $checkbox . $task . $i . '-desc'; // Don't show empty tooltip. if ($title === '') { $tip = false; } } if ($enabled) { Factory::getDocument()->getWebAssetManager()->useScript('list-view'); $html[] = '<a href="#" class="js-grid-item-action tbody-icon' . ($activeClass === 'publish' ? ' active' : '') . '"'; $html[] = ' data-item-id="' . $checkbox . $i . '" data-item-task="' . $prefix . $task . '" data-item-form-id="' . $formId . '"'; $html[] = $tip ? ' aria-labelledby="' . $ariaid . '"' : ''; $html[] = '>'; $html[] = LayoutHelper::render('joomla.icon.iconclass', ['icon' => $activeClass]); $html[] = '</a>'; $html[] = $tip ? '<div role="tooltip" id="' . $ariaid . '">' . $title . '</div>' : ''; } else { $html[] = '<span class="tbody-icon jgrid"'; $html[] = $tip ? ' aria-labelledby="' . $ariaid . '"' : ''; $html[] = '>'; $html[] = LayoutHelper::render('joomla.icon.iconclass', ['icon' => $inactiveClass]); $html[] = '</span>'; $html[] = $tip ? '<div role="tooltip" id="' . $ariaid . '">' . $title . '</div>' : ''; } return implode($html); } /** * Returns a state on a grid * * @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. * @param string $formId An optional form selector. * * @return string The HTML markup * * @since 1.6 */ public static function state($states, $value, $i, $prefix = '', $enabled = true, $translate = true, $checkbox = 'cb', $formId = null) { 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] : ''); $activeTitle = array_key_exists('active_title', $state) ? $state['active_title'] : (array_key_exists(2, $state) ? $state[2] : ''); $inactiveTitle = 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); $activeClass = array_key_exists('active_class', $state) ? $state['active_class'] : (array_key_exists(5, $state) ? $state[5] : ''); $inactiveClass = array_key_exists('inactive_class', $state) ? $state['inactive_class'] : (array_key_exists(6, $state) ? $state[6] : ''); return static::action( $i, $task, $prefix, $activeTitle, $inactiveTitle, $tip, $activeClass, $inactiveClass, $enabled, $translate, $checkbox, $formId ); } /** * Returns a published state on a grid * * @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 $publishUp An optional start publishing date. * @param string $publishDown An optional finish publishing date. * @param string $formId An optional form selector. * * @return string The HTML markup * * @see JHtmlJGrid::state() * @since 1.6 */ public static function published( $value, $i, $prefix = '', $enabled = true, $checkbox = 'cb', $publishUp = null, $publishDown = null, $formId = null ) { 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 = [ 1 => ['unpublish', 'JPUBLISHED', 'JLIB_HTML_UNPUBLISH_ITEM', 'JPUBLISHED', true, 'publish', 'publish'], 0 => ['publish', 'JUNPUBLISHED', 'JLIB_HTML_PUBLISH_ITEM', 'JUNPUBLISHED', true, 'unpublish', 'unpublish'], 2 => ['unpublish', 'JARCHIVED', 'JLIB_HTML_UNPUBLISH_ITEM', 'JARCHIVED', true, 'archive', 'archive'], -2 => ['publish', 'JTRASHED', 'JLIB_HTML_PUBLISH_ITEM', 'JTRASHED', true, 'trash', 'trash'], ]; // Special state for dates if ($publishUp || $publishDown) { $nullDate = Factory::getDbo()->getNullDate(); $nowDate = Factory::getDate()->toUnix(); $tz = Factory::getUser()->getTimezone(); $publishUp = ($publishUp !== null && $publishUp !== $nullDate) ? Factory::getDate($publishUp, 'UTC')->setTimezone($tz) : false; $publishDown = ($publishDown !== null && $publishDown !== $nullDate) ? Factory::getDate($publishDown, 'UTC')->setTimezone($tz) : false; // Create tip text, only we have publish up or down settings $tips = []; if ($publishUp) { $tips[] = Text::sprintf('JLIB_HTML_PUBLISHED_START', HTMLHelper::_('date', $publishUp, Text::_('DATE_FORMAT_LC5'), 'UTC')); } if ($publishDown) { $tips[] = Text::sprintf('JLIB_HTML_PUBLISHED_FINISHED', HTMLHelper::_('date', $publishDown, Text::_('DATE_FORMAT_LC5'), 'UTC')); } $tip = empty($tips) ? false : implode('<br>', $tips); // Add tips and special titles foreach ($states as $key => $state) { // Create special titles for published items if ($key == 1) { $states[$key][2] = $states[$key][3] = 'JLIB_HTML_PUBLISHED_ITEM'; if ($publishUp > $nullDate && $nowDate < $publishUp->toUnix()) { $states[$key][2] = $states[$key][3] = 'JLIB_HTML_PUBLISHED_PENDING_ITEM'; $states[$key][5] = $states[$key][6] = 'pending'; } if ($publishDown > $nullDate && $nowDate > $publishDown->toUnix()) { $states[$key][2] = $states[$key][3] = 'JLIB_HTML_PUBLISHED_EXPIRED_ITEM'; $states[$key][5] = $states[$key][6] = 'expired'; } } // 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, $formId); } return static::state($states, $value, $i, $prefix, $enabled, true, $checkbox, $formId); } /** * Returns an isDefault state on a grid * * @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 $formId An optional form selector. * @param string $active_class The class for active items. * @param string $inactive_class The class for inactive items. * * @return string The HTML markup * * @see JHtmlJGrid::state() * @since 1.6 */ public static function isdefault($value, $i, $prefix = '', $enabled = true, $checkbox = 'cb', $formId = null, $active_class = 'icon-color-featured icon-star', $inactive_class = 'icon-unfeatured') { 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, $inactive_class, $inactive_class], 1 => ['unsetDefault', 'JDEFAULT', 'JLIB_HTML_UNSETDEFAULT_ITEM', 'JDEFAULT', 1, $active_class, $active_class], ]; return static::state($states, $value, $i, $prefix, $enabled, true, $checkbox, $formId); } /** * Returns an array of standard published state filter options. * * @param array $config An array of configuration options. * This array can contain a list of key/value pairs where values are boolean * and keys can be taken from 'published', 'unpublished', 'archived', 'trash', 'all'. * These pairs determine which values are displayed. * * @return array The array of standard published state filter options * * @since 1.6 */ public static function publishedOptions($config = []) { // Build the active state filter options. $options = []; if (!array_key_exists('published', $config) || $config['published']) { $options[] = HTMLHelper::_('select.option', '1', 'JPUBLISHED'); } if (!array_key_exists('unpublished', $config) || $config['unpublished']) { $options[] = HTMLHelper::_('select.option', '0', 'JUNPUBLISHED'); } if (!array_key_exists('archived', $config) || $config['archived']) { $options[] = HTMLHelper::_('select.option', '2', 'JARCHIVED'); } if (!array_key_exists('trash', $config) || $config['trash']) { $options[] = HTMLHelper::_('select.option', '-2', 'JTRASHED'); } if (!array_key_exists('all', $config) || $config['all']) { $options[] = HTMLHelper::_('select.option', '*', 'JALL'); } return $options; } /** * 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. * @param string $formId An optional form selector. * * @return string The HTML markup * * @since 1.6 */ public static function checkedout($i, $editorName, $time, $prefix = '', $enabled = false, $checkbox = 'cb', $formId = null) { 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'); $activeTitle = HTMLHelper::_('tooltipText', Text::_('JLIB_HTML_CHECKIN'), $text, 0); $inactiveTitle = HTMLHelper::_('tooltipText', Text::_('JLIB_HTML_CHECKED_OUT'), $text, 0); return static::action( $i, 'checkin', $prefix, html_entity_decode($activeTitle, ENT_QUOTES, 'UTF-8'), html_entity_decode($inactiveTitle, ENT_QUOTES, 'UTF-8'), true, 'checkedout', 'checkedout', $enabled, false, $checkbox, $formId ); } /** * 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. * @param string $formId An optional form selector. * * @return string The HTML markup * * @since 1.6 */ public static function orderUp($i, $task = 'orderup', $prefix = '', $text = 'JLIB_HTML_MOVE_UP', $enabled = true, $checkbox = 'cb', $formId = null) { 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, 'uparrow', 'uparrow_disabled', $enabled, true, $checkbox, $formId); } /** * 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. * @param string $formId An optional form selector. * * @return string The HTML markup * * @since 1.6 */ public static function orderDown( $i, $task = 'orderdown', $prefix = '', $text = 'JLIB_HTML_MOVE_DOWN', $enabled = true, $checkbox = 'cb', $formId = null ) { 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, 'downarrow', 'downarrow_disabled', $enabled, true, $checkbox, $formId); } } Helpers/Number.php 0000644 00000010044 15172602426 0010113 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Language\Text; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * HTML helper class for rendering numbers. * * @since 1.6 */ abstract class Number { /** * Converts bytes to more distinguishable formats such as: * kilobytes, megabytes, etc. * * By default, the proper format will automatically be chosen. * However, one of the allowed unit types (viz. 'b', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB') may also be used instead. * IEC standard unit types ('KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB') can be used as well. * * @param string $bytes The number of bytes. Can be either numeric or suffixed format: 32M, 60K, 12G or 812b * @param string $unit The type of unit to return, few special values are: * Blank string '' for no unit, * 'auto' to choose automatically (default) * 'binary' to choose automatically but use binary unit prefix * @param integer $precision The number of digits to be used after the decimal place. * @param bool $iec Whether to be aware of IEC standards. IEC prefixes are always acceptable in input. * When IEC is ON: KiB = 1024 B, KB = 1000 B * When IEC is OFF: KiB = 1024 B, KB = 1024 B * * @return string The number of bytes in the proper units. * * @since 1.6 * @link https://en.wikipedia.org/wiki/Binary_prefix */ public static function bytes($bytes, $unit = 'auto', $precision = 2, $iec = false) { /* * Allowed 123.45, 123.45 M, 123.45 Mi, 123.45 MB, 123.45 MiB, 1.2345E+12MB, 1.2345E+12 MB , 1.2345E+12 MiB etc. * Meaning any number in decimal digits or in sci. notation, optional space, optional 1-3 letter unit suffix */ if (is_numeric($bytes)) { $oBytes = $bytes; } else { preg_match('/(.*?)\s?((?:[KMGTPEZY]i?)?B?)$/i', trim($bytes), $matches); list(, $oBytes, $oUnit) = $matches; if ($oUnit && is_numeric($oBytes)) { $oBase = $iec && strpos($oUnit, 'i') === false ? 1000 : 1024; $factor = pow($oBase, stripos('BKMGTPEZY', $oUnit[0])); $oBytes *= $factor; } } if (empty($oBytes) || !is_numeric($oBytes)) { return 0; } $oBytes = round($oBytes); // If no unit is requested return early if ($unit === '') { return (string) $oBytes; } $stdSuffixes = ['b', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; $iecSuffixes = ['b', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; // User supplied method if (in_array($unit, $iecSuffixes)) { $base = 1024; $i = array_search($unit, $iecSuffixes, true); $suffix = $unit; } elseif (in_array($unit, $stdSuffixes)) { $base = $iec ? 1000 : 1024; $i = array_search($unit, $stdSuffixes, true); $suffix = $unit; } elseif ($unit === 'binary') { $base = 1024; $i = (int) floor(log($oBytes, $base)); $suffix = $iecSuffixes[$i]; } else { // Default method $base = $iec ? 1000 : 1024; $i = (int) floor(log($oBytes, $base)); $suffix = $stdSuffixes[$i]; } return number_format( round($oBytes / pow($base, $i), (int) $precision), (int) $precision, Text::_('DECIMALS_SEPARATOR'), Text::_('THOUSANDS_SEPARATOR') ) . ' ' . $suffix; } } Helpers/Access.php 0000644 00000024424 15172602426 0010073 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Access\Access as AccessCheck; use Joomla\CMS\Factory; use Joomla\CMS\Helper\UserGroupsHelper; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Extended Utility class for all HTML drawing classes. * * @since 1.6 */ abstract class Access { /** * A cached array of the asset groups * * @var array * @since 1.6 */ protected static $asset_groups = null; /** * Displays a list of the available access view levels * * @param string $name The form field name. * @param string $selected The name of the selected section. * @param string $attribs Additional attributes to add to the select field. * @param mixed $params True to add "All Sections" option or an array of options * @param mixed $id The form field id or false if not used * * @return string The required HTML for the SELECT tag. * * @see \Joomla\CMS\Form\Field\AccesslevelField * @since 1.6 */ public static function level($name, $selected, $attribs = '', $params = true, $id = false) { $db = Factory::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'), $db->quoteName('a.title'), $db->quoteName('a.ordering'), ] ) ->order( [ $db->quoteName('a.ordering') . ' ASC', $db->quoteName('a.title') . ' ASC', ] ); // Get the options. $db->setQuery($query); $options = $db->loadObjectList(); // If params is an array, push these options to the array if (is_array($params)) { $options = array_merge($params, $options); } elseif ($params) { // If all levels is allowed, push it into the array. array_unshift($options, HTMLHelper::_('select.option', '', Text::_('JOPTION_ACCESS_SHOW_ALL_LEVELS'))); } return HTMLHelper::_( 'select.genericlist', $options, $name, [ 'list.attr' => $attribs, 'list.select' => $selected, 'id' => $id, ] ); } /** * Displays a list of the available user groups. * * @param string $name The form field name. * @param string $selected The name of the selected section. * @param string $attribs Additional attributes to add to the select field. * @param boolean $allowAll True to add "All Groups" option. * @param mixed $id The form field id * * @return string The required HTML for the SELECT tag. * * @see \Joomla\CMS\Form\Field\UsergrouplistField * @since 1.6 */ public static function usergroup($name, $selected, $attribs = '', $allowAll = true, $id = false) { $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 ($allowAll) { array_unshift($options, HTMLHelper::_('select.option', '', Text::_('JOPTION_ACCESS_SHOW_ALL_GROUPS'))); } return HTMLHelper::_('select.genericlist', $options, $name, ['list.attr' => $attribs, 'list.select' => $selected, 'id' => $id]); } /** * Returns a UL list of user groups with checkboxes * * @param string $name The name of the checkbox controls array * @param array $selected An array of the checked boxes * @param boolean $checkSuperAdmin If false only super admins can add to super admin groups * * @return string * * @since 1.6 */ public static function usergroups($name, $selected, $checkSuperAdmin = false) { static $count; $count++; $isSuperAdmin = Factory::getUser()->authorise('core.admin'); $groups = array_values(UserGroupsHelper::getInstance()->getAll()); $html = []; for ($i = 0, $n = count($groups); $i < $n; $i++) { $item = &$groups[$i]; // If checkSuperAdmin is true, only add item if the user is superadmin or the group is not super admin if ((!$checkSuperAdmin) || $isSuperAdmin || (!AccessCheck::checkGroup($item->id, 'core.admin'))) { // Set up the variable attributes. ID may not start with a number (CSS) $eid = 'group_' . $item->id . '_' . $count; // Don't call in_array unless something is selected $checked = ''; if ($selected) { $checked = in_array($item->id, $selected) ? ' checked="checked"' : ''; } $rel = ($item->parent_id > 0) ? ' rel="group_' . $item->parent_id . '_' . $count . '"' : ''; // Build the HTML for the item. $html[] = ' <div class="control-group">'; $html[] = ' <div class="controls">'; $html[] = ' <label class="form-check-label checkbox" for="' . $eid . '">'; $html[] = ' <input class="form-check-input" type="checkbox" name="' . $name . '[]" value="' . $item->id . '" id="' . $eid . '"'; $html[] = ' ' . $checked . $rel . '>'; $html[] = ' ' . LayoutHelper::render('joomla.html.treeprefix', ['level' => $item->level + 1]) . $item->title; $html[] = ' </label>'; $html[] = ' </div>'; $html[] = ' </div>'; } } return implode("\n", $html); } /** * Returns a UL list of actions with checkboxes * * @param string $name The name of the checkbox controls array * @param array $selected An array of the checked boxes * @param string $component The component the permissions apply to * @param string $section The section (within a component) the permissions apply to * * @return string * * @see AccessCheck * @since 1.6 */ public static function actions($name, $selected, $component, $section = 'global') { static $count; $count++; $actions = AccessCheck::getActionsFromFile( JPATH_ADMINISTRATOR . '/components/' . $component . '/access.xml', "/access/section[@name='" . $section . "']/" ); $html = []; $html[] = '<ul class="checklist access-actions">'; for ($i = 0, $n = count($actions); $i < $n; $i++) { $item = &$actions[$i]; // Setup the variable attributes. $eid = $count . 'action_' . $item->id; $checked = in_array($item->id, $selected) ? ' checked="checked"' : ''; // Build the HTML for the item. $html[] = ' <li>'; $html[] = ' <input type="checkbox" name="' . $name . '[]" value="' . $item->id . '" id="' . $eid . '"'; $html[] = ' ' . $checked . '>'; $html[] = ' <label for="' . $eid . '">'; $html[] = ' ' . Text::_($item->title); $html[] = ' </label>'; $html[] = ' </li>'; } $html[] = '</ul>'; return implode("\n", $html); } /** * Gets a list of the asset groups as an array of JHtml compatible options. * * @return mixed An array or false if an error occurs * * @since 1.6 */ public static function assetgroups() { if (empty(static::$asset_groups)) { $db = Factory::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'), $db->quoteName('a.title'), $db->quoteName('a.ordering'), ] ) ->order($db->quoteName('a.ordering') . ' ASC'); $db->setQuery($query); static::$asset_groups = $db->loadObjectList(); } return static::$asset_groups; } /** * Displays a Select list of the available asset groups * * @param string $name The name of the select element * @param mixed $selected The selected asset group id * @param string $attribs Optional attributes for the select field * @param array $config An array of options for the control * * @return mixed An HTML string or null if an error occurs * * @since 1.6 */ public static function assetgrouplist($name, $selected, $attribs = null, $config = []) { static $count; $options = static::assetgroups(); if (isset($config['title'])) { array_unshift($options, HTMLHelper::_('select.option', '', $config['title'])); } return HTMLHelper::_( 'select.genericlist', $options, $name, [ 'id' => isset($config['id']) ? $config['id'] : 'assetgroups_' . (++$count), 'list.attr' => $attribs === null ? 'class="inputbox" size="3"' : $attribs, 'list.select' => (int) $selected, ] ); } } Helpers/Telephone.php 0000644 00000005057 15172602426 0010616 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * HTML helper class for rendering telephone numbers. * * @since 1.6 */ abstract class Telephone { /** * Converts strings of integers into more readable telephone format * * By default, the ITU-T format will automatically be used. * However, one of the allowed unit types may also be used instead. * * @param integer $number The integers in a phone number with dot separated country code * ccc.nnnnnnn where ccc represents country code and nnn represents the local number. * @param string $displayplan The numbering plan used to display the numbers. * * @return string The formatted telephone number. * * @see \Joomla\CMS\Form\Rule\TelRule * @since 1.6 */ public static function tel($number, $displayplan) { $display = []; $number = explode('.', $number); $countrycode = $number[0]; $number = $number[1]; if ($displayplan === 'ITU-T' || $displayplan === 'International' || $displayplan === 'int' || $displayplan === 'missdn' || $displayplan == null) { $display[0] = '+'; $display[1] = $countrycode; $display[2] = ' '; $display[3] = implode(' ', str_split($number, 2)); } elseif ($displayplan === 'NANP' || $displayplan === 'northamerica' || $displayplan === 'US') { $display[0] = '('; $display[1] = substr($number, 0, 3); $display[2] = ') '; $display[3] = substr($number, 3, 3); $display[4] = '-'; $display[5] = substr($number, 6, 4); } elseif ($displayplan === 'EPP' || $displayplan === 'IETF') { $display[0] = '+'; $display[1] = $countrycode; $display[2] = '.'; $display[3] = $number; } elseif ($displayplan === 'ARPA' || $displayplan === 'ENUM') { $number = implode('.', str_split(strrev($number), 1)); $display[0] = '+'; $display[1] = $number; $display[2] = '.'; $display[3] = $countrycode; $display[4] = '.e164.arpa'; } return implode('', $display); } } Helpers/ActionsDropdown.php 0000644 00000015307 15172602426 0012007 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * HTML utility class for building a dropdown menu * * @since 3.2 */ abstract class ActionsDropdown { /** * @var string HTML markup for the dropdown list * @since 3.2 */ protected static $dropDownList = []; /** * Method to render current dropdown menu * * @param string $item An item to render. * * @return string HTML markup for the dropdown list * * @since 3.2 */ public static function render($item = '') { $html = []; $html[] = '<button data-bs-toggle="dropdown" class="dropdown-toggle btn btn-sm btn-secondary">'; $html[] = '<span class="caret"></span>'; if ($item) { $html[] = '<span class="visually-hidden">' . Text::sprintf('JACTIONS', $item) . '</span>'; } $html[] = '</button>'; $html[] = '<ul class="dropdown-menu">'; $html[] = implode('', static::$dropDownList); $html[] = '</ul>'; static::$dropDownList = null; return implode('', $html); } /** * Append a publish item to the current dropdown menu * * @param string $id ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.2 */ public static function publish($id, $prefix = '') { $task = ($prefix ? $prefix . '.' : '') . 'publish'; static::addCustomItem(Text::_('JTOOLBAR_PUBLISH'), 'publish', $id, $task); } /** * Append an unpublish item to the current dropdown menu * * @param string $id ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.2 */ public static function unpublish($id, $prefix = '') { $task = ($prefix ? $prefix . '.' : '') . 'unpublish'; static::addCustomItem(Text::_('JTOOLBAR_UNPUBLISH'), 'unpublish', $id, $task); } /** * Append a feature item to the current dropdown menu * * @param string $id ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.2 */ public static function feature($id, $prefix = '') { $task = ($prefix ? $prefix . '.' : '') . 'featured'; static::addCustomItem(Text::_('JFEATURE'), 'featured', $id, $task); } /** * Append an unfeature item to the current dropdown menu * * @param string $id ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.2 */ public static function unfeature($id, $prefix = '') { $task = ($prefix ? $prefix . '.' : '') . 'unfeatured'; static::addCustomItem(Text::_('JUNFEATURE'), 'unfeatured', $id, $task); } /** * Append an archive item to the current dropdown menu * * @param string $id ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.2 */ public static function archive($id, $prefix = '') { $task = ($prefix ? $prefix . '.' : '') . 'archive'; static::addCustomItem(Text::_('JTOOLBAR_ARCHIVE'), 'archive', $id, $task); } /** * Append an unarchive item to the current dropdown menu * * @param string $id ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.2 */ public static function unarchive($id, $prefix = '') { $task = ($prefix ? $prefix . '.' : '') . 'unpublish'; static::addCustomItem(Text::_('JTOOLBAR_UNARCHIVE'), 'unarchive', $id, $task); } /** * Append a duplicate item to the current dropdown menu * * @param string $id ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.2 */ public static function duplicate($id, $prefix = '') { $task = ($prefix ? $prefix . '.' : '') . 'duplicate'; static::addCustomItem(Text::_('JTOOLBAR_DUPLICATE'), 'copy', $id, $task); } /** * Append a trash item to the current dropdown menu * * @param string $id ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.2 */ public static function trash($id, $prefix = '') { $task = ($prefix ? $prefix . '.' : '') . 'trash'; static::addCustomItem(Text::_('JTOOLBAR_TRASH'), 'trash', $id, $task); } /** * Append an untrash item to the current dropdown menu * * @param string $id ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.2 */ public static function untrash($id, $prefix = '') { self::publish($id, $prefix); } /** * Writes a divider between dropdown items * * @return void * * @since 3.0 */ public static function divider() { static::$dropDownList[] = '<li class="divider"></li>'; } /** * Append a custom item to current dropdown menu. * * @param string $label The label of the item. * @param string $icon The icon classname. * @param string $id The item id. * @param string $task The task. * * @return void * * @since 3.2 */ public static function addCustomItem($label, $icon = '', $id = '', $task = '') { Factory::getDocument()->getWebAssetManager()->useScript('list-view'); static::$dropDownList[] = '<li>' . HTMLHelper::link( '#', ($icon ? LayoutHelper::render('joomla.icon.iconclass', ['icon' => $icon]) : '') . $label, [ 'data-item-id' => $id, 'data-item-task' => $task, 'class' => 'js-grid-item-action', ] ) . '</li>'; } } Helpers/Category.php 0000644 00000017246 15172602426 0010453 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\Database\ParameterType; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for categories * * @since 1.5 */ abstract class Category { /** * Cached array of the category items. * * @var array * @since 1.5 */ protected static $items = []; /** * Returns an array of categories for the given extension. * * @param string $extension The extension option e.g. com_something. * @param array $config An array of configuration options. By default, only * published and unpublished categories are returned. * * @return array * * @since 1.5 */ public static function options($extension, $config = ['filter.published' => [0, 1]]) { $hash = md5($extension . '.' . serialize($config)); if (!isset(static::$items[$hash])) { $config = (array) $config; $db = Factory::getDbo(); $user = Factory::getUser(); $query = $db->getQuery(true) ->select( [ $db->quoteName('a.id'), $db->quoteName('a.title'), $db->quoteName('a.level'), $db->quoteName('a.language'), ] ) ->from($db->quoteName('#__categories', 'a')) ->where($db->quoteName('a.parent_id') . ' > 0'); // Filter on extension. $query->where($db->quoteName('a.extension') . ' = :extension') ->bind(':extension', $extension); // Filter on user access level if (!$user->authorise('core.admin')) { $query->whereIn($db->quoteName('a.access'), $user->getAuthorisedViewLevels()); } // Filter on the published state if (isset($config['filter.published'])) { if (is_numeric($config['filter.published'])) { $query->where($db->quoteName('a.published') . ' = :published') ->bind(':published', $config['filter.published'], ParameterType::INTEGER); } elseif (is_array($config['filter.published'])) { $config['filter.published'] = ArrayHelper::toInteger($config['filter.published']); $query->whereIn($db->quoteName('a.published'), $config['filter.published']); } } // Filter on the language if (isset($config['filter.language'])) { if (is_string($config['filter.language'])) { $query->where($db->quoteName('a.language') . ' = :language') ->bind(':language', $config['filter.language']); } elseif (is_array($config['filter.language'])) { $query->whereIn($db->quoteName('a.language'), $config['filter.language'], ParameterType::STRING); } } // Filter on the access if (isset($config['filter.access'])) { if (is_numeric($config['filter.access'])) { $query->where($db->quoteName('a.access') . ' = :access') ->bind(':access', $config['filter_access'], ParameterType::INTEGER); } elseif (is_array($config['filter.access'])) { $config['filter.access'] = ArrayHelper::toInteger($config['filter.access']); $query->whereIn($db->quoteName('a.access'), $config['filter.access']); } } $query->order($db->quoteName('a.lft')); $db->setQuery($query); $items = $db->loadObjectList(); // Assemble the list options. static::$items[$hash] = []; foreach ($items as &$item) { $repeat = ($item->level - 1 >= 0) ? $item->level - 1 : 0; $item->title = str_repeat('- ', $repeat) . $item->title; if ($item->language !== '*') { $item->title .= ' (' . $item->language . ')'; } static::$items[$hash][] = HTMLHelper::_('select.option', $item->id, $item->title); } } return static::$items[$hash]; } /** * Returns an array of categories for the given extension. * * @param string $extension The extension option. * @param array $config An array of configuration options. By default, only published and unpublished categories are returned. * * @return array Categories for the extension * * @since 1.6 */ public static function categories($extension, $config = ['filter.published' => [0, 1]]) { $hash = md5($extension . '.' . serialize($config)); if (!isset(static::$items[$hash])) { $config = (array) $config; $user = Factory::getUser(); $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( [ $db->quoteName('a.id'), $db->quoteName('a.title'), $db->quoteName('a.level'), $db->quoteName('a.parent_id'), $db->quoteName('a.language'), ] ) ->from($db->quoteName('#__categories', 'a')) ->where($db->quoteName('a.parent_id') . ' > 0'); // Filter on extension. $query->where($db->quoteName('extension') . ' = :extension') ->bind(':extension', $extension); // Filter on user level. if (!$user->authorise('core.admin')) { $query->whereIn($db->quoteName('a.access'), $user->getAuthorisedViewLevels()); } // Filter on the published state if (isset($config['filter.published'])) { if (is_numeric($config['filter.published'])) { $query->where($db->quoteName('a.published') . ' = :published') ->bind(':published', $config['filter.published'], ParameterType::INTEGER); } elseif (is_array($config['filter.published'])) { $config['filter.published'] = ArrayHelper::toInteger($config['filter.published']); $query->whereIn($db->quoteName('a.published'), $config['filter.published']); } } $query->order($db->quoteName('a.lft')); $db->setQuery($query); $items = $db->loadObjectList(); // Assemble the list options. static::$items[$hash] = []; foreach ($items as &$item) { $repeat = ($item->level - 1 >= 0) ? $item->level - 1 : 0; $item->title = str_repeat('- ', $repeat) . $item->title; if ($item->language !== '*') { $item->title .= ' (' . $item->language . ')'; } static::$items[$hash][] = HTMLHelper::_('select.option', $item->id, $item->title); } // Special "Add to root" option: static::$items[$hash][] = HTMLHelper::_('select.option', '1', Text::_('JLIB_HTML_ADD_TO_ROOT')); } return static::$items[$hash]; } } Helpers/ListHelper.php 0000644 00000021010 15172602426 0010731 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\Database\DatabaseQuery; use Joomla\String\StringHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for creating different select lists * * @since 1.5 */ abstract class ListHelper { /** * Build the select list to choose an image * * @param string $name The name of the field * @param string $active The selected item * @param string $javascript Alternative javascript * @param string $directory Directory the images are stored in * @param string $extensions Allowed extensions * * @return array Image names * * @since 1.5 */ public static function images($name, $active = null, $javascript = null, $directory = null, $extensions = 'bmp|gif|jpg|png') { if (!$directory) { $directory = '/images/'; } if (!$javascript) { $javascript = "onchange=\"if (document.forms.adminForm." . $name . ".options[selectedIndex].value!='') {document.imagelib.src='..$directory' + document.forms.adminForm." . $name . ".options[selectedIndex].value} else {document.imagelib.src='media/system/images/blank.png'}\""; } $imageFiles = new \DirectoryIterator(JPATH_SITE . '/' . $directory); $images = [HTMLHelper::_('select.option', '', Text::_('JOPTION_SELECT_IMAGE'))]; foreach ($imageFiles as $file) { $fileName = $file->getFilename(); if (!$file->isFile()) { continue; } if (preg_match('#(' . $extensions . ')$#', $fileName)) { $images[] = HTMLHelper::_('select.option', $fileName); } } $images = HTMLHelper::_( 'select.genericlist', $images, $name, [ 'list.attr' => 'size="1" ' . $javascript, 'list.select' => $active, ] ); return $images; } /** * Returns an array of options * * @param DatabaseQuery|string $query SQL with 'ordering' AS value and 'name field' AS text * @param integer $chop The length of the truncated headline * * @return array An array of objects formatted for JHtml list processing * * @since 1.5 */ public static function genericordering($query, $chop = 30) { $db = Factory::getDbo(); $options = []; $db->setQuery($query); $items = $db->loadObjectList(); if (empty($items)) { $options[] = HTMLHelper::_('select.option', 1, Text::_('JLIB_FORM_FIELD_PARAM_INTEGER_FIRST_LABEL')); return $options; } $options[] = HTMLHelper::_('select.option', 0, ' - ' . Text::_('JLIB_FORM_FIELD_PARAM_INTEGER_FIRST_LABEL') . ' - '); for ($i = 0, $n = count($items); $i < $n; $i++) { $items[$i]->text = Text::_($items[$i]->text); if (StringHelper::strlen($items[$i]->text) > $chop) { $text = StringHelper::substr($items[$i]->text, 0, $chop) . '...'; } else { $text = $items[$i]->text; } $options[] = HTMLHelper::_('select.option', $items[$i]->value, $text); } $options[] = HTMLHelper::_('select.option', $items[$i - 1]->value + 1, ' - ' . Text::_('JLIB_FORM_FIELD_PARAM_INTEGER_LAST_LABEL') . ' - '); return $options; } /** * Build the select list for Ordering derived from a query * * @param integer $name The scalar value * @param string $query The query * @param string $attribs HTML tag attributes * @param string $selected The selected item * @param integer $neworder 1 if new and first, -1 if new and last, 0 or null if existing item * @param string $id ID attribute for the resulting <select> element * * @return string HTML markup for the select list * * @since 1.6 */ public static function ordering($name, $query, $attribs = null, $selected = null, $neworder = null, ?string $id = null) { if (empty($attribs)) { $attribs = 'size="1"'; } if (empty($neworder)) { $orders = HTMLHelper::_('list.genericordering', $query); $html = HTMLHelper::_( 'select.genericlist', $orders, $name, ['list.attr' => $attribs, 'list.select' => (int) $selected, 'id' => $id ?? false] ); } else { if ($neworder > 0) { $text = Text::_('JGLOBAL_NEWITEMSLAST_DESC'); } elseif ($neworder <= 0) { $text = Text::_('JGLOBAL_NEWITEMSFIRST_DESC'); } $html = '<input type="hidden" name="' . $name . '" value="' . (int) $selected . '"><span class="readonly">' . $text . '</span>'; } return $html; } /** * Select list of active users * * @param string $name The name of the field * @param string $active The active user * @param integer $nouser If set include an option to select no user * @param string $javascript Custom javascript * @param string $order Specify a field to order by * * @return string The HTML for a list of users list of users * * @since 1.5 */ public static function users($name, $active, $nouser = 0, $javascript = null, $order = 'name') { $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( [ $db->quoteName('u.id', 'value'), $db->quoteName('u.name', 'text'), ] ) ->from($db->quoteName('#__users', 'u')) ->join('LEFT', $db->quoteName('#__user_usergroup_map', 'm'), $db->quoteName('m.user_id') . ' = ' . $db->quoteName('u.id')) ->where($db->quoteName('u.block') . ' = 0') ->order($order) ->group($db->quoteName('u.id')); $db->setQuery($query); if ($nouser) { $users[] = HTMLHelper::_('select.option', '0', Text::_('JOPTION_NO_USER')); $users = array_merge($users, $db->loadObjectList()); } else { $users = $db->loadObjectList(); } $users = HTMLHelper::_( 'select.genericlist', $users, $name, [ 'list.attr' => 'size="1" ' . $javascript, 'list.select' => $active, ] ); return $users; } /** * Select list of positions - generally used for location of images * * @param string $name Name of the field * @param string $active The active value * @param string $javascript Alternative javascript * @param boolean $none Null if not assigned * @param boolean $center Null if not assigned * @param boolean $left Null if not assigned * @param boolean $right Null if not assigned * @param boolean $id Null if not assigned * * @return array The positions * * @since 1.5 */ public static function positions( $name, $active = null, $javascript = null, $none = true, $center = true, $left = true, $right = true, $id = false ) { $pos = []; if ($none) { $pos[''] = Text::_('JNONE'); } if ($center) { $pos['center'] = Text::_('JGLOBAL_CENTER'); } if ($left) { $pos['left'] = Text::_('JGLOBAL_LEFT'); } if ($right) { $pos['right'] = Text::_('JGLOBAL_RIGHT'); } $positions = HTMLHelper::_( 'select.genericlist', $pos, $name, [ 'id' => $id, 'list.attr' => 'size="1"' . $javascript, 'list.select' => $active, 'option.key' => null, ] ); return $positions; } } Helpers/Content.php 0000644 00000005253 15172602426 0010303 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Date\Date; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class to fire onContentPrepare for non-article based content. * * @since 1.5 */ abstract class Content { /** * Fire onContentPrepare for content that isn't part of an article. * * @param string $text The content to be transformed. * @param array $params The content params. * @param string $context The context of the content to be transformed. * * @return string The content after transformation. * * @since 1.5 */ public static function prepare($text, $params = null, $context = 'text') { if ($params === null) { $params = new CMSObject(); } $article = new \stdClass(); $article->text = $text; PluginHelper::importPlugin('content'); Factory::getApplication()->triggerEvent('onContentPrepare', [$context, &$article, &$params, 0]); return $article->text; } /** * Returns an array of months. * * @param Registry $state The state object. * * @return array * * @since 3.9.0 */ public static function months($state) { /** @var \Joomla\Component\Content\Administrator\Extension\ContentComponent $contentComponent */ $contentComponent = Factory::getApplication()->bootComponent('com_content'); /** @var \Joomla\Component\Content\Site\Model\ArticlesModel $model */ $model = $contentComponent->getMVCFactory() ->createModel('Articles', 'Site', ['ignore_request' => true]); foreach ($state as $key => $value) { $model->setState($key, $value); } $model->setState('filter.category_id', $state->get('category.id')); $model->setState('list.start', 0); $model->setState('list.limit', -1); $model->setState('list.direction', 'asc'); $model->setState('list.filter', ''); $items = []; foreach ($model->countItemsByMonth() as $item) { $date = new Date($item->d); $items[] = HTMLHelper::_('select.option', $item->d, $date->format('F Y') . ' [' . $item->c . ']'); } return $items; } } Helpers/Grid.php 0000644 00000023341 15172602426 0007554 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Table\Table; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for creating HTML Grids * * @since 1.5 */ abstract class Grid { /** * Method to sort a column in a grid * * @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 $newDirection 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 1.5 */ public static function sort($title, $order, $direction = 'asc', $selected = '', $task = null, $newDirection = 'asc', $tip = '', $form = null) { HTMLHelper::_('bootstrap.tooltip', '.hasTooltip'); $direction = strtolower($direction); $icon = ['arrow-up-3', 'arrow-down-3']; $index = (int) ($direction === 'desc'); if ($order != $selected) { $direction = $newDirection; } 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="hasTooltip" title="' . htmlspecialchars(Text::_('JGLOBAL_CLICK_TO_SORT_THIS_COLUMN')) . '" data-bs-placement="top">'; if (isset($title['0']) && $title['0'] === '<') { $html .= $title; } else { $html .= Text::_($title); } if ($order == $selected) { $html .= '<span class="icon-' . $icon[$index] . '"></span>'; } $html .= '</a>'; return $html; } /** * Method to check all checkboxes in a grid * * @param string $name The name of the form element * @param string $action The action to perform on clicking the checkbox * * @return string * * @since 3.1.2 */ public static function checkall($name = 'checkall-toggle', $action = 'Joomla.checkAll(this)') { HTMLHelper::_('behavior.core'); return '<input class="form-check-input" autocomplete="off" type="checkbox" name="' . $name . '" value="" title="' . Text::_('JGLOBAL_CHECK_ALL') . '" onclick="' . $action . '">'; } /** * Method to create a checkbox for a grid row. * * @param integer $rowNum The row index * @param integer $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 * @param string $title The name of the item * @param string $formId An optional form selector. * * @return mixed String of html with a checkbox if item is not checked out, null if checked out. * * @since 1.5 */ public static function id($rowNum, $recId, $checkedOut = false, $name = 'cid', $stub = 'cb', $title = '', $formId = null) { if ($formId !== null) { return $checkedOut ? '' : '<label for="' . $stub . $rowNum . '"><span class="visually-hidden">' . Text::_('JSELECT') . ' ' . htmlspecialchars($title, ENT_COMPAT, 'UTF-8') . '</span></label>' . '<input class="form-check-input" type="checkbox" id="' . $stub . $rowNum . '" name="' . $name . '[]" value="' . $recId . '" onclick="Joomla.isChecked(this.checked, \'' . $formId . '\');">'; } return $checkedOut ? '' : '<label for="' . $stub . $rowNum . '"><span class="visually-hidden">' . Text::_('JSELECT') . ' ' . htmlspecialchars($title, ENT_COMPAT, 'UTF-8') . '</span></label>' . '<input class="form-check-input" autocomplete="off" type="checkbox" id="' . $stub . $rowNum . '" name="' . $name . '[]" value="' . $recId . '" onclick="Joomla.isChecked(this.checked);">'; } /** * Displays a checked out icon. * * @param object $row A data object (must contain checked out as a property). * @param integer $i The index of the row. * @param string $identifier The property name of the primary key or index of the row. * * @return string * * @since 1.5 */ public static function checkedOut(&$row, $i, $identifier = 'id') { $user = Factory::getUser(); $userid = $user->get('id'); if ($row instanceof Table) { $result = $row->isCheckedOut($userid); } else { $result = false; } if ($result) { return static::_checkedOut($row); } else { if ($identifier === 'id') { return HTMLHelper::_('grid.id', $i, $row->$identifier); } else { return HTMLHelper::_('grid.id', $i, $row->$identifier, $result, $identifier); } } } /** * Method to create a clickable icon to change the state of an item * * @param mixed $value Either the scalar value or an object (for backward compatibility, deprecated) * @param integer $i The index * @param string $img1 Image for a positive or on value * @param string $img0 Image for the empty or off value * @param string $prefix An optional prefix for the task * * @return string * * @since 1.5 */ public static function published($value, $i, $img1 = 'tick.png', $img0 = 'publish_x.png', $prefix = '') { if (is_object($value)) { $value = $value->published; } $img = $value ? $img1 : $img0; $task = $value ? 'unpublish' : 'publish'; $alt = $value ? Text::_('JPUBLISHED') : Text::_('JUNPUBLISHED'); $action = $value ? Text::_('JLIB_HTML_UNPUBLISH_ITEM') : Text::_('JLIB_HTML_PUBLISH_ITEM'); return '<a href="#" onclick="return Joomla.listItemTask(\'cb' . $i . '\',\'' . $prefix . $task . '\')" title="' . $action . '">' . HTMLHelper::_('image', 'admin/' . $img, $alt, null, true) . '</a>'; } /** * Method to create a select list of states for filtering * By default the filter shows only published and unpublished items * * @param string $filterState The initial filter state * @param string $published The Text string for published * @param string $unpublished The Text string for Unpublished * @param string $archived The Text string for Archived * @param string $trashed The Text string for Trashed * * @return string * * @since 1.5 */ public static function state($filterState = '*', $published = 'JPUBLISHED', $unpublished = 'JUNPUBLISHED', $archived = null, $trashed = null) { $state = ['' => '- ' . Text::_('JLIB_HTML_SELECT_STATE') . ' -', 'P' => Text::_($published), 'U' => Text::_($unpublished)]; if ($archived) { $state['A'] = Text::_($archived); } if ($trashed) { $state['T'] = Text::_($trashed); } return HTMLHelper::_( 'select.genericlist', $state, 'filter_state', [ 'list.attr' => 'class="form-select" size="1" onchange="Joomla.submitform();"', 'list.select' => $filterState, 'option.key' => null, ] ); } /** * Method to create an icon for saving a new ordering in a grid * * @param array $rows The array of rows of rows * @param string $image The image [UNUSED] * @param string $task The task to use, defaults to save order * * @return string * * @since 1.5 */ public static function order($rows, $image = 'filesave.png', $task = 'saveorder') { return '<a href="javascript:saveorder(' . (count($rows) - 1) . ', \'' . $task . '\')" rel="tooltip" class="saveorder btn btn-sm btn-secondary float-end" title="' . Text::_('JLIB_HTML_SAVE_ORDER') . '"><span class="icon-sort"></span></a>'; } /** * Method to create a checked out icon with optional overlib in a grid. * * @param object $row The row object * @param boolean $overlib True if an overlib with checkout information should be created. * * @return string HTMl for the icon and overlib * * @since 1.5 */ protected static function _checkedOut(&$row, $overlib = true) { $hover = ''; if ($overlib) { $date = HTMLHelper::_('date', $row->checked_out_time, Text::_('DATE_FORMAT_LC1')); $time = HTMLHelper::_('date', $row->checked_out_time, 'H:i'); $hover = '<span class="editlinktip hasTooltip" title="' . HTMLHelper::_('tooltipText', 'JLIB_HTML_CHECKED_OUT', $row->editor) . '<br>' . $date . '<br>' . $time . '">'; } return $hover . HTMLHelper::_('image', 'admin/checked_out.png', null, null, true) . '</span>'; } } Helpers/Debug.php 0000644 00000003414 15172602426 0007714 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Filesystem\Path; use Joomla\CMS\HTML\HTMLHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Extended Utility class for render debug information. * * @since 3.7.0 */ abstract class Debug { /** * xdebug.file_link_format from the php.ini. * * Make this property public to support test. * * @var string * * @since 3.7.0 */ public static $xdebugLinkFormat; /** * Replaces the Joomla! root with "JROOT" to improve readability. * Formats a link with a special value xdebug.file_link_format * from the php.ini file. * * @param string $file The full path to the file. * @param string $line The line number. * * @return string * * @throws \InvalidArgumentException * * @since 3.7.0 */ public static function xdebuglink($file, $line = '') { if (static::$xdebugLinkFormat === null) { static::$xdebugLinkFormat = ini_get('xdebug.file_link_format'); } $link = str_replace(JPATH_ROOT, 'JROOT', Path::clean($file)); $link .= $line ? ':' . $line : ''; if (static::$xdebugLinkFormat) { $href = static::$xdebugLinkFormat; $href = str_replace('%f', $file, $href); $href = str_replace('%l', $line, $href); $html = HTMLHelper::_('link', $href, $link); } else { $html = $link; } return $html; } } Helpers/Sidebar.php 0000644 00000007174 15172602426 0010246 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\Layout\FileLayout; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class to render a list view sidebar * * @since 3.0 */ abstract class Sidebar { /** * Menu entries * * @var array * @since 3.0 */ protected static $entries = []; /** * Filters * * @var array * @since 3.0 */ protected static $filters = []; /** * Value for the action attribute of the form. * * @var string * @since 3.0 */ protected static $action = ''; /** * Render the sidebar. * * @return string The necessary HTML to display the sidebar * * @since 3.0 */ public static function render() { // Collect display data $data = new \stdClass(); $data->list = static::getEntries(); $data->filters = static::getFilters(); $data->action = static::getAction(); $data->displayMenu = count($data->list); $data->displayFilters = count($data->filters); $data->hide = Factory::getApplication()->getInput()->getBool('hidemainmenu'); // Create a layout object and ask it to render the sidebar $layout = new FileLayout('joomla.sidebars.submenu'); return $layout->render($data); } /** * Method to add a menu item to submenu. * * @param string $name Name of the menu item. * @param string $link URL of the menu item. * @param bool $active True if the item is active, false otherwise. * * @return void * * @since 3.0 */ public static function addEntry($name, $link = '', $active = false) { static::$entries[] = [$name, $link, $active]; } /** * Returns an array of all submenu entries * * @return array * * @since 3.0 */ public static function getEntries() { return static::$entries; } /** * Method to add a filter to the submenu * * @param string $label Label for the menu item. * @param string $name Name for the filter. Also used as id. * @param string $options Options for the select field. * @param bool $noDefault Don't show the label as the empty option * * @return void * * @since 3.0 */ public static function addFilter($label, $name, $options, $noDefault = false) { static::$filters[] = ['label' => $label, 'name' => $name, 'options' => $options, 'noDefault' => $noDefault]; } /** * Returns an array of all filters * * @return array * * @since 3.0 */ public static function getFilters() { return static::$filters; } /** * Set value for the action attribute of the filter form * * @param string $action Value for the action attribute of the form * * @return void * * @since 3.0 */ public static function setAction($action) { static::$action = $action; } /** * Get value for the action attribute of the filter form * * @return string * * @since 3.0 */ public static function getAction() { return static::$action; } } Helpers/Jquery.php 0000644 00000005410 15172602426 0010143 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for jQuery JavaScript behaviors * * @since 3.0 */ abstract class Jquery { /** * Array containing information for loaded files * * @var array * @since 3.0 */ protected static $loaded = []; /** * Method to load the jQuery JavaScript framework into the document head * * If debugging mode is on an uncompressed version of jQuery is included for easier debugging. * * @param boolean $noConflict True to load jQuery in noConflict mode [optional] * @param mixed $debug Is debugging mode on? [optional] * @param boolean $migrate True to enable the jQuery Migrate plugin * * @return void * * @since 3.0 * * @deprecated 4.0 will be removed in 6.0 * Use webasset manager instead * Example: * $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); * $wa->useScript('jquery'); * $wa->useScript('jquery-noconflict'); * $wa->useScript('jquery-migrate'); */ public static function framework($noConflict = true, $debug = null, $migrate = false) { $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); $wa->useScript('jquery'); // Check if we are loading in noConflict if ($noConflict) { $wa->useScript('jquery-noconflict'); } // Check if we are loading Migrate if ($migrate) { $wa->useScript('jquery-migrate'); } } /** * Auto set CSRF token to ajaxSetup so all jQuery ajax call will contains CSRF token. * * @param string $name The CSRF meta tag name. * * @return void * * @throws \InvalidArgumentException * * @since 3.8.0 */ public static function token($name = 'csrf.token') { // Only load once if (!empty(static::$loaded[__METHOD__][$name])) { return; } static::framework(); HTMLHelper::_('form.csrf', $name); $doc = Factory::getDocument(); $doc->addScriptDeclaration( <<<JS ;(function ($) { $.ajaxSetup({ headers: { 'X-CSRF-Token': Joomla.getOptions('$name') } }); })(jQuery); JS ); static::$loaded[__METHOD__][$name] = true; } } Helpers/Behavior.php 0000644 00000026514 15172602426 0010433 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for JavaScript behaviors * * @since 1.5 */ abstract class Behavior { /** * Array containing information for loaded files * * @var array * @since 2.5 */ protected static $loaded = []; /** * Method to load core.js into the document head. * * Core.js defines the 'Joomla' namespace and contains functions which are used across extensions * * @return void * * @since 3.3 * * @deprecated 4.0 will be removed in 6.0 * Use the webasset manager instead * Example: Factory::getApplication()->getDocument()->getWebAssetManager()->useScript('core'); */ public static function core() { Factory::getApplication()->getDocument()->getWebAssetManager()->useScript('core'); } /** * Add unobtrusive JavaScript support for form validation. * * To enable form validation the form tag must have class="form-validate". * Each field that needs to be validated needs to have class="validate". * Additional handlers can be added to the handler for username, password, * numeric and email. To use these add class="validate-email" and so on. * * @return void * * @since 3.4 * * @deprecated 4.0 will be removed in 6.0 * Use the webasset manager instead * Example: Factory::getApplication()->getDocument()->getWebAssetManager()->useScript('form.validate'); */ public static function formvalidator() { // Only load once if (isset(static::$loaded[__METHOD__])) { return; } Factory::getDocument()->getWebAssetManager()->useScript('form.validate'); static::$loaded[__METHOD__] = true; } /** * Add unobtrusive JavaScript support for a combobox effect. * * Note that this control is only reliable in absolutely positioned elements. * Avoid using a combobox in a slider or dynamic pane. * * @return void * * @since 1.5 * * @deprecated 4.0 will be removed in 6.0 * Use the webasset manager instead * Example: Factory::getApplication()->getDocument()->getWebAssetManager()->useScript('awesomeplete'); */ public static function combobox() { Factory::getDocument()->getWebAssetManager()->usePreset('awesomplete'); } /** * JavaScript behavior to allow shift select in grids * * @param string $id The id of the form for which a multiselect behaviour is to be applied. * * @return void * * @since 1.7 * * @deprecated 4.0 will be removed in 6.0 * Use the webasset manager instead * Example: * Factory::getApplication()->getDocument()->getWebAssetManager()->useScript('multiselect'); * Factory::getDocument()->addScriptOptions('js-multiselect', ['formName' => $id]); */ public static function multiselect($id = 'adminForm') { // Only load once if (isset(static::$loaded[__METHOD__][$id])) { return; } Factory::getDocument()->getWebAssetManager()->useScript('multiselect'); // Pass the required options to the javascript Factory::getDocument()->addScriptOptions('js-multiselect', ['formName' => $id]); // Set static array static::$loaded[__METHOD__][$id] = true; } /** * Keep session alive, for example, while editing or creating an article. * * @return void * * @since 1.5 * * @deprecated 4.0 will be removed in 6.0 * Use the webasset manager instead * Example: Factory::getApplication()->getDocument()->getWebAssetManager()->useScript('keepalive'); */ public static function keepalive() { Factory::getApplication()->getDocument()->getWebAssetManager()->useScript('keepalive'); } /** * Highlight some words via Javascript. * * @param array $terms Array of words that should be highlighted. * @param string $start ID of the element that marks the begin of the section in which words * should be highlighted. Note this element will be removed from the DOM. * @param string $end ID of the element that end this section. * Note this element will be removed from the DOM. * @param string $className Class name of the element highlights are wrapped in. * @param string $tag Tag that will be used to wrap the highlighted words. * * @return void * * @since 2.5 * * @deprecated 4.0 will be removed in 6.0 * Use the script directly */ public static function highlighter(array $terms, $start = 'highlighter-start', $end = 'highlighter-end', $className = 'highlight', $tag = 'span') { $terms = array_filter($terms, 'strlen'); if (!empty($terms)) { $doc = Factory::getDocument(); $doc->getWebAssetManager()->useScript('highlight'); $doc->addScriptOptions( 'highlight', [[ 'class' => 'js-highlight', 'highLight' => $terms, 'compatibility' => true, 'start' => $start, 'end' => $end, ]] ); } } /** * Add javascript polyfills. * * @param string|array $polyfillTypes The polyfill type(s). Examples: event, array('event', 'classlist'). * @param string $conditionalBrowser An IE conditional expression. Example: lt IE 9 (lower than IE 9). * * @return void * * @since 3.7.0 */ public static function polyfill($polyfillTypes = null, $conditionalBrowser = null) { if ($polyfillTypes === null) { return; } foreach ((array) $polyfillTypes as $polyfillType) { $sig = md5(serialize([$polyfillType, $conditionalBrowser])); // Only load once if (isset(static::$loaded[__METHOD__][$sig])) { continue; } // If include according to browser. $scriptOptions = ['version' => 'auto', 'relative' => true]; $scriptOptions = $conditionalBrowser !== null ? array_replace($scriptOptions, ['conditional' => $conditionalBrowser]) : $scriptOptions; /** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); $wa->registerAndUseScript('polyfill.' . $polyfillType, 'vendor/polyfills/polyfill-' . $polyfillType . '.js', $scriptOptions); // Set static array static::$loaded[__METHOD__][$sig] = true; } } /** * Internal method to translate the JavaScript Calendar * * @return string JavaScript that translates the object * * @since 1.5 */ protected static function calendartranslation() { static $jsscript = 0; // Guard clause, avoids unnecessary nesting if ($jsscript) { return false; } $jsscript = 1; // To keep the code simple here, run strings through Text::_() using array_map() $callback = ['Text', '_']; $weekdays_full = array_map( $callback, [ 'SUNDAY', 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY', ] ); $weekdays_short = array_map( $callback, [ 'SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN', ] ); $months_long = array_map( $callback, [ 'JANUARY', 'FEBRUARY', 'MARCH', 'APRIL', 'MAY', 'JUNE', 'JULY', 'AUGUST', 'SEPTEMBER', 'OCTOBER', 'NOVEMBER', 'DECEMBER', ] ); $months_short = array_map( $callback, [ 'JANUARY_SHORT', 'FEBRUARY_SHORT', 'MARCH_SHORT', 'APRIL_SHORT', 'MAY_SHORT', 'JUNE_SHORT', 'JULY_SHORT', 'AUGUST_SHORT', 'SEPTEMBER_SHORT', 'OCTOBER_SHORT', 'NOVEMBER_SHORT', 'DECEMBER_SHORT', ] ); // This will become an object in Javascript but define it first in PHP for readability $today = " " . Text::_('JLIB_HTML_BEHAVIOR_TODAY') . " "; $text = [ 'INFO' => Text::_('JLIB_HTML_BEHAVIOR_ABOUT_THE_CALENDAR'), 'ABOUT' => "DHTML Date/Time Selector\n" . "(c) dynarch.com 20022005 / Author: Mihai Bazon\n" . "For latest version visit: http://www.dynarch.com/projects/calendar/\n" . "Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." . "\n\n" . Text::_('JLIB_HTML_BEHAVIOR_DATE_SELECTION') . Text::_('JLIB_HTML_BEHAVIOR_YEAR_SELECT') . Text::_('JLIB_HTML_BEHAVIOR_MONTH_SELECT') . Text::_('JLIB_HTML_BEHAVIOR_HOLD_MOUSE'), 'ABOUT_TIME' => "\n\n" . "Time selection:\n" . " Click on any of the time parts to increase it\n" . " or Shiftclick to decrease it\n" . " or click and drag for faster selection.", 'PREV_YEAR' => Text::_('JLIB_HTML_BEHAVIOR_PREV_YEAR_HOLD_FOR_MENU'), 'PREV_MONTH' => Text::_('JLIB_HTML_BEHAVIOR_PREV_MONTH_HOLD_FOR_MENU'), 'GO_TODAY' => Text::_('JLIB_HTML_BEHAVIOR_GO_TODAY'), 'NEXT_MONTH' => Text::_('JLIB_HTML_BEHAVIOR_NEXT_MONTH_HOLD_FOR_MENU'), 'SEL_DATE' => Text::_('JLIB_HTML_BEHAVIOR_SELECT_DATE'), 'DRAG_TO_MOVE' => Text::_('JLIB_HTML_BEHAVIOR_DRAG_TO_MOVE'), 'PART_TODAY' => $today, 'DAY_FIRST' => Text::_('JLIB_HTML_BEHAVIOR_DISPLAY_S_FIRST'), 'WEEKEND' => Factory::getLanguage()->getWeekEnd(), 'CLOSE' => Text::_('JLIB_HTML_BEHAVIOR_CLOSE'), 'TODAY' => Text::_('JLIB_HTML_BEHAVIOR_TODAY'), 'TIME_PART' => Text::_('JLIB_HTML_BEHAVIOR_SHIFT_CLICK_OR_DRAG_TO_CHANGE_VALUE'), 'DEF_DATE_FORMAT' => "%Y%m%d", 'TT_DATE_FORMAT' => Text::_('JLIB_HTML_BEHAVIOR_TT_DATE_FORMAT'), 'WK' => Text::_('JLIB_HTML_BEHAVIOR_WK'), 'TIME' => Text::_('JLIB_HTML_BEHAVIOR_TIME'), ]; return 'Calendar._DN = ' . json_encode($weekdays_full) . ';' . ' Calendar._SDN = ' . json_encode($weekdays_short) . ';' . ' Calendar._FD = 0;' . ' Calendar._MN = ' . json_encode($months_long) . ';' . ' Calendar._SMN = ' . json_encode($months_short) . ';' . ' Calendar._TT = ' . json_encode($text) . ';'; } } Helpers/Select.php 0000644 00000072711 15172602426 0010113 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for creating HTML select lists * * @since 1.5 */ abstract class Select { /** * Default values for options. Organized by option group. * * @var array * @since 1.5 */ 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 string $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 * * @since 1.5 * @see \Joomla\CMS\Form\Field\RadioField */ public static function booleanlist($name, $attribs = [], $selected = null, $yes = 'JYES', $no = 'JNO', $id = false) { $arr = [HTMLHelper::_('select.option', '0', Text::_($no)), HTMLHelper::_('select.option', '1', Text::_($yes))]; return HTMLHelper::_('select.radiolist', $arr, $name, $attribs, 'value', 'text', (int) $selected, $id); } /** * 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 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 1.5 */ public static function genericlist( $data, $name, $attribs = null, $optKey = 'value', $optText = 'text', $selected = null, $idtag = false, $translate = false ) { // 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); // If the selectbox contains "form-select-color-state" then load the JS file if (strpos($attribs, 'form-select-color-state') !== false) { Factory::getDocument()->getWebAssetManager() ->registerScript( 'webcomponent.select-colour-es5', 'system/fields/select-colour-es5.min.js', ['dependencies' => ['wcpolyfill']], ['defer' => true, 'nomodule' => true] ) ->registerAndUseScript( 'webcomponent.select-colour', 'system/fields/select-colour.min.js', ['dependencies' => ['webcomponent.select-colour-es5']], ['type' => 'module'] ); } $baseIndent = str_repeat($options['format.indent'], $options['format.depth']++); $html = $baseIndent . '<select' . ($id !== '' ? ' id="' . $id . '"' : '') . ' name="' . $name . '"' . $attribs . '>' . $options['format.eol'] . static::options($data, $options) . $baseIndent . '</select>' . $options['format.eol']; return $html; } /** * 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 JHtmlSelect::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 * * @since 1.5 * @throws \RuntimeException If a group has contents that cannot be processed. */ public static function groupedlist($data, $name, $options = []) { // 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']; } } $html .= $baseIndent . '</select>' . $options['format.eol']; return $html; } /** * 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 * * @since 1.5 */ public static function integerlist($start, $end, $inc, $name, $attribs = null, $selected = null, $format = '') { // Set default options $options = array_merge(HTMLHelper::$formatOptions, ['format.depth' => 0, 'option.format' => '', 'id' => false]); 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::_('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 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 displayed text. This * parameter is ignored if an options array is passed. * @param boolean $disable Not used. * * @return \stdClass * * @since 1.5 */ public static function option($value, $text = '', $optKey = 'value', $optText = 'text', $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 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 * * @since 1.5 */ public static function options($arr, $optKey = 'value', $optText = 'text', $selected = null, $translate = false) { $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 string $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 * * @since 1.5 */ public static function radiolist( $data, $name, $attribs = null, $optKey = 'value', $optText = 'text', $selected = null, $idtag = false, $translate = false ) { if (is_array($attribs)) { $attribs = ArrayHelper::toString($attribs); } $id_text = $idtag ?: $name; $html = '<div class="controls">'; foreach ($data as $obj) { $html .= '<div class="form-check form-check-inline">'; $k = $obj->$optKey; $t = $translate ? Text::_($obj->$optText) : $obj->$optText; $id = (isset($obj->id) ? $obj->id : null); $extra = ''; $id = $id ? $obj->id : $id_text . $k; if (is_array($selected)) { foreach ($selected as $val) { $k2 = is_object($val) ? $val->$optKey : $val; if ($k == $k2) { $extra .= ' selected="selected" '; break; } } } else { $extra .= ((string) $k === (string) $selected ? ' checked="checked" ' : ''); } $html .= '<input type="radio" class="form-check-input" name="' . $name . '" id="' . $id . '" value="' . $k . '" ' . $extra . $attribs . '>'; $html .= '<label for="' . $id . '" class="form-check-label" id="' . $id . '-lbl">' . $t . '</label>'; $html .= '</div>'; } $html .= '</div>'; return $html; } } Helpers/User.php 0000644 00000004435 15172602426 0007610 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Access\Access; use Joomla\CMS\Factory; use Joomla\CMS\Helper\UserGroupsHelper; use Joomla\CMS\HTML\HTMLHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class working with users * * @since 2.5 */ abstract class User { /** * Displays a list of user groups. * * @param boolean $includeSuperAdmin true to include super admin groups, false to exclude them * * @return array An array containing a list of user groups. * * @since 2.5 */ public static function groups($includeSuperAdmin = false) { $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; $groups[] = HTMLHelper::_('select.option', $options[$i]->value, $options[$i]->text); } // Exclude super admin groups if requested if (!$includeSuperAdmin) { $filteredGroups = []; foreach ($groups as $group) { if (!Access::checkGroup($group->value, 'core.admin')) { $filteredGroups[] = $group; } } $groups = $filteredGroups; } return $groups; } /** * Get a list of users. * * @return string * * @since 2.5 */ public static function userlist() { $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( [ $db->quoteName('a.id', 'value'), $db->quoteName('a.name', 'text'), ] ) ->from($db->quoteName('#__users', 'a')) ->where($db->quoteName('a.block') . ' = 0') ->order($db->quoteName('a.name')); $db->setQuery($query); return $db->loadObjectList(); } } Helpers/Dropdown.php 0000644 00000023544 15172602426 0010470 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * HTML utility class for building a dropdown menu * * @since 3.0 */ abstract class Dropdown { /** * @var array Array containing information for loaded files * @since 3.0 */ protected static $loaded = []; /** * @var string HTML markup for the dropdown list * @since 3.0 */ protected static $dropDownList = null; /** * Method to inject needed script * * @return void * * @since 3.0 */ public static function init() { // Only load once if (isset(static::$loaded[__METHOD__])) { return; } // Depends on Bootstrap HTMLHelper::_('bootstrap.framework'); Factory::getDocument()->addScriptDeclaration(" (function($){ $(document).ready(function (){ $('.has-context') .mouseenter(function (){ $('.btn-group',$(this)).show(); }) .mouseleave(function (){ $('.btn-group',$(this)).hide(); $('.btn-group',$(this)).removeClass('open'); }); contextAction =function (cbId, task) { $('input[name=\"cid[]\"]').removeAttr('checked'); $('#' + cbId).attr('checked','checked'); Joomla.submitbutton(task); } }); })(jQuery); "); // Set static array static::$loaded[__METHOD__] = true; } /** * Method to start a new dropdown menu * * @return void * * @since 3.0 */ public static function start() { // Only start once if (isset(static::$loaded[__METHOD__]) && static::$loaded[__METHOD__] == true) { return; } $dropDownList = '<div class="btn-group" style="margin-left:6px;display:none"> <a href="#" data-bs-toggle="dropdown" class="dropdown-toggle btn btn-secondary btn-sm"> <span class="caret"></span> </a> <ul class="dropdown-menu">'; static::$dropDownList = $dropDownList; static::$loaded[__METHOD__] = true; } /** * Method to render current dropdown menu * * @return string HTML markup for the dropdown list * * @since 3.0 */ public static function render() { $dropDownList = static::$dropDownList; $dropDownList .= '</ul></div>'; static::$dropDownList = null; static::$loaded[__CLASS__ . '::start'] = false; return $dropDownList; } /** * Append an edit item to the current dropdown menu * * @param integer $id Record ID * @param string $prefix Task prefix * @param string $customLink The custom link if dont use default Joomla action format * * @return void * * @since 3.0 */ public static function edit($id, $prefix = '', $customLink = '') { static::start(); if (!$customLink) { $option = Factory::getApplication()->getInput()->getCmd('option'); $link = 'index.php?option=' . $option; } else { $link = $customLink; } $link .= '&task=' . $prefix . 'edit&id=' . $id; $link = Route::_($link); static::addCustomItem(Text::_('JACTION_EDIT'), $link); } /** * Append a publish item to the current dropdown menu * * @param string $checkboxId ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.0 */ public static function publish($checkboxId, $prefix = '') { $task = $prefix . 'publish'; static::addCustomItem(Text::_('JTOOLBAR_PUBLISH'), 'javascript:void(0)', 'onclick="contextAction(\'' . $checkboxId . '\', \'' . $task . '\')"'); } /** * Append an unpublish item to the current dropdown menu * * @param string $checkboxId ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.0 */ public static function unpublish($checkboxId, $prefix = '') { $task = $prefix . 'unpublish'; static::addCustomItem(Text::_('JTOOLBAR_UNPUBLISH'), 'javascript:void(0)', 'onclick="contextAction(\'' . $checkboxId . '\', \'' . $task . '\')"'); } /** * Append a featured item to the current dropdown menu * * @param string $checkboxId ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.0 */ public static function featured($checkboxId, $prefix = '') { $task = $prefix . 'featured'; static::addCustomItem(Text::_('JFEATURED'), 'javascript:void(0)', 'onclick="contextAction(\'' . $checkboxId . '\', \'' . $task . '\')"'); } /** * Append an unfeatured item to the current dropdown menu * * @param string $checkboxId ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.0 */ public static function unfeatured($checkboxId, $prefix = '') { $task = $prefix . 'unfeatured'; static::addCustomItem(Text::_('JUNFEATURED'), 'javascript:void(0)', 'onclick="contextAction(\'' . $checkboxId . '\', \'' . $task . '\')"'); } /** * Append an archive item to the current dropdown menu * * @param string $checkboxId ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.0 */ public static function archive($checkboxId, $prefix = '') { $task = $prefix . 'archive'; static::addCustomItem(Text::_('JTOOLBAR_ARCHIVE'), 'javascript:void(0)', 'onclick="contextAction(\'' . $checkboxId . '\', \'' . $task . '\')"'); } /** * Append an unarchive item to the current dropdown menu * * @param string $checkboxId ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.0 */ public static function unarchive($checkboxId, $prefix = '') { $task = $prefix . 'unpublish'; static::addCustomItem(Text::_('JTOOLBAR_UNARCHIVE'), 'javascript:void(0)', 'onclick="contextAction(\'' . $checkboxId . '\', \'' . $task . '\')"'); } /** * Append a trash item to the current dropdown menu * * @param string $checkboxId ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.0 */ public static function trash($checkboxId, $prefix = '') { $task = $prefix . 'trash'; static::addCustomItem(Text::_('JTOOLBAR_TRASH'), 'javascript:void(0)', 'onclick="contextAction(\'' . $checkboxId . '\', \'' . $task . '\')"'); } /** * Append an untrash item to the current dropdown menu * * @param string $checkboxId ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.0 */ public static function untrash($checkboxId, $prefix = '') { $task = $prefix . 'publish'; static::addCustomItem(Text::_('JTOOLBAR_UNTRASH'), 'javascript:void(0)', 'onclick="contextAction(\'' . $checkboxId . '\', \'' . $task . '\')"'); } /** * Append a checkin item to the current dropdown menu * * @param string $checkboxId ID of corresponding checkbox of the record * @param string $prefix The task prefix * * @return void * * @since 3.0 */ public static function checkin($checkboxId, $prefix = '') { $task = $prefix . 'checkin'; static::addCustomItem(Text::_('JTOOLBAR_CHECKIN'), 'javascript:void(0)', 'onclick="contextAction(\'' . $checkboxId . '\', \'' . $task . '\')"'); } /** * Writes a divider between dropdown items * * @return void * * @since 3.0 */ public static function divider() { static::$dropDownList .= '<li class="divider"></li>'; } /** * Append a custom item to current dropdown menu * * @param string $label The label of item * @param string $link The link of item * @param string $linkAttributes Custom link attributes * @param string $className Class name of item * @param boolean $ajaxLoad True if using ajax load when item clicked * @param string $jsCallBackFunc Javascript function name, called when ajax load successfully * * @return void * * @since 3.0 */ public static function addCustomItem( $label, $link = 'javascript:void(0)', $linkAttributes = '', $className = '', $ajaxLoad = false, $jsCallBackFunc = null ) { static::start(); if ($ajaxLoad) { $href = ' href = "javascript:void(0)" onclick="loadAjax(\'' . $link . '\', \'' . $jsCallBackFunc . '\')"'; } else { $href = ' href = "' . $link . '" '; } $dropDownList = static::$dropDownList; $dropDownList .= '<li class="' . $className . '"><a ' . $linkAttributes . $href . ' >'; $dropDownList .= $label; $dropDownList .= '</a></li>'; static::$dropDownList = $dropDownList; } } Helpers/Date.php 0000644 00000004766 15172602426 0007556 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Date\Date as DateHelper; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Extended Utility class for handling date display. * * @since 2.5 */ abstract class Date { /** * Function to convert a static time into a relative measurement * * @param string $date The date to convert * @param string $unit The optional unit of measurement to return * if the value of the diff is greater than one * @param string $time An optional time to compare to, defaults to now * @param string $format An optional format for the HTMLHelper::date output * * @return string The converted time string * * @since 2.5 */ public static function relative($date, $unit = null, $time = null, $format = null) { if ($time === null) { // Get now $time = new DateHelper('now'); } // Get the difference in seconds between now and the time $diff = strtotime($time) - strtotime($date); // Less than a minute if ($diff < 60) { return Text::_('JLIB_HTML_DATE_RELATIVE_LESSTHANAMINUTE'); } // Round to minutes $diff = round($diff / 60); // 1 to 59 minutes if ($diff < 60 || $unit === 'minute') { return Text::plural('JLIB_HTML_DATE_RELATIVE_MINUTES', $diff); } // Round to hours $diff = round($diff / 60); // 1 to 23 hours if ($diff < 24 || $unit === 'hour') { return Text::plural('JLIB_HTML_DATE_RELATIVE_HOURS', $diff); } // Round to days $diff = round($diff / 24); // 1 to 6 days if ($diff < 7 || $unit === 'day') { return Text::plural('JLIB_HTML_DATE_RELATIVE_DAYS', $diff); } // Round to weeks $diff = round($diff / 7); // 1 to 4 weeks if ($diff <= 4 || $unit === 'week') { return Text::plural('JLIB_HTML_DATE_RELATIVE_WEEKS', $diff); } // Over a month, return the absolute time return HTMLHelper::_('date', $date, $format); } } Helpers/Email.php 0000644 00000004756 15172602426 0007727 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML\Helpers; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\String\PunycodeHelper; use Joomla\CMS\Uri\Uri; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for cloaking email addresses * * @since 1.5 */ abstract class Email { /** * Simple JavaScript email cloaker * * By default replaces an email with a mailto link with email cloaked * * @param string $mail The -mail address to cloak. * @param boolean $mailto True if text and mailing address differ * @param string $text Text for the link * @param boolean $email True if text is an email address * @param string $attribsBefore Any attributes before the email address * @param string $attribsAfter Any attributes before the email address * * @return string The cloaked email. * * @since 1.5 */ public static function cloak($mail, $mailto = true, $text = '', $email = true, $attribsBefore = '', $attribsAfter = '') { // Handle IDN addresses: punycode for href but utf-8 for text displayed. if ($mailto && (empty($text) || $email)) { // Use dedicated $text whereas $mail is used as href and must be punycoded. $text = PunycodeHelper::emailToUTF8($text ?: $mail); } elseif (!$mailto) { // In that case we don't use link - so convert $mail back to utf-8. $mail = PunycodeHelper::emailToUTF8($mail); } // Split email by @ symbol $mail = explode('@', $mail); $name = @$mail[0]; $domain = @$mail[1]; // Include the email cloaking script Factory::getDocument()->getWebAssetManager() ->useScript('webcomponent.hidden-mail'); return '<joomla-hidden-mail ' . $attribsBefore . ' is-link="' . $mailto . '" is-email="' . $email . '" first="' . base64_encode($name) . '" last="' . base64_encode($domain) . '" text="' . base64_encode($text) . '" base="' . Uri::root(true) . '" ' . $attribsAfter . '>' . Text::_('JLIB_HTML_CLOAKING') . '</joomla-hidden-mail>'; } } Registry.php 0000644 00000010722 15172602426 0007074 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Service registry for JHtml services * * @since 4.0.0 */ final class Registry { /** * Mapping array of the core CMS JHtml helpers * * @var array * @since 4.0.0 */ private $serviceMap = [ 'access' => Helpers\Access::class, 'actionsdropdown' => Helpers\ActionsDropdown::class, 'adminlanguage' => Helpers\AdminLanguage::class, 'behavior' => Helpers\Behavior::class, 'bootstrap' => Helpers\Bootstrap::class, 'category' => Helpers\Category::class, 'content' => Helpers\Content::class, 'contentlanguage' => Helpers\ContentLanguage::class, 'date' => Helpers\Date::class, 'debug' => Helpers\Debug::class, 'draggablelist' => Helpers\DraggableList::class, 'dropdown' => Helpers\Dropdown::class, 'email' => Helpers\Email::class, 'form' => Helpers\Form::class, 'formbehavior' => Helpers\FormBehavior::class, 'grid' => Helpers\Grid::class, 'icons' => Helpers\Icons::class, 'jgrid' => Helpers\JGrid::class, 'jquery' => Helpers\Jquery::class, 'links' => Helpers\Links::class, 'list' => Helpers\ListHelper::class, 'menu' => Helpers\Menu::class, 'number' => Helpers\Number::class, 'searchtools' => Helpers\SearchTools::class, 'select' => Helpers\Select::class, 'sidebar' => Helpers\Sidebar::class, 'sortablelist' => Helpers\SortableList::class, 'string' => Helpers\StringHelper::class, 'tag' => Helpers\Tag::class, 'tel' => Helpers\Telephone::class, 'uitab' => Helpers\UiTab::class, 'user' => Helpers\User::class, 'workflowstage' => Helpers\WorkflowStage::class, ]; /** * Get the service for a given key * * @param string $key The service key to look up * * @return string|object * * @since 4.0.0 */ public function getService(string $key) { if (!$this->hasService($key)) { throw new \InvalidArgumentException("The '$key' service key is not registered."); } return $this->serviceMap[$key]; } /** * Check if the registry has a service for the given key * * @param string $key The service key to look up * * @return boolean * * @since 4.0.0 */ public function hasService(string $key): bool { return isset($this->serviceMap[$key]); } /** * Register a service * * @param string $key The service key to be registered * @param string|object $handler The handler for the service as either a PHP class name or class object * @param boolean $replace Flag indicating the service key may replace an existing definition * * @return void * * @since 4.0.0 */ public function register(string $key, $handler, bool $replace = false) { // If the key exists already and we aren't instructed to replace existing services, bail early if (isset($this->serviceMap[$key]) && !$replace) { throw new \RuntimeException("The '$key' service key is already registered."); } // If the handler is a string, it must be a class that exists if (\is_string($handler) && !class_exists($handler)) { throw new \RuntimeException("The '$handler' class for service key '$key' does not exist."); } // Otherwise the handler must be a class object if (!\is_string($handler) && !\is_object($handler)) { throw new \RuntimeException( sprintf( 'The handler for service key %1$s must be a PHP class name or class object, a %2$s was given.', $key, \gettype($handler) ) ); } $this->serviceMap[$key] = $handler; } } HTMLRegistryAwareTrait.php 0000644 00000002334 15172602426 0011545 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Defines the trait for a HTML Registry aware class. * * @since 4.0.0 */ trait HTMLRegistryAwareTrait { /** * The registry * * @var Registry * @since 4.0.0 */ private $registry; /** * Get the registry. * * @return Registry * * @since 4.0.0 * @throws \UnexpectedValueException May be thrown if the registry has not been set. */ public function getRegistry() { if ($this->registry) { return $this->registry; } throw new \UnexpectedValueException('HTML registry not set in ' . __CLASS__); } /** * Set the registry to use. * * @param Registry $registry The registry * * @return void * * @since 4.0.0 */ public function setRegistry(Registry $registry = null) { $this->registry = $registry; } } HTMLHelper.php 0000644 00000135063 15172602426 0007176 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\HTML; use Joomla\CMS\Environment\Browser; use Joomla\CMS\Factory; use Joomla\CMS\Filesystem\File; use Joomla\CMS\Filesystem\Path; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Uri\Uri; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('JPATH_PLATFORM') or die; // phpcs:enable PSR1.Files.SideEffects /** * Utility class for all HTML drawing classes * * @since 1.5 */ abstract class HTMLHelper { /** * Option values related to the generation of HTML output. Recognized * options are: * fmtDepth, integer. The current indent depth. * fmtEol, string. The end of line string, default is linefeed. * fmtIndent, string. The string to use for indentation, default is * tab. * * @var array * @since 1.5 */ public static $formatOptions = ['format.depth' => 0, 'format.eol' => "\n", 'format.indent' => "\t"]; /** * An array to hold included paths * * @var string[] * @since 1.5 * @deprecated 4.0 will be removed in 6.0 */ protected static $includePaths = []; /** * An array to hold method references * * @var callable[] * @since 1.6 * @deprecated 4.0 will be removed in 6.0 */ protected static $registry = []; /** * The service registry for custom and overridden JHtml helpers * * @var Registry * @since 4.0.0 */ protected static $serviceRegistry; /** * Method to extract a key * * @param string $key The name of helper method to load, (prefix).(class).function * prefix and class are optional and can be used to load custom html helpers. * * @return array Contains lowercase key, prefix, file, function. * * @since 1.6 * @deprecated 4.0 will be removed in 6.0 * Use the service registry instead * HTMLHelper::getServiceRegistry()->getService($file); */ protected static function extract($key) { $key = preg_replace('#[^A-Z0-9_\.]#i', '', $key); // Check to see whether we need to load a helper file $parts = explode('.', $key); if (\count($parts) === 3) { @trigger_error( 'Support for a three segment service key is deprecated and will be removed in Joomla 5.0, use the service registry instead', E_USER_DEPRECATED ); } $prefix = \count($parts) === 3 ? array_shift($parts) : 'JHtml'; $file = \count($parts) === 2 ? array_shift($parts) : ''; $func = array_shift($parts); return [strtolower($prefix . '.' . $file . '.' . $func), $prefix, $file, $func]; } /** * Class loader method * * Additional arguments may be supplied and are passed to the sub-class. * Additional include paths are also able to be specified for third-party use * * @param string $key The name of helper method to load, (prefix).(class).function * prefix and class are optional and can be used to load custom * html helpers. * @param mixed $methodArgs The arguments to pass forward to the method being called * * @return mixed Result of HTMLHelper::call($function, $args) * * @since 1.5 * @throws \InvalidArgumentException */ final public static function _(string $key, ...$methodArgs) { list($key, $prefix, $file, $func) = static::extract($key); if (\array_key_exists($key, static::$registry)) { $function = static::$registry[$key]; return static::call($function, $methodArgs); } /* * Support fetching services from the registry if a custom class prefix was not given (a three segment key), * the service comes from a class other than this one, and a service has been registered for the file. */ if ($prefix === 'JHtml' && $file !== '' && static::getServiceRegistry()->hasService($file)) { $service = static::getServiceRegistry()->getService($file); $toCall = [$service, $func]; if (!\is_callable($toCall)) { throw new \InvalidArgumentException(sprintf('%s::%s not found.', $file, $func), 500); } static::register($key, $toCall); return static::call($toCall, $methodArgs); } $className = $prefix . ucfirst($file); if (!class_exists($className)) { $path = Path::find(static::$includePaths, strtolower($file) . '.php'); if (!$path) { throw new \InvalidArgumentException(sprintf('%s %s not found.', $prefix, $file), 500); } \JLoader::register($className, $path); if (!class_exists($className)) { throw new \InvalidArgumentException(sprintf('%s not found.', $className), 500); } } // If calling a method from this class, do not allow access to internal methods if ($className === __CLASS__) { if (!((new \ReflectionMethod($className, $func))->isPublic())) { throw new \InvalidArgumentException('Access to internal class methods is not allowed.'); } } $toCall = [$className, $func]; if (!\is_callable($toCall)) { throw new \InvalidArgumentException(sprintf('%s::%s not found.', $className, $func), 500); } static::register($key, $toCall); return static::call($toCall, $methodArgs); } /** * Registers a function to be called with a specific key * * @param string $key The name of the key * @param callable $function Function or method * * @return boolean True if the function is callable * * @since 1.6 * @deprecated 4.0 will be removed in 6.0 * Use the service registry instead * HTMLHelper::getServiceRegistry()->register($key, $function); */ public static function register($key, callable $function) { @trigger_error( 'Support for registering functions is deprecated and will be removed in Joomla 5.0, use the service registry instead', E_USER_DEPRECATED ); list($key) = static::extract($key); static::$registry[$key] = $function; return true; } /** * Removes a key for a method from registry. * * @param string $key The name of the key * * @return boolean True if a set key is unset * * @since 1.6 * @deprecated 4.0 will be removed in 6.0 * Use the service registry instead */ public static function unregister($key) { @trigger_error( 'Support for registering functions is deprecated and will be removed in Joomla 5.0, use the service registry instead', E_USER_DEPRECATED ); list($key) = static::extract($key); if (isset(static::$registry[$key])) { unset(static::$registry[$key]); return true; } return false; } /** * Test if the key is registered. * * @param string $key The name of the key * * @return boolean True if the key is registered. * * @since 1.6 */ public static function isRegistered($key) { list($key) = static::extract($key); return isset(static::$registry[$key]); } /** * Retrieves the service registry. * * @return Registry * * @since 4.0.0 */ public static function getServiceRegistry(): Registry { if (!static::$serviceRegistry) { static::$serviceRegistry = Factory::getContainer()->get(Registry::class); } return static::$serviceRegistry; } /** * Function caller method * * @param callable $function Function or method to call * @param array $args Arguments to be passed to function * * @return mixed Function result or false on error. * * @link https://www.php.net/manual/en/function.call-user-func-array.php * @since 1.6 * @throws \InvalidArgumentException */ protected static function call(callable $function, $args) { // Workaround to allow calling helper methods have arguments passed by reference $temp = []; foreach ($args as &$arg) { $temp[] = &$arg; } return \call_user_func_array($function, $temp); } /** * Write a `<a>` element * * @param string $url The relative URL to use for the href attribute * @param string $text The target attribute to use * @param array|string $attribs Attributes to be added to the `<a>` element * * @return string * * @since 1.5 */ public static function link($url, $text, $attribs = null) { if (\is_array($attribs)) { $attribs = ArrayHelper::toString($attribs); } return '<a href="' . $url . '" ' . $attribs . '>' . $text . '</a>'; } /** * Write a `<iframe>` element * * @param string $url The relative URL to use for the src attribute. * @param string $name The target attribute to use. * @param array|string $attribs Attributes to be added to the `<iframe>` element * @param string $noFrames The message to display if the iframe tag is not supported. * * @return string * * @since 1.5 */ public static function iframe($url, $name, $attribs = null, $noFrames = '') { if (\is_array($attribs)) { $attribs = ArrayHelper::toString($attribs); } return '<iframe src="' . $url . '" ' . $attribs . ' name="' . $name . '">' . $noFrames . '</iframe>'; } /** * Compute the files to be included * * @param string $folder Folder name to search in (i.e. images, css, js). * @param string $file Path to file. * @param boolean $relative Flag if the path to the file is relative to the /media folder (and searches in template). * @param boolean $detectBrowser Flag if the browser should be detected to include specific browser files. * @param boolean $detectDebug Flag if debug mode is enabled to include uncompressed files if debug is on. * * @return array files to be included. * * @see Browser * @since 1.6 */ protected static function includeRelativeFiles($folder, $file, $relative, $detectBrowser, $detectDebug) { // Set debug flag $debugMode = false; // Detect debug mode if ($detectDebug && JDEBUG) { $debugMode = true; } // If http is present in filename if (strpos($file, 'http') === 0 || strpos($file, '//') === 0) { $includes = [$file]; } else { // Extract extension and strip the file $strip = File::stripExt($file); $ext = File::getExt($file); // Prepare array of files $includes = []; // Detect browser and compute potential files if ($detectBrowser) { $navigator = Browser::getInstance(); $browser = $navigator->getBrowser(); $major = $navigator->getMajor(); $minor = $navigator->getMinor(); $minExt = ''; if (\strlen($strip) > 4 && preg_match('#\.min$#', $strip)) { $minExt = '.min'; $strip = preg_replace('#\.min$#', '', $strip); } // Try to include files named filename.ext, filename_browser.ext, filename_browser_major.ext, filename_browser_major_minor.ext // where major and minor are the browser version names $potential = [ $strip . $minExt, $strip . '_' . $browser . $minExt, $strip . '_' . $browser . '_' . $major . $minExt, $strip . '_' . $browser . '_' . $major . '_' . $minor . $minExt, ]; } else { $potential = [$strip]; } // If relative search in template directory or media directory if ($relative) { $app = Factory::getApplication(); $template = $app->getTemplate(true); $templaPath = JPATH_THEMES; if ($template->inheritable || !empty($template->parent)) { $client = $app->isClient('administrator') === true ? 'administrator' : 'site'; $templaPath = JPATH_ROOT . "/media/templates/$client"; } // For each potential files foreach ($potential as $strip) { $files = []; $files[] = $strip . '.' . $ext; /** * Loop on 1 or 2 files and break on first found. * Add the content of the MD5SUM file located in the same folder to url to ensure cache browser refresh * This MD5SUM file must represent the signature of the folder content */ foreach ($files as $file) { if (!empty($template->parent)) { $found = static::addFileToBuffer("$templaPath/$template->template/$folder/$file", $ext, $debugMode); if (empty($found)) { $found = static::addFileToBuffer("$templaPath/$template->parent/$folder/$file", $ext, $debugMode); } } else { $found = static::addFileToBuffer("$templaPath/$template->template/$folder/$file", $ext, $debugMode); } if (!empty($found)) { $includes[] = $found; break; } else { // If the file contains any /: it can be in a media extension subfolder if (strpos($file, '/')) { // Divide the file extracting the extension as the first part before / list($extension, $file) = explode('/', $file, 2); // If the file yet contains any /: it can be a plugin if (strpos($file, '/')) { // Divide the file extracting the element as the first part before / list($element, $file) = explode('/', $file, 2); // Try to deal with plugins group in the media folder $found = static::addFileToBuffer(JPATH_ROOT . "/media/$extension/$element/$folder/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } // Try to deal with classical file in a media subfolder called element $found = static::addFileToBuffer(JPATH_ROOT . "/media/$extension/$folder/$element/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } // Try to deal with system files in the template folder if (!empty($template->parent)) { $found = static::addFileToBuffer("$templaPath/$template->template/$folder/system/$element/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } $found = static::addFileToBuffer("$templaPath/$template->parent/$folder/system/$element/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } } else { // Try to deal with system files in the media folder $found = static::addFileToBuffer(JPATH_ROOT . "/media/system/$folder/$element/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } } } else { // Try to deal with files in the extension's media folder $found = static::addFileToBuffer(JPATH_ROOT . "/media/$extension/$folder/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } // Try to deal with system files in the template folder if (!empty($template->parent)) { $found = static::addFileToBuffer("$templaPath/$template->template/$folder/system/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } $found = static::addFileToBuffer("$templaPath/$template->parent/$folder/system/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } } else { // Try to deal with system files in the template folder $found = static::addFileToBuffer("$templaPath/$template->template/$folder/system/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } } // Try to deal with system files in the media folder $found = static::addFileToBuffer(JPATH_ROOT . "/media/system/$folder/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } } } else { // Try to deal with system files in the media folder $found = static::addFileToBuffer(JPATH_ROOT . "/media/system/$folder/$file", $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } } } } } } else { // If not relative and http is not present in filename foreach ($potential as $strip) { $files = []; $files[] = $strip . '.' . $ext; /** * Loop on 1 or 2 files and break on first found. * Add the content of the MD5SUM file located in the same folder to url to ensure cache browser refresh * This MD5SUM file must represent the signature of the folder content */ foreach ($files as $file) { $path = JPATH_ROOT . "/$file"; $found = static::addFileToBuffer($path, $ext, $debugMode); if (!empty($found)) { $includes[] = $found; break; } } } } } return $includes; } /** * Gets a URL, cleans the Joomla specific params and returns an object * * @param string $url The relative or absolute URL to use for the src attribute. * * @return object * @example { * url: 'string', * attributes: [ * width: integer, * height: integer, * ] * } * * @since 4.0.0 */ public static function cleanImageURL($url) { $obj = new \stdClass(); $obj->attributes = [ 'width' => 0, 'height' => 0, ]; if ($url === null) { $url = ''; } if (!strpos($url, '?')) { $obj->url = $url; return $obj; } $mediaUri = new Uri($url); // Old image URL format if ($mediaUri->hasVar('joomla_image_height')) { $height = (int) $mediaUri->getVar('joomla_image_height'); $width = (int) $mediaUri->getVar('joomla_image_width'); $mediaUri->delVar('joomla_image_height'); $mediaUri->delVar('joomla_image_width'); } else { // New Image URL format $fragmentUri = new Uri($mediaUri->getFragment()); $width = (int) $fragmentUri->getVar('width', 0); $height = (int) $fragmentUri->getVar('height', 0); } if ($width > 0) { $obj->attributes['width'] = $width; } if ($height > 0) { $obj->attributes['height'] = $height; } $mediaUri->setFragment(''); $obj->url = $mediaUri->toString(); return $obj; } /** * Write a `<img>` element * * @param string $file The relative or absolute URL to use for the src attribute. * @param string $alt The alt text. * @param array|string $attribs Attributes to be added to the `<img>` element * @param boolean $relative Flag if the path to the file is relative to the /media folder (and searches in template). * @param integer $returnPath Defines the return value for the method: * -1: Returns a `<img>` tag without looking for relative files * 0: Returns a `<img>` tag while searching for relative files * 1: Returns the file path to the image while searching for relative files * * @return string|null HTML markup for the image, relative path to the image, or null if path is to be returned but image is not found * * @since 1.5 */ public static function image($file, $alt, $attribs = null, $relative = false, $returnPath = 0) { // Ensure is an integer $returnPath = (int) $returnPath; // The path of the file $path = $file; // The arguments of the file path $arguments = ''; // Get the arguments positions $pos1 = strpos($file, '?'); $pos2 = strpos($file, '#'); // Check if there are arguments if ($pos1 !== false || $pos2 !== false) { // Get the path only $path = substr($file, 0, min($pos1, $pos2)); // Determine the arguments is mostly the part behind the # $arguments = str_replace($path, '', $file); } // Get the relative file name when requested if ($returnPath !== -1) { // Search for relative file names $includes = static::includeRelativeFiles('images', $path, $relative, false, false); // Grab the first found path and if none exists default to null $path = \count($includes) ? $includes[0] : null; } // Compile the file name $file = ($path === null ? null : $path . $arguments); // If only the file is required, return here if ($returnPath === 1) { return $file; } // Ensure we have a valid default for concatenating if ($attribs === null || $attribs === false) { $attribs = []; } // When it is a string, we need convert it to an array if (is_string($attribs)) { $attributes = []; // Go through each argument foreach (explode(' ', $attribs) as $attribute) { // When an argument without a value, default to an empty string if (strpos($attribute, '=') === false) { $attributes[$attribute] = ''; continue; } // Set the attribute list($key, $value) = explode('=', $attribute); $attributes[$key] = trim($value, '"'); } // Add the attributes from the string to the original attributes $attribs = $attributes; } // Fill the attributes with the file and alt text $attribs['src'] = $file; $attribs['alt'] = $alt; // Render the layout with the attributes return LayoutHelper::render('joomla.html.image', $attribs); } /** * Write a `<link>` element to load a CSS file * * @param string $file Path to file * @param array $options Array of options. Example: array('version' => 'auto', 'conditional' => 'lt IE 9') * @param array $attribs Array of attributes. Example: array('id' => 'scriptid', 'async' => 'async', 'data-test' => 1) * * @return array|string|null nothing if $returnPath is false, null, path or array of path if specific CSS browser files were detected * * @see Browser * @since 1.5 */ public static function stylesheet($file, $options = [], $attribs = []) { $options['relative'] = $options['relative'] ?? false; $options['pathOnly'] = $options['pathOnly'] ?? false; $options['detectBrowser'] = $options['detectBrowser'] ?? false; $options['detectDebug'] = $options['detectDebug'] ?? true; $includes = static::includeRelativeFiles('css', $file, $options['relative'], $options['detectBrowser'], $options['detectDebug']); // If only path is required if ($options['pathOnly']) { if (\count($includes) === 0) { return; } if (\count($includes) === 1) { return $includes[0]; } return $includes; } // If inclusion is required $document = Factory::getApplication()->getDocument(); foreach ($includes as $include) { // If there is already a version hash in the script reference (by using deprecated MD5SUM). if ($pos = strpos($include, '?') !== false) { $options['version'] = substr($include, $pos + 1); } $document->addStyleSheet($include, $options, $attribs); } } /** * Write a `<script>` element to load a JavaScript file * * @param string $file Path to file. * @param array $options Array of options. Example: array('version' => 'auto', 'conditional' => 'lt IE 9') * @param array $attribs Array of attributes. Example: array('id' => 'scriptid', 'async' => 'async', 'data-test' => 1) * * @return array|string|null Nothing if $returnPath is false, null, path or array of path if specific JavaScript browser files were detected * * @see HTMLHelper::stylesheet() * @since 1.5 */ public static function script($file, $options = [], $attribs = []) { $options['relative'] = $options['relative'] ?? false; $options['pathOnly'] = $options['pathOnly'] ?? false; $options['detectBrowser'] = $options['detectBrowser'] ?? false; $options['detectDebug'] = $options['detectDebug'] ?? true; $includes = static::includeRelativeFiles('js', $file, $options['relative'], $options['detectBrowser'], $options['detectDebug']); // If only path is required if ($options['pathOnly']) { if (\count($includes) === 0) { return; } if (\count($includes) === 1) { return $includes[0]; } return $includes; } // If inclusion is required $document = Factory::getApplication()->getDocument(); foreach ($includes as $include) { // If there is already a version hash in the script reference (by using deprecated MD5SUM). if ($pos = strpos($include, '?') !== false) { $options['version'] = substr($include, $pos + 1); } $document->addScript($include, $options, $attribs); } } /** * Set format related options. * * Updates the formatOptions array with all valid values in the passed array. * * @param array $options Option key/value pairs. * * @return void * * @see HTMLHelper::$formatOptions * @since 1.5 */ public static function setFormatOptions($options) { foreach ($options as $key => $val) { if (isset(static::$formatOptions[$key])) { static::$formatOptions[$key] = $val; } } } /** * Returns formatted date according to a given format and time zone. * * @param string $input String in a format accepted by date(), defaults to "now". * @param string $format The date format specification string (see {@link PHP_MANUAL#date}). * @param mixed $tz Time zone to be used for the date. Special cases: boolean true for user * setting, boolean false for server setting. * @param boolean $gregorian True to use Gregorian calendar. * * @return string A date translated by the given format and time zone. * * @see strftime * @since 1.5 */ public static function date($input = 'now', $format = null, $tz = true, $gregorian = false) { $app = Factory::getApplication(); // UTC date converted to user time zone. if ($tz === true) { // Get a date object based on UTC. $date = Factory::getDate($input, 'UTC'); // Set the correct time zone based on the user configuration. $date->setTimezone($app->getIdentity()->getTimezone()); } elseif ($tz === false) { // UTC date converted to server time zone. // Get a date object based on UTC. $date = Factory::getDate($input, 'UTC'); // Set the correct time zone based on the server configuration. $date->setTimezone(new \DateTimeZone($app->get('offset'))); } elseif ($tz === null) { // No date conversion. $date = Factory::getDate($input); } else { // UTC date converted to given time zone. // Get a date object based on UTC. $date = Factory::getDate($input, 'UTC'); // Set the correct time zone based on the server configuration. $date->setTimezone(new \DateTimeZone($tz)); } // If no format is given use the default locale based format. if (!$format) { $format = Text::_('DATE_FORMAT_LC1'); } elseif (Factory::getLanguage()->hasKey($format)) { // $format is an existing language key $format = Text::_($format); } if ($gregorian) { return $date->format($format, true); } return $date->calendar($format, true); } /** * Creates a tooltip with an image as button * * @param string $tooltip The tip string. * @param mixed $title The title of the tooltip or an associative array with keys contained in * {'title','image','text','href','alt'} and values corresponding to parameters of the same name. * @param string $image The image for the tip, if no text is provided. * @param string $text The text for the tip. * @param string $href A URL that will be used to create the link. * @param string $alt The alt attribute for img tag. * @param string $class CSS class for the tool tip. * * @return string * * @since 1.5 */ public static function tooltip($tooltip, $title = '', $image = 'tooltip.png', $text = '', $href = '', $alt = 'Tooltip', $class = 'hasTooltip') { if (\is_array($title)) { foreach (['image', 'text', 'href', 'alt', 'class'] as $param) { if (isset($title[$param])) { $$param = $title[$param]; } } if (isset($title['title'])) { $title = $title['title']; } else { $title = ''; } } if (!$text) { $alt = htmlspecialchars($alt, ENT_COMPAT, 'UTF-8'); $text = static::image($image, $alt, null, true); } if ($href) { $tip = '<a href="' . $href . '">' . $text . '</a>'; } else { $tip = $text; } if ($class === 'hasTip') { // Still using MooTools tooltips! $tooltip = htmlspecialchars($tooltip, ENT_COMPAT, 'UTF-8'); if ($title) { $title = htmlspecialchars($title, ENT_COMPAT, 'UTF-8'); $tooltip = $title . '::' . $tooltip; } } else { $tooltip = self::tooltipText($title, $tooltip, 0); } return '<span class="' . $class . '" title="' . $tooltip . '">' . $tip . '</span>'; } /** * Converts a double colon separated string or 2 separate strings to a string ready for bootstrap tooltips * * @param string $title The title of the tooltip (or combined '::' separated string). * @param string $content The content to tooltip. * @param boolean $translate If true will pass texts through Text. * @param boolean $escape If true will pass texts through htmlspecialchars. * * @return string The tooltip string * * @since 3.1.2 */ public static function tooltipText($title = '', $content = '', $translate = true, $escape = true) { // Initialise return value. $result = ''; // Don't process empty strings if ($content !== '' || $title !== '') { // Split title into title and content if the title contains '::' (old Mootools format). if ($content === '' && !(strpos($title, '::') === false)) { list($title, $content) = explode('::', $title, 2); } // Pass texts through Text if required. if ($translate) { $title = Text::_($title); $content = Text::_($content); } // Use only the content if no title is given. if ($title === '') { $result = $content; } elseif ($title === $content) { // Use only the title, if title and text are the same. $result = '<strong>' . $title . '</strong>'; } elseif ($content !== '') { // Use a formatted string combining the title and content. $result = '<strong>' . $title . '</strong><br>' . $content; } else { $result = $title; } // Escape everything, if required. if ($escape) { $result = htmlspecialchars($result); } } return $result; } /** * Displays a calendar control field * * @param string $value The date value * @param string $name The name of the text field * @param string $id The id of the text field * @param string $format The date format * @param mixed $attribs Additional HTML attributes * The array can have the following keys: * readonly Sets the readonly parameter for the input tag * disabled Sets the disabled parameter for the input tag * autofocus Sets the autofocus parameter for the input tag * autocomplete Sets the autocomplete parameter for the input tag * filter Sets the filter for the input tag * * @return string HTML markup for a calendar field * * @since 1.5 * */ public static function calendar($value, $name, $id, $format = '%Y-%m-%d', $attribs = []) { $app = Factory::getApplication(); $lang = $app->getLanguage(); $tag = $lang->getTag(); $calendar = $lang->getCalendar(); $direction = strtolower($app->getDocument()->getDirection()); // Get the appropriate file for the current language date helper $helperPath = 'system/fields/calendar-locales/date/gregorian/date-helper.min.js'; if ($calendar && is_dir(JPATH_ROOT . '/media/system/js/fields/calendar-locales/date/' . strtolower($calendar))) { $helperPath = 'system/fields/calendar-locales/date/' . strtolower($calendar) . '/date-helper.min.js'; } $readonly = isset($attribs['readonly']) && $attribs['readonly'] === 'readonly'; $disabled = isset($attribs['disabled']) && $attribs['disabled'] === 'disabled'; $autocomplete = isset($attribs['autocomplete']) && $attribs['autocomplete'] === ''; $autofocus = isset($attribs['autofocus']) && $attribs['autofocus'] === ''; $required = isset($attribs['required']) && $attribs['required'] === ''; $filter = isset($attribs['filter']) && $attribs['filter'] === ''; $todayBtn = $attribs['todayBtn'] ?? true; $weekNumbers = $attribs['weekNumbers'] ?? true; $showTime = $attribs['showTime'] ?? false; $fillTable = $attribs['fillTable'] ?? true; $timeFormat = $attribs['timeFormat'] ?? 24; $singleHeader = $attribs['singleHeader'] ?? false; $hint = $attribs['placeholder'] ?? ''; $class = $attribs['class'] ?? ''; $onchange = $attribs['onChange'] ?? ''; $minYear = $attribs['minYear'] ?? null; $maxYear = $attribs['maxYear'] ?? null; $showTime = ($showTime) ? "1" : "0"; $todayBtn = ($todayBtn) ? "1" : "0"; $weekNumbers = ($weekNumbers) ? "1" : "0"; $fillTable = ($fillTable) ? "1" : "0"; $singleHeader = ($singleHeader) ? "1" : "0"; // Format value when not nulldate ('0000-00-00 00:00:00'), otherwise blank it as it would result in 1970-01-01. if ($value && $value !== Factory::getDbo()->getNullDate() && strtotime($value) !== false) { $tz = date_default_timezone_get(); date_default_timezone_set('UTC'); /** * Try to convert strftime format to date format, if success, use DateTimeImmutable to format * the passed datetime to avoid deprecated warnings on PHP 8.1. We only support converting most * common used format here. */ $dateFormat = self::strftimeFormatToDateFormat($format); if ($dateFormat !== false) { $date = \DateTimeImmutable::createFromFormat('U', strtotime($value)); $inputValue = $date->format($dateFormat); } else { $inputValue = strftime($format, strtotime($value)); } date_default_timezone_set($tz); } else { $inputValue = ''; } $data = [ 'id' => $id, 'name' => $name, 'class' => $class, 'value' => $inputValue, 'format' => $format, 'filter' => $filter, 'required' => $required, 'readonly' => $readonly, 'disabled' => $disabled, 'hint' => $hint, 'autofocus' => $autofocus, 'autocomplete' => $autocomplete, 'todaybutton' => $todayBtn, 'weeknumbers' => $weekNumbers, 'showtime' => $showTime, 'filltable' => $fillTable, 'timeformat' => $timeFormat, 'singleheader' => $singleHeader, 'tag' => $tag, 'helperPath' => $helperPath, 'direction' => $direction, 'onchange' => $onchange, 'minYear' => $minYear, 'maxYear' => $maxYear, 'dataAttribute' => '', 'dataAttributes' => '', 'calendar' => $calendar, 'firstday' => $lang->getFirstDay(), 'weekend' => explode(',', $lang->getWeekEnd()), ]; return LayoutHelper::render('joomla.form.field.calendar', $data, null, null); } /** * Add a directory where HTMLHelper should search for helpers. You may * either pass a string or an array of directories. * * @param string $path A path to search. * * @return array An array with directory elements * * @since 1.5 * @deprecated 4.0 will be removed in 6.0 * Use the service registry instead */ public static function addIncludePath($path = '') { @trigger_error( 'Support for registering lookup paths is deprecated and will be removed in Joomla 5.0, use the service registry instead', E_USER_DEPRECATED ); // Loop through the path directories foreach ((array) $path as $dir) { if (!empty($dir) && !\in_array($dir, static::$includePaths)) { array_unshift(static::$includePaths, Path::clean($dir)); } } return static::$includePaths; } /** * Method that searches if file exists in given path and returns the relative path. If a minified version exists it will be preferred. * * @param string $path The actual path of the file * @param string $ext The extension of the file * @param boolean $debugMode Signifies if debug is enabled * * @return string The relative path of the file * * @since 4.0.0 */ protected static function addFileToBuffer($path = '', $ext = '', $debugMode = false) { $position = strrpos($path, '.min.'); // We are handling a name.min.ext file: if ($position !== false) { $minifiedPath = $path; $nonMinifiedPath = substr_replace($path, '', $position, 4); if ($debugMode) { return self::checkFileOrder($minifiedPath, $nonMinifiedPath); } return self::checkFileOrder($nonMinifiedPath, $minifiedPath); } $minifiedPath = pathinfo($path, PATHINFO_DIRNAME) . '/' . pathinfo($path, PATHINFO_FILENAME) . '.min.' . $ext; if ($debugMode) { return self::checkFileOrder($minifiedPath, $path); } return self::checkFileOrder($path, $minifiedPath); } /** * Method that takes a file path and converts it to a relative path * * @param string $path The actual path of the file * * @return string The relative path of the file * * @since 4.0.0 */ protected static function convertToRelativePath($path) { $relativeFilePath = Uri::root(true) . str_replace(JPATH_ROOT, '', $path); // On windows devices we need to replace "\" with "/" otherwise some browsers will not load the asset return str_replace(DIRECTORY_SEPARATOR, '/', $relativeFilePath); } /** * Method that takes two paths and checks if the files exist with different order * * @param string $first the path of the minified file * @param string $second the path of the non minified file * * @return string * * @since 4.0.0 */ private static function checkFileOrder($first, $second) { if (is_file($second)) { return static::convertToRelativePath($second); } if (is_file($first)) { return static::convertToRelativePath($first); } return ''; } /** * Convert most popular strftime format to php date format as strftime is deprecated and we have * to be able to provide same backward compatibility with existing format strings. * * @param $strftimeformat string The format compatible with strftime. * * @return mixed The format compatible with PHP's Date functions if success, false otherwise * * @since 4.2.9 */ public static function strftimeFormatToDateFormat(string $strftimeformat) { $format = str_replace( [ '%Y', '%m', '%d', '%H', '%M', '%S', ], [ 'Y', 'm', 'd', 'H', 'i', 's', ], $strftimeformat ); /** * If there is % character left after replacing, that mean one of unsupported format is used * the conversion false */ if (strpos($format, '%') !== false) { return false; } return $format; } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.23 | Generation time: 0 |
proxy
|
phpinfo
|
Settings