diff --git a/administrator/components/com_content/src/Field/VotelistField.php b/administrator/components/com_content/src/Field/VotelistField.php index 35ab56c415f7d..7fc097a6d4327 100644 --- a/administrator/components/com_content/src/Field/VotelistField.php +++ b/administrator/components/com_content/src/Field/VotelistField.php @@ -37,7 +37,7 @@ class VotelistField extends ListField * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. * @param mixed $value The form field value to validate. - * @param string $group The field name group control value. This acts as as an array container for the field. + * @param string $group The field name group control value. This acts as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * diff --git a/administrator/components/com_content/src/Field/VoteradioField.php b/administrator/components/com_content/src/Field/VoteradioField.php index 5e02579a8b60a..8c654138ec0df 100644 --- a/administrator/components/com_content/src/Field/VoteradioField.php +++ b/administrator/components/com_content/src/Field/VoteradioField.php @@ -37,7 +37,7 @@ class VoteradioField extends RadioField * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. * @param mixed $value The form field value to validate. - * @param string $group The field name group control value. This acts as as an array container for the field. + * @param string $group The field name group control value. This acts as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * diff --git a/administrator/components/com_content/src/View/Articles/HtmlView.php b/administrator/components/com_content/src/View/Articles/HtmlView.php index fd8be990c4247..5662aa0597568 100644 --- a/administrator/components/com_content/src/View/Articles/HtmlView.php +++ b/administrator/components/com_content/src/View/Articles/HtmlView.php @@ -234,7 +234,6 @@ protected function addToolbar() if ( $user->authorise('core.create', 'com_content') && $user->authorise('core.edit', 'com_content') - && $user->authorise('core.execute.transition', 'com_content') ) { $childBar->popupButton('batch', 'JTOOLBAR_BATCH') ->popupType('inline') diff --git a/administrator/components/com_fields/src/Field/FieldLayoutField.php b/administrator/components/com_fields/src/Field/FieldLayoutField.php index 4eb681fd172f3..95216b097eadb 100644 --- a/administrator/components/com_fields/src/Field/FieldLayoutField.php +++ b/administrator/components/com_fields/src/Field/FieldLayoutField.php @@ -56,9 +56,9 @@ protected function getInput() // Build the query. $query->select('element, name') ->from('#__extensions') - ->where('client_id = 0') - ->where('type = ' . $db->quote('template')) - ->where('enabled = 1'); + ->where($db->quoteName('client_id') . ' = 0') + ->where($db->quoteName('type') . ' = ' . $db->quote('template')) + ->where($db->quoteName('enabled') . ' = 1'); // Set the query and load the templates. $db->setQuery($query); diff --git a/administrator/components/com_users/src/Helper/Mfa.php b/administrator/components/com_users/src/Helper/Mfa.php index 64499ce5efe5a..cc743ce007a98 100644 --- a/administrator/components/com_users/src/Helper/Mfa.php +++ b/administrator/components/com_users/src/Helper/Mfa.php @@ -77,7 +77,7 @@ public static function getConfigurationInterface(User $user): ?string /** @var CMSApplication $app */ $app = Factory::getApplication(); - if (!$app->getInput()->getCmd('option', '') === 'com_users') { + if ($app->getInput()->getCmd('option', '') !== 'com_users') { $app->getLanguage()->load('com_users'); $app->getDocument() ->getWebAssetManager() diff --git a/build/build-modules-js/javascript/compile-to-es2017.es6.js b/build/build-modules-js/javascript/compile-to-es2017.es6.js index 84386773f3cde..b3c005513adb1 100644 --- a/build/build-modules-js/javascript/compile-to-es2017.es6.js +++ b/build/build-modules-js/javascript/compile-to-es2017.es6.js @@ -12,6 +12,13 @@ const { renderSync } = require('sass-embedded'); const { minifyJsCode } = require('./minify.es6.js'); const { getPackagesUnderScope } = require('../init/common/resolve-package.es6.js'); +function esmOrIife(file) { + if (file.endsWith('core.es6.js') || file.endsWith('validate.es6.js')) { + return 'iife'; + } + return 'es'; +} + const getWcMinifiedCss = async (file) => { let scssFileExists = false; const scssFile = file.replace(`${sep}js${sep}`, `${sep}scss${sep}`).replace(/\.w-c\.es6\.js$/, '.scss'); @@ -126,7 +133,7 @@ module.exports.handleESMFile = async (file) => { }); bundle.write({ - format: 'es', + format: esmOrIife(file), sourcemap: false, file: resolve(`${newPath}.js`), }) diff --git a/build/media_source/system/js/core.es6.js b/build/media_source/system/js/core.es6.js index 9707f1a0a9d8d..c55187e4dea63 100644 --- a/build/media_source/system/js/core.es6.js +++ b/build/media_source/system/js/core.es6.js @@ -3,6 +3,8 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ +'use strict'; + import { sanitizeHtml } from 'bootstrap/js/src/util/sanitizer.js'; const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; @@ -56,7 +58,52 @@ const DefaultAllowlist = { // Only define the Joomla namespace if not defined. window.Joomla = window.Joomla || {}; -window.Joomla.Modal = window.Joomla.Modal || { +// Only define editors if not defined +Joomla.editors = Joomla.editors || {}; + +// An object to hold each editor instance on page, only define if not defined. +Joomla.editors.instances = Joomla.editors.instances || { + /** + * ***************************************************************** + * All Editors MUST register, per instance, the following callbacks: + * ***************************************************************** + * + * getValue Type Function Should return the complete data from the editor + * Example: () => { return this.element.value; } + * setValue Type Function Should replace the complete data of the editor + * Example: (text) => { return this.element.value = text; } + * getSelection Type Function Should return the selected text from the editor + * Example: function () { return this.selectedText; } + * disable Type Function Toggles the editor into disabled mode. When the editor is + * active then everything should be usable. When inactive the + * editor should be unusable AND disabled for form validation + * Example: (bool) => { return this.disable = value; } + * replaceSelection Type Function Should replace the selected text of the editor + * If nothing selected, will insert the data at the cursor + * Example: + * (text) => { + * return insertAtCursor(this.element, text); + * } + * + * USAGE (assuming that jform_articletext is the textarea id) + * { + * To get the current editor value: + * Joomla.editors.instances['jform_articletext'].getValue(); + * To set the current editor value: + * Joomla.editors.instances['jform_articletext'].setValue('Joomla! rocks'); + * To replace(selection) or insert a value at the current editor cursor (replaces the J3 + * jInsertEditorText API): + * replaceSelection: + * Joomla.editors.instances['jform_articletext'].replaceSelection('Joomla! rocks') + * } + * + * ********************************************************* + * ANY INTERACTION WITH THE EDITORS SHOULD USE THE ABOVE API + * ********************************************************* + */ +}; + +Joomla.Modal = Joomla.Modal || { /** * ***************************************************************** * Modals should implement @@ -82,670 +129,666 @@ window.Joomla.Modal = window.Joomla.Modal || { */ current: '', setCurrent: (element) => { - window.Joomla.Modal.current = element; + Joomla.Modal.current = element; }, - getCurrent: () => window.Joomla.Modal.current, + getCurrent: () => Joomla.Modal.current, }; -((Joomla) => { - 'use strict'; - +/** + * Method to Extend Objects + * + * @param {Object} destination + * @param {Object} source + * + * @return Object + */ +Joomla.extend = (destination, source) => { + let newDestination = destination; /** - * Method to Extend Objects - * - * @param {Object} destination - * @param {Object} source - * - * @return Object + * Technically null is an object, but trying to treat the destination as one in this + * context will error out. + * So emulate jQuery.extend(), and treat a destination null as an empty object. */ - Joomla.extend = (destination, source) => { - let newDestination = destination; - /** - * Technically null is an object, but trying to treat the destination as one in this - * context will error out. - * So emulate jQuery.extend(), and treat a destination null as an empty object. - */ - if (destination === null) { - newDestination = {}; - } + if (destination === null) { + newDestination = {}; + } - [].slice.call(Object.keys(source)).forEach((key) => { - newDestination[key] = source[key]; - }); + [].slice.call(Object.keys(source)).forEach((key) => { + newDestination[key] = source[key]; + }); - return destination; - }; + return destination; +}; - /** - * Joomla options storage - * - * @type {{}} - * - * @since 3.7.0 - */ - Joomla.optionsStorage = Joomla.optionsStorage || null; +/** + * Joomla options storage + * + * @type {{}} + * + * @since 3.7.0 + */ +Joomla.optionsStorage = Joomla.optionsStorage || null; - /** - * Get script(s) options - * - * @param {String} key Name in Storage - * @param {mixed} def Default value if nothing found - * - * @return {mixed} - * - * @since 3.7.0 - */ - Joomla.getOptions = (key, def) => { - // Load options if they not exists - if (!Joomla.optionsStorage) { - Joomla.loadOptions(); - } +/** + * Get script(s) options + * + * @param {String} key Name in Storage + * @param {mixed} def Default value if nothing found + * + * @return {mixed} + * + * @since 3.7.0 + */ +Joomla.getOptions = (key, def) => { + // Load options if they not exists + if (!Joomla.optionsStorage) { + Joomla.loadOptions(); + } - return Joomla.optionsStorage[key] !== undefined ? Joomla.optionsStorage[key] : def; - }; + return Joomla.optionsStorage[key] !== undefined ? Joomla.optionsStorage[key] : def; +}; - /** - * Load new options from given options object or from Element - * - * @param {Object|undefined} options The options object to load. - * Eg {"com_foobar" : {"option1": 1, "option2": 2}} - * - * @since 3.7.0 - */ - Joomla.loadOptions = (options) => { - // Load form the script container - if (!options) { - const elements = [].slice.call(document.querySelectorAll('.joomla-script-options.new')); - let counter = 0; - - elements.forEach((element) => { - const str = element.text || element.textContent; - const option = JSON.parse(str); - - if (option) { - Joomla.loadOptions(option); - counter += 1; - } +/** + * Load new options from given options object or from Element + * + * @param {Object|undefined} options The options object to load. + * Eg {"com_foobar" : {"option1": 1, "option2": 2}} + * + * @since 3.7.0 + */ +Joomla.loadOptions = (options) => { + // Load form the script container + if (!options) { + const elements = [].slice.call(document.querySelectorAll('.joomla-script-options.new')); + let counter = 0; - element.className = element.className.replace(' new', ' loaded'); - }); + elements.forEach((element) => { + const str = element.text || element.textContent; + const option = JSON.parse(str); - if (counter) { - return; + if (option) { + Joomla.loadOptions(option); + counter += 1; } - } - // Initial loading - if (!Joomla.optionsStorage) { - Joomla.optionsStorage = options || {}; - } else if (options) { - // Merge with existing - [].slice.call(Object.keys(options)).forEach((key) => { - /** - * If both existing and new options are objects, merge them with Joomla.extend(). - * But test for new option being null, as null is an object, but we want to allow - * clearing of options with ... - * - * Joomla.loadOptions({'joomla.jtext': null}); - */ - if (options[key] !== null && typeof Joomla.optionsStorage[key] === 'object' && typeof options[key] === 'object') { - Joomla.optionsStorage[key] = Joomla.extend(Joomla.optionsStorage[key], options[key]); - } else { - Joomla.optionsStorage[key] = options[key]; - } - }); - } - }; + element.className = element.className.replace(' new', ' loaded'); + }); - /** - * Custom behavior for JavaScript I18N in Joomla! 1.6 - * - * @type {{}} - * - * Allows you to call Joomla.Text._() to get a translated JavaScript string - * pushed in with Text::script() in Joomla. - */ - Joomla.Text = { - strings: {}, - - /** - * Translates a string into the current language. - * - * @param {String} key The string to translate - * @param {String} def Default string - * - * @returns {String} - */ - _: (key, def) => { - let newKey = key; - let newDef = def; - // Check for new strings in the optionsStorage, and load them - const newStrings = Joomla.getOptions('joomla.jtext'); - if (newStrings) { - Joomla.Text.load(newStrings); - - // Clean up the optionsStorage from useless data - Joomla.loadOptions({ 'joomla.jtext': null }); + if (counter) { + return; + } + } + + // Initial loading + if (!Joomla.optionsStorage) { + Joomla.optionsStorage = options || {}; + } else if (options) { + // Merge with existing + [].slice.call(Object.keys(options)).forEach((key) => { + /** + * If both existing and new options are objects, merge them with Joomla.extend(). + * But test for new option being null, as null is an object, but we want to allow + * clearing of options with ... + * + * Joomla.loadOptions({'joomla.jtext': null}); + */ + if (options[key] !== null && typeof Joomla.optionsStorage[key] === 'object' && typeof options[key] === 'object') { + Joomla.optionsStorage[key] = Joomla.extend(Joomla.optionsStorage[key], options[key]); + } else { + Joomla.optionsStorage[key] = options[key]; } + }); + } +}; - newDef = newDef === undefined ? newKey : newDef; - newKey = newKey.toUpperCase(); - - return Joomla.Text.strings[newKey] !== undefined ? Joomla.Text.strings[newKey] : newDef; - }, - - /** - * Load new strings in to Joomla.Text - * - * @param {Object} object Object with new strings - * @returns {Joomla.Text} - */ - load: (object) => { - [].slice.call(Object.keys(object)).forEach((key) => { - Joomla.Text.strings[key.toUpperCase()] = object[key]; - }); - - return Joomla.Text; - }, - }; - - /** - * For B/C we still support Joomla.JText - * - * @type {{}} - * - * @deprecated 4.0 will be removed in 6.0 - * Example: Joomla.Text._('...'); - * Joomla.Text.load(...); - */ - Joomla.JText = Joomla.Text; +/** + * Custom behavior for JavaScript I18N in Joomla! 1.6 + * + * @type {{}} + * + * Allows you to call Joomla.Text._() to get a translated JavaScript string + * pushed in with Text::script() in Joomla. + */ +Joomla.Text = { + strings: {}, /** - * Generic submit form + * Translates a string into the current language. * - * @param {String} task The given task - * @param {node} form The form element - * @param {bool} validate The form element + * @param {String} key The string to translate + * @param {String} def Default string * - * @returns {void} + * @returns {String} */ - Joomla.submitform = (task, form, validate) => { - let newForm = form; - const newTask = task; - - if (!newForm) { - newForm = document.getElementById('adminForm'); + _: (key, def) => { + let newKey = key; + let newDef = def; + // Check for new strings in the optionsStorage, and load them + const newStrings = Joomla.getOptions('joomla.jtext'); + if (newStrings) { + Joomla.Text.load(newStrings); + + // Clean up the optionsStorage from useless data + Joomla.loadOptions({ 'joomla.jtext': null }); } - if (newTask) { - newForm.task.value = newTask; - } - - // Toggle HTML5 validation - newForm.noValidate = !validate; - - if (!validate) { - newForm.setAttribute('novalidate', ''); - } else if (newForm.hasAttribute('novalidate')) { - newForm.removeAttribute('novalidate'); - } + newDef = newDef === undefined ? newKey : newDef; + newKey = newKey.toUpperCase(); - // Submit the form. - // Create the input type="submit" - const button = document.createElement('input'); - button.classList.add('hidden'); - button.type = 'submit'; - - // Append it and click it - newForm.appendChild(button).click(); - - // If "submit" was prevented, make sure we don't get a build up of buttons - newForm.removeChild(button); - }; + return Joomla.Text.strings[newKey] !== undefined ? Joomla.Text.strings[newKey] : newDef; + }, /** - * Default function. Can be overridden by the component to add custom logic - * - * @param {String} task The given task - * @param {String} formSelector The form selector eg '#adminForm' - * @param {bool} validate The form element + * Load new strings in to Joomla.Text * - * @returns {void} + * @param {Object} object Object with new strings + * @returns {Joomla.Text} */ - Joomla.submitbutton = (task, formSelector, validate) => { - let form = document.querySelector(formSelector || 'form.form-validate'); - let newValidate = validate; - - if (typeof formSelector === 'string' && form === null) { - form = document.querySelector(`#${formSelector}`); - } + load: (object) => { + [].slice.call(Object.keys(object)).forEach((key) => { + Joomla.Text.strings[key.toUpperCase()] = object[key]; + }); - if (form) { - if (newValidate === undefined || newValidate === null) { - const pressbutton = task.split('.'); - let cancelTask = form.getAttribute('data-cancel-task'); + return Joomla.Text; + }, +}; - if (!cancelTask) { - cancelTask = `${pressbutton[0]}.cancel`; - } +/** + * For B/C we still support Joomla.JText + * + * @type {{}} + * + * @deprecated 4.0 will be removed in 6.0 + * Example: Joomla.Text._('...'); + * Joomla.Text.load(...); + */ +Joomla.JText = Joomla.Text; - newValidate = task !== cancelTask; - } +/** + * Generic submit form + * + * @param {String} task The given task + * @param {node} form The form element + * @param {bool} validate The form element + * + * @returns {void} + */ +Joomla.submitform = (task, form, validate) => { + let newForm = form; + const newTask = task; + + if (!newForm) { + newForm = document.getElementById('adminForm'); + } + + if (newTask) { + newForm.task.value = newTask; + } + + // Toggle HTML5 validation + newForm.noValidate = !validate; + + if (!validate) { + newForm.setAttribute('novalidate', ''); + } else if (newForm.hasAttribute('novalidate')) { + newForm.removeAttribute('novalidate'); + } + + // Submit the form. + // Create the input type="submit" + const button = document.createElement('input'); + button.classList.add('hidden'); + button.type = 'submit'; + + // Append it and click it + newForm.appendChild(button).click(); + + // If "submit" was prevented, make sure we don't get a build up of buttons + newForm.removeChild(button); +}; - if (!newValidate || document.formvalidator.isValid(form)) { - Joomla.submitform(task, form); - } - } else { - Joomla.submitform(task); - } - }; +/** + * Default function. Can be overridden by the component to add custom logic + * + * @param {String} task The given task + * @param {String} formSelector The form selector eg '#adminForm' + * @param {bool} validate The form element + * + * @returns {void} + */ +Joomla.submitbutton = (task, formSelector, validate) => { + let form = document.querySelector(formSelector || 'form.form-validate'); + let newValidate = validate; - /** - * USED IN: all list forms. - * - * Toggles the check state of a group of boxes - * - * Checkboxes must have an id attribute in the form cb0, cb1... - * - * @param {mixed} checkbox The number of box to 'check', for a checkbox element - * @param {string} stub An alternative field name - * - * @return {boolean} - */ - Joomla.checkAll = (checkbox, stub) => { - if (!checkbox.form) { - return false; - } + if (typeof formSelector === 'string' && form === null) { + form = document.querySelector(`#${formSelector}`); + } - const currentStab = stub || 'cb'; - const elements = [].slice.call(checkbox.form.elements); - let state = 0; + if (form) { + if (newValidate === undefined || newValidate === null) { + const pressbutton = task.split('.'); + let cancelTask = form.getAttribute('data-cancel-task'); - elements.forEach((element) => { - if (element.type === checkbox.type && element.id.indexOf(currentStab) === 0) { - element.checked = checkbox.checked; - state += element.checked ? 1 : 0; + if (!cancelTask) { + cancelTask = `${pressbutton[0]}.cancel`; } - }); - if (checkbox.form.boxchecked) { - checkbox.form.boxchecked.value = state; - checkbox.form.boxchecked.dispatchEvent(new CustomEvent('change', { - bubbles: true, - cancelable: true, - })); + newValidate = task !== cancelTask; } - return true; - }; - - /** - * USED IN: administrator/components/com_cache/views/cache/tmpl/default.php - * administrator/components/com_installer/views/discover/tmpl/default_item.php - * administrator/components/com_installer/views/update/tmpl/default_item.php - * administrator/components/com_languages/helpers/html/languages.php - * libraries/joomla/html/html/grid.php - * - * @param {boolean} isitchecked Flag for checked - * @param {node} form The form - * - * @return {void} - */ - Joomla.isChecked = (isitchecked, form) => { - let newForm = form; - if (typeof newForm === 'undefined') { - newForm = document.getElementById('adminForm'); - } else if (typeof form === 'string') { - newForm = document.getElementById(form); + if (!newValidate || document.formvalidator.isValid(form)) { + Joomla.submitform(task, form); } + } else { + Joomla.submitform(task); + } +}; - newForm.boxchecked.value = isitchecked - ? parseInt(newForm.boxchecked.value, 10) + 1 - : parseInt(newForm.boxchecked.value, 10) - 1; +/** + * USED IN: all list forms. + * + * Toggles the check state of a group of boxes + * + * Checkboxes must have an id attribute in the form cb0, cb1... + * + * @param {mixed} checkbox The number of box to 'check', for a checkbox element + * @param {string} stub An alternative field name + * + * @return {boolean} + */ +Joomla.checkAll = (checkbox, stub) => { + if (!checkbox.form) { + return false; + } - newForm.boxchecked.dispatchEvent(new CustomEvent('change', { - bubbles: true, - cancelable: true, - })); + const currentStab = stub || 'cb'; + const elements = [].slice.call(checkbox.form.elements); + let state = 0; - // If we don't have a checkall-toggle, done. - if (!newForm.elements['checkall-toggle']) { - return; + elements.forEach((element) => { + if (element.type === checkbox.type && element.id.indexOf(currentStab) === 0) { + element.checked = checkbox.checked; + state += element.checked ? 1 : 0; } + }); - // Toggle main toggle checkbox depending on checkbox selection - let c = true; - let i; - let e; - let n; + if (checkbox.form.boxchecked) { + checkbox.form.boxchecked.value = state; + checkbox.form.boxchecked.dispatchEvent(new CustomEvent('change', { + bubbles: true, + cancelable: true, + })); + } - // eslint-disable-next-line no-plusplus - for (i = 0, n = newForm.elements.length; i < n; i++) { - e = newForm.elements[i]; + return true; +}; - if (e.type === 'checkbox' && e.name !== 'checkall-toggle' && !e.checked) { - c = false; - break; - } +/** + * USED IN: administrator/components/com_cache/views/cache/tmpl/default.php + * administrator/components/com_installer/views/discover/tmpl/default_item.php + * administrator/components/com_installer/views/update/tmpl/default_item.php + * administrator/components/com_languages/helpers/html/languages.php + * libraries/joomla/html/html/grid.php + * + * @param {boolean} isitchecked Flag for checked + * @param {node} form The form + * + * @return {void} + */ +Joomla.isChecked = (isitchecked, form) => { + let newForm = form; + if (typeof newForm === 'undefined') { + newForm = document.getElementById('adminForm'); + } else if (typeof form === 'string') { + newForm = document.getElementById(form); + } + + newForm.boxchecked.value = isitchecked + ? parseInt(newForm.boxchecked.value, 10) + 1 + : parseInt(newForm.boxchecked.value, 10) - 1; + + newForm.boxchecked.dispatchEvent(new CustomEvent('change', { + bubbles: true, + cancelable: true, + })); + + // If we don't have a checkall-toggle, done. + if (!newForm.elements['checkall-toggle']) { + return; + } + + // Toggle main toggle checkbox depending on checkbox selection + let c = true; + let i; + let e; + let n; + + // eslint-disable-next-line no-plusplus + for (i = 0, n = newForm.elements.length; i < n; i++) { + e = newForm.elements[i]; + + if (e.type === 'checkbox' && e.name !== 'checkall-toggle' && !e.checked) { + c = false; + break; } + } - newForm.elements['checkall-toggle'].checked = c; - }; - - /** - * USED IN: libraries/joomla/html/html/grid.php - * In other words, on any reorderable table - * - * @param {string} order The order value - * @param {string} dir The direction - * @param {string} task The task - * @param {node} form The form - * - * return {void} - */ - Joomla.tableOrdering = (order, dir, task, form) => { - let newForm = form; - if (typeof newForm === 'undefined') { - newForm = document.getElementById('adminForm'); - } else if (typeof form === 'string') { - newForm = document.getElementById(form); - } + newForm.elements['checkall-toggle'].checked = c; +}; - newForm.filter_order.value = order; - newForm.filter_order_Dir.value = dir; - Joomla.submitform(task, newForm); - }; +/** + * USED IN: libraries/joomla/html/html/grid.php + * In other words, on any reorderable table + * + * @param {string} order The order value + * @param {string} dir The direction + * @param {string} task The task + * @param {node} form The form + * + * return {void} + */ +Joomla.tableOrdering = (order, dir, task, form) => { + let newForm = form; + if (typeof newForm === 'undefined') { + newForm = document.getElementById('adminForm'); + } else if (typeof form === 'string') { + newForm = document.getElementById(form); + } + + newForm.filter_order.value = order; + newForm.filter_order_Dir.value = dir; + Joomla.submitform(task, newForm); +}; - /** - * USED IN: all over :) - * - * @param {string} id The id - * @param {string} task The task - * @param {string} form The optional form - * - * @return {boolean} - */ - Joomla.listItemTask = (id, task, form = null) => { - let newForm = form; - if (form !== null) { - newForm = document.getElementById(form); - } else { - newForm = document.adminForm; - } +/** + * USED IN: all over :) + * + * @param {string} id The id + * @param {string} task The task + * @param {string} form The optional form + * + * @return {boolean} + */ +Joomla.listItemTask = (id, task, form = null) => { + let newForm = form; + if (form !== null) { + newForm = document.getElementById(form); + } else { + newForm = document.adminForm; + } + + const cb = newForm[id]; + let i = 0; + let cbx; + + if (!cb) { + return false; + } - const cb = newForm[id]; - let i = 0; - let cbx; + // eslint-disable-next-line no-constant-condition + while (true) { + cbx = newForm[`cb${i}`]; - if (!cb) { - return false; + if (!cbx) { + break; } - // eslint-disable-next-line no-constant-condition - while (true) { - cbx = newForm[`cb${i}`]; + cbx.checked = false; - if (!cbx) { - break; - } + i += 1; + } - cbx.checked = false; + cb.checked = true; + newForm.boxchecked.value = 1; + Joomla.submitform(task, newForm); - i += 1; - } + return false; +}; - cb.checked = true; - newForm.boxchecked.value = 1; - Joomla.submitform(task, newForm); +/** + * Method to replace all request tokens on the page with a new one. + * + * @param {String} newToken The token + * + * Used in Joomla Installation + */ +Joomla.replaceTokens = (newToken) => { + if (!/^[0-9A-F]{32}$/i.test(newToken)) { + return; + } - return false; - }; + const elements = [].slice.call(document.getElementsByTagName('input')); - /** - * Method to replace all request tokens on the page with a new one. - * - * @param {String} newToken The token - * - * Used in Joomla Installation - */ - Joomla.replaceTokens = (newToken) => { - if (!/^[0-9A-F]{32}$/i.test(newToken)) { - return; + elements.forEach((element) => { + if (element.type === 'hidden' && element.value === '1' && element.name.length === 32) { + element.name = newToken; } + }); +}; - const elements = [].slice.call(document.getElementsByTagName('input')); +/** + * Method to perform AJAX request + * + * @param {Object} options Request options: + * { + * url: 'index.php', Request URL + * method: 'GET', Request method GET (default), POST + * data: null, Data to be sent, see + * https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/send + * perform: true, Perform the request immediately + * or return XMLHttpRequest instance and perform it later + * headers: null, Object of custom headers, eg {'X-Foo': 'Bar', 'X-Bar': 'Foo'} + * promise: false Whether return a Promise instance. + * When true then next options is ignored: perform, onSuccess, onError, onComplete + * + * onBefore: (xhr) => {} // Callback on before the request + * onSuccess: (response, xhr) => {}, // Callback on the request success + * onError: (xhr) => {}, // Callback on the request error + * onComplete: (xhr) => {}, // Callback on the request completed, with/without error + * } + * + * @return XMLHttpRequest|Boolean + * + * @example + * + * Joomla.request({ + * url: 'index.php?option=com_example&view=example', + * onSuccess: (response, xhr) => { + * JSON.parse(response); + * } + * }) + * + * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest + */ +Joomla.request = (options) => { + // Prepare the options + const newOptions = Joomla.extend({ + url: '', + method: 'GET', + data: null, + perform: true, + promise: false, + }, options); + + // Setup XMLHttpRequest instance + const createRequest = (onSuccess, onError) => { + const xhr = new XMLHttpRequest(); + + xhr.open(newOptions.method, newOptions.url, true); + + // Set the headers + xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + xhr.setRequestHeader('X-Ajax-Engine', 'Joomla!'); + + if (newOptions.method !== 'GET') { + const token = Joomla.getOptions('csrf.token', ''); + + // Use the CSRF only on the site's domain + if ( + token && ( + (!newOptions.url.startsWith('http:') && !newOptions.url.startsWith('https:')) + || newOptions.url.startsWith(window.location.origin) + ) + ) { + xhr.setRequestHeader('X-CSRF-Token', token); + } - elements.forEach((element) => { - if (element.type === 'hidden' && element.value === '1' && element.name.length === 32) { - element.name = newToken; + if (typeof newOptions.data === 'string' && (!newOptions.headers || !newOptions.headers['Content-Type'])) { + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); } - }); - }; + } - /** - * Method to perform AJAX request - * - * @param {Object} options Request options: - * { - * url: 'index.php', Request URL - * method: 'GET', Request method GET (default), POST - * data: null, Data to be sent, see - * https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/send - * perform: true, Perform the request immediately - * or return XMLHttpRequest instance and perform it later - * headers: null, Object of custom headers, eg {'X-Foo': 'Bar', 'X-Bar': 'Foo'} - * promise: false Whether return a Promise instance. - * When true then next options is ignored: perform, onSuccess, onError, onComplete - * - * onBefore: (xhr) => {} // Callback on before the request - * onSuccess: (response, xhr) => {}, // Callback on the request success - * onError: (xhr) => {}, // Callback on the request error - * onComplete: (xhr) => {}, // Callback on the request completed, with/without error - * } - * - * @return XMLHttpRequest|Boolean - * - * @example - * - * Joomla.request({ - * url: 'index.php?option=com_example&view=example', - * onSuccess: (response, xhr) => { - * JSON.parse(response); - * } - * }) - * - * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest - */ - Joomla.request = (options) => { - // Prepare the options - const newOptions = Joomla.extend({ - url: '', - method: 'GET', - data: null, - perform: true, - promise: false, - }, options); - - // Setup XMLHttpRequest instance - const createRequest = (onSuccess, onError) => { - const xhr = new XMLHttpRequest(); - - xhr.open(newOptions.method, newOptions.url, true); - - // Set the headers - xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - xhr.setRequestHeader('X-Ajax-Engine', 'Joomla!'); - - if (newOptions.method !== 'GET') { - const token = Joomla.getOptions('csrf.token', ''); - - // Use the CSRF only on the site's domain - if ( - token && ( - (!newOptions.url.startsWith('http:') && !newOptions.url.startsWith('https:')) - || newOptions.url.startsWith(window.location.origin) - ) - ) { - xhr.setRequestHeader('X-CSRF-Token', token); - } + // Custom headers + if (newOptions.headers) { + [].slice.call(Object.keys(newOptions.headers)).forEach((key) => { + // Allow request without Content-Type + // eslint-disable-next-line no-empty + if (key === 'Content-Type' && newOptions.headers['Content-Type'] === 'false') { - if (typeof newOptions.data === 'string' && (!newOptions.headers || !newOptions.headers['Content-Type'])) { - xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + } else { + xhr.setRequestHeader(key, newOptions.headers[key]); } - } + }); + } - // Custom headers - if (newOptions.headers) { - [].slice.call(Object.keys(newOptions.headers)).forEach((key) => { - // Allow request without Content-Type - // eslint-disable-next-line no-empty - if (key === 'Content-Type' && newOptions.headers['Content-Type'] === 'false') { - - } else { - xhr.setRequestHeader(key, newOptions.headers[key]); - } - }); + xhr.onreadystatechange = () => { + // Request not finished + if (xhr.readyState !== 4) { + return; } - xhr.onreadystatechange = () => { - // Request not finished - if (xhr.readyState !== 4) { - return; - } - - // Request finished and response is ready - if (xhr.status === 200) { - if (newOptions.promise) { - // A Promise accepts only one argument - onSuccess.call(window, xhr); - } else { - onSuccess.call(window, xhr.responseText, xhr); - } + // Request finished and response is ready + if (xhr.status === 200) { + if (newOptions.promise) { + // A Promise accepts only one argument + onSuccess.call(window, xhr); } else { - onError.call(window, xhr); + onSuccess.call(window, xhr.responseText, xhr); } - - if (newOptions.onComplete && !newOptions.promise) { - newOptions.onComplete.call(window, xhr); - } - }; - - // Do request - if (newOptions.perform) { - if (newOptions.onBefore && newOptions.onBefore.call(window, xhr) === false) { - // Request interrupted - if (newOptions.promise) { - onSuccess.call(window, xhr); - } - return xhr; - } - - xhr.send(newOptions.data); + } else { + onError.call(window, xhr); } - return xhr; + if (newOptions.onComplete && !newOptions.promise) { + newOptions.onComplete.call(window, xhr); + } }; - // Return a Promise - if (newOptions.promise) { - return new Promise((resolve, reject) => { - newOptions.perform = true; - createRequest(resolve, reject); - }); - } + // Do request + if (newOptions.perform) { + if (newOptions.onBefore && newOptions.onBefore.call(window, xhr) === false) { + // Request interrupted + if (newOptions.promise) { + onSuccess.call(window, xhr); + } + return xhr; + } - // Return a Request - try { - return createRequest(newOptions.onSuccess || (() => {}), newOptions.onError || (() => {})); - } catch (error) { - // eslint-disable-next-line no-unused-expressions,no-console - console.error(error); - return false; + xhr.send(newOptions.data); } + + return xhr; }; - let lastRequestPromise; + // Return a Promise + if (newOptions.promise) { + return new Promise((resolve, reject) => { + newOptions.perform = true; + createRequest(resolve, reject); + }); + } + + // Return a Request + try { + return createRequest(newOptions.onSuccess || (() => {}), newOptions.onError || (() => {})); + } catch (error) { + // eslint-disable-next-line no-unused-expressions,no-console + console.error(error); + return false; + } +}; - /** - * Joomla Request queue. - * - * A FIFO queue of requests to execute serially. Used to prevent simultaneous execution of - * multiple requests against the server which could trigger its Denial of Service protection. - * - * @param {object} options Options for Joomla.request() - * @returns {Promise} - */ - Joomla.enqueueRequest = (options) => { - if (!options.promise) { - throw new Error('Joomla.enqueueRequest supports only Joomla.request as Promise'); - } - if (!lastRequestPromise) { - lastRequestPromise = Joomla.request(options); - } else { - lastRequestPromise = lastRequestPromise.then(() => Joomla.request(options)); - } - return lastRequestPromise; - }; +let lastRequestPromise; - /** - * - * @param {string} unsafeHtml The html for sanitization - * @param {object} allowList The list of HTMLElements with an array of allowed attributes - * @param {function} sanitizeFn A custom sanitization function - * - * @return string - */ - Joomla.sanitizeHtml = (unsafeHtml, allowList, sanitizeFn) => { - const allowed = (allowList === undefined || allowList === null) - ? DefaultAllowlist : { ...DefaultAllowlist, ...allowList }; - return sanitizeHtml(unsafeHtml, allowed, sanitizeFn); - }; +/** + * Joomla Request queue. + * + * A FIFO queue of requests to execute serially. Used to prevent simultaneous execution of + * multiple requests against the server which could trigger its Denial of Service protection. + * + * @param {object} options Options for Joomla.request() + * @returns {Promise} + */ +Joomla.enqueueRequest = (options) => { + if (!options.promise) { + throw new Error('Joomla.enqueueRequest supports only Joomla.request as Promise'); + } + if (!lastRequestPromise) { + lastRequestPromise = Joomla.request(options); + } else { + lastRequestPromise = lastRequestPromise.then(() => Joomla.request(options)); + } + return lastRequestPromise; +}; - /** - * Treat AJAX errors. - * Used by some javascripts such as sendtestmail.js and permissions.js - * - * @param {object} xhr XHR object. - * @param {string} textStatus Type of error that occurred. - * @param {string} error Textual portion of the HTTP status. - * - * @return {object} JavaScript object containing the system error message. - * - * @since 3.6.0 - */ - Joomla.ajaxErrorsMessages = (xhr, textStatus) => { - const msg = {}; +/** + * + * @param {string} unsafeHtml The html for sanitization + * @param {object} allowList The list of HTMLElements with an array of allowed attributes + * @param {function} sanitizeFn A custom sanitization function + * + * @return string + */ +Joomla.sanitizeHtml = (unsafeHtml, allowList, sanitizeFn) => { + const allowed = (allowList === undefined || allowList === null) + ? DefaultAllowlist : { ...DefaultAllowlist, ...allowList }; + return sanitizeHtml(unsafeHtml, allowed, sanitizeFn); +}; - if (textStatus === 'parsererror') { - // For jQuery jqXHR - const buf = []; +/** + * Treat AJAX errors. + * Used by some javascripts such as sendtestmail.js and permissions.js + * + * @param {object} xhr XHR object. + * @param {string} textStatus Type of error that occurred. + * @param {string} error Textual portion of the HTTP status. + * + * @return {object} JavaScript object containing the system error message. + * + * @since 3.6.0 + */ +Joomla.ajaxErrorsMessages = (xhr, textStatus) => { + const msg = {}; - // Html entity encode. - let encodedJson = xhr.responseText.trim(); + if (textStatus === 'parsererror') { + // For jQuery jqXHR + const buf = []; - // eslint-disable-next-line no-plusplus - for (let i = encodedJson.length - 1; i >= 0; i--) { - buf.unshift(['&#', encodedJson[i].charCodeAt(), ';'].join('')); - } + // Html entity encode. + let encodedJson = xhr.responseText.trim(); - encodedJson = buf.join(''); - - msg.error = [Joomla.Text._('JLIB_JS_AJAX_ERROR_PARSE').replace('%s', encodedJson)]; - } else if (textStatus === 'nocontent') { - msg.error = [Joomla.Text._('JLIB_JS_AJAX_ERROR_NO_CONTENT')]; - } else if (textStatus === 'timeout') { - msg.error = [Joomla.Text._('JLIB_JS_AJAX_ERROR_TIMEOUT')]; - } else if (textStatus === 'abort') { - msg.error = [Joomla.Text._('JLIB_JS_AJAX_ERROR_CONNECTION_ABORT')]; - } else if (xhr.responseJSON && xhr.responseJSON.message) { - // For vanilla XHR - msg.error = [`${Joomla.Text._('JLIB_JS_AJAX_ERROR_OTHER').replace('%s', xhr.status)} ${xhr.responseJSON.message}`]; - } else if (xhr.statusText) { - msg.error = [`${Joomla.Text._('JLIB_JS_AJAX_ERROR_OTHER').replace('%s', xhr.status)} ${xhr.statusText}`]; - } else { - msg.error = [Joomla.Text._('JLIB_JS_AJAX_ERROR_OTHER').replace('%s', xhr.status)]; + // eslint-disable-next-line no-plusplus + for (let i = encodedJson.length - 1; i >= 0; i--) { + buf.unshift(['&#', encodedJson[i].charCodeAt(), ';'].join('')); } - return msg; - }; -})(Joomla); + encodedJson = buf.join(''); + + msg.error = [Joomla.Text._('JLIB_JS_AJAX_ERROR_PARSE').replace('%s', encodedJson)]; + } else if (textStatus === 'nocontent') { + msg.error = [Joomla.Text._('JLIB_JS_AJAX_ERROR_NO_CONTENT')]; + } else if (textStatus === 'timeout') { + msg.error = [Joomla.Text._('JLIB_JS_AJAX_ERROR_TIMEOUT')]; + } else if (textStatus === 'abort') { + msg.error = [Joomla.Text._('JLIB_JS_AJAX_ERROR_CONNECTION_ABORT')]; + } else if (xhr.responseJSON && xhr.responseJSON.message) { + // For vanilla XHR + msg.error = [`${Joomla.Text._('JLIB_JS_AJAX_ERROR_OTHER').replace('%s', xhr.status)} ${xhr.responseJSON.message}`]; + } else if (xhr.statusText) { + msg.error = [`${Joomla.Text._('JLIB_JS_AJAX_ERROR_OTHER').replace('%s', xhr.status)} ${xhr.statusText}`]; + } else { + msg.error = [Joomla.Text._('JLIB_JS_AJAX_ERROR_OTHER').replace('%s', xhr.status)]; + } + + return msg; +}; diff --git a/build/media_source/system/js/fields/validate.es6.js b/build/media_source/system/js/fields/validate.es6.js index 5412dc52bd15f..7a6dc220b071b 100644 --- a/build/media_source/system/js/fields/validate.es6.js +++ b/build/media_source/system/js/fields/validate.es6.js @@ -3,6 +3,8 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ +'use strict'; + import punycode from 'punycode'; class JFormValidator { @@ -333,3 +335,10 @@ const initialize = () => { }; document.addEventListener('DOMContentLoaded', initialize); + +/** + * Expose the classes to the global scope + * These will be removed in Joomla! 6.0 + */ +window.JFormValidator = JFormValidator; +window.punycode = punycode; diff --git a/build/media_source/system/js/multiselect.es6.js b/build/media_source/system/js/multiselect.es6.js index 46af672389fab..fb07448bf7f81 100644 --- a/build/media_source/system/js/multiselect.es6.js +++ b/build/media_source/system/js/multiselect.es6.js @@ -46,10 +46,8 @@ class JMultiSelect { // Handle click on a row onRowClick({ target, shiftKey }) { - // Do not interfere with links, buttons, inputs - if (target.tagName && (target.tagName === 'A' || target.tagName === 'BUTTON' - || target.tagName === 'SELECT' || target.tagName === 'TEXTAREA' - || (target.tagName === 'INPUT' && !target.matches(this.boxSelector)))) { + // Do not interfere with links, buttons, inputs and other interactive elements + if (target.closest('a, button, input, select, textarea, details, dialog, audio, video')) { return; } diff --git a/build/media_source/templates/administrator/atum/js/template.es6.js b/build/media_source/templates/administrator/atum/js/template.es6.js index fe1266dba6a43..2e97ef31fc0b8 100644 --- a/build/media_source/templates/administrator/atum/js/template.es6.js +++ b/build/media_source/templates/administrator/atum/js/template.es6.js @@ -286,3 +286,20 @@ window.addEventListener('joomla:menu-toggle', (event) => { changeLogo(event.detail); } }); + +/** + * Close any open data-bs-toggle="collapse" when opening a data-bs-toggle="dropdown" + * + * @since 4.4 + */ +document.querySelectorAll('[data-bs-toggle="dropdown"]').forEach((button) => { + button.addEventListener('click', () => { + document.querySelectorAll('[data-bs-toggle="collapse"]').forEach((cb) => { + const target = document.querySelector(cb.getAttribute('data-bs-target')); + const collapseMenu = bootstrap.Collapse.getInstance(target) || new bootstrap.Collapse(target, { + toggle: false, + }); + collapseMenu.hide(); + }); + }); +}); diff --git a/build/media_source/templates/site/cassiopeia/scss/blocks/_header.scss b/build/media_source/templates/site/cassiopeia/scss/blocks/_header.scss index ece7792b12ba3..34271e4aa36ce 100644 --- a/build/media_source/templates/site/cassiopeia/scss/blocks/_header.scss +++ b/build/media_source/templates/site/cassiopeia/scss/blocks/_header.scss @@ -204,6 +204,10 @@ .fas { font-size: 1.5rem; } + + > * { + pointer-events: none; + } } .container-search { diff --git a/build/media_source/templates/site/cassiopeia/scss/blocks/_toolbar.scss b/build/media_source/templates/site/cassiopeia/scss/blocks/_toolbar.scss index 9ce695bdda44c..d9ca1c7652498 100644 --- a/build/media_source/templates/site/cassiopeia/scss/blocks/_toolbar.scss +++ b/build/media_source/templates/site/cassiopeia/scss/blocks/_toolbar.scss @@ -119,6 +119,10 @@ &.btn { padding-inline-end: 0; } + + > * { + pointer-events: none; + } } .btn-group:not(:last-child) > .dropdown-toggle-split { diff --git a/installation/src/Form/Field/Installation/LanguageField.php b/installation/src/Form/Field/Installation/LanguageField.php index dc80d658e7ab0..20b86e57b132e 100644 --- a/installation/src/Form/Field/Installation/LanguageField.php +++ b/installation/src/Form/Field/Installation/LanguageField.php @@ -38,7 +38,7 @@ class LanguageField extends ListField * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. * @param mixed $value The form field value to validate. - * @param string $group The field name group control value. This acts as as an array container for the field. + * @param string $group The field name group control value. This acts as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * diff --git a/layouts/joomla/form/field/text.php b/layouts/joomla/form/field/text.php index cba5f453b9e6f..4dcaf2c4fce1f 100644 --- a/layouts/joomla/form/field/text.php +++ b/layouts/joomla/form/field/text.php @@ -95,7 +95,7 @@ !empty($pattern) ? 'pattern="' . $pattern . '"' : '', // @TODO add a proper string here!!! - !empty($validationtext) ? 'data-validation-text="' . $validationtext . '"' : '', + !empty($validationtext) ? 'data-validation-text="' . $this->escape(Text::_($validationtext)) . '"' : '', ]; $addonBeforeHtml = '' . Text::_($addonBefore) . ''; diff --git a/libraries/src/Captcha/Captcha.php b/libraries/src/Captcha/Captcha.php index a5b673de074a8..260e81f1cc922 100644 --- a/libraries/src/Captcha/Captcha.php +++ b/libraries/src/Captcha/Captcha.php @@ -51,7 +51,7 @@ class Captcha implements DispatcherAwareInterface private $provider; /** - * Editor Plugin name + * Captcha Plugin name * * @var string * @since 2.5 @@ -281,10 +281,10 @@ private function _load(array $options = []) // Build the path to the needed captcha plugin $name = InputFilter::getInstance()->clean($this->name, 'cmd'); - // Boot the editor plugin + // Boot the captcha plugin $this->captcha = Factory::getApplication()->bootPlugin($name, 'captcha'); - // Check if the editor can be loaded + // Check if the captcha can be loaded if (!$this->captcha) { throw new \RuntimeException(Text::sprintf('JLIB_CAPTCHA_ERROR_PLUGIN_NOT_FOUND', $name)); } diff --git a/libraries/src/Form/Field/SqlField.php b/libraries/src/Form/Field/SqlField.php index cb1bd4aeaacee..9a3893cdc2519 100644 --- a/libraries/src/Form/Field/SqlField.php +++ b/libraries/src/Form/Field/SqlField.php @@ -233,12 +233,21 @@ protected function processQuery($conditions, $filters, $defaults) // Process the filters if (\is_array($filters)) { - $html_filters = Factory::getApplication()->getUserStateFromRequest($this->context . '.filter', 'filter', [], 'array'); + // @TODO: Loading the filtering value from the request need to be deprecated. + $html_filters = $this->context ? Factory::getApplication()->getUserStateFromRequest($this->context . '.filter', 'filter', [], 'array') : false; + $form = $this->form; foreach ($filters as $k => $value) { - if (!empty($html_filters[$value])) { + // Get the filter value from the linked filter field + $filterFieldValue = $form->getValue($value, $this->group); + + if ($html_filters && !empty($html_filters[$value])) { $escape = $db->quote($db->escape($html_filters[$value]), false); + $query->where("{$value} = {$escape}"); + } elseif ($filterFieldValue !== null) { + $escape = $db->quote($db->escape($filterFieldValue), false); + $query->where("{$value} = {$escape}"); } elseif (!empty($defaults[$value])) { $escape = $db->quote($db->escape($defaults[$value]), false); diff --git a/libraries/src/Form/Field/TransitionField.php b/libraries/src/Form/Field/TransitionField.php index 3a064d6df550a..0ffdccec55498 100644 --- a/libraries/src/Form/Field/TransitionField.php +++ b/libraries/src/Form/Field/TransitionField.php @@ -53,7 +53,7 @@ class TransitionField extends GroupedlistField * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. * @param mixed $value The form field value to validate. - * @param string $group The field name group control value. This acts as as an array container for the field. + * @param string $group The field name group control value. This acts as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * diff --git a/libraries/src/Form/Field/WorkflowconditionField.php b/libraries/src/Form/Field/WorkflowconditionField.php index 55a07674afe8a..b0aacdc21598e 100644 --- a/libraries/src/Form/Field/WorkflowconditionField.php +++ b/libraries/src/Form/Field/WorkflowconditionField.php @@ -53,7 +53,7 @@ class WorkflowconditionField extends ListField * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. * @param mixed $value The form field value to validate. - * @param string $group The field name group control value. This acts as as an array container for the field. + * @param string $group The field name group control value. This acts as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * diff --git a/libraries/src/Form/Field/WorkflowstageField.php b/libraries/src/Form/Field/WorkflowstageField.php index 0651d32416848..6145028899086 100644 --- a/libraries/src/Form/Field/WorkflowstageField.php +++ b/libraries/src/Form/Field/WorkflowstageField.php @@ -53,7 +53,7 @@ class WorkflowstageField extends GroupedlistField * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. * @param mixed $value The form field value to validate. - * @param string $group The field name group control value. This acts as as an array container for the field. + * @param string $group The field name group control value. This acts as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * diff --git a/libraries/src/Form/FormField.php b/libraries/src/Form/FormField.php index 36f3e90c0f6b8..0be3179f1ccc1 100644 --- a/libraries/src/Form/FormField.php +++ b/libraries/src/Form/FormField.php @@ -627,7 +627,7 @@ public function setForm(Form $form) * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. * @param mixed $value The form field value to validate. - * @param string $group The field name group control value. This acts as as an array container for the field. + * @param string $group The field name group control value. This acts as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * diff --git a/libraries/src/Form/FormRule.php b/libraries/src/Form/FormRule.php index 0214326571bb6..c6e916df06258 100644 --- a/libraries/src/Form/FormRule.php +++ b/libraries/src/Form/FormRule.php @@ -58,7 +58,7 @@ class FormRule * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. * @param mixed $value The form field value to validate. - * @param string $group The field name group control value. This acts as as an array container for the field. + * @param string $group The field name group control value. This acts as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * @param ?Registry $input An optional Registry object with the entire data set to validate against the entire form. diff --git a/libraries/src/Form/Rule/SubformRule.php b/libraries/src/Form/Rule/SubformRule.php index 6a822763a0c89..b24b4cd512c82 100644 --- a/libraries/src/Form/Rule/SubformRule.php +++ b/libraries/src/Form/Rule/SubformRule.php @@ -30,7 +30,7 @@ class SubformRule extends FormRule * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `` tag for the form field object. * @param mixed $value The form field value to validate. - * @param string $group The field name group control value. This acts as as an array container for the field. + * @param string $group The field name group control value. This acts as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * @param ?Registry $input An optional Registry object with the entire data set to validate against the entire form. diff --git a/plugins/content/vote/tmpl/rating.php b/plugins/content/vote/tmpl/rating.php index e0f2a78b290ca..df37497f05e55 100644 --- a/plugins/content/vote/tmpl/rating.php +++ b/plugins/content/vote/tmpl/rating.php @@ -79,8 +79,7 @@ ?>