diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000000..fbb91302cfb5a --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,9 @@ +# Short array syntax change https://github.com/joomla/joomla-cms/pull/39616 +10f250f418851674c2e4104b6b39b9b665496544 + +# Code style fixes from PHP CS fixer https://github.com/joomla/joomla-cms/pull/39745 +1e7527b60ec42032abe7bfb9c000bacf38f65845 + +# PSR 12 +dd91072a956a19a43798515239892edd2b49ac7b +e7f5cc182bb1cd39c7f085d529888ac4fa6fc77e diff --git a/administrator/components/com_admin/sql/updates/mysql/4.4.0-2023-05-08.sql b/administrator/components/com_admin/sql/updates/mysql/4.4.0-2023-05-08.sql new file mode 100644 index 0000000000000..4c621665e1d7c --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/4.4.0-2023-05-08.sql @@ -0,0 +1,2 @@ +INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) VALUES + (0, 'plg_quickicon_eos', 'plugin', 'eos', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 7, 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/4.4.0-2023-05-08.sql b/administrator/components/com_admin/sql/updates/postgresql/4.4.0-2023-05-08.sql new file mode 100644 index 0000000000000..46f7bf62de406 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/4.4.0-2023-05-08.sql @@ -0,0 +1,2 @@ +INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") VALUES + (0, 'plg_quickicon_eos', 'plugin', 'eos', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 7, 0); diff --git a/administrator/components/com_banners/src/Model/BannerModel.php b/administrator/components/com_banners/src/Model/BannerModel.php index 9ed2672ff51ed..ab620973e81a0 100644 --- a/administrator/components/com_banners/src/Model/BannerModel.php +++ b/administrator/components/com_banners/src/Model/BannerModel.php @@ -75,7 +75,7 @@ class BannerModel extends AdminModel * * @return void * - * @since __DEPLOY_VERSION__ + * @since 4.3.2 */ protected function cleanupPostBatchCopy(TableInterface $table, $newId, $oldId) { diff --git a/administrator/language/en-GB/plg_quickicon_eos.ini b/administrator/language/en-GB/plg_quickicon_eos.ini new file mode 100644 index 0000000000000..f4af7d0ce7683 --- /dev/null +++ b/administrator/language/en-GB/plg_quickicon_eos.ini @@ -0,0 +1,39 @@ +; Joomla! Project +; (C) 2023 Open Source Matters, Inc. +; License GNU General Public License version 2 or later; see LICENSE.txt +; Note : All ini files need to be saved as UTF-8 + +PLG_QUICKICON_EOS="Quick Icon - Joomla! End Of Support Notification" +PLG_QUICKICON_EOS_GROUPNAME_EOS="End Of Support" +PLG_QUICKICON_EOS_GROUPNAME_INFO="Upgrade Information" +PLG_QUICKICON_EOS_GROUPNAME_WARNING="Support Status" +PLG_QUICKICON_EOS_MESSAGE_ERROR_SUPPORT_ENDED="

Support has ended for your version of Joomla. Migrate to the next version as soon as possible.

" +PLG_QUICKICON_EOS_MESSAGE_ERROR_SUPPORT_ENDED_SHORT="Support has ended for your version of Joomla " +PLG_QUICKICON_EOS_MESSAGE_INFO_01="

The latest version of Joomla has arrived! Find out all that it has to offer you. Check the landing page for its features and improvements.

" +PLG_QUICKICON_EOS_MESSAGE_INFO_01_SHORT="The latest version of Joomla has arrived! " +PLG_QUICKICON_EOS_MESSAGE_INFO_02="

When is the time to migrate to the next version? Once the extensions your site needs are compatible. Learn how to use the Pre-Update Checker.

" +PLG_QUICKICON_EOS_MESSAGE_INFO_02_SHORT="Use Pre-Update Check for extension compatibility " +PLG_QUICKICON_EOS_MESSAGE_WARNING_SECURITY_ONLY="

This version of Joomla has entered security only mode. Support ends %1$s. Start planning to migrate to the next version of Joomla today.

" +PLG_QUICKICON_EOS_MESSAGE_WARNING_SECURITY_ONLY_SHORT="This version of Joomla ends support on %1$s. " +PLG_QUICKICON_EOS_MESSAGE_WARNING_SUPPORT_ENDING="

Support ends on %1$s for this version of Joomla. Migrate to the latest version of Joomla as soon as possible.

" +PLG_QUICKICON_EOS_MESSAGE_WARNING_SUPPORT_ENDING_SHORT="End of support for this version of Joomla on %1$s. " +PLG_QUICKICON_EOS_SNOOZE_BUTTON="Snooze this message for all users" +PLG_QUICKICON_EOS_XML_DESCRIPTION="Checks for the end of support status of Joomla and notifies you when visiting the Control Panel page." +; Below is a copy of the 3.10 text definitions for reference. +PLG_QUICKICON_EOS310="Quick Icon - Joomla 3.10 End Of Support Notification" +PLG_QUICKICON_EOS310_GROUPNAME_EOS="End Of Support" +PLG_QUICKICON_EOS310_GROUPNAME_INFO="Upgrade Information" +PLG_QUICKICON_EOS310_GROUPNAME_WARNING="Support Status" +PLG_QUICKICON_EOS310_MESSAGE_ERROR_SUPPORT_ENDED="

Support has ended for your version of Joomla 3.10. Migrate to Joomla 4 as soon as possible.

" +PLG_QUICKICON_EOS310_MESSAGE_ERROR_SUPPORT_ENDED_SHORT="Support has ended for Joomla 3.10 " +PLG_QUICKICON_EOS310_MESSAGE_INFO_01="

Joomla 4 has arrived! Find out all that Joomla 4 has to offer you. Check the landing page for Joomla 4 features and improvements.

" +PLG_QUICKICON_EOS310_MESSAGE_INFO_01_SHORT="Joomla 4 has arrived! " +PLG_QUICKICON_EOS310_MESSAGE_INFO_02="

When is the time to migrate to Joomla 4? Once the extensions your site needs are compatible. Learn how to use the Pre-Update Checker.

" +PLG_QUICKICON_EOS310_MESSAGE_INFO_02_SHORT="Use Pre-Update Check for extension compatibility " +PLG_QUICKICON_EOS310_MESSAGE_WARNING_SECURITY_ONLY="

Joomla 3.10 has entered security only mode. Support ends %1$s. Start planning to migrate to Joomla 4 today.

" +PLG_QUICKICON_EOS310_MESSAGE_WARNING_SECURITY_ONLY_SHORT="Joomla 3.10 to end support on %1$s. " +PLG_QUICKICON_EOS310_MESSAGE_WARNING_SUPPORT_ENDING="

Support ends on %1$s for Joomla 3.10. Migrate to Joomla 4 as soon as possible.

" +PLG_QUICKICON_EOS310_MESSAGE_WARNING_SUPPORT_ENDING_SHORT="End of support for Joomla 3.10 on %1$s. " +PLG_QUICKICON_EOS310_SNOOZE_BUTTON="Snooze this message for all users" +PLG_QUICKICON_EOS310_XML_DESCRIPTION="Checks for the end of support status of Joomla 3.10 and notifies you when visiting the Control Panel page." +;All of this text is currently being written for Joomla 5 by Phil Watson and Jenn Gress. TODO diff --git a/administrator/language/en-GB/plg_quickicon_eos.sys.ini b/administrator/language/en-GB/plg_quickicon_eos.sys.ini new file mode 100644 index 0000000000000..9e3b85198e25a --- /dev/null +++ b/administrator/language/en-GB/plg_quickicon_eos.sys.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2023 Open Source Matters, Inc. +; License GNU General Public License version 2 or later; see LICENSE.txt +; Note : All ini files need to be saved as UTF-8 + +PLG_QUICKICON_EOS="Quick Icon - Joomla! End Of Support Notification" +PLG_QUICKICON_EOS_XML_DESCRIPTION="Checks for the end of support status of Joomla and places a notification on the Control Panel page." diff --git a/build/media_source/com_users/js/two-factor-focus.es6.js b/build/media_source/com_users/js/two-factor-focus.es6.js index 9ef99e6e6b0a8..04292d3fbcc97 100644 --- a/build/media_source/com_users/js/two-factor-focus.es6.js +++ b/build/media_source/com_users/js/two-factor-focus.es6.js @@ -9,7 +9,7 @@ document.addEventListener('DOMContentLoaded', () => { const elCodeField = document.getElementById('users-mfa-code'); const elValidateButton = document.getElementById('users-mfa-captive-button-submit'); - const elToolbarCustomElement = document.getElementById('toolbar-user-mfa-submit'); + const elToolbarButton = document.getElementById('toolbar-user-mfa-submit')?.querySelector('button'); // Focus the code field. If the code field is hidden, focus the submit button (useful e.g. for WebAuthn) if ( @@ -21,8 +21,8 @@ if (elValidateButton) { elValidateButton.focus(); } - if (elToolbarCustomElement) { - elToolbarCustomElement.querySelector('button').focus(); + if (elToolbarButton) { + elToolbarButton.focus(); } } diff --git a/build/media_source/plg_quickicon_eos/js/snooze.es6.js b/build/media_source/plg_quickicon_eos/js/snooze.es6.js new file mode 100644 index 0000000000000..cda59294cbbcd --- /dev/null +++ b/build/media_source/plg_quickicon_eos/js/snooze.es6.js @@ -0,0 +1,37 @@ +/** + * @package Joomla.Plugin + * @subpackage Quickicon.eos + * @copyright (C) 2023 Open Source Matters, Inc. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ +if (!Joomla) { + throw new Error('Joomla API is not properly initialised'); +} + +const url = new URL(`${Joomla.getOptions('system.paths').baseFull}index.php?option=com_ajax&group=quickicon&plugin=eos&format=json`); + +async function onMutatedMessagesContainer(mutationList, observer) { + // eslint-disable-next-line no-restricted-syntax + for (const mutation of mutationList) { + const nodes = Array.from(mutation.addedNodes); + if (!nodes.length) { + return; + } + + const alerts = nodes.filter((node) => node.querySelector('.eosnotify-snooze-btn')); + if (!alerts.length) { + return; + } + + observer.disconnect(); + alerts[0].querySelector('.eosnotify-snooze-btn').addEventListener('click', () => fetch(url, { headers: { 'X-CSRF-Token': Joomla.getOptions('csrf.token') || '' } }) + .then((response) => { + if (response.ok) { + alerts[0].closest('joomla-alert').close(); + } + })); + } +} + +const observer = new MutationObserver(onMutatedMessagesContainer); +observer.observe(document.querySelector('#system-message-container'), { attributes: false, childList: true, subtree: true }); diff --git a/build/media_source/system/js/list-view.es6.js b/build/media_source/system/js/list-view.es6.js index f70366e205f31..28d18bd6eaedb 100644 --- a/build/media_source/system/js/list-view.es6.js +++ b/build/media_source/system/js/list-view.es6.js @@ -89,8 +89,18 @@ function applyIsChecked(event) { } } -document.querySelectorAll('.js-grid-item-check-all').forEach((element) => element.addEventListener('click', (event) => Joomla.checkAll(event.target))); -document.querySelectorAll('.js-grid-item-is-checked').forEach((element) => element.addEventListener('click', applyIsChecked)); -document.querySelectorAll('.js-grid-item-action').forEach((element) => element.addEventListener('click', gridItemAction)); -document.querySelectorAll('.js-grid-item-transition-action').forEach((element) => element.addEventListener('change', gridTransitionItemAction)); -document.querySelectorAll('.js-grid-button-transition-action').forEach((element) => element.addEventListener('click', gridTransitionButtonAction)); +/* + * Set up an interactive list elements + * + * @param {Event} event + */ +const setup = ({ target }) => { + target.querySelectorAll('.js-grid-item-check-all').forEach((element) => element.addEventListener('click', (event) => Joomla.checkAll(event.target))); + target.querySelectorAll('.js-grid-item-is-checked').forEach((element) => element.addEventListener('click', applyIsChecked)); + target.querySelectorAll('.js-grid-item-action').forEach((element) => element.addEventListener('click', gridItemAction)); + target.querySelectorAll('.js-grid-item-transition-action').forEach((element) => element.addEventListener('change', gridTransitionItemAction)); + target.querySelectorAll('.js-grid-button-transition-action').forEach((element) => element.addEventListener('click', gridTransitionButtonAction)); +}; + +setup({ target: document }); +document.addEventListener('joomla:updated', setup); diff --git a/components/com_content/tmpl/category/blog_links.php b/components/com_content/tmpl/category/blog_links.php index 9bb816005de2c..83250ff6b89c8 100644 --- a/components/com_content/tmpl/category/blog_links.php +++ b/components/com_content/tmpl/category/blog_links.php @@ -15,11 +15,11 @@ ?> - + diff --git a/components/com_users/tmpl/captive/default.php b/components/com_users/tmpl/captive/default.php index f656fbaaa02b9..dd09bba0b2f64 100644 --- a/components/com_users/tmpl/captive/default.php +++ b/components/com_users/tmpl/captive/default.php @@ -20,12 +20,10 @@ * @var HtmlView $this View object * @var CaptiveModel $model The model */ -$model = $this->getModel(); +$model = $this->getModel(); -if ($this->renderOptions['field_type'] !== 'custom') { - $this->document->getWebAssetManager() - ->useScript('com_users.two-factor-focus'); -} +$this->document->getWebAssetManager() + ->useScript('com_users.two-factor-focus'); ?>
diff --git a/composer.json b/composer.json index c2dec9b230340..1596f0aa1217a 100644 --- a/composer.json +++ b/composer.json @@ -71,7 +71,7 @@ "fig/link-util": "^1.1.2", "google/recaptcha": "^1.2.4", "laminas/laminas-diactoros": "^2.4.1", - "paragonie/sodium_compat": "^1.19", + "paragonie/sodium_compat": "^1.20", "phpmailer/phpmailer": "^6.8.0", "psr/link": "~1.1.0", "symfony/console": "^6.2.7", @@ -98,7 +98,7 @@ "lcobucci/jwt": "^4.2.1", "web-token/signature-pack": "^3.1.2", "phpseclib/bcmath_compat": "^2.0.1", - "jfcherng/php-diff": "^6.10.11", + "jfcherng/php-diff": "^6.10.12", "voku/portable-utf8": "6.0.12 as 5.4.0" }, "require-dev": { diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql index 6cbe27732c7ca..2757cd2a5b39f 100644 --- a/installation/sql/mysql/base.sql +++ b/installation/sql/mysql/base.sql @@ -328,6 +328,7 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'plg_quickicon_downloadkey', 'plugin', 'downloadkey', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 4, 0), (0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), (0, 'plg_quickicon_phpversioncheck', 'plugin', 'phpversioncheck', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 6, 0), +(0, 'plg_quickicon_eos', 'plugin', 'eos', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 7, 0), (0, 'plg_sampledata_blog', 'plugin', 'blog', 'sampledata', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_sampledata_multilang', 'plugin', 'multilang', 'sampledata', 0, 1, 1, 0, 1, '', '', '', 2, 0), (0, 'plg_system_accessibility', 'plugin', 'accessibility', 'system', 0, 0, 1, 0, 1, '', '{}', '', 1, 0), diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql index eaf4db92ad35f..3cab39bfccc6e 100644 --- a/installation/sql/postgresql/base.sql +++ b/installation/sql/postgresql/base.sql @@ -334,6 +334,7 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'plg_quickicon_downloadkey', 'plugin', 'downloadkey', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 4, 0), (0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), (0, 'plg_quickicon_phpversioncheck', 'plugin', 'phpversioncheck', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 6, 0), +(0, 'plg_quickicon_eos', 'plugin', 'eos', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 7, 0), (0, 'plg_sampledata_blog', 'plugin', 'blog', 'sampledata', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_sampledata_multilang', 'plugin', 'multilang', 'sampledata', 0, 1, 1, 0, 1, '', '', '', 2, 0), (0, 'plg_system_accessibility', 'plugin', 'accessibility', 'system', 0, 0, 1, 0, 1, '', '{}', '', 1, 0), diff --git a/libraries/src/Categories/Categories.php b/libraries/src/Categories/Categories.php index 19ae180fdb681..961d612fb920b 100644 --- a/libraries/src/Categories/Categories.php +++ b/libraries/src/Categories/Categories.php @@ -216,7 +216,7 @@ public function getExtension() * * @return array * - * @since __DEPLOY_VERSION__ + * @since 4.3.2 */ public function getOptions() { diff --git a/libraries/src/Categories/CategoryNode.php b/libraries/src/Categories/CategoryNode.php index 06fff814fa27a..d305369524e44 100644 --- a/libraries/src/Categories/CategoryNode.php +++ b/libraries/src/Categories/CategoryNode.php @@ -489,7 +489,7 @@ public function getNumItems($recursive = false) /** * Serialize the node. * - * @since __DEPLOY_VERSION__ + * @since 4.3.2 */ public function __serialize() { @@ -508,7 +508,7 @@ public function __serialize() * * @param array $data * - * @since __DEPLOY_VERSION__ + * @since 4.3.2 */ public function __unserialize($data) { diff --git a/libraries/src/Extension/ExtensionHelper.php b/libraries/src/Extension/ExtensionHelper.php index aec5e4eb2c349..167ef57a3142f 100644 --- a/libraries/src/Extension/ExtensionHelper.php +++ b/libraries/src/Extension/ExtensionHelper.php @@ -273,6 +273,7 @@ class ExtensionHelper ['plugin', 'overridecheck', 'quickicon', 0], ['plugin', 'phpversioncheck', 'quickicon', 0], ['plugin', 'privacycheck', 'quickicon', 0], + ['plugin', 'eos', 'quickicon', 0], // Core plugin extensions - sample data ['plugin', 'blog', 'sampledata', 0], diff --git a/libraries/src/Form/Field/MediaField.php b/libraries/src/Form/Field/MediaField.php index f40f9c53bc4e2..d728bd32fb28f 100644 --- a/libraries/src/Form/Field/MediaField.php +++ b/libraries/src/Form/Field/MediaField.php @@ -293,9 +293,9 @@ public function getLayoutData() $this->folder = $adapter . ':' . $path; } elseif ($this->value && is_file(JPATH_ROOT . '/' . $this->value)) { /** - * Local image, for example images/sampledata/cassiopeia/nasa2-640.jpg . We need to validate and make sure - * the top level folder is one of the directory configured in filesystem local plugin to avoid error message - * displayed in manage when users click on Select button to select a new image + * Local image, for example images/sampledata/cassiopeia/nasa2-640.jpg. We need to validate and make sure + * the top level folder is one of the directories configured in the filesystem local plugin to avoid an error + * message being displayed when users click on Select button to select a new image. */ $paths = explode('/', Path::clean($this->value, '/')); @@ -310,8 +310,8 @@ public function getLayoutData() /** * This is the case where a folder is configured in directory attribute of the form field. The directory needs * to be a relative folder of the folder configured in Path to Images Folder config option of Media component. - * Same with a already stored local image above, we need to validate and make sure top level folder is one of the directory - * configured in filesystem local plugin + * Same with an already stored local image above, we need to validate and make sure the top level folder is one of the + * directories configured in the filesystem local plugin. */ $path = ComponentHelper::getParams('com_media')->get('image_path', 'images') . '/' . $this->directory; $paths = explode('/', Path::clean($path, '/')); diff --git a/libraries/src/WebAsset/WebAssetItem.php b/libraries/src/WebAsset/WebAssetItem.php index 3bb084ebd6b83..b1e43b3587de3 100644 --- a/libraries/src/WebAsset/WebAssetItem.php +++ b/libraries/src/WebAsset/WebAssetItem.php @@ -338,6 +338,6 @@ protected function isPathExternal(string $path): bool protected function isPathAbsolute(string $path): bool { // We have a full path or not - return is_file(JPATH_ROOT . '/' . $path); + return strpos($path, '/') !== false && is_file(JPATH_ROOT . '/' . $path); } } diff --git a/libraries/src/Workflow/WorkflowPluginTrait.php b/libraries/src/Workflow/WorkflowPluginTrait.php index 42382f0f4a9ee..a4f7ebf85a7f6 100644 --- a/libraries/src/Workflow/WorkflowPluginTrait.php +++ b/libraries/src/Workflow/WorkflowPluginTrait.php @@ -47,6 +47,10 @@ protected function enhanceWorkflowTransitionForm(Form $form, $data) // Load XML file from "parent" plugin $path = dirname((new ReflectionClass(static::class))->getFileName()); + if (!is_file($path . '/forms/action.xml')) { + $path = JPATH_PLUGINS . '/' . $this->_type . '/' . $this->_name; + } + if (is_file($path . '/forms/action.xml')) { $form->loadFile($path . '/forms/action.xml'); } @@ -65,13 +69,14 @@ protected function enhanceWorkflowTransitionForm(Form $form, $data) */ protected function getWorkflow(int $workflowId = null) { - $workflowId = !empty($workflowId) ? $workflowId : $this->app->getInput()->getInt('workflow_id'); + $app = $this->getApplication() ?? $this->app; + $workflowId = !empty($workflowId) ? $workflowId : $app->getInput()->getInt('workflow_id'); if (is_array($workflowId)) { return false; } - return $this->app->bootComponent('com_workflow') + return $app->bootComponent('com_workflow') ->getMVCFactory() ->createModel('Workflow', 'Administrator', ['ignore_request' => true]) ->getItem($workflowId); @@ -134,7 +139,7 @@ protected function checkExtensionSupport($context, $functionality) { $parts = explode('.', $context); - $component = $this->app->bootComponent($parts[0]); + $component = ($this->getApplication() ?? $this->app)->bootComponent($parts[0]); if ( !$component instanceof WorkflowServiceInterface diff --git a/package.json b/package.json index 66cc1249712c9..af8abe1b17420 100644 --- a/package.json +++ b/package.json @@ -40,22 +40,22 @@ "@claviska/jquery-minicolors": "^2.3.6", "@fortawesome/fontawesome-free": "^5.15.4", "@joomla/joomla-a11y-checker": "^1.0.0", - "@popperjs/core": "^2.11.6", - "@webcomponents/webcomponentsjs": "^2.7.0", + "@popperjs/core": "^2.11.7", + "@webcomponents/webcomponentsjs": "^2.8.0", "accessibility": "^3.0.17", "awesomplete": "^1.1.5", "bootstrap": "~5.2.3", "choices.js": "^9.1.0", "chosen-js": "^1.8.7", - "codemirror": "^5.65.12", + "codemirror": "^5.65.13", "cropperjs": "^1.5.13", "diff": "^5.1.0", "dotenv": "^16.0.3", "dragula": "^3.7.3", "focus-visible": "^5.2.0", - "hotkeys-js": "^3.10.1", + "hotkeys-js": "^3.10.2", "joomla-ui-custom-elements": "^0.2.0", - "jquery": "^3.6.4", + "jquery": "^3.7.0", "jquery-migrate": "^3.4.1", "mark.js": "^8.11.1", "mediaelement": "^5.1.1", @@ -63,7 +63,7 @@ "punycode": "^2.3.0", "qrcode-generator": "^1.4.4", "roboto-fontface": "^0.10.0", - "shepherd.js": "^11.0.1", + "shepherd.js": "^11.1.1", "short-and-sweet": "^1.0.4", "skipto": "^4.1.7", "tinymce": "^6.1.2", @@ -73,21 +73,21 @@ "vuex-persist": "^3.1.3" }, "devDependencies": { - "@babel/core": "^7.21.3", - "@babel/preset-env": "^7.20.2", + "@babel/core": "^7.21.8", + "@babel/preset-env": "^7.21.5", "@dgrammatiko/compress": "^1.0.4", "@rollup/plugin-babel": "^5.3.1", "@rollup/plugin-commonjs": "^21.1.0", "@rollup/plugin-node-resolve": "^13.3.0", "@rollup/plugin-replace": "^3.1.0", - "@vue/compiler-sfc": "^3.2.47", + "@vue/compiler-sfc": "^3.3.4", "autoprefixer": "^10.4.14", "chokidar": "^3.5.3", "commander": "^8.3.0", - "core-js": "^3.29.1", + "core-js": "^3.30.2", "cssnano": "^5.1.15", - "cypress": "^12.8.1", - "eslint": "^8.36.0", + "cypress": "^12.12.0", + "eslint": "^8.41.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-vue": "^8.7.1", @@ -96,7 +96,7 @@ "jasmine-core": "^3.99.1", "joomla-cypress": "^0.0.16", "mysql": "^2.18.1", - "postcss": "^8.4.21", + "postcss": "^8.4.23", "postcss-scss": "^4.0.6", "postgres": "^3.3.4", "recursive-readdir": "^2.2.3", @@ -104,12 +104,12 @@ "rollup": "^2.79.1", "rollup-plugin-vue": "^6.0.0", "rtlcss": "^3.5.0", - "sass-embedded": "^1.59.3", + "sass-embedded": "^1.62.0", "smtp-tester": "^2.0.1", "stylelint": "^14.16.1", "stylelint-config-standard": "^24.0.0", "stylelint-order": "^5.0.0", - "stylelint-scss": "^4.5.0", - "terser": "^5.16.6" + "stylelint-scss": "^4.7.0", + "terser": "^5.17.6" } } diff --git a/plugins/content/finder/finder.xml b/plugins/content/finder/finder.xml index 1e6cf2ad55247..fd2b69748ff35 100644 --- a/plugins/content/finder/finder.xml +++ b/plugins/content/finder/finder.xml @@ -9,9 +9,10 @@ www.joomla.org 3.0.0 PLG_CONTENT_FINDER_XML_DESCRIPTION - + Joomla\Plugin\Content\Finder - finder.php + services + src language/en-GB/plg_content_finder.ini diff --git a/plugins/content/finder/services/provider.php b/plugins/content/finder/services/provider.php new file mode 100644 index 0000000000000..0034506e62d8c --- /dev/null +++ b/plugins/content/finder/services/provider.php @@ -0,0 +1,47 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Extension\PluginInterface; +use Joomla\CMS\Factory; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherInterface; +use Joomla\Plugin\Content\Finder\Extension\Finder; + +return new class () implements ServiceProviderInterface { + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function register(Container $container): void + { + $container->set( + PluginInterface::class, + function (Container $container) { + $dispatcher = $container->get(DispatcherInterface::class); + $plugin = new Finder( + $dispatcher, + (array) PluginHelper::getPlugin('content', 'finder') + ); + $plugin->setApplication(Factory::getApplication()); + + return $plugin; + } + ); + } +}; diff --git a/plugins/content/finder/finder.php b/plugins/content/finder/src/Extension/Finder.php similarity index 85% rename from plugins/content/finder/finder.php rename to plugins/content/finder/src/Extension/Finder.php index 7e0b5ff24a767..463f925827c36 100644 --- a/plugins/content/finder/finder.php +++ b/plugins/content/finder/src/Extension/Finder.php @@ -6,11 +6,10 @@ * * @copyright (C) 2011 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt - - * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace */ -use Joomla\CMS\Factory; +namespace Joomla\Plugin\Content\Finder\Extension; + use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Plugin\PluginHelper; @@ -23,7 +22,7 @@ * * @since 2.5 */ -class PlgContentFinder extends CMSPlugin +final class Finder extends CMSPlugin { /** * Smart Search after save content method. @@ -43,7 +42,7 @@ public function onContentAfterSave($context, $article, $isNew): void PluginHelper::importPlugin('finder'); // Trigger the onFinderAfterSave event. - Factory::getApplication()->triggerEvent('onFinderAfterSave', [$context, $article, $isNew]); + $this->getApplication()->triggerEvent('onFinderAfterSave', [$context, $article, $isNew]); } /** @@ -63,7 +62,7 @@ public function onContentBeforeSave($context, $article, $isNew) PluginHelper::importPlugin('finder'); // Trigger the onFinderBeforeSave event. - Factory::getApplication()->triggerEvent('onFinderBeforeSave', [$context, $article, $isNew]); + $this->getApplication()->triggerEvent('onFinderBeforeSave', [$context, $article, $isNew]); } /** @@ -82,7 +81,7 @@ public function onContentAfterDelete($context, $article): void PluginHelper::importPlugin('finder'); // Trigger the onFinderAfterDelete event. - Factory::getApplication()->triggerEvent('onFinderAfterDelete', [$context, $article]); + $this->getApplication()->triggerEvent('onFinderAfterDelete', [$context, $article]); } /** @@ -104,7 +103,7 @@ public function onContentChangeState($context, $pks, $value) PluginHelper::importPlugin('finder'); // Trigger the onFinderChangeState event. - Factory::getApplication()->triggerEvent('onFinderChangeState', [$context, $pks, $value]); + $this->getApplication()->triggerEvent('onFinderChangeState', [$context, $pks, $value]); } /** @@ -125,6 +124,6 @@ public function onCategoryChangeState($extension, $pks, $value) PluginHelper::importPlugin('finder'); // Trigger the onFinderCategoryChangeState event. - Factory::getApplication()->triggerEvent('onFinderCategoryChangeState', [$extension, $pks, $value]); + $this->getApplication()->triggerEvent('onFinderCategoryChangeState', [$extension, $pks, $value]); } } diff --git a/plugins/content/joomla/joomla.xml b/plugins/content/joomla/joomla.xml index 272bdd471bd58..2e82d7d3fba5f 100644 --- a/plugins/content/joomla/joomla.xml +++ b/plugins/content/joomla/joomla.xml @@ -9,8 +9,10 @@ www.joomla.org 3.0.0 PLG_CONTENT_JOOMLA_XML_DESCRIPTION + Joomla\Plugin\Content\Joomla - joomla.php + services + src language/en-GB/plg_content_joomla.ini diff --git a/plugins/content/joomla/services/provider.php b/plugins/content/joomla/services/provider.php new file mode 100644 index 0000000000000..c85bce318799b --- /dev/null +++ b/plugins/content/joomla/services/provider.php @@ -0,0 +1,51 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Extension\PluginInterface; +use Joomla\CMS\Factory; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\User\UserFactoryInterface; +use Joomla\Database\DatabaseInterface; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherInterface; +use Joomla\Plugin\Content\Joomla\Extension\Joomla; + +return new class () implements ServiceProviderInterface { + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function register(Container $container): void + { + $container->set( + PluginInterface::class, + function (Container $container) { + $dispatcher = $container->get(DispatcherInterface::class); + $plugin = new Joomla( + $dispatcher, + (array) PluginHelper::getPlugin('content', 'joomla') + ); + $plugin->setApplication(Factory::getApplication()); + $plugin->setDatabase($container->get(DatabaseInterface::class)); + $plugin->setUserFactory($container->get(UserFactoryInterface::class)); + + return $plugin; + } + ); + } +}; diff --git a/plugins/content/joomla/joomla.php b/plugins/content/joomla/src/Extension/Joomla.php similarity index 82% rename from plugins/content/joomla/joomla.php rename to plugins/content/joomla/src/Extension/Joomla.php index ba4deb8f58e02..24c44f84419d6 100644 --- a/plugins/content/joomla/joomla.php +++ b/plugins/content/joomla/src/Extension/Joomla.php @@ -6,23 +6,24 @@ * * @copyright (C) 2010 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt - - * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace */ -use Joomla\CMS\Application\CMSApplicationInterface; +namespace Joomla\Plugin\Content\Joomla\Extension; + +use Exception; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Language\Language; use Joomla\CMS\Language\Text; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Table\CoreContent; -use Joomla\CMS\User\User; +use Joomla\CMS\User\UserFactoryAwareTrait; use Joomla\CMS\Workflow\WorkflowServiceInterface; use Joomla\Component\Workflow\Administrator\Table\StageTable; use Joomla\Component\Workflow\Administrator\Table\WorkflowTable; -use Joomla\Database\DatabaseDriver; +use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; use Joomla\Utilities\ArrayHelper; +use RuntimeException; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -33,23 +34,10 @@ * * @since 1.6 */ -class PlgContentJoomla extends CMSPlugin +final class Joomla extends CMSPlugin { - /** - * Application object - * - * @var CMSApplicationInterface - * @since 4.0.0 - */ - protected $app; - - /** - * Database Driver Instance - * - * @var DatabaseDriver - * @since 4.0.0 - */ - protected $db; + use DatabaseAwareTrait; + use UserFactoryAwareTrait; /** * The save event. @@ -83,10 +71,10 @@ public function onContentBeforeSave($context, $table, $isNew, $data) if ($item->$publishedField > 0 && isset($data[$publishedField]) && $data[$publishedField] < 1) { switch ($context) { case 'com_workflow.workflow': - return $this->_workflowNotUsed($item->id); + return $this->workflowNotUsed($item->id); case 'com_workflow.stage': - return $this->_stageNotUsed($item->id); + return $this->stageNotUsed($item->id); } } @@ -123,7 +111,7 @@ public function onContentAfterSave($context, $article, $isNew): void return; } - $db = $this->db; + $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) @@ -136,17 +124,17 @@ public function onContentAfterSave($context, $article, $isNew): void return; } - $user = $this->app->getIdentity(); + $user = $this->getApplication()->getIdentity(); // Messaging for new items $default_language = ComponentHelper::getParams('com_languages')->get('administrator'); - $debug = $this->app->get('debug_lang'); + $debug = $this->getApplication()->get('debug_lang'); foreach ($users as $user_id) { if ($user_id != $user->id) { // Load language for messaging - $receiver = User::getInstance($user_id); + $receiver = $this->getUserFactory()->loadUserById($user_id); $lang = Language::getInstance($receiver->getParam('admin_language', $default_language), $debug); $lang->load('com_content'); $message = [ @@ -154,7 +142,7 @@ public function onContentAfterSave($context, $article, $isNew): void 'subject' => $lang->_('COM_CONTENT_NEW_ARTICLE'), 'message' => sprintf($lang->_('COM_CONTENT_ON_NEW_CONTENT'), $user->get('name'), $article->title), ]; - $model_message = $this->app->bootComponent('com_messages')->getMVCFactory() + $model_message = $this->getApplication()->bootComponent('com_messages')->getMVCFactory() ->createModel('Message', 'Administrator'); $model_message->save($message); } @@ -180,13 +168,13 @@ public function onContentBeforeDelete($context, $data) switch ($context) { case 'com_categories.category': - return $this->_canDeleteCategories($data); + return $this->canDeleteCategories($data); case 'com_workflow.workflow': - return $this->_workflowNotUsed($data->id); + return $this->workflowNotUsed($data->id); case 'com_workflow.stage': - return $this->_stageNotUsed($data->id); + return $this->stageNotUsed($data->id); } } @@ -212,11 +200,11 @@ public function onContentBeforeChangeState($context, $pks, $value) foreach ($pks as $id) { switch ($context) { case 'com_workflow.workflow': - $result = $result && $this->_workflowNotUsed($id); + $result = $result && $this->workflowNotUsed($id); break; case 'com_workflow.stage': - $result = $result && $this->_stageNotUsed($id); + $result = $result && $this->stageNotUsed($id); break; } } @@ -231,14 +219,14 @@ public function onContentBeforeChangeState($context, $pks, $value) * * @return boolean */ - private function _canDeleteCategories($data) + private function canDeleteCategories($data) { // Check if this function is enabled. if (!$this->params->def('check_categories', 1)) { return true; } - $extension = $this->app->getInput()->getString('extension'); + $extension = $this->getApplication()->getInput()->getString('extension'); // Default to true if not a core extension $result = true; @@ -258,7 +246,7 @@ private function _canDeleteCategories($data) $table = $tableInfo[$extension]['table_name']; // See if this category has any content items - $count = $this->_countItemsInCategory($table, $data->get('id')); + $count = $this->countItemsInCategory($table, $data->get('id')); // Return false if db error if ($count === false) { @@ -268,20 +256,20 @@ private function _canDeleteCategories($data) if ($count > 0) { $msg = Text::sprintf('COM_CATEGORIES_DELETE_NOT_ALLOWED', $data->get('title')) . ' ' . Text::plural('COM_CATEGORIES_N_ITEMS_ASSIGNED', $count); - $this->app->enqueueMessage($msg, 'error'); + $this->getApplication()->enqueueMessage($msg, 'error'); $result = false; } // Check for items in any child categories (if it is a leaf, there are no child categories) if (!$data->isLeaf()) { - $count = $this->_countItemsInChildren($table, $data->get('id'), $data); + $count = $this->countItemsInChildren($table, $data->get('id'), $data); if ($count === false) { $result = false; } elseif ($count > 0) { $msg = Text::sprintf('COM_CATEGORIES_DELETE_NOT_ALLOWED', $data->get('title')) . ' ' . Text::plural('COM_CATEGORIES_HAS_SUBCATEGORY_ITEMS', $count); - $this->app->enqueueMessage($msg, 'error'); + $this->getApplication()->enqueueMessage($msg, 'error'); $result = false; } } @@ -300,10 +288,10 @@ private function _canDeleteCategories($data) * * @since 4.0.0 */ - private function _workflowNotUsed($pk) + private function workflowNotUsed($pk) { // Check if this workflow is the default stage - $table = new WorkflowTable($this->db); + $table = new WorkflowTable($this->getDatabase()); $table->load($pk); @@ -312,12 +300,12 @@ private function _workflowNotUsed($pk) } if ($table->default) { - throw new Exception(Text::_('COM_WORKFLOW_MSG_DELETE_IS_DEFAULT')); + throw new Exception($this->getApplication()->getLanguage()->_('COM_WORKFLOW_MSG_DELETE_IS_DEFAULT')); } $parts = explode('.', $table->extension); - $component = $this->app->bootComponent($parts[0]); + $component = $this->getApplication()->bootComponent($parts[0]); $section = ''; @@ -331,7 +319,7 @@ private function _workflowNotUsed($pk) } /** @var \Joomla\Component\Workflow\Administrator\Model\StagesModel $model */ - $model = $this->app->bootComponent('com_workflow')->getMVCFactory() + $model = $this->getApplication()->bootComponent('com_workflow')->getMVCFactory() ->createModel('Stages', 'Administrator', ['ignore_request' => true]); $model->setState('filter.workflow_id', $pk); @@ -341,11 +329,11 @@ private function _workflowNotUsed($pk) $stage_ids = array_column($stages, 'id'); - $result = $this->_countItemsInStage($stage_ids, $table->extension); + $result = $this->countItemsInStage($stage_ids, $table->extension); // Return false if db error if ($result > 0) { - throw new Exception(Text::_('COM_WORKFLOW_MSG_DELETE_WORKFLOW_IS_ASSIGNED')); + throw new Exception($this->getApplication()->getLanguage()->_('COM_WORKFLOW_MSG_DELETE_WORKFLOW_IS_ASSIGNED')); } return true; @@ -360,9 +348,9 @@ private function _workflowNotUsed($pk) * * @since 4.0.0 */ - private function _stageNotUsed($pk) + private function stageNotUsed($pk) { - $table = new StageTable($this->db); + $table = new StageTable($this->getDatabase()); $table->load($pk); @@ -372,10 +360,10 @@ private function _stageNotUsed($pk) // Check if this stage is the default stage if ($table->default) { - throw new Exception(Text::_('COM_WORKFLOW_MSG_DELETE_IS_DEFAULT')); + throw new Exception($this->getApplication()->getLanguage()->_('COM_WORKFLOW_MSG_DELETE_IS_DEFAULT')); } - $workflow = new WorkflowTable($this->db); + $workflow = new WorkflowTable($this->getDatabase()); $workflow->load($table->workflow_id); @@ -385,7 +373,7 @@ private function _stageNotUsed($pk) $parts = explode('.', $workflow->extension); - $component = $this->app->bootComponent($parts[0]); + $component = $this->getApplication()->bootComponent($parts[0]); // No core interface => we're ok if (!$component instanceof WorkflowServiceInterface) { @@ -394,11 +382,11 @@ private function _stageNotUsed($pk) $stage_ids = [$table->id]; - $result = $this->_countItemsInStage($stage_ids, $workflow->extension); + $result = $this->countItemsInStage($stage_ids, $workflow->extension); // Return false if db error if ($result > 0) { - throw new Exception(Text::_('COM_WORKFLOW_MSG_DELETE_STAGE_IS_ASSIGNED')); + throw new Exception($this->getApplication()->getLanguage()->_('COM_WORKFLOW_MSG_DELETE_STAGE_IS_ASSIGNED')); } return true; @@ -414,9 +402,9 @@ private function _stageNotUsed($pk) * * @since 1.6 */ - private function _countItemsInCategory($table, $catid) + private function countItemsInCategory($table, $catid) { - $db = $this->db; + $db = $this->getDatabase(); $query = $db->getQuery(true); // Count the items in this category @@ -429,7 +417,7 @@ private function _countItemsInCategory($table, $catid) try { $count = $db->loadResult(); } catch (RuntimeException $e) { - $this->app->enqueueMessage($e->getMessage(), 'error'); + $this->getApplication()->enqueueMessage($e->getMessage(), 'error'); return false; } @@ -447,9 +435,9 @@ private function _countItemsInCategory($table, $catid) * * @since 4.0.0 */ - private function _countItemsInStage(array $stageIds, string $extension): bool + private function countItemsInStage(array $stageIds, string $extension): bool { - $db = $this->db; + $db = $this->getDatabase(); $parts = explode('.', $extension); @@ -462,7 +450,7 @@ private function _countItemsInStage(array $stageIds, string $extension): bool $section = $parts[1]; } - $component = $this->app->bootComponent($parts[0]); + $component = $this->getApplication()->bootComponent($parts[0]); $table = $component->getWorkflowTableBySection($section); @@ -483,7 +471,7 @@ private function _countItemsInStage(array $stageIds, string $extension): bool try { return (int) $db->setQuery($query)->loadResult(); } catch (Exception $e) { - $this->app->enqueueMessage($e->getMessage(), 'error'); + $this->getApplication()->enqueueMessage($e->getMessage(), 'error'); } return false; @@ -500,9 +488,9 @@ private function _countItemsInStage(array $stageIds, string $extension): bool * * @since 1.6 */ - private function _countItemsInChildren($table, $catid, $data) + private function countItemsInChildren($table, $catid, $data) { - $db = $this->db; + $db = $this->getDatabase(); // Create subquery for list of child categories $childCategoryTree = $data->getTree(); @@ -527,7 +515,7 @@ private function _countItemsInChildren($table, $catid, $data) try { $count = $db->loadResult(); } catch (RuntimeException $e) { - $this->app->enqueueMessage($e->getMessage(), 'error'); + $this->getApplication()->enqueueMessage($e->getMessage(), 'error'); return false; } @@ -555,7 +543,7 @@ public function onContentChangeState($context, $pks, $value) if ($context === 'com_workflow.stage' && $value < 1) { foreach ($pks as $pk) { - if (!$this->_stageNotUsed($pk)) { + if (!$this->stageNotUsed($pk)) { return false; } } @@ -563,7 +551,7 @@ public function onContentChangeState($context, $pks, $value) return true; } - $db = $this->db; + $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName('core_content_id')) ->from($db->quoteName('#__ucm_content')) @@ -607,7 +595,7 @@ private function checkMenuItemBeforeSave($context, $table, $isNew, $data) $params = json_decode($table->params, true); if ($params['enable_category'] == 1 && empty($params['catid'])) { - $table->setError(Text::_('COM_CONTENT_CREATE_ARTICLE_ERROR')); + $table->setError($this->getApplication()->getLanguage()->_('COM_CONTENT_CREATE_ARTICLE_ERROR')); return false; } diff --git a/plugins/content/loadmodule/loadmodule.xml b/plugins/content/loadmodule/loadmodule.xml index c62080c283466..3eeb863e4a9a2 100644 --- a/plugins/content/loadmodule/loadmodule.xml +++ b/plugins/content/loadmodule/loadmodule.xml @@ -9,8 +9,10 @@ www.joomla.org 3.0.0 PLG_LOADMODULE_XML_DESCRIPTION + Joomla\Plugin\Content\LoadModule - loadmodule.php + services + src language/en-GB/plg_content_loadmodule.ini diff --git a/plugins/content/loadmodule/services/provider.php b/plugins/content/loadmodule/services/provider.php new file mode 100644 index 0000000000000..50dbb6eeecfba --- /dev/null +++ b/plugins/content/loadmodule/services/provider.php @@ -0,0 +1,47 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Extension\PluginInterface; +use Joomla\CMS\Factory; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherInterface; +use Joomla\Plugin\Content\LoadModule\Extension\LoadModule; + +return new class () implements ServiceProviderInterface { + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function register(Container $container): void + { + $container->set( + PluginInterface::class, + function (Container $container) { + $dispatcher = $container->get(DispatcherInterface::class); + $plugin = new LoadModule( + $dispatcher, + (array) PluginHelper::getPlugin('content', 'loadmodule') + ); + $plugin->setApplication(Factory::getApplication()); + + return $plugin; + } + ); + } +}; diff --git a/plugins/content/loadmodule/loadmodule.php b/plugins/content/loadmodule/src/Extension/LoadModule.php similarity index 92% rename from plugins/content/loadmodule/loadmodule.php rename to plugins/content/loadmodule/src/Extension/LoadModule.php index ce5074f81902b..78c4a3845b7f2 100644 --- a/plugins/content/loadmodule/loadmodule.php +++ b/plugins/content/loadmodule/src/Extension/LoadModule.php @@ -6,11 +6,10 @@ * * @copyright (C) 2006 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt - - * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace */ -use Joomla\CMS\Factory; +namespace Joomla\Plugin\Content\LoadModule\Extension; + use Joomla\CMS\Helper\ModuleHelper; use Joomla\CMS\Plugin\CMSPlugin; @@ -24,7 +23,7 @@ * * @since 1.5 */ -class PlgContentLoadmodule extends CMSPlugin +final class LoadModule extends CMSPlugin { protected static $modules = []; @@ -88,7 +87,7 @@ public function onContentPrepare($context, &$article, &$params, $page = 0) $position = trim($matcheslist[0]); $style = trim($matcheslist[1]); - $output = $this->_load($position, $style); + $output = $this->load($position, $style); // We should replace only first occurrence in order to allow positions with the same name to regenerate their content: if (($start = strpos($article->text, $match[0])) !== false) { @@ -124,7 +123,7 @@ public function onContentPrepare($context, &$article, &$params, $page = 0) $stylemod = trim($matchesmodlist[2]); } - $output = $this->_loadmod($module, $title, $stylemod); + $output = $this->loadModule($module, $title, $stylemod); // We should replace only first occurrence in order to allow positions with the same name to regenerate their content: if (($start = strpos($article->text, $matchmod[0])) !== false) { @@ -142,7 +141,7 @@ public function onContentPrepare($context, &$article, &$params, $page = 0) if ($matchesmodid) { foreach ($matchesmodid as $match) { $id = trim($match[1]); - $output = $this->_loadid($id); + $output = $this->loadID($id); // We should replace only first occurrence in order to allow positions with the same name to regenerate their content: if (($start = strpos($article->text, $match[0])) !== false) { @@ -163,9 +162,9 @@ public function onContentPrepare($context, &$article, &$params, $page = 0) * * @since 1.6 */ - protected function _load($position, $style = 'none') + private function load($position, $style = 'none') { - $document = Factory::getDocument(); + $document = $this->getApplication()->getDocument(); $renderer = $document->loadRenderer('module'); $modules = ModuleHelper::getModules($position); $params = ['style' => $style]; @@ -190,9 +189,9 @@ protected function _load($position, $style = 'none') * * @since 1.6 */ - protected function _loadmod($module, $title, $style = 'none') + private function loadModule($module, $title, $style = 'none') { - $document = Factory::getDocument(); + $document = $this->getApplication()->getDocument(); $renderer = $document->loadRenderer('module'); $mod = ModuleHelper::getModule($module, $title); @@ -222,9 +221,9 @@ protected function _loadmod($module, $title, $style = 'none') * * @since 3.9.0 */ - protected function _loadid($id) + private function loadID($id) { - $document = Factory::getDocument(); + $document = $this->getApplication()->getDocument(); $renderer = $document->loadRenderer('module'); $modules = ModuleHelper::getModuleById($id); $params = ['style' => 'none']; diff --git a/plugins/content/pagebreak/pagebreak.xml b/plugins/content/pagebreak/pagebreak.xml index 3d91dff6c0f9e..c447ce17a7152 100644 --- a/plugins/content/pagebreak/pagebreak.xml +++ b/plugins/content/pagebreak/pagebreak.xml @@ -9,8 +9,11 @@ www.joomla.org 3.0.0 PLG_CONTENT_PAGEBREAK_XML_DESCRIPTION + Joomla\Plugin\Content\PageBreak - pagebreak.php + services + src + tmpl language/en-GB/plg_content_pagebreak.ini diff --git a/plugins/content/pagebreak/services/provider.php b/plugins/content/pagebreak/services/provider.php new file mode 100644 index 0000000000000..cb10f0e198ac3 --- /dev/null +++ b/plugins/content/pagebreak/services/provider.php @@ -0,0 +1,47 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Extension\PluginInterface; +use Joomla\CMS\Factory; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherInterface; +use Joomla\Plugin\Content\PageBreak\Extension\PageBreak; + +return new class () implements ServiceProviderInterface { + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function register(Container $container): void + { + $container->set( + PluginInterface::class, + function (Container $container) { + $dispatcher = $container->get(DispatcherInterface::class); + $plugin = new PageBreak( + $dispatcher, + (array) PluginHelper::getPlugin('content', 'pagebreak') + ); + $plugin->setApplication(Factory::getApplication()); + + return $plugin; + } + ); + } +}; diff --git a/plugins/content/pagebreak/pagebreak.php b/plugins/content/pagebreak/src/Extension/PageBreak.php similarity index 91% rename from plugins/content/pagebreak/pagebreak.php rename to plugins/content/pagebreak/src/Extension/PageBreak.php index 6d4ec0c6b7b85..7794434d24db2 100644 --- a/plugins/content/pagebreak/pagebreak.php +++ b/plugins/content/pagebreak/src/Extension/PageBreak.php @@ -6,11 +6,11 @@ * * @copyright (C) 2006 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt - - * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace */ -use Joomla\CMS\Factory; +namespace Joomla\Plugin\Content\PageBreak\Extension; + +use Exception; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Pagination\Pagination; @@ -19,6 +19,7 @@ use Joomla\CMS\Utility\Utility; use Joomla\Component\Content\Site\Helper\RouteHelper; use Joomla\String\StringHelper; +use stdClass; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -39,7 +40,7 @@ * * @since 1.6 */ -class PlgContentPagebreak extends CMSPlugin +final class PageBreak extends CMSPlugin { /** * The navigation list with all page objects if parameter 'multipage_toc' is active. @@ -74,7 +75,7 @@ public function onContentPrepare($context, &$row, &$params, $page = 0) // Expression to search for. $regex = '##iU'; - $input = Factory::getApplication()->getInput(); + $input = $this->getApplication()->getInput(); $print = $input->getBool('print'); $showall = $input->getBool('showall'); @@ -92,7 +93,7 @@ public function onContentPrepare($context, &$row, &$params, $page = 0) // Simple performance check to determine whether bot should process further. if (StringHelper::strpos($row->text, 'class="system-pagebreak') === false) { if ($page > 0) { - throw new Exception(Text::_('JERROR_PAGE_NOT_FOUND'), 404); + throw new Exception($this->getApplication()->getLanguage()->_('JERROR_PAGE_NOT_FOUND'), 404); } return; @@ -124,7 +125,7 @@ public function onContentPrepare($context, &$row, &$params, $page = 0) if ($hasToc) { // Display TOC. $page = 1; - $this->_createToc($row, $matches, $page); + $this->createToc($row, $matches, $page); } else { $row->toc = ''; } @@ -138,7 +139,7 @@ public function onContentPrepare($context, &$row, &$params, $page = 0) $text = preg_split($regex, $row->text); if (!isset($text[$page])) { - throw new Exception(Text::_('JERROR_PAGE_NOT_FOUND'), 404); + throw new Exception($this->getApplication()->getLanguage()->_('JERROR_PAGE_NOT_FOUND'), 404); } // Count the number of pages. @@ -164,7 +165,7 @@ public function onContentPrepare($context, &$row, &$params, $page = 0) if ($style === 'pages') { // Display TOC. if ($hasToc) { - $this->_createToc($row, $matches, $page); + $this->createToc($row, $matches, $page); } else { $row->toc = ''; } @@ -189,7 +190,7 @@ public function onContentPrepare($context, &$row, &$params, $page = 0) // Adds navigation between pages to bottom of text. if ($hasToc) { - $this->_createNavigation($row, $page, $n); + $this->createNavigation($row, $page, $n); } // Page links shown at bottom of page if TOC disabled. @@ -260,16 +261,16 @@ public function onContentPrepare($context, &$row, &$params, $page = 0) * * @since 1.6 */ - protected function _createToc(&$row, &$matches, &$page) + private function createToc(&$row, &$matches, &$page) { - $heading = $row->title ?? Text::_('PLG_CONTENT_PAGEBREAK_NO_TITLE'); - $input = Factory::getApplication()->getInput(); + $heading = $row->title ?? $this->getApplication()->getLanguage()->_('PLG_CONTENT_PAGEBREAK_NO_TITLE'); + $input = $this->getApplication()->getInput(); $limitstart = $input->getUint('limitstart', 0); $showall = $input->getInt('showall', 0); $headingtext = ''; if ($this->params->get('article_index', 1) == 1) { - $headingtext = Text::_('PLG_CONTENT_PAGEBREAK_ARTICLE_INDEX'); + $headingtext = $this->getApplication()->getLanguage()->_('PLG_CONTENT_PAGEBREAK_ARTICLE_INDEX'); if ($this->params->get('article_index_text')) { $headingtext = htmlspecialchars($this->params->get('article_index_text'), ENT_QUOTES, 'UTF-8'); @@ -310,7 +311,7 @@ protected function _createToc(&$row, &$matches, &$page) if ($this->params->get('showall')) { $this->list[$i] = new stdClass(); $this->list[$i]->link = RouteHelper::getArticleRoute($row->slug, $row->catid, $row->language) . '&showall=1'; - $this->list[$i]->title = Text::_('PLG_CONTENT_PAGEBREAK_ALL_PAGES'); + $this->list[$i]->title = $this->getApplication()->getLanguage()->_('PLG_CONTENT_PAGEBREAK_ALL_PAGES'); $this->list[$i]->active = ($limitstart === $i - 1); } @@ -332,7 +333,7 @@ protected function _createToc(&$row, &$matches, &$page) * * @since 1.6 */ - protected function _createNavigation(&$row, $page, $n) + private function createNavigation(&$row, $page, $n) { $links = [ 'next' => '', diff --git a/plugins/content/pagebreak/tmpl/navigation.php b/plugins/content/pagebreak/tmpl/navigation.php index 7e7a7ab8836ad..19794c861cce8 100644 --- a/plugins/content/pagebreak/tmpl/navigation.php +++ b/plugins/content/pagebreak/tmpl/navigation.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -19,7 +18,7 @@ * @var $page integer The page number */ -$lang = Factory::getLanguage(); +$lang = $this->getApplication()->getLanguage(); ?>